diff --git a/.clang-format b/.clang-format index 14c0a235995..c5979d77ba1 100644 --- a/.clang-format +++ b/.clang-format @@ -24,6 +24,7 @@ ExperimentalAutoDetectBinPacking: false IndentCaseLabels: true IndentFunctionDeclarationAfterType: true IndentWidth: 2 +InsertNewlineAtEOF: true # It is broken on windows. Breaks all #include "header.h" --- Language: Cpp diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 88d5e20cf96..4f71b741dcf 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -38,7 +38,7 @@ jobs: id: ml # You can override MegaLinter flavor used to have faster performances # More info at https://megalinter.io/flavors/ - uses: oxsecurity/megalinter@v7 + uses: oxsecurity/megalinter@v8 env: # All available variables are described in documentation: # https://megalinter.io/configuration/ @@ -47,6 +47,16 @@ jobs: VALIDATE_ALL_CODEBASE: false GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Upload MegaLinter artifacts + - name: Archive production artifacts + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: MegaLinter reports + path: | + megalinter-reports + mega-linter.log + # Create or delete the cleanup branch - name: Update cleanup branch if: ${{ github.event.repository.owner.login == 'AliceO2Group' }} diff --git a/ALICE3/Core/CMakeLists.txt b/ALICE3/Core/CMakeLists.txt index 6db27c117d8..788711ac277 100644 --- a/ALICE3/Core/CMakeLists.txt +++ b/ALICE3/Core/CMakeLists.txt @@ -15,6 +15,14 @@ o2physics_add_library(ALICE3Core PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) o2physics_target_root_dictionary(ALICE3Core - HEADERS TOFResoALICE3.h - DelphesO2TrackSmearer.h - LINKDEF ALICE3CoreLinkDef.h) + HEADERS TOFResoALICE3.h + DelphesO2TrackSmearer.h + LINKDEF ALICE3CoreLinkDef.h) + +o2physics_add_library(FastTracker + SOURCES FastTracker.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + +o2physics_target_root_dictionary(FastTracker + HEADERS FastTracker.h + LINKDEF FastTrackerLinkDef.h) diff --git a/ALICE3/Core/DetLayer.h b/ALICE3/Core/DetLayer.h new file mode 100644 index 00000000000..6b9fea14c06 --- /dev/null +++ b/ALICE3/Core/DetLayer.h @@ -0,0 +1,52 @@ +// Copyright 2019-2020 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. + +/// +/// \file DetLayer.h +/// \author David Dobrigkeit Chinellato +/// \since 11/03/2021 +/// \brief Basic struct to hold information regarding a detector layer to be used in fast simulation +/// + +#ifndef ALICE3_CORE_DETLAYER_H_ +#define ALICE3_CORE_DETLAYER_H_ + +#include "TString.h" + +namespace o2::fastsim +{ + +struct DetLayer { + // TString for holding name + TString name; + + // position variables + float r; // radius in centimeters + float z; // z dimension in centimeters + + // material variables + float x0; // radiation length + float xrho; // density + + // resolution variables for active layers + float resRPhi; // RPhi resolution in centimeters + float resZ; // Z resolution in centimeters + + // efficiency + float eff; // detection efficiency + + // layer type + int type; // 0: undefined/inert, 1: silicon, 2: gas/tpc +}; + +} // namespace o2::fastsim + +#endif // ALICE3_CORE_DETLAYER_H_ diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx new file mode 100644 index 00000000000..715ed9343e2 --- /dev/null +++ b/ALICE3/Core/FastTracker.cxx @@ -0,0 +1,395 @@ +// Copyright 2019-2020 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. + +#include +#include "TMath.h" +#include "TMatrixD.h" +#include "TRandom.h" +#include "TMatrixDSymEigen.h" +#include "FastTracker.h" + +namespace o2 +{ +namespace fastsim +{ + +// +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + +FastTracker::FastTracker() +{ + // base constructor + magneticField = 5; // in kiloGauss + applyZacceptance = false; + covMatFactor = 0.99f; + verboseLevel = 0; + + // last fast-tracked track properties + covMatOK = 0; + covMatNotOK = 0; + nIntercepts = 0; + nSiliconPoints = 0; + nGasPoints = 0; +} + +void FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi, float resZ, float eff, int type) +{ + DetLayer newLayer{name.Data(), r, z, x0, xrho, resRPhi, resZ, eff, type}; + layers.push_back(newLayer); +} + +void FastTracker::Print() +{ + // print out layer setup + LOG(info) << "+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+"; + LOG(info) << " Printing detector layout with " << layers.size() << " effective elements: "; + for (uint32_t il = 0; il < layers.size(); il++) { + LOG(info) << " Layer #" << il << "\t" << layers[il].name.Data() << "\tr = " << Form("%.2f", layers[il].r) << "cm\tz = " << layers[il].z << "\t" + << "x0 = " << layers[il].x0 << "\txrho = " << layers[il].xrho << "\tresRPhi = " << layers[il].resRPhi << "\tresZ = " << layers[il].resZ << "\teff = " << layers[il].eff; + } + LOG(info) << "+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+"; +} + +void FastTracker::AddSiliconALICE3v4() +{ + LOG(info) << " Adding ALICE 3 v4 ITS layers"; + float x0IT = 0.001; // 0.1% + float x0OT = 0.005; // 0.5% + float xrhoIB = 1.1646e-02; // 50 mum Si + float xrhoOB = 1.1646e-01; // 500 mum Si + + float resRPhiIT = 0.00025; // 2.5 mum + float resZIT = 0.00025; // 2.5 mum + float resRPhiOT = 0.0005; // 5 mum + float resZOT = 0.0005; // 5 mum + float eff = 1.00; + + layers.push_back(DetLayer{"bpipe0", 0.48, 250, 0.00042, 2.772e-02, 0.0f, 0.0f, 0.0f, 0}); // 150 mum Be + layers.push_back(DetLayer{"ddd0", 0.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1}); + layers.push_back(DetLayer{"ddd1", 1.2, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1}); + layers.push_back(DetLayer{"ddd2", 2.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1}); + layers.push_back(DetLayer{"bpipe1", 5.7, 250, 0.0014, 9.24e-02, 0.0f, 0.0f, 0.0f, 0}); // 500 mum Be + layers.push_back(DetLayer{"ddd3", 7., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"ddd4", 10., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"ddd5", 13., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"ddd6", 16., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"ddd7", 25., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"ddd8", 40., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"ddd9", 45., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); +} + +void FastTracker::AddSiliconALICE3v1() +{ + LOG(info) << " Adding ALICE 3 v1 ITS layers"; + float x0IT = 0.001; // 0.1% + float x0OT = 0.005; // 0.5% + float xrhoIB = 2.3292e-02; // 100 mum Si + float xrhoOB = 2.3292e-01; // 1000 mum Si + + float resRPhiIT = 0.00025; // 2.5 mum + float resZIT = 0.00025; // 2.5 mum + float resRPhiOT = 0.00100; // 5 mum + float resZOT = 0.00100; // 5 mum + float eff = 1.00; + + layers.push_back(DetLayer{"bpipe0", 0.48, 250, 0.00042, 2.772e-02, 0.0f, 0.0f, 0.0f, 1}); // 150 mum Be + layers.push_back(DetLayer{"B00", 0.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1}); + layers.push_back(DetLayer{"B01", 1.2, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1}); + layers.push_back(DetLayer{"B02", 2.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1}); + layers.push_back(DetLayer{"bpipe1", 3.7, 250, 0.0014, 9.24e-02, 0.0f, 0.0f, 0.0f, 1}); // 500 mum Be + layers.push_back(DetLayer{"B03", 3.75, 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B04", 7., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B05", 12., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B06", 20., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B07", 30., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B08", 45., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B09", 60., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); + layers.push_back(DetLayer{"B10", 80., 250, x0OT, xrhoOB, resRPhiOT, resZOT, eff, 1}); +} + +void FastTracker::AddTPC(float phiResMean, float zResMean) +{ + LOG(info) << " Adding standard time projection chamber"; + + // porting of DetectorK::AddTPC + // see here: + // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx + // % Radiation Lengths ... Average per TPC row (i.e. total/159 ) + const int kNPassiveBound = 2; + const float radLBoundary[kNPassiveBound] = {1.692612e-01, 8.711904e-02}; + const float xrhoBoundary[kNPassiveBound] = {6.795774e+00, 3.111401e+00}; + const float rBoundary[kNPassiveBound] = {50, 70.0}; // cm + + float radLPerRow = 0.000036; + + float tpcInnerRadialPitch = 0.75; // cm + float tpcMiddleRadialPitch = 1.0; // cm + float tpcOuterRadialPitch = 1.5; // cm + float innerRows = 63; + float middleRows = 64; + float outerRows = 32; + float tpcRows = (innerRows + middleRows + outerRows); + float rowOneRadius = 85.2; // cm + float row64Radius = 135.1; // cm + float row128Radius = 199.2; // cm + + float zLength = 250.0f; // to be checked + + // add boundaries between ITS and TPC + for (int i = 0; i < kNPassiveBound; i++) { + AddLayer(Form("tpc_boundary%d", i), rBoundary[i], zLength, radLBoundary[i], xrhoBoundary[i], 0); // dummy errors + } + for (Int_t k = 0; k < tpcRows; k++) { + Float_t rowRadius = 0; + if (k < innerRows) + rowRadius = rowOneRadius + k * tpcInnerRadialPitch; + else if (k >= innerRows && k < (innerRows + middleRows)) + rowRadius = row64Radius + (k - innerRows + 1) * tpcMiddleRadialPitch; + else if (k >= (innerRows + middleRows) && k < tpcRows) + rowRadius = row128Radius + (k - innerRows - middleRows + 1) * tpcOuterRadialPitch; + + AddLayer(Form("tpc_%d", k), rowRadius, zLength, radLPerRow, 0, phiResMean, zResMean, 1.0f, 2); + } +} + +// function to provide a reconstructed track from a perfect input track +// returns number of intercepts (generic for now) +int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack) +{ + hits.clear(); + nIntercepts = 0; + nSiliconPoints = 0; + nGasPoints = 0; + std::array posIni; // provision for != PV + inputTrack.getXYZGlo(posIni); + float initialRadius = std::hypot(posIni[0], posIni[1]); + + // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + // Outward pass to find intercepts + int firstLayerReached = -1; + int lastLayerReached = -1; + for (uint32_t il = 0; il < layers.size(); il++) { + // check if layer is doable + if (layers[il].r < initialRadius) + continue; // this layer should not be attempted, but go ahead + if (layers[il].type == 0) + continue; // inert layer, skip + + // check if layer is reached + float targetX = 1e+3; + inputTrack.getXatLabR(layers[il].r, targetX, magneticField); + if (targetX > 999) + break; // failed to find intercept + + if (!inputTrack.propagateTo(targetX, magneticField)) { + break; // failed to propagate + } + if (std::abs(inputTrack.getZ()) > layers[il].z && applyZacceptance) { + break; // out of acceptance bounds + } + + // layer is reached + if (firstLayerReached < 0) + firstLayerReached = il; + lastLayerReached = il; + nIntercepts++; + } + + // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + // initialize track at outer point + new (&outputTrack)(o2::track::TrackParCov)(inputTrack); + + // Enlarge covariance matrix + std::array trPars = {0.}; + for (int ip = 0; ip < 5; ip++) { + trPars[ip] = outputTrack.getParam(ip); + } + std::array largeCov = {0.}; + enum { kY, + kZ, + kSnp, + kTgl, + kPtI }; // track parameter aliases + enum { kY2, + kYZ, + kZ2, + kYSnp, + kZSnp, + kSnp2, + kYTgl, + kZTgl, + kSnpTgl, + kTgl2, + kYPtI, + kZPtI, + kSnpPtI, + kTglPtI, + kPtI2 }; // cov.matrix aliases + const double kLargeErr2Coord = 5 * 5; + const double kLargeErr2Dir = 0.7 * 0.7; + const double kLargeErr2PtI = 30.5 * 30.5; + for (int ic = 15; ic--;) + largeCov[ic] = 0.; + largeCov[kY2] = largeCov[kZ2] = kLargeErr2Coord; + largeCov[kSnp2] = largeCov[kTgl2] = kLargeErr2Dir; + largeCov[kPtI2] = kLargeErr2PtI * trPars[kPtI] * trPars[kPtI]; + + outputTrack.setCov(largeCov); + outputTrack.checkCovariance(); + + // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + // Inward pass to calculate covariances + for (int il = lastLayerReached; il >= firstLayerReached; il--) { + if (layers[il].type == 0) + continue; // inert layer, skip + + float targetX = 1e+3; + inputTrack.getXatLabR(layers[il].r, targetX, magneticField); + if (targetX > 999) + continue; // failed to find intercept + + if (!inputTrack.propagateTo(targetX, magneticField)) { + continue; // failed to propagate + } + if (std::abs(inputTrack.getZ()) > layers[il].z && applyZacceptance) { + continue; // out of acceptance bounds but continue inwards + } + + // get perfect data point position + std::array spacePoint; + inputTrack.getXYZGlo(spacePoint); + std::vector thisHit = {spacePoint[0], spacePoint[1], spacePoint[2]}; + + // towards adding cluster: move to track alpha + double alpha = outputTrack.getAlpha(); + double xyz1[3]{ + TMath::Cos(alpha) * spacePoint[0] + TMath::Sin(alpha) * spacePoint[1], + -TMath::Sin(alpha) * spacePoint[0] + TMath::Cos(alpha) * spacePoint[1], + spacePoint[2]}; + if (!(outputTrack.propagateTo(xyz1[0], magneticField))) + continue; + + const o2::track::TrackParametrization::dim2_t hitpoint = { + static_cast(xyz1[1]), + static_cast(xyz1[2])}; + const o2::track::TrackParametrization::dim3_t hitpointcov = {layers[il].resRPhi * layers[il].resRPhi, 0.f, layers[il].resZ * layers[il].resZ}; + outputTrack.update(hitpoint, hitpointcov); + outputTrack.checkCovariance(); + + if (layers[il].type == 1) + nSiliconPoints++; // count silicon hits + if (layers[il].type == 2) + nGasPoints++; // count TPC/gas hits + + hits.push_back(thisHit); + } + + // backpropagate to original radius + float finalX = 1e+3; + outputTrack.getXatLabR(initialRadius, finalX, magneticField); + if (finalX > 999) + return -3; // failed to find intercept + + if (!outputTrack.propagateTo(finalX, magneticField)) { + return -4; // failed to propagate + } + + // only attempt to continue if intercepts are at least four + if (nIntercepts < 4) + return nIntercepts; + + // Use covariance matrix based smearing + std::array covMat = {0.}; + for (int ii = 0; ii < 15; ii++) + covMat[ii] = outputTrack.getCov()[ii]; + TMatrixDSym m(5); + double fcovm[5][5]; + + for (int ii = 0, k = 0; ii < 5; ++ii) { + for (int j = 0; j < ii + 1; ++j, ++k) { + fcovm[ii][j] = covMat[k]; + fcovm[j][ii] = covMat[k]; + } + } + + // evaluate ruben's conditional, regularise + bool makePositiveDefinite = (covMatFactor > -1e-5); // apply fix + bool rubenConditional = false; + for (int ii = 0; ii < 5; ii++) { + for (int jj = 0; jj < 5; jj++) { + if (ii == jj) + continue; // don't evaluate diagonals + if (fcovm[ii][jj] * fcovm[ii][jj] > std::abs(fcovm[ii][ii] * fcovm[jj][jj])) { + rubenConditional = true; + if (makePositiveDefinite) { + fcovm[ii][jj] = TMath::Sign(1, fcovm[ii][jj]) * covMatFactor * sqrt(std::abs(fcovm[ii][ii] * fcovm[jj][jj])); + } + } + } + } + + // Should have a valid cov matrix now + m.SetMatrixArray(reinterpret_cast(fcovm)); + TMatrixDSymEigen eigen(m); + TMatrixD eigVec = eigen.GetEigenVectors(); + TVectorD eigVal = eigen.GetEigenValues(); + bool negEigVal = false; + for (int ii = 0; ii < 5; ii++) { + if (eigVal[ii] < 0.0f) + negEigVal = true; + } + + if (negEigVal && rubenConditional && makePositiveDefinite) { + if (verboseLevel > 0) { + LOG(info) << "WARNING: this diagonalization (at pt = " << inputTrack.getPt() << ") has negative eigenvalues despite Ruben's fix! Please be careful!"; + LOG(info) << "Printing info:"; + LOG(info) << "Kalman updates: " << nIntercepts; + LOG(info) << "Cov matrix: "; + m.Print(); + } + covMatNotOK++; + nIntercepts = -1; // mark as problematic so that it isn't used + return -1; + } + covMatOK++; + + // transform parameter vector and smear + double params_[5]; + for (int ii = 0; ii < 5; ++ii) { + double val = 0.; + for (int j = 0; j < 5; ++j) + val += eigVec[j][ii] * outputTrack.getParam(j); + // smear parameters according to eigenvalues + params_[ii] = gRandom->Gaus(val, sqrt(eigVal[ii])); + } + + // invert eigenvector matrix + eigVec.Invert(); + // transform back params vector + for (int ii = 0; ii < 5; ++ii) { + double val = 0.; + for (int j = 0; j < 5; ++j) + val += eigVec[j][ii] * params_[j]; + outputTrack.setParam(val, ii); + } + // should make a sanity check that par[2] sin(phi) is in [-1, 1] + if (fabs(outputTrack.getParam(2)) > 1.) { + LOG(info) << " --- smearTrack failed sin(phi) sanity check: " << outputTrack.getParam(2); + return -2; + } + + return nIntercepts; +} +// +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + +} /* namespace fastsim */ +} /* namespace o2 */ + +ClassImp(o2::fastsim::FastTracker); diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h new file mode 100644 index 00000000000..ecd7d19cb98 --- /dev/null +++ b/ALICE3/Core/FastTracker.h @@ -0,0 +1,72 @@ +// Copyright 2019-2020 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. + +#ifndef ALICE3_CORE_FASTTRACKER_H_ +#define ALICE3_CORE_FASTTRACKER_H_ + +#include // not a system header but megalinter thinks so +#include +#include "DetLayer.h" +#include "ReconstructionDataFormats/Track.h" + +namespace o2 +{ +namespace fastsim +{ + +// +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + +// this class implements a synthetic smearer that allows +// for on-demand smearing of TrackParCovs in a certain flexible t +// detector layout. +class FastTracker +{ + public: + // Constructor/destructor + FastTracker(); + virtual ~FastTracker() {} + + void AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi = 0.0f, float resZ = 0.0f, float eff = 0.0f, int type = 0); + + void AddSiliconALICE3v4(); + void AddSiliconALICE3v1(); + void AddTPC(float phiResMean, float zResMean); + + void Print(); + int FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack); + + // Definition of detector layers + std::vector layers; + std::vector> hits; // bookkeep last added hits + + // operational + float magneticField; // in kiloGauss (5 = 0.5T, etc) + bool applyZacceptance; // check z acceptance or not + float covMatFactor; // covmat off-diagonal factor to use for covmat fix (negative: no factor) + int verboseLevel; // 0: not verbose, >0 more verbose + + uint64_t covMatOK; // cov mat has negative eigenvals + uint64_t covMatNotOK; // cov mat has negative eigenvals + + // last track information + int nIntercepts; // found in first outward propagation + int nSiliconPoints; // silicon-based space points added to track + int nGasPoints; // tpc-based space points added to track + + ClassDef(FastTracker, 1); +}; + +// +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ + +} // namespace fastsim +} // namespace o2 + +#endif // ALICE3_CORE_FASTTRACKER_H_ diff --git a/ALICE3/Core/FastTrackerLinkDef.h b/ALICE3/Core/FastTrackerLinkDef.h new file mode 100644 index 00000000000..a69755b7e92 --- /dev/null +++ b/ALICE3/Core/FastTrackerLinkDef.h @@ -0,0 +1,21 @@ +// Copyright 2019-2020 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. + +#ifndef ALICE3_CORE_FASTTRACKERLINKDEF_H_ +#define ALICE3_CORE_FASTTRACKERLINKDEF_H_ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::fastsim::FastTracker + ; + +#endif // ALICE3_CORE_FASTTRACKERLINKDEF_H_ diff --git a/ALICE3/DataModel/A3DecayFinderTables.h b/ALICE3/DataModel/A3DecayFinderTables.h index cc7e8f3d3c7..05eb5ad9307 100644 --- a/ALICE3/DataModel/A3DecayFinderTables.h +++ b/ALICE3/DataModel/A3DecayFinderTables.h @@ -43,7 +43,10 @@ enum a3selectionBit : uint32_t { kDCAxy = 0, kTruePrPlusFromLc, kTruePiMinusFromLc, kTrueKaMinusFromLc, - kTruePrMinusFromLc }; + kTruePrMinusFromLc, + kTrueXiFromXiC, + kTruePiFromXiC, + kTruePiFromXiCC }; namespace o2::aod { @@ -51,7 +54,7 @@ namespace a3DecayMap { DECLARE_SOA_COLUMN(DecayMap, decayMap, uint32_t); //! simple map to process passing / not passing criteria } // namespace a3DecayMap -DECLARE_SOA_TABLE(Alice3DecayMaps, "AOD", "ALICE3DECAYMAP", +DECLARE_SOA_TABLE(Alice3DecayMaps, "AOD", "ALICE3DECAYMAPS", a3DecayMap::DecayMap); using Alice3DecayMap = Alice3DecayMaps::iterator; diff --git a/ALICE3/DataModel/OTFMcTrackExtra.h b/ALICE3/DataModel/OTFMcTrackExtra.h new file mode 100644 index 00000000000..bb75c86746c --- /dev/null +++ b/ALICE3/DataModel/OTFMcTrackExtra.h @@ -0,0 +1,42 @@ +// Copyright 2019-2020 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. + +/// +/// \file OTFMcTrackExtra.h +/// \author Jesper Karlsson Gumprecht +/// \since 05/08/2024 +/// \brief Table to to hold MC information specifically for xi daughters created in the otf-tracker +/// + +#ifndef ALICE3_DATAMODEL_OTFMCTRACKEXTRA_H_ +#define ALICE3_DATAMODEL_OTFMCTRACKEXTRA_H_ + +// O2 includes +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace otf_mctrack_extra +{ +DECLARE_SOA_COLUMN(NewPdgCode, newPdgCode, int); //! PDG code (duplicate column but needed for particles created in the otf-tracker) +DECLARE_SOA_COLUMN(IsFromXi, isFromXi, bool); //! From Xi decayed in otf-tracker +DECLARE_SOA_COLUMN(IsFromL0, isFromL0, bool); //! From L0 decayed in otf-tracker +} // namespace otf_mctrack_extra +DECLARE_SOA_TABLE(OTFMcExtra, "AOD", "OTFMcExtra", + otf_mctrack_extra::NewPdgCode, + otf_mctrack_extra::IsFromXi, + otf_mctrack_extra::IsFromL0); + +using OTFMcTrackExtra = OTFMcExtra::iterator; + +} // namespace o2::aod + +#endif // ALICE3_DATAMODEL_OTFMCTRACKEXTRA_H_ diff --git a/ALICE3/DataModel/OTFMulticharm.h b/ALICE3/DataModel/OTFMulticharm.h new file mode 100644 index 00000000000..7dbde7bdc9a --- /dev/null +++ b/ALICE3/DataModel/OTFMulticharm.h @@ -0,0 +1,116 @@ +// Copyright 2019-2020 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. + +/// +/// \file OTFStrangeness.h +/// \author David Dobrigkeit Chinellato +/// \since 05/08/2024 +/// \brief Set of tables for the ALICE3 strangeness information +/// + +#ifndef ALICE3_DATAMODEL_OTFMULTICHARM_H_ +#define ALICE3_DATAMODEL_OTFMULTICHARM_H_ + +// O2 includes +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace otfmulticharm +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Cascade, cascade, int, UpgradeCascades, "_Cascade"); +DECLARE_SOA_INDEX_COLUMN_FULL(XiCPion1, xiCPion1, int, Tracks, "_Pi1XiC"); +DECLARE_SOA_INDEX_COLUMN_FULL(XiCPion2, xiCPion2, int, Tracks, "_Pi2XiC"); +DECLARE_SOA_INDEX_COLUMN_FULL(XiCCPion, xiCCPion, int, Tracks, "_PiXiCC"); + +// topo vars +DECLARE_SOA_COLUMN(DCAXiCDaughters, dcaXiCDaughters, float); +DECLARE_SOA_COLUMN(DCAXiCCDaughters, dcaXiCCDaughters, float); + +DECLARE_SOA_COLUMN(MXiC, mXiC, float); +DECLARE_SOA_COLUMN(MXiCC, mXiCC, float); + +// kine vars +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); + +// tracking counters +DECLARE_SOA_COLUMN(NSiliconHitsXi, nSiliconHitsXi, int); +DECLARE_SOA_COLUMN(NSiliconHitsPiFromXi, nSiliconHitsPiFromXi, int); +DECLARE_SOA_COLUMN(NSiliconHitsPiFromLa, nSiliconHitsPiFromLa, int); +DECLARE_SOA_COLUMN(NSiliconHitsPrFromLa, nSiliconHitsPrFromLa, int); +DECLARE_SOA_COLUMN(NSiliconHitsPiC1, nSiliconHitsPiC1, int); +DECLARE_SOA_COLUMN(NSiliconHitsPiC2, nSiliconHitsPiC2, int); +DECLARE_SOA_COLUMN(NSiliconHitsPiCC, nSiliconHitsPiCC, int); + +DECLARE_SOA_COLUMN(NTPCHitsPiFromXi, nTPCHitsPiFromXi, int); +DECLARE_SOA_COLUMN(NTPCHitsPiFromLa, nTPCHitsPiFromLa, int); +DECLARE_SOA_COLUMN(NTPCHitsPrFromLa, nTPCHitsPrFromLa, int); +DECLARE_SOA_COLUMN(NTPCHitsPiC1, nTPCHitsPiC1, int); +DECLARE_SOA_COLUMN(NTPCHitsPiC2, nTPCHitsPiC2, int); +DECLARE_SOA_COLUMN(NTPCHitsPiCC, nTPCHitsPiCC, int); + +// DCA to PV variables +DECLARE_SOA_COLUMN(DCAToPVXi, dcaToPVXi, float); +DECLARE_SOA_COLUMN(DCAToPVXiC, dcaToPVXiC, float); +DECLARE_SOA_COLUMN(DCAToPVXiCC, dcaToPVXiCC, float); + +DECLARE_SOA_COLUMN(DCAToPVPiFromXi, dcaToPVPiFromXi, float); +DECLARE_SOA_COLUMN(DCAToPVPiFromLa, dcaToPVPiFromLa, float); +DECLARE_SOA_COLUMN(DCAToPVPrFromLa, dcaToPVPrFromLa, float); + +DECLARE_SOA_COLUMN(DCAToPVPiC1, dcaToPVPiC1, float); +DECLARE_SOA_COLUMN(DCAToPVPiC2, dcaToPVPiC2, float); +DECLARE_SOA_COLUMN(DCAToPVPiCC, dcaToPVPiCC, float); + +} // namespace otfmulticharm +DECLARE_SOA_TABLE(MCharmIndices, "AOD", "MCharmIndices", + o2::soa::Index<>, + otfmulticharm::CascadeId, + otfmulticharm::XiCPion1Id, + otfmulticharm::XiCPion2Id, + otfmulticharm::XiCCPionId); + +DECLARE_SOA_TABLE(MCharmCores, "AOD", "MCharmCores", + otfmulticharm::DCAXiCDaughters, + otfmulticharm::DCAXiCCDaughters, + otfmulticharm::MXiC, + otfmulticharm::MXiCC, + otfmulticharm::Pt, + otfmulticharm::Eta, + + otfmulticharm::NSiliconHitsXi, + otfmulticharm::NSiliconHitsPiFromXi, + otfmulticharm::NSiliconHitsPiFromLa, + otfmulticharm::NSiliconHitsPrFromLa, + otfmulticharm::NSiliconHitsPiC1, + otfmulticharm::NSiliconHitsPiC2, + otfmulticharm::NSiliconHitsPiCC, + otfmulticharm::NTPCHitsPiFromXi, + otfmulticharm::NTPCHitsPiFromLa, + otfmulticharm::NTPCHitsPrFromLa, + otfmulticharm::NTPCHitsPiC1, + otfmulticharm::NTPCHitsPiC2, + otfmulticharm::NTPCHitsPiCC, + + otfmulticharm::DCAToPVXi, + otfmulticharm::DCAToPVXiC, + otfmulticharm::DCAToPVXiCC, + otfmulticharm::DCAToPVPiFromXi, + otfmulticharm::DCAToPVPiFromLa, + otfmulticharm::DCAToPVPrFromLa, + otfmulticharm::DCAToPVPiC1, + otfmulticharm::DCAToPVPiC2, + otfmulticharm::DCAToPVPiCC); + +} // namespace o2::aod + +#endif // ALICE3_DATAMODEL_OTFMULTICHARM_H_ diff --git a/ALICE3/DataModel/OTFStrangeness.h b/ALICE3/DataModel/OTFStrangeness.h new file mode 100644 index 00000000000..861ec3a7af8 --- /dev/null +++ b/ALICE3/DataModel/OTFStrangeness.h @@ -0,0 +1,70 @@ +// Copyright 2019-2020 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. + +/// +/// \file OTFStrangeness.h +/// \author David Dobrigkeit Chinellato +/// \since 05/08/2024 +/// \brief Set of tables for the ALICE3 strangeness information +/// + +#ifndef ALICE3_DATAMODEL_OTFSTRANGENESS_H_ +#define ALICE3_DATAMODEL_OTFSTRANGENESS_H_ + +// O2 includes +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace otfcascade +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_INDEX_COLUMN_FULL(CascadeTrack, cascadeTrack, int, Tracks, "_Cascade"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, Tracks, "_Pos"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, Tracks, "_Neg"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(BachTrack, bachTrack, int, Tracks, "_Bach"); //! + +// topo vars +DECLARE_SOA_COLUMN(DCAV0Daughters, dcaV0Daughters, float); +DECLARE_SOA_COLUMN(DCACascadeDaughters, dcaCascadeDaughters, float); +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); +DECLARE_SOA_COLUMN(CascRadius, cascRadius, float); +DECLARE_SOA_COLUMN(CascRadiusMC, cascRadiusMC, float); +DECLARE_SOA_COLUMN(MLambda, mLambda, float); +DECLARE_SOA_COLUMN(MXi, mXi, float); + +// strangeness tracking +DECLARE_SOA_COLUMN(FindableClusters, findableClusters, int); +DECLARE_SOA_COLUMN(FoundClusters, foundClusters, int); + +} // namespace otfcascade +DECLARE_SOA_TABLE(UpgradeCascades, "AOD", "UPGRADECASCADES", + o2::soa::Index<>, + otfcascade::CollisionId, + otfcascade::CascadeTrackId, + otfcascade::PosTrackId, + otfcascade::NegTrackId, + otfcascade::BachTrackId, + otfcascade::DCAV0Daughters, + otfcascade::DCACascadeDaughters, + otfcascade::V0Radius, + otfcascade::CascRadius, + otfcascade::CascRadiusMC, + otfcascade::MLambda, + otfcascade::MXi, + otfcascade::FindableClusters, + otfcascade::FoundClusters); + +using UpgradeCascade = UpgradeCascades::iterator; + +} // namespace o2::aod + +#endif // ALICE3_DATAMODEL_OTFSTRANGENESS_H_ diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index c3a3e82a994..280c5ccb110 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -27,12 +27,18 @@ namespace o2::aod namespace track_alice3 { DECLARE_SOA_COLUMN(IsReconstructed, isReconstructed, bool); //! is reconstructed or not +DECLARE_SOA_COLUMN(NSiliconHits, nSiliconHits, int); //! number of silicon hits +DECLARE_SOA_COLUMN(NTPCHits, nTPCHits, int); //! number of tpc hits } // namespace track_alice3 DECLARE_SOA_TABLE(TracksAlice3, "AOD", "TRACKSALICE3", track_alice3::IsReconstructed); - using TrackAlice3 = TracksAlice3::iterator; +DECLARE_SOA_TABLE(TracksExtraA3, "AOD", "TracksExtraA3", + track_alice3::NSiliconHits, + track_alice3::NTPCHits); +using TrackExtraA3 = TracksExtraA3::iterator; + } // namespace o2::aod #endif // ALICE3_DATAMODEL_TRACKSALICE3_H_ diff --git a/ALICE3/TableProducer/CMakeLists.txt b/ALICE3/TableProducer/CMakeLists.txt index 52300bfc644..9c3d710d358 100644 --- a/ALICE3/TableProducer/CMakeLists.txt +++ b/ALICE3/TableProducer/CMakeLists.txt @@ -31,8 +31,17 @@ o2physics_add_dpl_workflow(alice3-centrality PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(alice3-decaypreselector + SOURCES alice3-decaypreselector.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(alice3-decayfinder SOURCES alice3-decayfinder.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(alice3-multicharm + SOURCES alice3-multicharm.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) diff --git a/ALICE3/TableProducer/OTF/CMakeLists.txt b/ALICE3/TableProducer/OTF/CMakeLists.txt index 305fcce4b66..d20b6c6ba5c 100644 --- a/ALICE3/TableProducer/OTF/CMakeLists.txt +++ b/ALICE3/TableProducer/OTF/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(onthefly-tracker SOURCES onTheFlyTracker.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing O2Physics::ALICE3Core + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing O2::DCAFitter O2Physics::ALICE3Core O2Physics::FastTracker COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(onthefly-tofpid diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 163fc73058e..9f0578cd97e 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -24,14 +24,20 @@ /// #include +#include #include +#include +#include +#include #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" #include +#include "DCAFitter/DCAFitterN.h" +#include "Common/Core/RecoDecay.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Common/DataModel/TrackSelectionTables.h" #include "ReconstructionDataFormats/DCA.h" @@ -42,12 +48,22 @@ #include "SimulationDataFormat/InteractionSampler.h" #include "Field/MagneticField.h" +#include "ITSMFTSimulation/Hit.h" +#include "ITStracking/Configuration.h" +#include "ITStracking/IOUtils.h" +#include "ITStracking/Tracker.h" +#include "ITStracking/Vertexer.h" +#include "ITStracking/VertexerTraits.h" + #include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/Core/FastTracker.h" #include "ALICE3/DataModel/collisionAlice3.h" #include "ALICE3/DataModel/tracksAlice3.h" +#include "ALICE3/DataModel/OTFStrangeness.h" using namespace o2; using namespace o2::framework; +using std::array; struct OnTheFlyTracker { Produces collisions; @@ -58,30 +74,42 @@ struct OnTheFlyTracker { Produces tracksParCovExtension; Produces tracksLabels; Produces tracksDCA; + Produces tracksDCACov; Produces collisionsAlice3; Produces TracksAlice3; + Produces TracksExtraA3; + Produces upgradeCascades; // optionally produced, empty (to be tuned later) Produces tracksExtra; // base table, extend later Produces trackSelection; Produces trackSelectionExtension; + Configurable seed{"seed", 0, "TGenPhaseSpace seed"}; Configurable magneticField{"magneticField", 20.0f, "magnetic field in kG"}; Configurable maxEta{"maxEta", 1.5, "maximum eta to consider viable"}; Configurable multEtaRange{"multEtaRange", 0.8, "eta range to compute the multiplicity"}; Configurable minPt{"minPt", 0.1, "minimum pt to consider viable"}; Configurable enableLUT{"enableLUT", false, "Enable track smearing"}; + Configurable enablePrimarySmearing{"enablePrimarySmearing", false, "Enable smearing of primary particles"}; + Configurable enableSecondarySmearing{"enableSecondarySmearing", false, "Enable smearing of weak decay daughters"}; Configurable enableNucleiSmearing{"enableNucleiSmearing", false, "Enable smearing of nuclei"}; Configurable enablePrimaryVertexing{"enablePrimaryVertexing", true, "Enable primary vertexing"}; Configurable interpolateLutEfficiencyVsNch{"interpolateLutEfficiencyVsNch", true, "interpolate LUT efficiency as f(Nch)"}; + Configurable treatXi{"treatXi", false, "Manually decay Xi and fill tables with daughters"}; + Configurable findXi{"findXi", false, "if treatXi on, find Xi and fill Tracks table also with Xi"}; + Configurable trackXi{"trackXi", false, "if findXi on, attempt to track Xi"}; + Configurable pixelResolution{"pixelResolution", 2.5e-4, "pixel resolution in centimeters (for OTF strangeness tracking)"}; Configurable populateTracksDCA{"populateTracksDCA", true, "populate TracksDCA table"}; + Configurable populateTracksDCACov{"populateTracksDCACov", false, "populate TracksDCACov table"}; Configurable populateTracksExtra{"populateTracksExtra", false, "populate TracksExtra table (legacy)"}; Configurable populateTrackSelection{"populateTrackSelection", false, "populate TrackSelection table (legacy)"}; Configurable processUnreconstructedTracks{"processUnreconstructedTracks", false, "process (smear) unreco-ed tracks"}; Configurable doExtraQA{"doExtraQA", false, "do extra 2D QA plots"}; Configurable extraQAwithoutDecayDaughters{"extraQAwithoutDecayDaughters", false, "remove decay daughters from qa plots (yes/no)"}; + Configurable doXiQA{"doXiQA", false, "QA plots for when treating Xi"}; Configurable lutEl{"lutEl", "lutCovm.el.dat", "LUT for electrons"}; Configurable lutMu{"lutMu", "lutCovm.mu.dat", "LUT for muons"}; @@ -92,15 +120,42 @@ struct OnTheFlyTracker { Configurable lutTr{"lutTr", "lutCovm.tr.dat", "LUT for tritons"}; Configurable lutHe3{"lutHe3", "lutCovm.he3.dat", "LUT for Helium-3"}; - ConfigurableAxis axisMomentum{"axisMomentum", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "#it{p} (GeV/#it{c})"}; - ConfigurableAxis axisNVertices{"axisNVertices", {20, -0.5, 19.5}, "N_{vertices}"}; - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {100, -0.5, 99.5}, "N_{contributors}"}; - ConfigurableAxis axisVertexZ{"axisVertexZ", {40, -20, 20}, "vertex Z (cm)"}; - ConfigurableAxis axisDCA{"axisDCA", {400, -200, 200}, "DCA (#mum)"}; - ConfigurableAxis axisX{"axisX", {250, -50, 200}, "track X (cm)"}; + struct : ConfigurableGroup { + ConfigurableAxis axisMomentum{"axisMomentum", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "#it{p} (GeV/#it{c})"}; + ConfigurableAxis axisNVertices{"axisNVertices", {20, -0.5, 19.5}, "N_{vertices}"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {100, -0.5, 99.5}, "N_{contributors}"}; + ConfigurableAxis axisVertexZ{"axisVertexZ", {40, -20, 20}, "vertex Z (cm)"}; + ConfigurableAxis axisDCA{"axisDCA", {400, -200, 200}, "DCA (#mum)"}; + ConfigurableAxis axisX{"axisX", {250, -50, 200}, "track X (cm)"}; + ConfigurableAxis axisDecayRadius{"axisDecayRadius", {55, 0.01, 100}, "decay radius"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {200, 1.101f, 1.131f}, ""}; + ConfigurableAxis axisXiMass{"axisXiMass", {200, 1.22f, 1.42f}, ""}; + + ConfigurableAxis axisDeltaPt{"axisDeltaPt", {200, -1.0f, +1.0f}, "#Delta p_{T}"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {200, -0.5f, +0.5f}, "#Delta #eta"}; + + ConfigurableAxis axisRadius{"axisRadius", {2500, 0.0f, +250.0f}, "R (cm)"}; + ConfigurableAxis axisZ{"axisZ", {100, -250.0f, +250.0f}, "Z (cm)"}; + } axes; + + // for topo var QA + struct : ConfigurableGroup { + std::string prefix = "fastTrackerSettings"; // JSON group name + Configurable minSiliconHits{"minSiliconHits", 4, "minimum number of silicon hits to accept track"}; + Configurable minSiliconHitsIfTPCUsed{"minSiliconHitsIfTPCUsed", 2, "minimum number of silicon hits to accept track in case TPC info is present"}; + Configurable minTPCClusters{"minTPCClusters", 70, "minimum number of TPC hits necessary to consider minSiliconHitsIfTPCUsed"}; + Configurable alice3detector{"alice3detector", 0, "0: ALICE 3 v1, 1: ALICE 3 v4"}; + Configurable applyZacceptance{"applyZacceptance", false, "apply z limits to detector layers or not"}; + } fastTrackerSettings; // allows for gap between peak and bg in case someone wants to using PVertex = o2::dataformats::PrimaryVertex; + // for secondary vertex finding + o2::vertexing::DCAFitterN<2> fitter; + + // FastTracker machinery + o2::fastsim::FastTracker fastTracker; + // Class to hold the track information for the O2 vertexing class TrackAlice3 : public o2::track::TrackParCov { @@ -110,12 +165,52 @@ struct OnTheFlyTracker { TrackAlice3() = default; ~TrackAlice3() = default; TrackAlice3(const TrackAlice3& src) = default; - TrackAlice3(const o2::track::TrackParCov& src, const int64_t label, const float t = 0, const float te = 1, bool decayDauInput = false) : o2::track::TrackParCov(src), mcLabel{label}, timeEst{t, te}, isDecayDau(decayDauInput) {} + TrackAlice3(const o2::track::TrackParCov& src, const int64_t label, + const float t = 0, + const float te = 1, + bool decayDauInput = false, + bool weakDecayDauInput = false, + int isUsedInCascadingInput = 0, + int nSiliconHitsInput = 0, + int nTPCHitsInput = 0) : o2::track::TrackParCov(src), + mcLabel{label}, + timeEst{t, te}, + isDecayDau(decayDauInput), + isWeakDecayDau(weakDecayDauInput), + isUsedInCascading(isUsedInCascadingInput), + nSiliconHits(nSiliconHitsInput), + nTPCHits(nTPCHitsInput) {} const TimeEst& getTimeMUS() const { return timeEst; } int64_t mcLabel; TimeEst timeEst; ///< time estimate in ns bool isDecayDau; + bool isWeakDecayDau; + int isUsedInCascading; // 0: not at all, 1: is a cascade, 2: is a bachelor, 3: is a pion, 4: is a proton + int nSiliconHits; + int nTPCHits; + }; + + // Helper struct to pass cascade information + struct cascadecandidate { + int cascadeTrackId; // track index in the Tracks table + int positiveId; // track index in the Tracks table + int negativeId; // track index in the Tracks table + int bachelorId; // track index in the Tracks table + + float dcaV0dau; + float dcacascdau; + float v0radius; + float cascradius; + float cascradiusMC; + + // for tracking + int findableClusters; + int foundClusters; + + float mLambda; + float mXi; }; + cascadecandidate thisCascade; // necessary for particle charges Service pdgDB; @@ -128,12 +223,24 @@ struct OnTheFlyTracker { // Track smearer o2::delphes::DelphesO2TrackSmearer mSmearer; + // Xi daughters uses different smearers + o2::delphes::DelphesO2TrackSmearer mSmearer0; + o2::delphes::DelphesO2TrackSmearer mSmearer1; + o2::delphes::DelphesO2TrackSmearer mSmearer2; + o2::delphes::DelphesO2TrackSmearer mSmearer3; + o2::delphes::DelphesO2TrackSmearer mSmearer4; + o2::delphes::DelphesO2TrackSmearer mSmearer5; + // For processing and vertexing std::vector tracksAlice3; std::vector ghostTracksAlice3; std::vector bcData; o2::steer::InteractionSampler irSampler; o2::vertexing::PVertexer vertexer; + std::vector cascadesAlice3; + + // For TGenPhaseSpace seed + TRandom3 rand; void init(o2::framework::InitContext&) { @@ -178,31 +285,76 @@ struct OnTheFlyTracker { } // Basic QA - histos.add("hPtGenerated", "hPtGenerated", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedEl", "hPtGeneratedEl", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedPi", "hPtGeneratedPi", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedKa", "hPtGeneratedKa", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedPr", "hPtGeneratedPr", kTH1F, {axisMomentum}); - histos.add("hPtReconstructed", "hPtReconstructed", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedEl", "hPtReconstructedEl", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedPi", "hPtReconstructedPi", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedKa", "hPtReconstructedKa", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedPr", "hPtReconstructedPr", kTH1F, {axisMomentum}); + auto hNaN = histos.add("hNaNBookkeeping", "hNaNBookkeeping", kTH2F, {{10, -0.5f, 9.5f}, {10, -0.5f, 9.5f}}); + + hNaN->GetXaxis()->SetBinLabel(1, "Primary"); + hNaN->GetXaxis()->SetBinLabel(2, "Bachelor"); + hNaN->GetXaxis()->SetBinLabel(3, "Pi from La"); + hNaN->GetXaxis()->SetBinLabel(4, "Pr from La"); + + hNaN->GetYaxis()->SetBinLabel(1, "Smear NaN"); + hNaN->GetYaxis()->SetBinLabel(2, "Smear OK"); + + auto hCovMatOK = histos.add("hCovMatOK", "hCovMatOK", kTH1D, {{2, -0.5f, 1.5f}}); + hCovMatOK->GetXaxis()->SetBinLabel(1, "Not OK"); + hCovMatOK->GetXaxis()->SetBinLabel(2, "OK"); + + histos.add("hPtGenerated", "hPtGenerated", kTH1F, {axes.axisMomentum}); + histos.add("hPtGeneratedEl", "hPtGeneratedEl", kTH1F, {axes.axisMomentum}); + histos.add("hPtGeneratedPi", "hPtGeneratedPi", kTH1F, {axes.axisMomentum}); + histos.add("hPtGeneratedKa", "hPtGeneratedKa", kTH1F, {axes.axisMomentum}); + histos.add("hPtGeneratedPr", "hPtGeneratedPr", kTH1F, {axes.axisMomentum}); + histos.add("hPtReconstructed", "hPtReconstructed", kTH1F, {axes.axisMomentum}); + histos.add("hPtReconstructedEl", "hPtReconstructedEl", kTH1F, {axes.axisMomentum}); + histos.add("hPtReconstructedPi", "hPtReconstructedPi", kTH1F, {axes.axisMomentum}); + histos.add("hPtReconstructedKa", "hPtReconstructedKa", kTH1F, {axes.axisMomentum}); + histos.add("hPtReconstructedPr", "hPtReconstructedPr", kTH1F, {axes.axisMomentum}); // Collision QA - histos.add("hPVz", "hPVz", kTH1F, {axisVertexZ}); - histos.add("hLUTMultiplicity", "hLUTMultiplicity", kTH1F, {axisMultiplicity}); - histos.add("hSimMultiplicity", "hSimMultiplicity", kTH1F, {axisMultiplicity}); - histos.add("hRecoMultiplicity", "hRecoMultiplicity", kTH1F, {axisMultiplicity}); + histos.add("hPVz", "hPVz", kTH1F, {axes.axisVertexZ}); + histos.add("hLUTMultiplicity", "hLUTMultiplicity", kTH1F, {axes.axisMultiplicity}); + histos.add("hSimMultiplicity", "hSimMultiplicity", kTH1F, {axes.axisMultiplicity}); + histos.add("hRecoMultiplicity", "hRecoMultiplicity", kTH1F, {axes.axisMultiplicity}); if (doExtraQA) { - histos.add("h2dVerticesVsContributors", "h2dVerticesVsContributors", kTH2F, {axisMultiplicity, axisNVertices}); - histos.add("hRecoVsSimMultiplicity", "hRecoVsSimMultiplicity", kTH2F, {axisMultiplicity, axisMultiplicity}); - histos.add("h2dDCAxy", "h2dDCAxy", kTH2F, {axisMomentum, axisDCA}); + histos.add("h2dVerticesVsContributors", "h2dVerticesVsContributors", kTH2F, {axes.axisMultiplicity, axes.axisNVertices}); + histos.add("hRecoVsSimMultiplicity", "hRecoVsSimMultiplicity", kTH2F, {axes.axisMultiplicity, axes.axisMultiplicity}); + histos.add("h2dDCAxy", "h2dDCAxy", kTH2F, {axes.axisMomentum, axes.axisDCA}); + + histos.add("hSimTrackX", "hSimTrackX", kTH1F, {axes.axisX}); + histos.add("hRecoTrackX", "hRecoTrackX", kTH1F, {axes.axisX}); + histos.add("hTrackXatDCA", "hTrackXatDCA", kTH1F, {axes.axisX}); + } + + if (doXiQA) { + histos.add("hXiBuilding", "hXiBuilding", kTH1F, {{10, -0.5f, 9.5f}}); - histos.add("hSimTrackX", "hSimTrackX", kTH1F, {axisX}); - histos.add("hRecoTrackX", "hRecoTrackX", kTH1F, {axisX}); - histos.add("hTrackXatDCA", "hTrackXatDCA", kTH1F, {axisX}); + histos.add("hGenXi", "hGenXi", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + histos.add("hRecoXi", "hRecoXi", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + + histos.add("hGenPiFromXi", "hGenPiFromXi", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + histos.add("hGenPiFromL0", "hGenPiFromL0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + histos.add("hGenPrFromL0", "hGenPrFromL0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + histos.add("hRecoPiFromXi", "hRecoPiFromXi", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + histos.add("hRecoPiFromL0", "hRecoPiFromL0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + histos.add("hRecoPrFromL0", "hRecoPrFromL0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); + + // basic mass histograms to see if we're in business + histos.add("hMassLambda", "hMassLambda", kTH1F, {axes.axisLambdaMass}); + histos.add("hMassXi", "hMassXi", kTH1F, {axes.axisXiMass}); + + // OTF strangeness tracking QA + histos.add("hFoundVsFindable", "hFoundVsFindable", kTH2F, {{10, -0.5f, 9.5f}, {10, -0.5f, 9.5f}}); + + histos.add("h2dDCAxyCascade", "h2dDCAxyCascade", kTH2F, {axes.axisMomentum, axes.axisDCA}); + histos.add("h2dDCAxyCascadeBachelor", "h2dDCAxyCascadeBachelor", kTH2F, {axes.axisMomentum, axes.axisDCA}); + histos.add("h2dDCAxyCascadeNegative", "h2dDCAxyCascadeNegative", kTH2F, {axes.axisMomentum, axes.axisDCA}); + histos.add("h2dDCAxyCascadePositive", "h2dDCAxyCascadePositive", kTH2F, {axes.axisMomentum, axes.axisDCA}); + + histos.add("h2dDeltaPtVsPt", "h2dDeltaPtVsPt", kTH2F, {axes.axisMomentum, axes.axisDeltaPt}); + histos.add("h2dDeltaEtaVsPt", "h2dDeltaEtaVsPt", kTH2F, {axes.axisMomentum, axes.axisDeltaEta}); + + histos.add("hFastTrackerHits", "hFastTrackerHits", kTH2F, {axes.axisZ, axes.axisRadius}); } LOGF(info, "Initializing magnetic field to value: %.3f kG", static_cast(magneticField)); @@ -235,6 +387,110 @@ struct OnTheFlyTracker { vertexer.setValidateWithIR(kFALSE); vertexer.setBunchFilling(irSampler.getBunchFilling()); vertexer.init(); + + // initialize O2 2-prong fitter + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxDXYIni(4); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + fitter.setWeightedFinalPCA(false); + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); // such a light detector here + + // Set seed for TGenPhaseSpace + rand.SetSeed(seed); + + // configure FastTracker + fastTracker.magneticField = magneticField; + fastTracker.applyZacceptance = fastTrackerSettings.applyZacceptance; + + if (fastTrackerSettings.alice3detector == 0) { + fastTracker.AddSiliconALICE3v1(); + } + if (fastTrackerSettings.alice3detector == 1) { + fastTracker.AddSiliconALICE3v4(); + fastTracker.AddTPC(0.1, 0.1); + } + + // print fastTracker settings + fastTracker.Print(); + } + + /// Function to decay the xi + /// \param particle the particle to decay + /// \param track track of particle to decay + /// \param decayDaughters the address of resulting daughters + /// \param xiDecayVertex the address of the xi decay vertex + /// \param l0DecayVertex the address of the l0 decay vertex + template + void decayParticle(McParticleType particle, o2::track::TrackParCov track, std::vector& decayDaughters, std::vector& xiDecayVertex, std::vector& l0DecayVertex) + { + double u = rand.Uniform(0, 1); + double xi_ctau = 4.91; // xi + double xi_rxyz = (-xi_ctau * log(1 - u)); + float sna, csa; + o2::math_utils::CircleXYf_t xi_circle; + track.getCircleParams(magneticField, xi_circle, sna, csa); + double xi_rxy = xi_rxyz / sqrt(1. + track.getTgl() * track.getTgl()); + double theta = xi_rxy / xi_circle.rC; + double newX = ((particle.vx() - xi_circle.xC) * std::cos(theta) - (particle.vy() - xi_circle.yC) * std::sin(theta)) + xi_circle.xC; + double newY = ((particle.vy() - xi_circle.yC) * std::cos(theta) + (particle.vx() - xi_circle.xC) * std::sin(theta)) + xi_circle.yC; + double newPx = particle.px() * std::cos(theta) - particle.py() * std::sin(theta); + double newPy = particle.py() * std::cos(theta) + particle.px() * std::sin(theta); + xiDecayVertex.push_back(newX); + xiDecayVertex.push_back(newY); + xiDecayVertex.push_back(particle.vz() + xi_rxyz * (particle.pz() / particle.p())); + + std::vector xiDaughters = {1.115, 0.139570}; + TLorentzVector xi(newPx, newPy, particle.pz(), particle.e()); + TGenPhaseSpace xiDecay; + xiDecay.SetDecay(xi, 2, xiDaughters.data()); + xiDecay.Generate(); + decayDaughters.push_back(*xiDecay.GetDecay(1)); + + double l0_ctau = 7.89; // lambda + std::vector l0Daughters = {0.139570, 0.938272}; + double l0_rxyz = (-l0_ctau * log(1 - u)); + l0DecayVertex.push_back(xiDecayVertex[0] + l0_rxyz * (xiDecay.GetDecay(0)->Px() / xiDecay.GetDecay(0)->P())); + l0DecayVertex.push_back(xiDecayVertex[1] + l0_rxyz * (xiDecay.GetDecay(0)->Py() / xiDecay.GetDecay(0)->P())); + l0DecayVertex.push_back(xiDecayVertex[2] + l0_rxyz * (xiDecay.GetDecay(0)->Pz() / xiDecay.GetDecay(0)->P())); + + TLorentzVector l0 = *xiDecay.GetDecay(0); + TGenPhaseSpace l0Decay; + l0Decay.SetDecay(l0, 2, l0Daughters.data()); + l0Decay.Generate(); + decayDaughters.push_back(*l0Decay.GetDecay(0)); + decayDaughters.push_back(*l0Decay.GetDecay(1)); + } + + /// Function to convert a TLorentzVector into a perfect Track + /// \param pdgCode particle pdg + /// \param particle the particle to convert (TLorentzVector) + /// \param productionVertex where the particle was produced + /// \param o2track the address of the resulting TrackParCov + void convertTLorentzVectorToO2Track(int pdgCode, TLorentzVector particle, std::vector productionVertex, o2::track::TrackParCov& o2track) + { + auto pdgInfo = pdgDB->GetParticle(pdgCode); + int charge = 0; + if (pdgInfo != nullptr) { + charge = pdgInfo->Charge() / 3; + } + std::array params; + std::array covm = {0.}; + float s, c, x; + o2::math_utils::sincos(static_cast(particle.Phi()), s, c); + o2::math_utils::rotateZInv(static_cast(productionVertex[0]), static_cast(productionVertex[1]), x, params[0], s, c); + params[1] = static_cast(productionVertex[2]); + params[2] = 0; + auto theta = 2. * std::atan(std::exp(-particle.PseudoRapidity())); + params[3] = 1. / std::tan(theta); + params[4] = charge / particle.Pt(); + + // Initialize TrackParCov in-place + new (&o2track)(o2::track::TrackParCov)(x, particle.Phi(), params, covm); } /// Function to convert a McParticle into a perfect Track @@ -266,9 +522,12 @@ struct OnTheFlyTracker { float dNdEta = 0.f; // Charged particle multiplicity to use in the efficiency evaluation void process(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) { + int lastTrackIndex = tracksParCov.lastIndex() + 1; // bookkeep the last added track + tracksAlice3.clear(); ghostTracksAlice3.clear(); bcData.clear(); + cascadesAlice3.clear(); o2::dataformats::DCA dcaInfo; o2::dataformats::VertexBase vtx; @@ -287,7 +546,11 @@ struct OnTheFlyTracker { } const auto pdg = std::abs(mcParticle.pdgCode()); if (pdg != kElectron && pdg != kMuonMinus && pdg != kPiPlus && pdg != kKPlus && pdg != kProton) { - continue; + if (!treatXi) { + continue; + } else if (pdg != 3312) { + continue; + } } const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); if (!pdgInfo) { @@ -303,14 +566,38 @@ struct OnTheFlyTracker { dNdEta /= (multEtaRange * 2.0f); uint32_t multiplicityCounter = 0; histos.fill(HIST("hLUTMultiplicity"), dNdEta); + gRandom->SetSeed(seed); for (const auto& mcParticle : mcParticles) { - if (!mcParticle.isPhysicalPrimary()) { - continue; + double xiDecayRadius2D = 0; + double l0DecayRadius2D = 0; + std::vector decayProducts; + std::vector xiDecayVertex, l0DecayVertex; + std::vector layers = {0.50, 1.20, 2.50, 3.75, 7.00, 12.0, 20.0}; + if (treatXi) { + if (mcParticle.pdgCode() == 3312) { + o2::track::TrackParCov xiTrackParCov; + convertMCParticleToO2Track(mcParticle, xiTrackParCov); + decayParticle(mcParticle, xiTrackParCov, decayProducts, xiDecayVertex, l0DecayVertex); + xiDecayRadius2D = sqrt(xiDecayVertex[0] * xiDecayVertex[0] + xiDecayVertex[1] * xiDecayVertex[1]); + l0DecayRadius2D = sqrt(l0DecayVertex[0] * l0DecayVertex[0] + l0DecayVertex[1] * l0DecayVertex[1]); + } } + const auto pdg = std::abs(mcParticle.pdgCode()); + if (!mcParticle.isPhysicalPrimary()) { + if (!treatXi) { + continue; + } else if (pdg != 3312) { + continue; + } + } if (pdg != kElectron && pdg != kMuonMinus && pdg != kPiPlus && pdg != kKPlus && pdg != kProton) { - continue; + if (!treatXi) { + continue; + } else if (pdg != 3312) { + continue; + } } if (std::fabs(mcParticle.eta()) > maxEta) { continue; @@ -326,29 +613,291 @@ struct OnTheFlyTracker { if (TMath::Abs(mcParticle.pdgCode()) == 2212) histos.fill(HIST("hPtGeneratedPr"), mcParticle.pt()); + if (doXiQA && mcParticle.pdgCode() == 3312) { + histos.fill(HIST("hGenXi"), xiDecayRadius2D, mcParticle.pt()); + histos.fill(HIST("hGenPiFromXi"), xiDecayRadius2D, decayProducts[0].Pt()); + histos.fill(HIST("hGenPiFromL0"), l0DecayRadius2D, decayProducts[1].Pt()); + histos.fill(HIST("hGenPrFromL0"), l0DecayRadius2D, decayProducts[2].Pt()); + } + if (mcParticle.pt() < minPt) { continue; } + o2::track::TrackParCov trackParCov; + convertMCParticleToO2Track(mcParticle, trackParCov); + bool isDecayDaughter = false; if (mcParticle.getProcess() == 4) isDecayDaughter = true; multiplicityCounter++; - o2::track::TrackParCov trackParCov; - convertMCParticleToO2Track(mcParticle, trackParCov); + const float t = (ir.timeInBCNS + gRandom->Gaus(0., 100.)) * 1e-3; + std::vector xiDaughterTrackParCovsPerfect(3); + std::vector xiDaughterTrackParCovsTracked(3); + std::vector isReco(3); + std::vector nHits(3); // total + std::vector nSiliconHits(3); // silicon type + std::vector nTPCHits(3); // TPC type + std::vector smearer = {mSmearer0, mSmearer1, mSmearer2, mSmearer3, mSmearer4, mSmearer5}; + if (treatXi && mcParticle.pdgCode() == 3312) { + histos.fill(HIST("hXiBuilding"), 0.0f); + if (xiDecayRadius2D > 20) { + continue; + } + + convertTLorentzVectorToO2Track(-211, decayProducts[0], xiDecayVertex, xiDaughterTrackParCovsPerfect[0]); + convertTLorentzVectorToO2Track(-211, decayProducts[1], l0DecayVertex, xiDaughterTrackParCovsPerfect[1]); + convertTLorentzVectorToO2Track(2212, decayProducts[2], l0DecayVertex, xiDaughterTrackParCovsPerfect[2]); + + for (int i = 0; i < 3; i++) { + isReco[i] = false; + nHits[i] = 0; + nSiliconHits[i] = 0; + nTPCHits[i] = 0; + if (enableSecondarySmearing) { + + nHits[i] = fastTracker.FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i]); + nSiliconHits[i] = fastTracker.nSiliconPoints; + nTPCHits[i] = fastTracker.nGasPoints; + + if (nSiliconHits[i] >= fastTrackerSettings.minSiliconHits || (nSiliconHits[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nTPCHits[i] >= fastTrackerSettings.minTPCClusters)) { + isReco[i] = true; + } else { + continue; // extra sure + } + for (uint32_t ih = 0; ih < fastTracker.hits.size(); ih++) { + histos.fill(HIST("hFastTrackerHits"), fastTracker.hits[ih][2], std::hypot(fastTracker.hits[ih][0], fastTracker.hits[ih][1])); + } + } else { + isReco[i] = true; + xiDaughterTrackParCovsTracked[i] = xiDaughterTrackParCovsPerfect[i]; + } + + if (TMath::IsNaN(xiDaughterTrackParCovsTracked[i].getZ())) { + continue; + } else { + histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); + } + if (isReco[i]) { + tracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), t, 100.f * 1e-3, true, true, i + 2, nSiliconHits[i], nTPCHits[i]}); + } else { + ghostTracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), t, 100.f * 1e-3, true, true, i + 2}); + } + } + + if (doXiQA && mcParticle.pdgCode() == 3312) { + if (isReco[0] && isReco[1] && isReco[2]) { + histos.fill(HIST("hXiBuilding"), 2.0f); + histos.fill(HIST("hRecoXi"), xiDecayRadius2D, mcParticle.pt()); + } + if (isReco[0]) + histos.fill(HIST("hRecoPiFromXi"), xiDecayRadius2D, decayProducts[0].Pt()); + if (isReco[1]) + histos.fill(HIST("hRecoPiFromL0"), l0DecayRadius2D, decayProducts[1].Pt()); + if (isReco[2]) + histos.fill(HIST("hRecoPrFromL0"), l0DecayRadius2D, decayProducts[2].Pt()); + } + + // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ + // combine particles into actual Xi candidate + // cascade building starts here + if (findXi && mcParticle.pdgCode() == 3312 && isReco[0] && isReco[1] && isReco[2]) { + histos.fill(HIST("hXiBuilding"), 3.0f); + // assign indices of the particles we've used + // they should be the last ones to be filled, in order: + // n-1: proton from lambda + // n-2: pion from lambda + // n-3: pion from xi + thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1; + thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 2; + thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - 3; + + // use DCA fitters + int nCand = 0; + bool dcaFitterOK_V0 = true; + try { + nCand = fitter.process(xiDaughterTrackParCovsTracked[1], xiDaughterTrackParCovsTracked[2]); + } catch (...) { + // LOG(error) << "Exception caught in DCA fitter process call!"; + dcaFitterOK_V0 = false; + } + if (nCand == 0) { + dcaFitterOK_V0 = false; + } + // V0 found successfully + if (dcaFitterOK_V0) { + histos.fill(HIST("hXiBuilding"), 4.0f); + std::array pos; + std::array posCascade; + std::array posP; + std::array negP; + std::array bachP; + + o2::track::TrackParCov pTrackAtPCA = fitter.getTrack(1); // proton (positive) + o2::track::TrackParCov nTrackAtPCA = fitter.getTrack(0); // pion (negative) + pTrackAtPCA.getPxPyPzGlo(posP); + nTrackAtPCA.getPxPyPzGlo(negP); + + // get decay vertex coordinates + const auto& vtx = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + pos[i] = vtx[i]; + } + + // calculate basic V0 properties here + // DCA to PV taken care of in daughter tracks already, not necessary + thisCascade.dcaV0dau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.v0radius = std::hypot(pos[0], pos[1]); + thisCascade.mLambda = RecoDecay::m(array{array{posP[0], posP[1], posP[2]}, array{negP[0], negP[1], negP[2]}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + + // go for cascade: create V0 (pseudo)track from reconstructed V0 + std::array covV = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV[MomInd[i]] = 1e-6; + covV[i] = 1e-6; + } + o2::track::TrackParCov v0Track = o2::track::TrackParCov( + {pos[0], pos[1], pos[2]}, + {posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}, + covV, 0, true); + v0Track.setAbsCharge(0); + v0Track.setPID(o2::track::PID::Lambda); + + // dca fitter step + nCand = 0; + bool dcaFitterOK_Cascade = true; + try { + nCand = fitter.process(v0Track, xiDaughterTrackParCovsTracked[0]); + } catch (...) { + // LOG(error) << "Exception caught in DCA fitter process call!"; + dcaFitterOK_Cascade = false; + } + if (nCand == 0) { + dcaFitterOK_Cascade = false; + } + + // Cascade found successfully + if (dcaFitterOK_Cascade) { + histos.fill(HIST("hXiBuilding"), 5.0f); + o2::track::TrackParCov bachelorTrackAtPCA = fitter.getTrack(1); + + const auto& vtxCascade = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + posCascade[i] = vtxCascade[i]; + } + + // basic properties of the cascade + thisCascade.dcacascdau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.cascradius = std::hypot(posCascade[0], posCascade[1]); + bachelorTrackAtPCA.getPxPyPzGlo(bachP); + + thisCascade.mXi = RecoDecay::m(array{array{bachP[0], bachP[1], bachP[2]}, array{posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); + + // initialize cascade track + o2::track::TrackParCov cascadeTrack = fitter.createParentTrackParCov(); + cascadeTrack.setAbsCharge(-1); // may require more adjustments + cascadeTrack.setPID(o2::track::PID::XiMinus); // FIXME: not OK for omegas + + thisCascade.cascradiusMC = xiDecayRadius2D; + thisCascade.findableClusters = 0; + thisCascade.foundClusters = 0; + + if (trackXi) { + // optionally, add the points in the layers before the decay of the Xi + // will back-track the perfect MC cascade to relevant layers, find hit, smear and add to smeared cascade + for (int i = layers.size() - 1; i >= 0; i--) { + if (thisCascade.cascradiusMC > layers[i]) { + // will add this layer, since cascade decayed after the corresponding radius + thisCascade.findableClusters++; // add to findable + + // find perfect intercept XYZ + float targetX = 1e+3; + trackParCov.getXatLabR(layers[i], targetX, magneticField); + if (targetX > 999) + continue; // failed to find intercept + + if (!trackParCov.propagateTo(targetX, magneticField)) { + continue; // failed to propagate + } + + // get potential cluster position + std::array posClusterCandidate; + trackParCov.getXYZGlo(posClusterCandidate); + float r{std::hypot(posClusterCandidate[0], posClusterCandidate[1])}; + float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::its::constants::math::Pi}; + + if (pixelResolution > 1e-8) { // catch zero (though should not really happen...) + phi = gRandom->Gaus(phi, std::asin(pixelResolution / r)); + posClusterCandidate[0] = r * std::cos(phi); + posClusterCandidate[1] = r * std::sin(phi); + posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], pixelResolution); + } + + // towards adding cluster: move to track alpha + double alpha = cascadeTrack.getAlpha(); + double xyz1[3]{ + TMath::Cos(alpha) * posClusterCandidate[0] + TMath::Sin(alpha) * posClusterCandidate[1], + -TMath::Sin(alpha) * posClusterCandidate[0] + TMath::Cos(alpha) * posClusterCandidate[1], + posClusterCandidate[2]}; + + if (!(cascadeTrack.propagateTo(xyz1[0], magneticField))) + continue; + const o2::track::TrackParametrization::dim2_t hitpoint = { + static_cast(xyz1[1]), + static_cast(xyz1[2])}; + const o2::track::TrackParametrization::dim3_t hitpointcov = {pixelResolution * pixelResolution, 0.f, pixelResolution * pixelResolution}; + cascadeTrack.update(hitpoint, hitpointcov); + thisCascade.foundClusters++; // add to findable + } + } + } + + // add cascade track + + histos.fill(HIST("hXiBuilding"), 6.0f); + thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this is the next index to be filled -> should be it + + tracksAlice3.push_back(TrackAlice3{cascadeTrack, mcParticle.globalIndex(), t, 100.f * 1e-3, false, false, 1, thisCascade.foundClusters}); + + if (doXiQA) { + histos.fill(HIST("h2dDeltaPtVsPt"), trackParCov.getPt(), cascadeTrack.getPt() - trackParCov.getPt()); + histos.fill(HIST("h2dDeltaEtaVsPt"), trackParCov.getPt(), cascadeTrack.getEta() - trackParCov.getEta()); + + histos.fill(HIST("hMassLambda"), thisCascade.mLambda); + histos.fill(HIST("hMassXi"), thisCascade.mXi); + histos.fill(HIST("hFoundVsFindable"), thisCascade.findableClusters, thisCascade.foundClusters); + } + + // add this cascade to vector (will fill cursor later with collision ID) + cascadesAlice3.push_back(thisCascade); + } + } + } // end cascade building + // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ + + continue; // Not filling the tables with the xi itself + } if (doExtraQA) { histos.fill(HIST("hSimTrackX"), trackParCov.getX()); } - bool reconstructed = mSmearer.smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + bool reconstructed = true; + if (enablePrimarySmearing) { + reconstructed = mSmearer.smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + } + if (!reconstructed && !processUnreconstructedTracks) { continue; } if (TMath::IsNaN(trackParCov.getZ())) { // capture rare smearing mistakes / corrupted tracks + histos.fill(HIST("hNaNBookkeeping"), 0.0f, 0.0f); continue; + } else { + histos.fill(HIST("hNaNBookkeeping"), 0.0f, 1.0f); // ok! } // Base QA (note: reco pT here) @@ -367,7 +916,6 @@ struct OnTheFlyTracker { } // populate vector with track if we reco-ed it - const float t = (ir.timeInBCNS + gRandom->Gaus(0., 100.)) * 1e-3; if (reconstructed) { tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), t, 100.f * 1e-3, isDecayDaughter}); } else { @@ -463,9 +1011,21 @@ struct OnTheFlyTracker { histos.fill(HIST("h2dDCAxy"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please histos.fill(HIST("hTrackXatDCA"), trackParametrization.getX()); } + if (doXiQA) { + if (trackParCov.isUsedInCascading == 1) + histos.fill(HIST("h2dDCAxyCascade"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + if (trackParCov.isUsedInCascading == 2) + histos.fill(HIST("h2dDCAxyCascadeBachelor"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + if (trackParCov.isUsedInCascading == 3) + histos.fill(HIST("h2dDCAxyCascadeNegative"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + if (trackParCov.isUsedInCascading == 4) + histos.fill(HIST("h2dDCAxyCascadePositive"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + } tracksDCA(dcaXY, dcaZ); + if (populateTracksDCACov) { + tracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); + } } - tracksPar(collisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); tracksParExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); @@ -477,6 +1037,7 @@ struct OnTheFlyTracker { trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), trackParCov.getSigma1Pt2()); tracksLabels(trackParCov.mcLabel, 0); + TracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); // populate extra tables if required to do so if (populateTracksExtra) { @@ -508,6 +1069,9 @@ struct OnTheFlyTracker { histos.fill(HIST("hTrackXatDCA"), trackParametrization.getX()); } tracksDCA(dcaXY, dcaZ); + if (populateTracksDCACov) { + tracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); + } } tracksPar(collisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); @@ -521,6 +1085,7 @@ struct OnTheFlyTracker { trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), trackParCov.getSigma1Pt2()); tracksLabels(trackParCov.mcLabel, 0); + TracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); // populate extra tables if required to do so if (populateTracksExtra) { @@ -535,7 +1100,30 @@ struct OnTheFlyTracker { } TracksAlice3(false); } - } + + for (const auto& cascade : cascadesAlice3) { + upgradeCascades( + collisions.lastIndex(), // now we know the collision index -> populate table + cascade.cascadeTrackId, + cascade.positiveId, + cascade.negativeId, + cascade.bachelorId, + cascade.dcaV0dau, + cascade.dcacascdau, + cascade.v0radius, + cascade.cascradius, + cascade.cascradiusMC, + cascade.mLambda, + cascade.mXi, + cascade.findableClusters, + cascade.foundClusters); + } + + // do bookkeeping of fastTracker tracking + histos.fill(HIST("hCovMatOK"), 0.0f, fastTracker.covMatNotOK); + histos.fill(HIST("hCovMatOK"), 1.0f, fastTracker.covMatOK); + + } // end process }; /// Extends TracksExtra if necessary diff --git a/ALICE3/TableProducer/alice3-decayfinder.cxx b/ALICE3/TableProducer/alice3-decayfinder.cxx index 80b9de80238..4b88305fb60 100644 --- a/ALICE3/TableProducer/alice3-decayfinder.cxx +++ b/ALICE3/TableProducer/alice3-decayfinder.cxx @@ -65,149 +65,6 @@ using tofTracks = soa::Join; using richTracks = soa::Join; using alice3tracks = soa::Join; -struct alice3decayPreselector { - Produces a3decayMaps; - - // Operation and minimisation criteria - Configurable nSigmaTOF{"nSigmaTOF", 4.0f, "Nsigma for TOF PID (if enabled)"}; - Configurable nSigmaRICH{"nSigmaRICH", 4.0f, "Nsigma for RICH PID (if enabled)"}; - - // Define o2 fitter, 2-prong, active memory (no need to redefine per event) - o2::vertexing::DCAFitterN<2> fitter; - - // for bit-packed maps - std::vector selectionMap; - - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - /// function to check PDG + PDG mother - template - bool checkPDG(TTrack const& track, int pdgMother, int pdg) - { - bool returnValue = false; - // Association check - if (track.has_mcParticle()) { - auto mcParticle = track.template mcParticle_as(); - if (mcParticle.has_mothers()) { - for (auto& mcParticleMother : mcParticle.template mothers_as()) { - if (mcParticle.pdgCode() == pdg && mcParticleMother.pdgCode() == pdgMother) - returnValue = true; - } - } - } // end association check - return returnValue; - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - - void init(InitContext&) - { - // future dev if needed - } - - // go declarative: use partitions instead of "if", then just toggle bits to allow for mask selection later - Partition pInnerTOFPi = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) > nSigmaTOF; - Partition pInnerTOFKa = nabs(aod::upgrade_tof::nSigmaKaonInnerTOF) > nSigmaTOF; - Partition pInnerTOFPr = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) > nSigmaTOF; - Partition pOuterTOFPi = nabs(aod::upgrade_tof::nSigmaPionOuterTOF) > nSigmaTOF; - Partition pOuterTOFKa = nabs(aod::upgrade_tof::nSigmaKaonOuterTOF) > nSigmaTOF; - Partition pOuterTOFPr = nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) > nSigmaTOF; - Partition pRICHPi = nabs(aod::alice3rich::richNsigmaPi) > nSigmaRICH; - Partition pRICHKa = nabs(aod::alice3rich::richNsigmaKa) > nSigmaRICH; - Partition pRICHPr = nabs(aod::alice3rich::richNsigmaPr) > nSigmaRICH; - - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - /// Initialization of mask vectors if uninitialized - void initializeMasks(int size) - { - selectionMap.clear(); - selectionMap.resize(size, 0xFFFFFFFF); // all bits 1, please - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - /// This process function ensures that all V0s are built. It will simply tag everything as true. - void processInitialize(aod::Tracks const& tracks) - { - initializeMasks(tracks.size()); - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processFilterInnerTOF(tofTracks const&) - { - for (auto const& track : pInnerTOFPi) - bitoff(selectionMap[track.globalIndex()], kInnerTOFPion); - for (auto const& track : pInnerTOFKa) - bitoff(selectionMap[track.globalIndex()], kInnerTOFKaon); - for (auto const& track : pInnerTOFPr) - bitoff(selectionMap[track.globalIndex()], kInnerTOFProton); - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processFilterOuterTOF(tofTracks const&) - { - for (auto const& track : pOuterTOFPi) - bitoff(selectionMap[track.globalIndex()], kOuterTOFPion); - for (auto const& track : pOuterTOFKa) - bitoff(selectionMap[track.globalIndex()], kOuterTOFKaon); - for (auto const& track : pOuterTOFPr) - bitoff(selectionMap[track.globalIndex()], kOuterTOFProton); - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processFilterRICH(richTracks const&) - { - for (auto const& track : pRICHPi) - bitoff(selectionMap[track.globalIndex()], kRICHPion); - for (auto const& track : pRICHKa) - bitoff(selectionMap[track.globalIndex()], kRICHKaon); - for (auto const& track : pRICHPr) - bitoff(selectionMap[track.globalIndex()], kRICHProton); - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processFilterOnMonteCarloTruth(labeledTracks const& tracks, aod::McParticles const&) - { - for (auto const& track : tracks) { - // D mesons - if (!checkPDG(track, 421, -321)) //+421 -> -321 +211 - bitoff(selectionMap[track.globalIndex()], kTrueKaMinusFromD); - if (!checkPDG(track, -421, +321)) //-421 -> +321 -211 - bitoff(selectionMap[track.globalIndex()], kTrueKaPlusFromD); - if (!checkPDG(track, 421, +211)) //+421 -> -321 +211 - bitoff(selectionMap[track.globalIndex()], kTruePiPlusFromD); - if (!checkPDG(track, -421, -211)) //-421 -> +321 -211 - bitoff(selectionMap[track.globalIndex()], kTruePiMinusFromD); - - // Lambdac baryons - if (!checkPDG(track, +4122, +2212)) //+4122 -> +2212 -321 +211 - bitoff(selectionMap[track.globalIndex()], kTruePrPlusFromLc); - if (!checkPDG(track, +4122, -321)) //+4122 -> +2212 -321 +211 - bitoff(selectionMap[track.globalIndex()], kTrueKaMinusFromLc); - if (!checkPDG(track, +4122, +211)) //+4122 -> +2212 -321 +211 - bitoff(selectionMap[track.globalIndex()], kTruePiPlusFromLc); - if (!checkPDG(track, -4122, -2212)) //-4122 -> -2212 +321 -211 - bitoff(selectionMap[track.globalIndex()], kTruePrMinusFromLc); - if (!checkPDG(track, -4122, +321)) //-4122 -> -2212 +321 -211 - bitoff(selectionMap[track.globalIndex()], kTrueKaPlusFromLc); - if (!checkPDG(track, -4122, -211)) //-4122 -> -2212 +321 -211 - bitoff(selectionMap[track.globalIndex()], kTruePiMinusFromLc); - } - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processPublishDecision(aod::Tracks const& tracks) - { - for (uint32_t i = 0; i < tracks.size(); i++) { - a3decayMaps(selectionMap[i]); - } - selectionMap.clear(); - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - - //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* - PROCESS_SWITCH(alice3decayPreselector, processInitialize, "Initialize (MUST be on)", true); - PROCESS_SWITCH(alice3decayPreselector, processFilterInnerTOF, "Switch to use inner TOF PID", false); - PROCESS_SWITCH(alice3decayPreselector, processFilterOuterTOF, "Switch to use outer TOF PID", false); - PROCESS_SWITCH(alice3decayPreselector, processFilterRICH, "Switch to use RICH", false); - PROCESS_SWITCH(alice3decayPreselector, processFilterOnMonteCarloTruth, "Switch to use MC truth", false); - PROCESS_SWITCH(alice3decayPreselector, processPublishDecision, "Fill decision mask table (MUST be on)", true); - //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* -}; - struct alice3decayFinder { SliceCache cache; @@ -355,9 +212,9 @@ struct alice3decayFinder { } //}-{}-{}-{}-{}-{}-{}-{}-{}-{} - t0 = fitter.getTrack(0); - t1 = fitter.getTrack(1); - t2 = fitter.getTrack(2); + t0 = fitter3.getTrack(0); + t1 = fitter3.getTrack(1); + t2 = fitter3.getTrack(2); std::array P0; std::array P1; std::array P2; @@ -593,6 +450,5 @@ struct alice3decayFinder { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/TableProducer/alice3-decaypreselector.cxx b/ALICE3/TableProducer/alice3-decaypreselector.cxx new file mode 100644 index 00000000000..66569360db9 --- /dev/null +++ b/ALICE3/TableProducer/alice3-decaypreselector.cxx @@ -0,0 +1,222 @@ +// Copyright 2019-2020 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. +// +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// Decay finder task for ALICE 3 +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// +// Uses specific ALICE 3 PID and performance for studying +// HF decays. Work in progress: use at your own risk! +// + +#include +#include +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "DCAFitter/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "ALICE3/DataModel/RICH.h" +#include "ALICE3/DataModel/A3DecayFinderTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +// simple checkers +// #define biton(var, nbit) ((var) |= (static_cast(1) << (nbit))) +#define bitoff(var, nbit) ((var) &= ~(static_cast(1) << (nbit))) //((a) &= ~(1ULL<<(b))) +// #define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) + +using FullTracksExt = soa::Join; + +// For MC association in pre-selection +using labeledTracks = soa::Join; +using tofTracks = soa::Join; +using richTracks = soa::Join; + +struct alice3decaypreselector { + Produces a3decayMaps; + + // Operation and minimisation criteria + Configurable nSigmaTOF{"nSigmaTOF", 4.0f, "Nsigma for TOF PID (if enabled)"}; + Configurable nSigmaRICH{"nSigmaRICH", 4.0f, "Nsigma for RICH PID (if enabled)"}; + + // Define o2 fitter, 2-prong, active memory (no need to redefine per event) + o2::vertexing::DCAFitterN<2> fitter; + + // for bit-packed maps + std::vector selectionMap; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + /// function to check PDG + PDG mother + template + bool checkPDG(TTrack const& track, int pdgMother, int pdg) + { + bool returnValue = false; + // Association check + if (track.has_mcParticle()) { + auto mcParticle = track.template mcParticle_as(); + if (mcParticle.has_mothers()) { + for (auto& mcParticleMother : mcParticle.template mothers_as()) { + if (mcParticle.pdgCode() == pdg && mcParticleMother.pdgCode() == pdgMother) + returnValue = true; + } + } + } // end association check + return returnValue; + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + void init(InitContext&) + { + // future dev if needed + } + + // go declarative: use partitions instead of "if", then just toggle bits to allow for mask selection later + Partition pInnerTOFPi = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) > nSigmaTOF; + Partition pInnerTOFKa = nabs(aod::upgrade_tof::nSigmaKaonInnerTOF) > nSigmaTOF; + Partition pInnerTOFPr = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) > nSigmaTOF; + Partition pOuterTOFPi = nabs(aod::upgrade_tof::nSigmaPionOuterTOF) > nSigmaTOF; + Partition pOuterTOFKa = nabs(aod::upgrade_tof::nSigmaKaonOuterTOF) > nSigmaTOF; + Partition pOuterTOFPr = nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) > nSigmaTOF; + Partition pRICHPi = nabs(aod::alice3rich::richNsigmaPi) > nSigmaRICH; + Partition pRICHKa = nabs(aod::alice3rich::richNsigmaKa) > nSigmaRICH; + Partition pRICHPr = nabs(aod::alice3rich::richNsigmaPr) > nSigmaRICH; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + /// Initialization of mask vectors if uninitialized + void initializeMasks(int size) + { + selectionMap.clear(); + selectionMap.resize(size, 0xFFFFFFFF); // all bits 1, please + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + /// This process function ensures that all V0s are built. It will simply tag everything as true. + void processInitialize(aod::Tracks const& tracks) + { + initializeMasks(tracks.size()); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterInnerTOF(tofTracks const&) + { + for (auto const& track : pInnerTOFPi) + bitoff(selectionMap[track.globalIndex()], kInnerTOFPion); + for (auto const& track : pInnerTOFKa) + bitoff(selectionMap[track.globalIndex()], kInnerTOFKaon); + for (auto const& track : pInnerTOFPr) + bitoff(selectionMap[track.globalIndex()], kInnerTOFProton); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterOuterTOF(tofTracks const&) + { + for (auto const& track : pOuterTOFPi) + bitoff(selectionMap[track.globalIndex()], kOuterTOFPion); + for (auto const& track : pOuterTOFKa) + bitoff(selectionMap[track.globalIndex()], kOuterTOFKaon); + for (auto const& track : pOuterTOFPr) + bitoff(selectionMap[track.globalIndex()], kOuterTOFProton); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterRICH(richTracks const&) + { + for (auto const& track : pRICHPi) + bitoff(selectionMap[track.globalIndex()], kRICHPion); + for (auto const& track : pRICHKa) + bitoff(selectionMap[track.globalIndex()], kRICHKaon); + for (auto const& track : pRICHPr) + bitoff(selectionMap[track.globalIndex()], kRICHProton); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterOnMonteCarloTruth(labeledTracks const& tracks, aod::McParticles const&) + { + for (auto const& track : tracks) { + // D mesons + if (!checkPDG(track, 421, -321)) //+421 -> -321 +211 + bitoff(selectionMap[track.globalIndex()], kTrueKaMinusFromD); + if (!checkPDG(track, -421, +321)) //-421 -> +321 -211 + bitoff(selectionMap[track.globalIndex()], kTrueKaPlusFromD); + if (!checkPDG(track, 421, +211)) //+421 -> -321 +211 + bitoff(selectionMap[track.globalIndex()], kTruePiPlusFromD); + if (!checkPDG(track, -421, -211)) //-421 -> +321 -211 + bitoff(selectionMap[track.globalIndex()], kTruePiMinusFromD); + + // Lambdac baryons + if (!checkPDG(track, +4122, +2212)) //+4122 -> +2212 -321 +211 + bitoff(selectionMap[track.globalIndex()], kTruePrPlusFromLc); + if (!checkPDG(track, +4122, -321)) //+4122 -> +2212 -321 +211 + bitoff(selectionMap[track.globalIndex()], kTrueKaMinusFromLc); + if (!checkPDG(track, +4122, +211)) //+4122 -> +2212 -321 +211 + bitoff(selectionMap[track.globalIndex()], kTruePiPlusFromLc); + if (!checkPDG(track, -4122, -2212)) //-4122 -> -2212 +321 -211 + bitoff(selectionMap[track.globalIndex()], kTruePrMinusFromLc); + if (!checkPDG(track, -4122, +321)) //-4122 -> -2212 +321 -211 + bitoff(selectionMap[track.globalIndex()], kTrueKaPlusFromLc); + if (!checkPDG(track, -4122, -211)) //-4122 -> -2212 +321 -211 + bitoff(selectionMap[track.globalIndex()], kTruePiMinusFromLc); + + // XiCC daughters + if (!checkPDG(track, 4422, 211)) // 4422 -> 4232 211, pi from xicc + bitoff(selectionMap[track.globalIndex()], kTruePiFromXiCC); + if (!checkPDG(track, 4232, 3312)) // 4232 -> 3312 211 211, xi from xic + bitoff(selectionMap[track.globalIndex()], kTrueXiFromXiC); + if (!checkPDG(track, 4232, 211)) // 4232 -> 3312 211 211, pi from xic + bitoff(selectionMap[track.globalIndex()], kTruePiFromXiC); + } + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processPublishDecision(aod::Tracks const& tracks) + { + for (uint32_t i = 0; i < tracks.size(); i++) { + a3decayMaps(selectionMap[i]); + } + selectionMap.clear(); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* + PROCESS_SWITCH(alice3decaypreselector, processInitialize, "Initialize (MUST be on)", true); + PROCESS_SWITCH(alice3decaypreselector, processFilterInnerTOF, "Switch to use inner TOF PID", false); + PROCESS_SWITCH(alice3decaypreselector, processFilterOuterTOF, "Switch to use outer TOF PID", false); + PROCESS_SWITCH(alice3decaypreselector, processFilterRICH, "Switch to use RICH", false); + PROCESS_SWITCH(alice3decaypreselector, processFilterOnMonteCarloTruth, "Switch to use MC truth", false); + PROCESS_SWITCH(alice3decaypreselector, processPublishDecision, "Fill decision mask table (MUST be on)", true); + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/alice3-multicharm.cxx b/ALICE3/TableProducer/alice3-multicharm.cxx new file mode 100644 index 00000000000..f695224b7c5 --- /dev/null +++ b/ALICE3/TableProducer/alice3-multicharm.cxx @@ -0,0 +1,586 @@ +// Copyright 2019-2020 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. +// +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// Decay finder task for ALICE 3 +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// +// Uses specific ALICE 3 PID and performance for studying +// HF decays. Work in progress: use at your own risk! +// + +#include +#include +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "DCAFitter/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "ALICE3/DataModel/RICH.h" +#include "ALICE3/DataModel/A3DecayFinderTables.h" +#include "ALICE3/DataModel/OTFStrangeness.h" +#include "ALICE3/DataModel/OTFMulticharm.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "DetectorsVertexing/PVertexer.h" +#include "DetectorsVertexing/PVertexerHelpers.h" +#include "CommonConstants/PhysicsConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +// simple checkers +// #define biton(var, nbit) ((var) |= (static_cast(1) << (nbit))) +#define bitoff(var, nbit) ((var) &= ~(static_cast(1) << (nbit))) //((a) &= ~(1ULL<<(b))) +#define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) + +using FullTracksExt = soa::Join; + +// For MC association in pre-selection +using labeledTracks = soa::Join; +using tofTracks = soa::Join; +using richTracks = soa::Join; +using alice3tracks = soa::Join; + +struct alice3multicharm { + SliceCache cache; + + Produces multiCharmIdx; + Produces multiCharmCore; + + // Operation and minimisation criteria + Configurable fillDerivedTable{"fillDerivedTable", false, "fill MCharm[] tables (careful: memory)"}; + Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; + Configurable doDCAplots{"doDCAplots", true, "do daughter prong DCA plots for D mesons"}; + Configurable mcSameMotherCheck{"mcSameMotherCheck", true, "check if tracks come from the same MC mother"}; + Configurable dcaXiCDaughtersSelection{"dcaXiCDaughtersSelection", 200.0f, "DCA between XiC daughters (cm)"}; + Configurable dcaXiCCDaughtersSelection{"dcaXiCCDaughtersSelection", 200.0f, "DCA between XiCC daughters (cm)"}; + + Configurable piFromXiC_dcaXYconstant{"piFromXiC_dcaXYconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable piFromXiC_dcaXYpTdep{"piFromXiC_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable piFromXiCC_dcaXYconstant{"piFromXiCC_dcaXYconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable piFromXiCC_dcaXYpTdep{"piFromXiCC_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable xiFromXiC_dcaXYconstant{"xiFromXiC_dcaXYconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable xiFromXiC_dcaXYpTdep{"xiFromXiC_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + + Configurable minPiCPt{"minPiCPt", 0.15, "Minimum pT for XiC pions"}; + Configurable minPiCCPt{"minPiCCPt", 0.3, "Minimum pT for XiCC pions"}; + + Configurable minXiCRadius{"minXiCRadius", 0.001, "Minimum R2D for XiC decay (cm)"}; + Configurable massWindowXi{"massWindowXi", 0.015, "Mass window around Xi peak"}; + Configurable massWindowXiC{"massWindowXiC", 0.015, "Mass window around XiC peak"}; + + ConfigurableAxis axisEta{"axisEta", {80, -4.0f, +4.0f}, "#eta"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + ConfigurableAxis axisDCA{"axisDCA", {200, -100, 100}, "DCA (#mum)"}; + + ConfigurableAxis axisXiMass{"axisXiMass", {200, 1.221f, 1.421f}, "Xi Inv Mass (GeV/c^{2})"}; + ConfigurableAxis axisXiCMass{"axisXiCMass", {200, 2.368f, 2.568f}, "XiC Inv Mass (GeV/c^{2})"}; + ConfigurableAxis axisXiCCMass{"axisXiCCMass", {200, 3.521f, 3.721f}, "XiCC Inv Mass (GeV/c^{2})"}; + + ConfigurableAxis axisDCAXiCDaughters{"axisDCAXiCDaughters", {200, 0, 100}, "DCA (cm)"}; + ConfigurableAxis axisDCAXiCCDaughters{"axisDCAXiCCDaughters", {200, 0, 100}, "DCA (cm)"}; + + ConfigurableAxis axisNConsidered{"axisNConsidered", {200, -0.5f, 199.5f}, "Number of considered track combinations"}; + + o2::vertexing::DCAFitterN<2> fitter; + o2::vertexing::DCAFitterN<3> fitter3; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Partition trueXi = aod::mcparticle::pdgCode == 3312; + Partition trueXiC = aod::mcparticle::pdgCode == 4232; + Partition trueXiCC = aod::mcparticle::pdgCode == 4422; + + // filter expressions for D mesons + static constexpr uint32_t trackSelectionPiFromXiC = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiC; + static constexpr uint32_t trackSelectionPiFromXiCC = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiCC; + + // partitions for Xi daughters + Partition tracksPiFromXiC = + ((aod::a3DecayMap::decayMap & trackSelectionPiFromXiC) == trackSelectionPiFromXiC) && aod::track::signed1Pt > 0.0f && 1.0f / nabs(aod::track::signed1Pt) > minPiCPt&& nabs(aod::track::dcaXY) > piFromXiC_dcaXYconstant + piFromXiC_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksPiFromXiCC = + ((aod::a3DecayMap::decayMap & trackSelectionPiFromXiCC) == trackSelectionPiFromXiCC) && aod::track::signed1Pt > 0.0f && 1.0f / nabs(aod::track::signed1Pt) > minPiCCPt&& nabs(aod::track::dcaXY) > piFromXiCC_dcaXYconstant + piFromXiCC_dcaXYpTdep* nabs(aod::track::signed1Pt); + + // Helper struct to pass candidate information + struct { + // decay properties + float dca; + float mass; + float pt; + float eta; + std::array xyz; + std::array prong0mom; + std::array prong1mom; + std::array prong2mom; + std::array parentTrackCovMatrix; + } thisXiCcandidate; + + struct { + float dca; + float mass; + float pt; + float eta; + std::array xyz; + std::array prong0mom; + std::array prong1mom; + std::array parentTrackCovMatrix; + + float etaPiCC; + + // charm daughters + int nSiliconHitsPiCC; + int nTPCHitsPiCC; + } thisXiCCcandidate; + + template + bool buildDecayCandidateTwoBody(TTrackType const& t0, TTrackType const& t1, float mass0, float mass1) + { + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima + int nCand = 0; + try { + nCand = fitter.process(t0, t1); + } catch (...) { + return false; + } + if (nCand == 0) { + return false; + } + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + + o2::track::TrackParCov t0new = fitter.getTrack(0); + o2::track::TrackParCov t1new = fitter.getTrack(1); + t0new.getPxPyPzGlo(thisXiCCcandidate.prong0mom); + t1new.getPxPyPzGlo(thisXiCCcandidate.prong1mom); + + // get decay vertex coordinates + const auto& vtx = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + thisXiCCcandidate.xyz[i] = vtx[i]; + } + + // compute cov mat + for (int ii = 0; ii < 21; ii++) + thisXiCCcandidate.parentTrackCovMatrix[ii] = 0.0f; + + std::array covA = {0}; + std::array covB = {0}; + fitter.getTrack(0).getCovXYZPxPyPzGlo(covA); + fitter.getTrack(1).getCovXYZPxPyPzGlo(covB); + + const int momInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + int j = momInd[i]; + thisXiCCcandidate.parentTrackCovMatrix[j] = covA[j] + covB[j]; + } + + auto covVtx = fitter.calcPCACovMatrix(); + thisXiCCcandidate.parentTrackCovMatrix[0] = covVtx(0, 0); + thisXiCCcandidate.parentTrackCovMatrix[1] = covVtx(1, 0); + thisXiCCcandidate.parentTrackCovMatrix[2] = covVtx(1, 1); + thisXiCCcandidate.parentTrackCovMatrix[3] = covVtx(2, 0); + thisXiCCcandidate.parentTrackCovMatrix[4] = covVtx(2, 1); + thisXiCCcandidate.parentTrackCovMatrix[5] = covVtx(2, 2); + + // set relevant values + thisXiCCcandidate.dca = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + if (thisXiCCcandidate.dca > dcaXiCCDaughtersSelection) { + return false; + } + + thisXiCCcandidate.mass = RecoDecay::m(array{array{thisXiCCcandidate.prong0mom[0], thisXiCCcandidate.prong0mom[1], thisXiCCcandidate.prong0mom[2]}, array{thisXiCCcandidate.prong1mom[0], thisXiCCcandidate.prong1mom[1], thisXiCCcandidate.prong1mom[2]}}, array{mass0, mass1}); + thisXiCCcandidate.pt = std::hypot(thisXiCCcandidate.prong0mom[0] + thisXiCCcandidate.prong1mom[0], thisXiCCcandidate.prong0mom[1] + thisXiCCcandidate.prong1mom[1]); + thisXiCCcandidate.eta = RecoDecay::eta(array{thisXiCCcandidate.prong0mom[0] + thisXiCCcandidate.prong1mom[0], thisXiCCcandidate.prong0mom[1] + thisXiCCcandidate.prong1mom[1], thisXiCCcandidate.prong0mom[2] + thisXiCCcandidate.prong1mom[2]}); + return true; + } + + template + bool buildDecayCandidateThreeBody(TTrackType1 const& prong0, TTrackType2 const& prong1, TTrackType3 const& prong2, float p0mass, float p1mass, float p2mass) + { + o2::track::TrackParCov t0 = getTrackParCov(prong0); + o2::track::TrackParCov t1 = getTrackParCov(prong1); + o2::track::TrackParCov t2 = getTrackParCov(prong2); + + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima + int nCand = 0; + try { + nCand = fitter3.process(t0, t1, t2); + } catch (...) { + return false; + } + if (nCand == 0) { + return false; + } + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + + t0 = fitter3.getTrack(0); + t1 = fitter3.getTrack(1); + t2 = fitter3.getTrack(2); + t0.getPxPyPzGlo(thisXiCcandidate.prong0mom); + t1.getPxPyPzGlo(thisXiCcandidate.prong1mom); + t2.getPxPyPzGlo(thisXiCcandidate.prong2mom); + + // get decay vertex coordinates + const auto& vtx = fitter3.getPCACandidate(); + for (int i = 0; i < 3; i++) { + thisXiCcandidate.xyz[i] = vtx[i]; + } + + // compute cov mat + for (int ii = 0; ii < 21; ii++) + thisXiCcandidate.parentTrackCovMatrix[ii] = 0.0f; + + std::array covA = {0}; + std::array covB = {0}; + std::array covC = {0}; + fitter3.getTrack(0).getCovXYZPxPyPzGlo(covA); + fitter3.getTrack(1).getCovXYZPxPyPzGlo(covB); + fitter3.getTrack(2).getCovXYZPxPyPzGlo(covC); + + const int momInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + int j = momInd[i]; + thisXiCcandidate.parentTrackCovMatrix[j] = covA[j] + covB[j] + covC[j]; + } + + auto covVtx = fitter3.calcPCACovMatrix(); + thisXiCcandidate.parentTrackCovMatrix[0] = covVtx(0, 0); + thisXiCcandidate.parentTrackCovMatrix[1] = covVtx(1, 0); + thisXiCcandidate.parentTrackCovMatrix[2] = covVtx(1, 1); + thisXiCcandidate.parentTrackCovMatrix[3] = covVtx(2, 0); + thisXiCcandidate.parentTrackCovMatrix[4] = covVtx(2, 1); + thisXiCcandidate.parentTrackCovMatrix[5] = covVtx(2, 2); + + // set relevant values + thisXiCcandidate.dca = TMath::Sqrt(fitter3.getChi2AtPCACandidate()); + if (thisXiCcandidate.dca > dcaXiCDaughtersSelection) { + return false; + } + thisXiCcandidate.mass = RecoDecay::m(array{array{thisXiCcandidate.prong0mom[0], thisXiCcandidate.prong0mom[1], thisXiCcandidate.prong0mom[2]}, array{thisXiCcandidate.prong1mom[0], thisXiCcandidate.prong1mom[1], thisXiCcandidate.prong1mom[2]}, array{thisXiCcandidate.prong2mom[0], thisXiCcandidate.prong2mom[1], thisXiCcandidate.prong2mom[2]}}, array{p0mass, p1mass, p2mass}); + thisXiCcandidate.pt = std::hypot(thisXiCcandidate.prong0mom[0] + thisXiCcandidate.prong1mom[0] + thisXiCcandidate.prong2mom[0], thisXiCcandidate.prong0mom[1] + thisXiCcandidate.prong1mom[1] + thisXiCcandidate.prong2mom[1]); + thisXiCcandidate.eta = RecoDecay::eta(array{thisXiCcandidate.prong0mom[0] + thisXiCcandidate.prong1mom[0] + thisXiCcandidate.prong2mom[0], thisXiCcandidate.prong0mom[1] + thisXiCcandidate.prong1mom[1] + thisXiCcandidate.prong2mom[1], thisXiCcandidate.prong0mom[2] + thisXiCcandidate.prong1mom[2] + thisXiCcandidate.prong2mom[2]}); + return true; + } + + /// function to check if tracks have the same mother in MC + template + bool checkSameMother(TTrackType1 const& track1, TTrackType2 const& track2) + { + bool returnValue = false; + // Association check + // There might be smarter ways of doing this in the future + if (track1.has_mcParticle() && track2.has_mcParticle()) { + auto mcParticle1 = track1.template mcParticle_as(); + auto mcParticle2 = track2.template mcParticle_as(); + if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { + for (auto& mcParticleMother1 : mcParticle1.template mothers_as()) { + for (auto& mcParticleMother2 : mcParticle2.template mothers_as()) { + if (mcParticleMother1.globalIndex() == mcParticleMother2.globalIndex()) { + returnValue = true; + } + } + } + } + } // end association check + return returnValue; + } + + // Association check for the XiCC pion + template + bool checkSameMotherExtra(TTrackType1 const& track1, TTrackType2 const& track2) + { + bool returnValue = false; + // This might perhaps be a bit excessive + // Could be joined with `checkSameMother` but leaving as is for now + if (track1.has_mcParticle() && track2.has_mcParticle()) { + auto mcParticle1 = track1.template mcParticle_as(); + auto mcParticle2 = track2.template mcParticle_as(); + if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { + for (auto& mcParticleMother1 : mcParticle1.template mothers_as()) { + if (mcParticleMother1.has_mothers()) { + for (auto& mcParticleGrandMother1 : mcParticleMother1.template mothers_as()) { + for (auto& mcParticleMother2 : mcParticle2.template mothers_as()) { + if (mcParticleGrandMother1.globalIndex() == mcParticleMother2.globalIndex()) { + returnValue = true; + } + } + } + } + } + } + } // end association check + return returnValue; + } + + void init(InitContext&) + { + // initialize O2 2-prong fitter (only once) + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + fitter.setWeightedFinalPCA(false); + fitter.setBz(magneticField); + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + fitter3.setPropagateToPCA(true); + fitter3.setMaxR(200.); + fitter3.setMinParamChange(1e-3); + fitter3.setMinRelChi2Change(0.9); + fitter3.setMaxDZIni(1e9); + fitter3.setMaxChi2(1e9); + fitter3.setUseAbsDCA(true); + fitter3.setWeightedFinalPCA(false); + fitter3.setBz(magneticField); + fitter3.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + // This histogram bookkeeps the attempts at DCA minimization and their eventual + // failure rates. + // --- 0: attempt XiC, 1: success XiC + // --- 2: attempt XiCC, 3: success XiCC + histos.add("hCharmBuilding", "hCharmBuilding", kTH1D, {{10, -0.5, 9.5f}}); + + histos.add("h2dGenXi", "h2dGenXi", kTH2D, {axisPt, axisEta}); + histos.add("h2dGenXiC", "h2dGenXiC", kTH2D, {axisPt, axisEta}); + histos.add("h2dGenXiCC", "h2dGenXiCC", kTH2D, {axisPt, axisEta}); + + histos.add("hMassXi", "hMassXi", kTH1D, {axisXiMass}); + histos.add("hMassXiC", "hMassXiC", kTH1D, {axisXiCMass}); + histos.add("hMassXiCC", "hMassXiCC", kTH1D, {axisXiCCMass}); + + histos.add("hEtaXiCC", "hEtaXiCC", kTH1D, {axisEta}); + histos.add("hPtXiCC", "hPtXiCC", kTH1D, {axisPt}); + histos.add("hMcPtXiCC", "hMcPtXiCC", kTH1D, {axisPt}); + histos.add("h3dMassXiCC", "h3dMassXiCC", kTH3D, {axisPt, axisEta, axisXiCCMass}); + + histos.add("hDCAXiCDaughters", "hDCAXiCDaughters", kTH1D, {axisDCAXiCDaughters}); + histos.add("hDCAXiCCDaughters", "hDCAXiCCDaughters", kTH1D, {axisDCAXiCCDaughters}); + + // These histograms bookkeep the exact number of combinations attempted + // CombinationsXiC: triplets Xi-pi-pi considered per Xi + // CombinationsXiCC: doublets XiC-pi considered per XiC + histos.add("hCombinationsXiC", "hCombinationsXiC", kTH1D, {axisNConsidered}); + histos.add("hCombinationsXiCC", "hCombinationsXiCC", kTH1D, {axisNConsidered}); + + if (doDCAplots) { + histos.add("h2dDCAxyVsPtXiFromXiC", "h2dDCAxyVsPtXiFromXiC", kTH2D, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtPiFromXiC", "h2dDCAxyVsPtPiFromXiC", kTH2D, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtPiFromXiCC", "h2dDCAxyVsPtPiFromXiCC", kTH2D, {axisPt, axisDCA}); + } + } + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processGenerated(aod::McParticles const&) + { + for (auto const& mcParticle : trueXi) + histos.fill(HIST("h2dGenXi"), mcParticle.pt(), mcParticle.eta()); + for (auto const& mcParticle : trueXiC) + histos.fill(HIST("h2dGenXiC"), mcParticle.pt(), mcParticle.eta()); + for (auto const& mcParticle : trueXiCC) { + histos.fill(HIST("h2dGenXiCC"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("hMcPtXiCC"), mcParticle.pt()); + } + } + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFindXiCC(aod::Collision const& collision, alice3tracks const& tracks, aod::McParticles const&, aod::UpgradeCascades const& cascades) + { + // group with this collision + // n.b. cascades do not need to be grouped, being used directly in iterator-grouping + auto tracksPiFromXiCgrouped = tracksPiFromXiC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksPiFromXiCCgrouped = tracksPiFromXiCC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + if (doDCAplots) { + for (auto const& cascade : cascades) { + if (cascade.has_cascadeTrack()) { + auto track = cascade.cascadeTrack_as(); // de-reference cascade track + histos.fill(HIST("h2dDCAxyVsPtXiFromXiC"), track.pt(), track.dcaXY() * 1e+4); + } else { + LOGF(info, "Damn, something is wrong"); + } + } + for (auto const& track : tracks) { + if (bitcheck(track.decayMap(), kTruePiFromXiC)) + histos.fill(HIST("h2dDCAxyVsPtPiFromXiC"), track.pt(), track.dcaXY() * 1e+4); + if (bitcheck(track.decayMap(), kTruePiFromXiCC)) + histos.fill(HIST("h2dDCAxyVsPtPiFromXiCC"), track.pt(), track.dcaXY() * 1e+4); + } + } + + for (auto const& xiCand : cascades) { + histos.fill(HIST("hMassXi"), xiCand.mXi()); + + if (std::abs(xiCand.mXi() - o2::constants::physics::MassXiMinus) > massWindowXi) + continue; // out of mass region + + uint32_t nCombinationsC = 0; + auto xi = xiCand.cascadeTrack_as(); // de-reference cascade track + auto piFromXi = xiCand.bachTrack_as(); // de-reference bach track + auto piFromLa = xiCand.negTrack_as(); // de-reference neg track + auto prFromLa = xiCand.posTrack_as(); // de-reference pos track + + if (!bitcheck(xi.decayMap(), kTrueXiFromXiC)) + continue; + + for (auto const& pi1c : tracksPiFromXiCgrouped) { + if (mcSameMotherCheck && !checkSameMother(xi, pi1c)) + continue; + if (xiCand.posTrackId() == pi1c.globalIndex() || xiCand.negTrackId() == pi1c.globalIndex() || xiCand.bachTrackId() == pi1c.globalIndex()) + continue; // avoid using any track that was already used + if (pi1c.pt() < minPiCPt) + continue; + + // second pion from XiC decay for starts here + for (auto const& pi2c : tracksPiFromXiCgrouped) { + + if (mcSameMotherCheck && !checkSameMother(xi, pi2c)) + continue; // keep only if same mother + if (pi1c.globalIndex() >= pi2c.globalIndex()) + continue; // avoid same-mother, avoid double-counting + if (xiCand.posTrackId() == pi2c.globalIndex() || xiCand.negTrackId() == pi2c.globalIndex() || xiCand.bachTrackId() == pi2c.globalIndex()) + continue; // avoid using any track that was already used + if (pi2c.pt() < minPiCPt) + continue; + + // if I am here, it means this is a triplet to be considered for XiC vertexing. + // will now attempt to build a three-body decay candidate with these three track rows. + + nCombinationsC++; + histos.fill(HIST("hCharmBuilding"), 0.0f); + if (!buildDecayCandidateThreeBody(xi, pi1c, pi2c, 1.32171, 0.139570, 0.139570)) + continue; // failed at building candidate + + if (std::abs(thisXiCcandidate.mass - o2::constants::physics::MassXiCPlus) > massWindowXiC) + continue; // out of mass region + histos.fill(HIST("hCharmBuilding"), 1.0f); + + const std::array momentumC = { + thisXiCcandidate.prong0mom[0] + thisXiCcandidate.prong1mom[0] + thisXiCcandidate.prong2mom[0], + thisXiCcandidate.prong0mom[1] + thisXiCcandidate.prong1mom[1] + thisXiCcandidate.prong2mom[1], + thisXiCcandidate.prong0mom[2] + thisXiCcandidate.prong1mom[2] + thisXiCcandidate.prong2mom[2]}; + + o2::track::TrackParCov xicTrack(thisXiCcandidate.xyz, momentumC, thisXiCcandidate.parentTrackCovMatrix, +1); + + if (std::hypot(thisXiCcandidate.xyz[0], thisXiCcandidate.xyz[1]) < minXiCRadius) + continue; // do not take if radius too small, likely a primary combination + + o2::dataformats::DCA dcaInfo; + float xicdcaXY = 1e+10, xicdcaZ = 1e+10; + o2::track::TrackParCov xicTrackCopy(xicTrack); // paranoia + + o2::vertexing::PVertex primaryVertex; + primaryVertex.setXYZ(collision.posX(), collision.posY(), collision.posZ()); + + if (xicTrackCopy.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { + xicdcaXY = dcaInfo.getY(); + xicdcaZ = dcaInfo.getZ(); + } + + histos.fill(HIST("hMassXiC"), thisXiCcandidate.mass); + histos.fill(HIST("hDCAXiCDaughters"), thisXiCcandidate.dca); + + // attempt XiCC finding + uint32_t nCombinationsCC = 0; + for (auto const& picc : tracksPiFromXiCCgrouped) { + + if (xiCand.posTrackId() == picc.globalIndex() || xiCand.negTrackId() == picc.globalIndex() || xiCand.bachTrackId() == picc.globalIndex()) + continue; // avoid using any track that was already used + if (picc.pt() < minPiCCPt) + continue; + if (mcSameMotherCheck && !checkSameMotherExtra(xi, picc)) + continue; + o2::track::TrackParCov piccTrack = getTrackParCov(picc); + nCombinationsCC++; + histos.fill(HIST("hCharmBuilding"), 2.0f); + if (!buildDecayCandidateTwoBody(xicTrack, piccTrack, 2.46793, 0.139570)) + continue; // failed at building candidate + histos.fill(HIST("hCharmBuilding"), 3.0f); + + histos.fill(HIST("hMassXiCC"), thisXiCCcandidate.mass); + histos.fill(HIST("hPtXiCC"), thisXiCCcandidate.pt); + histos.fill(HIST("hEtaXiCC"), thisXiCCcandidate.eta); + histos.fill(HIST("h3dMassXiCC"), thisXiCCcandidate.pt, thisXiCCcandidate.eta, thisXiCCcandidate.mass); + histos.fill(HIST("hDCAXiCCDaughters"), thisXiCCcandidate.dca); + + const std::array momentumCC = { + thisXiCCcandidate.prong0mom[0] + thisXiCCcandidate.prong1mom[0], + thisXiCCcandidate.prong0mom[1] + thisXiCCcandidate.prong1mom[1], + thisXiCCcandidate.prong0mom[2] + thisXiCCcandidate.prong1mom[2]}; + + o2::track::TrackParCov xiccTrack(thisXiCCcandidate.xyz, momentumCC, thisXiCCcandidate.parentTrackCovMatrix, +2); + + float xiccdcaXY = 1e+10, xiccdcaZ = 1e+10; + if (xiccTrack.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { + xiccdcaXY = dcaInfo.getY(); + xiccdcaZ = dcaInfo.getZ(); + } + + // produce multi-charm table for posterior analysis + if (fillDerivedTable) { + multiCharmCore( + thisXiCcandidate.dca, thisXiCCcandidate.dca, + thisXiCcandidate.mass, thisXiCCcandidate.mass, + thisXiCCcandidate.pt, thisXiCCcandidate.eta, + xi.nSiliconHits(), piFromXi.nSiliconHits(), + piFromLa.nSiliconHits(), prFromLa.nSiliconHits(), + pi1c.nSiliconHits(), pi2c.nSiliconHits(), picc.nSiliconHits(), + piFromXi.nTPCHits(), piFromLa.nTPCHits(), prFromLa.nTPCHits(), + pi1c.nTPCHits(), pi2c.nTPCHits(), picc.nTPCHits(), + xi.dcaXY(), xicdcaXY, xiccdcaXY, + piFromXi.dcaXY(), piFromLa.dcaXY(), prFromLa.dcaXY(), + pi1c.dcaXY(), pi2c.dcaXY(), picc.dcaXY()); + } + } + histos.fill(HIST("hCombinationsXiCC"), nCombinationsCC); + } + } + histos.fill(HIST("hCombinationsXiC"), nCombinationsC); + } + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* + PROCESS_SWITCH(alice3multicharm, processGenerated, "fill MC-only histograms", true); + PROCESS_SWITCH(alice3multicharm, processFindXiCC, "find XiCC baryons", true); + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/Tasks/alice3-qa-singleparticle.cxx b/ALICE3/Tasks/alice3-qa-singleparticle.cxx index a5cfca5325c..1c8f0f19330 100644 --- a/ALICE3/Tasks/alice3-qa-singleparticle.cxx +++ b/ALICE3/Tasks/alice3-qa-singleparticle.cxx @@ -166,6 +166,16 @@ struct Alice3SingleParticle { histos.add("particle/mothers/prodVz", "Mothers Prod. Vertex Z " + tit, kTH1D, {axisProdz}); histos.add("particle/mothers/prodRadiusVsPt", "Mothers Prod. Vertex Radius " + tit, kTH2D, {axisPt, axisProdRadius}); histos.add("particle/mothers/prodRadius3DVsPt", "Mothers Prod. Vertex Radius XYZ " + tit, kTH2D, {axisPt, axisProdRadius}); + + histos.add("particle/mothers/mothers/PDGs", "Mothers mothers PDGs " + tit, kTH2D, {axisPDGs, axisCharge}); + histos.add("particle/mothers/mothers/PDGsPrimaries", "Mothers mothers PDGs Primaries of " + tit, kTH2D, {axisPDGs, axisCharge}); + histos.add("particle/mothers/mothers/PDGsSecondaries", "Mothers mothers PDGs Secondaries of " + tit, kTH2D, {axisPDGs, axisCharge}); + histos.add("particle/mothers/mothers/prodVx", "Mothers mothers Prod. Vertex X " + tit, kTH1D, {axisProdx}); + histos.add("particle/mothers/mothers/prodVy", "Mothers mothers Prod. Vertex Y " + tit, kTH1D, {axisPrody}); + histos.add("particle/mothers/mothers/prodVz", "Mothers mothers Prod. Vertex Z " + tit, kTH1D, {axisProdz}); + histos.add("particle/mothers/mothers/prodRadiusVsPt", "Mothers mothers Prod. Vertex Radius " + tit, kTH2D, {axisPt, axisProdRadius}); + histos.add("particle/mothers/mothers/prodRadius3DVsPt", "Mothers mothers Prod. Vertex Radius XYZ " + tit, kTH2D, {axisPt, axisProdRadius}); + if (doprocessParticleOnly) { return; } @@ -285,7 +295,7 @@ struct Alice3SingleParticle { } } if (mcParticle.has_mothers()) { - auto mothers = mcParticle.mothers_as(); + const auto& mothers = mcParticle.mothers_as(); for (const auto& mother : mothers) { const auto& pdgStringMot = getPdgCodeString(mother); const auto& pdgChargeMot = getCharge(mother); @@ -302,6 +312,26 @@ struct Alice3SingleParticle { histos.fill(HIST("particle/mothers/prodVz"), mother.vz()); histos.fill(HIST("particle/mothers/prodRadiusVsPt"), mother.pt(), std::sqrt(mother.vx() * mother.vx() + mother.vy() * mother.vy())); histos.fill(HIST("particle/mothers/prodRadius3DVsPt"), mother.pt(), std::sqrt(mother.vx() * mother.vx() + mother.vy() * mother.vy() + mother.vz() * mother.vz())); + if (mother.has_mothers()) { + const auto& mothers2 = mother.mothers_as(); + for (const auto& mother2 : mothers2) { + const auto& pdgStringMot2 = getPdgCodeString(mother2); + const auto& pdgChargeMot2 = getCharge(mother2); + + histos.get(HIST("particle/mothers/mothers/PDGs"))->Fill(pdgStringMot2, pdgChargeMot2, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/mothers/mothers/PDGsPrimaries"))->Fill(pdgStringMot2, pdgChargeMot2, 1.f); + } else { + histos.get(HIST("particle/mothers/mothers/PDGsSecondaries"))->Fill(pdgStringMot2, pdgChargeMot2, 1.f); + } + + histos.fill(HIST("particle/mothers/mothers/prodVx"), mother2.vx()); + histos.fill(HIST("particle/mothers/mothers/prodVy"), mother2.vy()); + histos.fill(HIST("particle/mothers/mothers/prodVz"), mother2.vz()); + histos.fill(HIST("particle/mothers/mothers/prodRadiusVsPt"), mother2.pt(), std::sqrt(mother2.vx() * mother2.vx() + mother2.vy() * mother2.vy())); + histos.fill(HIST("particle/mothers/mothers/prodRadius3DVsPt"), mother2.pt(), std::sqrt(mother2.vx() * mother2.vx() + mother2.vy() * mother2.vy() + mother2.vz() * mother2.vz())); + } + } } } @@ -335,7 +365,8 @@ struct Alice3SingleParticle { if (track.hasTOF()) { histos.get(HIST("track/tofPDGs"))->Fill(getPdgCodeString(mcParticle), getCharge(mcParticle), 1.f); } - if (!IsStable) { + if (IsStable.value == 0) { + LOG(info) << mcParticle.pdgCode() << " asked for " << PDG.value; if (!mcParticle.has_mothers()) { continue; } @@ -624,13 +655,12 @@ struct Alice3SingleParticle { if (track.hasTOF()) { histos.get(HIST("track/tofPDGs"))->Fill(getPdgCodeString(mcParticle), getCharge(mcParticle), 1.f); } - if (!IsStable) { + if (IsStable.value == 0) { if (!mcParticle.has_mothers()) { continue; } - // auto mothers = mcParticle.mothers(); - auto mothers = mcParticle.mothers_as(); - const auto ParticleIsInteresting = std::find(ParticlesOfInterest.begin(), ParticlesOfInterest.end(), mothers[0].globalIndex()) != ParticlesOfInterest.end(); + const auto& mothers = mcParticle.mothers_as(); + const auto& ParticleIsInteresting = std::find(ParticlesOfInterest.begin(), ParticlesOfInterest.end(), mothers[0].globalIndex()) != ParticlesOfInterest.end(); if (!ParticleIsInteresting) { continue; } diff --git a/CODEOWNERS b/CODEOWNERS index b57a03b8538..523a5a8cf64 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -16,17 +16,17 @@ /Common/Tools/Multiplicity @alibuild @ddobrigk @victor-gonzalez /ALICE3 @alibuild @njacazio @hscheid /DPG @alibuild @chiarazampolli @noferini -/DPG/Tasks/AOTEvent @alibuild @ekryshen @strogolo +/DPG/Tasks/AOTEvent @alibuild @ekryshen @strogolo @altsybee /DPG/Tasks/AOTTrack @alibuild @mfaggin @iouribelikov @njacazio /DPG/Tasks/TOF @alibuild @noferini @njacazio /DPG/Tasks/FT0 @alibuild @afurs -/EventFiltering @alibuild @mpuccio @strogolo -/EventFiltering/PWGHF @alibuild @fgrosa @zhangbiao-phy @mpuccio @strogolo -/EventFiltering/PWGUD @alibuild @pbuehler @mpuccio @strogolo -/EventFiltering/PWGLF @alibuild @mpuccio @ercolessi @ChiaraDeMartin95 @strogolo -/EventFiltering/PWGCF @alibuild @lauraser @mpuccio @strogolo -/EventFiltering/PWGMM @alibuild @aortizve @mpuccio @strogolo -/EventFiltering/PWGJE @alibuild @fkrizek @nzardosh @mpuccio @strogolo +/EventFiltering @alibuild @mpuccio @lietava +/EventFiltering/PWGHF @alibuild @fgrosa @zhangbiao-phy @mpuccio @lietava +/EventFiltering/PWGUD @alibuild @pbuehler @mpuccio @lietava +/EventFiltering/PWGLF @alibuild @mpuccio @ercolessi @ChiaraDeMartin95 @lietava +/EventFiltering/PWGCF @alibuild @lauraser @mpuccio @lietava +/EventFiltering/PWGMM @alibuild @aortizve @mpuccio @lietava +/EventFiltering/PWGJE @alibuild @fkrizek @nzardosh @mpuccio @lietava /PWGCF @alibuild @saganatt @victor-gonzalez @zchochul /PWGCF/Core @alibuild @jgrosseo @saganatt @victor-gonzalez @zchochul /PWGCF/DataModel @alibuild @jgrosseo @saganatt @victor-gonzalez @zchochul @@ -36,7 +36,7 @@ /PWGEM @alibuild @mikesas @rbailhac @feisenhu /PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu /PWGEM/PhotonMeson @alibuild @mikesas @rbailhac @m-c-danisch @novitzky @mhemmer-cern @dsekihat -/PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @nzardosh @NicoleBastid @hahassan7 @jpxrk +/PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @NicoleBastid @hahassan7 @jpxrk @apalasciano /PWGLF @alibuild @ercolessi @fmazzasc @chiarapinto @BongHwi @smaff92 @mbombara @ChiaraDeMartin95 @njacazio @skundu692 /PWGMM @alibuild @aalkin /PWGMM/Lumi @alibuild @aalkin diff --git a/Common/CCDB/macros/upload_trigger_aliases_run3.C b/Common/CCDB/macros/upload_trigger_aliases_run3.C index 45b2e694df6..e946d9117d4 100644 --- a/Common/CCDB/macros/upload_trigger_aliases_run3.C +++ b/Common/CCDB/macros/upload_trigger_aliases_run3.C @@ -46,8 +46,8 @@ void createPbPbAliases(map& mAliases) void upload_trigger_aliases_run3() { map mAliases; - // createDefaultAliases(mAliases); - createPbPbAliases(mAliases); + createDefaultAliases(mAliases); + // createPbPbAliases(mAliases); TObjArray* classNames[kNaliases]; for (auto& al : mAliases) { @@ -62,7 +62,7 @@ void upload_trigger_aliases_run3() map metadata; // read list of runs from text file - std::ifstream f("run3_pbpb2023.txt"); + std::ifstream f("runs.txt"); std::vector runs; int r = 0; while (f >> r) { @@ -117,7 +117,7 @@ void upload_trigger_aliases_run3() TriggerAliases* aliases = new TriggerAliases(); for (auto& al : mAliases) { int aliasId = al.first; - LOGP(debug, "alias = {}", al.second); + LOGP(debug, "alias = {}", al.second.Data()); for (const auto& className : *(classNames[aliasId])) { TString sname = className->GetName(); LOGP(debug, " className = {}", sname.Data()); @@ -150,6 +150,6 @@ void upload_trigger_aliases_run3() } } aliases->Print(); - ccdb.storeAsTFileAny(aliases, "EventSelection/TriggerAliases", metadata, sor, eor + 10000); // adding tolerance of 10s to eor + ccdb.storeAsTFileAny(aliases, "EventSelection/TriggerAliases", metadata, sor - 1000, eor + 10000); // adding tolerance of 10s to eor } } diff --git a/Common/Core/CMakeLists.txt b/Common/Core/CMakeLists.txt index 61ca933740c..babf1a6ccdc 100644 --- a/Common/Core/CMakeLists.txt +++ b/Common/Core/CMakeLists.txt @@ -18,6 +18,7 @@ o2physics_add_library(AnalysisCore EventPlaneHelper.cxx TableHelper.cxx MetadataHelper.cxx + CollisionTypeHelper.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsParameters ROOT::EG O2::CCDB ROOT::Physics O2::FT0Base O2::FV0Base) o2physics_target_root_dictionary(AnalysisCore @@ -31,4 +32,9 @@ o2physics_target_root_dictionary(AnalysisCore PID/DetectorResponse.h PID/PIDTOF.h PID/TPCPIDResponse.h + CollisionTypeHelper.h LINKDEF AnalysisCoreLinkDef.h) + +o2physics_add_header_only_library(TPCDriftManager + HEADERS TPCVDriftManager.h + INTERFACE_LINK_LIBRARIES O2::DataFormatsTPC) diff --git a/Common/Core/CollisionTypeHelper.cxx b/Common/Core/CollisionTypeHelper.cxx new file mode 100644 index 00000000000..c22510ec82e --- /dev/null +++ b/Common/Core/CollisionTypeHelper.cxx @@ -0,0 +1,58 @@ +// Copyright 2019-2020 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. + +/// +/// \file CollisionTypeHelper.h +/// \author NicolĂČ Jacazio nicolo.jacazio@cern.ch +/// \brief Utility to handle the collision type from the GRP information +/// + +#include "Common/Core/CollisionTypeHelper.h" +#include +#include +#include "DataFormatsParameters/GRPLHCIFData.h" + +std::string CollisionSystemType::getCollisionSystemName(collType collSys) +{ + switch (collSys) { + case kCollSyspp: + return "pp"; + case kCollSysPbPb: + return "PbPb"; + case kCollSysXeXe: + return "XeXe"; + case kCollSyspPb: + return "pPb"; + default: + return "Undefined"; + } +} + +int CollisionSystemType::getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif) +{ + const int ZBeamA = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamA); + const int ZBeamC = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamC); + LOG(debug) << "Collision system: " << ZBeamA << " * " << ZBeamC << " detected"; + switch (ZBeamA * ZBeamC) { + case 1: // pp 1*1 + return kCollSyspp; + case 6724: // Pb-Pb 82*82 + return kCollSysPbPb; + case 225: // Xe-Xe 54*54 + return kCollSysXeXe; + case 82: // p-Pb 82*1 + return kCollSyspPb; + default: + LOG(fatal) << "Undefined collision system in getCollisionTypeFromGrp with BeamA = " << ZBeamA << " and BeamC = " << ZBeamC; + return kCollSysUndef; + } + return kCollSysUndef; +} diff --git a/Common/Core/CollisionTypeHelper.h b/Common/Core/CollisionTypeHelper.h new file mode 100644 index 00000000000..0196fdc03bb --- /dev/null +++ b/Common/Core/CollisionTypeHelper.h @@ -0,0 +1,41 @@ +// Copyright 2019-2020 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. + +/// +/// \file CollisionTypeHelper.h +/// \author NicolĂČ Jacazio nicolo.jacazio@cern.ch +/// \brief Utility to handle the collision type from the GRP information +/// + +#ifndef COMMON_CORE_COLLISIONTYPEHELPER_H_ +#define COMMON_CORE_COLLISIONTYPEHELPER_H_ + +#include +#include "DataFormatsParameters/GRPLHCIFData.h" + +// Container for the collision system type +struct CollisionSystemType { + // Enum type for the collision system + typedef int collType; + + static constexpr collType kCollSysUndef = -1; // Undefined collision system + static constexpr collType kCollSyspp = 0; // pp + static constexpr collType kCollSysPbPb = 1; // PbPb + static constexpr collType kCollSysXeXe = 2; // XeXe + static constexpr collType kCollSyspPb = 3; // pPb + static constexpr collType kNCollSys = 4; // Number of collision systems + + static std::string getCollisionSystemName(collType collSys); + + static int getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif); +}; + +#endif // COMMON_CORE_COLLISIONTYPEHELPER_H_ diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index 34f80c959f1..f772ba40e09 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -935,6 +935,16 @@ struct RecoDecay { for (auto& iPart : arrayIds[-stage]) { // check all the particles that were the mothers at the previous stage auto particleMother = particlesMC.rawIteratorAt(iPart - particlesMC.offset()); if (particleMother.has_mothers()) { + + // we exit immediately if searchUpToQuark is false and the first mother is a parton (an hadron should never be the mother of a parton) + if (!searchUpToQuark) { + auto mother = particlesMC.rawIteratorAt(particleMother.mothersIds().front() - particlesMC.offset()); + auto PDGParticleIMother = std::abs(mother.pdgCode()); // PDG code of the mother + if (PDGParticleIMother < 9 || (PDGParticleIMother > 20 && PDGParticleIMother < 38)) { + return OriginType::Prompt; + } + } + for (auto iMother = particleMother.mothersIds().front(); iMother <= particleMother.mothersIds().back(); ++iMother) { // loop over the mother particles of the analysed particle if (std::find(arrayIdsStage.begin(), arrayIdsStage.end(), iMother) != arrayIdsStage.end()) { // if a mother is still present in the vector, do not check it again continue; diff --git a/Common/Core/TPCVDriftManager.h b/Common/Core/TPCVDriftManager.h new file mode 100644 index 00000000000..8fbecfc4bad --- /dev/null +++ b/Common/Core/TPCVDriftManager.h @@ -0,0 +1,171 @@ +// Copyright 2019-2020 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. + +#ifndef COMMON_CORE_TPCVDRIFTMANAGER_H_ +#define COMMON_CORE_TPCVDRIFTMANAGER_H_ + +#include + +#include "CCDB/BasicCCDBManager.h" +#include "Framework/Logger.h" +#include "Framework/DataTypes.h" +#include "DataFormatsTPC/VDriftCorrFact.h" +#include "CommonConstants/LHCConstants.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "ReconstructionDataFormats/Track.h" + +namespace o2::aod::common +{ + +// Thin wrapper for vdrift ccdb queries should partially mirror VDriftHelper class. +// Allows to move TPC standalone tracks under the assumption of a different +// collision than the track is associated to. +class TPCVDriftManager +{ + public: + void init(o2::ccdb::BasicCCDBManager* ccdb) noexcept + { + mCCDB = ccdb; + } + + void update(uint64_t timestamp) noexcept + { + // Check validity of already present obj, otherwise update + if (mVD != nullptr && (timestamp > static_cast(mVD->firstTime) || timestamp < static_cast(mVD->lastTime))) { + return; + } + + // Update Obj + mVD = mCCDB->getForTimeStamp("TPC/Calib/VDriftTgl", timestamp); + if (mVD == nullptr || mVD->firstTime < 0 || mVD->lastTime < 0) { + LOGP(error, "Got invalid VDriftCorrFact for {}", timestamp); + mValid = false; + return; + } + + // TODO account for laser calib + + // Update factors + mTPCVDriftNS = mVD->refVDrift * mVD->corrFact * 1e-3; + + mValid = true; + LOGP(info, "Updated VDrift for timestamp {} with vdrift={:.7f} (cm/ns)", mVD->creationTime, mTPCVDriftNS); + } + + template + [[nodiscard]] bool moveTPCTrack(const Collision& col, const TrackExtra& trackExtra, Track& track) noexcept + { + ++mCalls; + + // Check if there is a good object available otherwise pretend everything is fine + if (!mValid) { + if (mInvalid < mWarningLimit) { + LOGP(warn, "No VDrift object available, pretending track to be correct"); + if (mInvalid == mWarningLimit - 1) { + LOGP(warn, "Silencing further warnings!"); + } + } + ++mInvalid; + return true; + } + + // track is fine, or cannot be moved has information is not available + if (!(trackExtra.flags() & o2::aod::track::TrackFlags::TrackTimeAsym)) { + ++mNoFlag; + return true; + } + + // TPC time is given relative to the closest BC in ns + float tTB, tTBErr; + if (col.collisionTimeRes() < 0.f) { // use track data + ++mColResNeg; + tTB = trackExtra.trackTime(); + o2::aod::track::extensions::TPCTimeErrEncoding enc; + enc.encoding.timeErr = trackExtra.trackTimeRes(); + tTBErr = 0.5f * (enc.getDeltaTFwd() + enc.getDeltaTBwd()); + } else { + ++mColResPos; + // The TPC track can be associated to a different BC than the one the collision under assumption is; + // we need to calculate the difference and subtract this from the trackTime() + const auto trackBC = trackExtra.template collision_as().template foundBC_as().globalBC(); + const auto colBC = col.template foundBC_as().globalBC(); + float sign{1.f}; + uint64_t diffBC{0}; + if (colBC < trackBC) { + sign = -1.f; + diffBC = (trackBC - colBC); + } else { + diffBC = (colBC - trackBC); + } + float diffBCNS = sign * static_cast(diffBC) * static_cast(o2::constants::lhc::LHCBunchSpacingNS); + tTB = col.collisionTime() + diffBCNS; + tTBErr = col.collisionTimeRes(); + } + float dTime = tTB - trackExtra.trackTime(); + float dDrift = dTime * mTPCVDriftNS; + float dDriftErr = tTBErr * mTPCVDriftNS; + if (dDriftErr < 0.f || dDrift > 250.f) { // we cannot move a track outside the drift volume + if (mOutside < mWarningLimit) { + LOGP(warn, "Skipping correction outside of tpc volume with dDrift={} +- {}", dDrift, dDriftErr); + const auto& trackBC = trackExtra.template collision_as().template foundBC_as().globalBC(); + const auto& colBC = col.template foundBC_as().globalBC(); + int diffBC = colBC - trackBC; + LOGP(info, "ct={}; ctr={}; tTB={}; t0={}; dTime={}; dDrift={}; tgl={}: colBC={} trackBC={} diffBC={}", col.collisionTime(), col.collisionTimeRes(), tTB, trackExtra.trackTime(), dTime, dDrift, track.getTgl(), colBC, trackBC, diffBC); + if (mOutside == mWarningLimit - 1) { + LOGP(warn, "Silencing further warnings!"); + } + } + ++mOutside; + return false; + } + + // impose new Z coordinate + track.setZ(track.getZ() + ((track.getTgl() < 0.) ? -dDrift : dDrift)); + if constexpr (std::is_base_of_v) { + track.setCov(track.getSigmaZ2() + dDriftErr * dDriftErr, o2::track::kSigZ2); + } + + ++mMovedTrks; + + return true; + } + + void print() noexcept + { + LOGP(info, "TPC corrections called: {}; Moved Tracks: {}; Constrained Tracks={}; No Flag: {}; NULL: {}; Outside: {}; ColResPos {}; ColResNeg {};", mCalls, mMovedTrks, mConstrained, mNoFlag, mInvalid, mOutside, mColResPos, mColResNeg); + } + + private: + bool mValid{false}; + // Factors + float mTPCVDriftNS{0.f}; // drift velocity in cm/ns + + // CCDB + const o2::tpc::VDriftCorrFact* mVD{}; // reference to drift correction + o2::ccdb::BasicCCDBManager* mCCDB{}; // reference to initialized ccdb manager + + static constexpr unsigned int mWarningLimit{10}; + + // Counters + unsigned int mCalls{0}; // total number of calls + unsigned int mMovedTrks{0}; // number of moved tracks + unsigned int mInvalid{0}; // number of tracks where no drift object was available + unsigned int mColResNeg{0}; // number of collisions with negative resolution + unsigned int mColResPos{0}; // number of collisions with positive resolution + unsigned int mNoFlag{0}; // number of tracks without flag set + unsigned int mOutside{0}; // number of tracks moved but outside of sensible volume + unsigned int mConstrained{0}; // number of constrained tracks +}; + +} // namespace o2::aod::common + +#endif // COMMON_CORE_TPCVDRIFTMANAGER_H_ diff --git a/Common/Core/TrackSelection.h b/Common/Core/TrackSelection.h index 618124f638f..351b662c48d 100644 --- a/Common/Core/TrackSelection.h +++ b/Common/Core/TrackSelection.h @@ -195,10 +195,10 @@ class TrackSelection return (isRun2 && mRequireGoldenChi2) ? (track.flags() & o2::aod::track::GoldenChi2) : true; case TrackCuts::kDCAxy: - return abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + return std::fabs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); case TrackCuts::kDCAz: - return abs(track.dcaZ()) <= mMaxDcaZ; + return std::fabs(track.dcaZ()) <= mMaxDcaZ; default: return false; diff --git a/Common/DataModel/CMakeLists.txt b/Common/DataModel/CMakeLists.txt index 312e9c15225..e72e964862a 100644 --- a/Common/DataModel/CMakeLists.txt +++ b/Common/DataModel/CMakeLists.txt @@ -20,4 +20,6 @@ o2physics_add_header_only_library(DataModel TrackSelectionTables.h McCollisionExtra.h Qvectors.h - MftmchMatchingML.h) + MatchMFTFT0.h + MftmchMatchingML.h + ZDCInterCalib.h) diff --git a/Common/DataModel/Centrality.h b/Common/DataModel/Centrality.h index f89e6b23e71..a4701ef56a3 100644 --- a/Common/DataModel/Centrality.h +++ b/Common/DataModel/Centrality.h @@ -54,6 +54,23 @@ using CentFT0A = CentFT0As::iterator; using CentFT0C = CentFT0Cs::iterator; using CentFDDM = CentFDDMs::iterator; using CentNTPV = CentNTPVs::iterator; + +template +concept HasRun2Centrality = requires(T&& t) { + { t.centRun2V0M() }; + { t.centRun2CL0() }; + { t.centRun2CL1() }; +}; + +template +concept HasCentrality = requires(T&& t) { + { t.centFV0A() }; + { t.centFT0M() }; + { t.centFT0A() }; + { t.centFT0C() }; + { t.centNTPV() }; +}; + } // namespace o2::aod #endif // COMMON_DATAMODEL_CENTRALITY_H_ diff --git a/Common/DataModel/MatchMFTFT0.h b/Common/DataModel/MatchMFTFT0.h new file mode 100644 index 00000000000..21ee19b696f --- /dev/null +++ b/Common/DataModel/MatchMFTFT0.h @@ -0,0 +1,34 @@ +// Copyright 2019-2020 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. + +// \file MatchMFTFT0.h +// \author Sarah Herrmann +// +// \brief Declaration of tables useful for the matching of MFT tracks to FT0-C signals +// \date 03/09/24 + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace indices +{ // For bctoft0c +DECLARE_SOA_ARRAY_INDEX_COLUMN(FT0, ft0s); // has_ft0s works now, without it doesn't +DECLARE_SOA_ARRAY_INDEX_COLUMN(BC, bcs); // has_bcs works now, without it doesn't +} // namespace indices +namespace ambii +{ // for MA2T +DECLARE_SOA_INDEX_COLUMN(MFTTrack, track); +} // namespace ambii +DECLARE_SOA_TABLE(MatchedToFT0, "AOD", "MAFT", indices::BCId, indices::FT0Ids); + +DECLARE_SOA_TABLE(BCofMFT, "AOD", "BCOFMFT", ambii::MFTTrackId, indices::BCIds); +} // namespace o2::aod diff --git a/Common/DataModel/Multiplicity.h b/Common/DataModel/Multiplicity.h index 97d6661bb6a..ee56ebfedcb 100644 --- a/Common/DataModel/Multiplicity.h +++ b/Common/DataModel/Multiplicity.h @@ -51,6 +51,7 @@ DECLARE_SOA_COLUMN(MultMCFT0C, multMCFT0C, int); //! DECLARE_SOA_COLUMN(MultMCNParticlesEta10, multMCNParticlesEta10, int); //! DECLARE_SOA_COLUMN(MultMCNParticlesEta08, multMCNParticlesEta08, int); //! DECLARE_SOA_COLUMN(MultMCNParticlesEta05, multMCNParticlesEta05, int); //! +DECLARE_SOA_COLUMN(MultMCPVz, multMCPVz, float); //! // complementary / MultsExtra table DECLARE_SOA_COLUMN(MultPVTotalContributors, multPVTotalContributors, int); //! @@ -72,8 +73,9 @@ DECLARE_SOA_COLUMN(MultNTracksITSTPC, multNTracksITSTPC, int); //! DECLARE_SOA_COLUMN(MultAllTracksTPCOnly, multAllTracksTPCOnly, int); //! DECLARE_SOA_COLUMN(MultAllTracksITSTPC, multAllTracksITSTPC, int); //! DECLARE_SOA_COLUMN(MultNTracksGlobal, multNTracksGlobal, int); //! - -DECLARE_SOA_COLUMN(BCNumber, bcNumber, int); //! +DECLARE_SOA_COLUMN(MultNGlobalTracksPV, multNGlobalTracksPV, int); +DECLARE_SOA_COLUMN(MultNGlobalTracksPVeta1, multNGlobalTracksPVeta1, int); +DECLARE_SOA_COLUMN(MultNGlobalTracksPVetaHalf, multNGlobalTracksPVetaHalf, int); // even further QA: timing information for neighboring events DECLARE_SOA_COLUMN(TimeToPrePrevious, timeToPrePrevious, float); //! @@ -105,15 +107,16 @@ DECLARE_SOA_TABLE(PVMults, "AOD", "PVMULT", //! Multiplicity from the PV contrib mult::IsInelGt1); using BarrelMults = soa::Join; using Mults = soa::Join; +using FT0Mult = FT0Mults::iterator; using Mult = Mults::iterator; -// for QA purposes DECLARE_SOA_TABLE(MultsExtra, "AOD", "MULTEXTRA", //! mult::MultPVTotalContributors, mult::MultPVChi2, mult::MultCollisionTimeRes, mult::MultRunNumber, mult::MultPVz, mult::MultSel8, mult::MultNTracksHasITS, mult::MultNTracksHasTPC, mult::MultNTracksHasTOF, mult::MultNTracksHasTRD, mult::MultNTracksITSOnly, mult::MultNTracksTPCOnly, mult::MultNTracksITSTPC, mult::MultAllTracksTPCOnly, mult::MultAllTracksITSTPC, - mult::BCNumber, evsel::NumTracksInTimeRange); + evsel::NumTracksInTimeRange, + collision::Flags); DECLARE_SOA_TABLE(MultNeighs, "AOD", "MULTNEIGH", //! mult::TimeToPrePrevious, mult::TimeToPrevious, @@ -121,20 +124,36 @@ DECLARE_SOA_TABLE(MultNeighs, "AOD", "MULTNEIGH", //! // for QA purposes DECLARE_SOA_TABLE(MultsGlobal, "AOD", "MULTGLOBAL", //! counters that use Track Selection (optional) - mult::MultNTracksGlobal); + mult::MultNTracksGlobal, + mult::MultNGlobalTracksPV, + mult::MultNGlobalTracksPVeta1, + mult::MultNGlobalTracksPVetaHalf); DECLARE_SOA_TABLE(MultSelections, "AOD", "MULTSELECTIONS", //! evsel::Selection); // for derived data / QA studies using MultExtra = MultsExtra::iterator; -DECLARE_SOA_TABLE(MultsExtraMC, "AOD", "MULTEXTRAMC", //! Table for the MC information + +// mc collisions table - indexed to Mult +DECLARE_SOA_TABLE(MultMCExtras, "AOD", "MULTMCEXTRA", //! Table for the MC information mult::MultMCFT0A, mult::MultMCFT0C, mult::MultMCNParticlesEta05, mult::MultMCNParticlesEta08, mult::MultMCNParticlesEta10, + mult::MultMCPVz, mult::IsInelGt0, mult::IsInelGt1, o2::soa::Marker<1>); -using MultExtraMC = MultsExtraMC::iterator; +using MultMCExtra = MultMCExtras::iterator; +using MultsExtraMC = MultMCExtras; // for backwards compatibility with previous naming scheme + +// crosslinks +namespace mult +{ +DECLARE_SOA_INDEX_COLUMN(MultMCExtra, multMCExtra); +} + +DECLARE_SOA_TABLE(Mult2MCExtras, "AOD", "Mult2MCEXTRA", //! Relate reco mult entry to MC extras entry + o2::soa::Index<>, mult::MultMCExtraId); namespace multZeq { @@ -164,12 +183,12 @@ DECLARE_SOA_COLUMN(MultBCFV0A, multBCFV0A, float); //! DECLARE_SOA_COLUMN(MultBCFDDA, multBCFDDA, float); //! DECLARE_SOA_COLUMN(MultBCFDDC, multBCFDDC, float); //! -DECLARE_SOA_COLUMN(MultBCFZNA, multBCFZNA, float); //! -DECLARE_SOA_COLUMN(MultBCFZNC, multBCFZNC, float); //! -DECLARE_SOA_COLUMN(MultBCFZEM1, multBCFZEM1, float); //! -DECLARE_SOA_COLUMN(MultBCFZEM2, multBCFZEM2, float); //! -DECLARE_SOA_COLUMN(MultBCFZPA, multBCFZPA, float); //! -DECLARE_SOA_COLUMN(MultBCFZPC, multBCFZPC, float); //! +DECLARE_SOA_COLUMN(MultBCZNA, multBCZNA, float); //! +DECLARE_SOA_COLUMN(MultBCZNC, multBCZNC, float); //! +DECLARE_SOA_COLUMN(MultBCZEM1, multBCZEM1, float); //! +DECLARE_SOA_COLUMN(MultBCZEM2, multBCZEM2, float); //! +DECLARE_SOA_COLUMN(MultBCZPA, multBCZPA, float); //! +DECLARE_SOA_COLUMN(MultBCZPC, multBCZPC, float); //! DECLARE_SOA_COLUMN(MultBCTVX, multBCTVX, bool); //! DECLARE_SOA_COLUMN(MultBCFV0OrA, multBCFV0OrA, bool); //! @@ -178,27 +197,50 @@ DECLARE_SOA_COLUMN(MultBCT0triggerBits, multBCT0triggerBits, uint8_t); //! DECLARE_SOA_COLUMN(MultBCFDDtriggerBits, multBCFDDtriggerBits, uint8_t); //! DECLARE_SOA_COLUMN(MultBCTriggerMask, multBCTriggerMask, uint64_t); //! CTP trigger mask DECLARE_SOA_COLUMN(MultBCColliding, multBCColliding, bool); //! CTP trigger mask + +DECLARE_SOA_COLUMN(MultBCFT0PosZ, multBCFT0PosZ, float); //! Position along Z computed with the FT0 information within the BC +DECLARE_SOA_COLUMN(MultBCFT0PosZValid, multBCFT0PosZValid, bool); //! Validity of the position along Z computed with the FT0 information within the BC + } // namespace multBC -DECLARE_SOA_TABLE(MultsBC, "AOD", "MULTBC", //! +DECLARE_SOA_TABLE(MultBCs, "AOD", "MULTBC", //! multBC::MultBCFT0A, multBC::MultBCFT0C, + multBC::MultBCFT0PosZ, + multBC::MultBCFT0PosZValid, multBC::MultBCFV0A, multBC::MultBCFDDA, multBC::MultBCFDDC, - multBC::MultBCFZNA, - multBC::MultBCFZNC, - multBC::MultBCFZEM1, - multBC::MultBCFZEM2, - multBC::MultBCFZPA, - multBC::MultBCFZPC, + multBC::MultBCZNA, + multBC::MultBCZNC, + multBC::MultBCZEM1, + multBC::MultBCZEM2, + multBC::MultBCZPA, + multBC::MultBCZPC, multBC::MultBCTVX, multBC::MultBCFV0OrA, multBC::MultBCV0triggerBits, multBC::MultBCT0triggerBits, multBC::MultBCFDDtriggerBits, multBC::MultBCTriggerMask, - multBC::MultBCColliding); -using MultBC = MultsBC::iterator; + multBC::MultBCColliding, + bc::Flags); +using MultBC = MultBCs::iterator; + +// crosslinks +namespace mult +{ +DECLARE_SOA_INDEX_COLUMN(MultBC, multBC); +} +namespace multBC +{ +DECLARE_SOA_INDEX_COLUMN(FT0Mult, ft0Mult); +} + +// for QA purposes +DECLARE_SOA_TABLE(Mults2BC, "AOD", "MULTS2BC", //! Relate mult -> BC + o2::soa::Index<>, mult::MultBCId); +DECLARE_SOA_TABLE(BC2Mults, "AOD", "BC2MULTS", //! Relate BC -> mult + o2::soa::Index<>, multBC::FT0MultId); } // namespace o2::aod diff --git a/Common/DataModel/PIDResponse.h b/Common/DataModel/PIDResponse.h index 43c2f87c845..3ef77fef8d4 100644 --- a/Common/DataModel/PIDResponse.h +++ b/Common/DataModel/PIDResponse.h @@ -96,7 +96,7 @@ using hasTPCAl = decltype(std::declval().tpcNSigmaAl()); // PID index as template argument #define perSpeciesWrapper(functionName) \ template \ - const auto functionName(const TrackType& track) \ + auto functionName(const TrackType& track) \ { \ if constexpr (index == o2::track::PID::Electron) { \ return track.functionName##El(); \ @@ -122,7 +122,7 @@ using hasTPCAl = decltype(std::declval().tpcNSigmaAl()); perSpeciesWrapper(tofNSigma); perSpeciesWrapper(tofExpSigma); template -const auto tofExpSignal(const TrackType& track) +auto tofExpSignal(const TrackType& track) { if constexpr (index == o2::track::PID::Electron) { return track.tofExpSignalEl(track.tofSignal()); @@ -149,7 +149,7 @@ perSpeciesWrapper(tofExpSignalDiff); perSpeciesWrapper(tpcNSigma); perSpeciesWrapper(tpcExpSigma); template -const auto tpcExpSignal(const TrackType& track) +auto tpcExpSignal(const TrackType& track) { if constexpr (index == o2::track::PID::Electron) { return track.tpcExpSignalEl(track.tpcSignal()); @@ -178,7 +178,7 @@ perSpeciesWrapper(tpcExpSignalDiff); // PID index as function argument for TOF #define perSpeciesWrapper(functionName) \ template \ - const auto functionName(const o2::track::PID::ID index, const TrackType& track) \ + auto functionName(const o2::track::PID::ID index, const TrackType& track) \ { \ switch (index) { \ case o2::track::PID::Electron: \ @@ -226,7 +226,7 @@ perSpeciesWrapper(tpcExpSignalDiff); perSpeciesWrapper(tofNSigma); perSpeciesWrapper(tofExpSigma); template -const auto tofExpSignal(const o2::track::PID::ID index, const TrackType& track) +auto tofExpSignal(const o2::track::PID::ID index, const TrackType& track) { switch (index) { case o2::track::PID::Electron: @@ -277,7 +277,7 @@ perSpeciesWrapper(tofExpSignalDiff); // PID index as function argument for TPC #define perSpeciesWrapper(functionName) \ template \ - const auto functionName(const o2::track::PID::ID index, const TrackType& track) \ + auto functionName(const o2::track::PID::ID index, const TrackType& track) \ { \ switch (index) { \ case o2::track::PID::Electron: \ @@ -325,7 +325,7 @@ perSpeciesWrapper(tofExpSignalDiff); perSpeciesWrapper(tpcNSigma); perSpeciesWrapper(tpcExpSigma); template -const auto tpcExpSignal(const o2::track::PID::ID index, const TrackType& track) +auto tpcExpSignal(const o2::track::PID::ID index, const TrackType& track) { switch (index) { case o2::track::PID::Electron: diff --git a/Common/DataModel/Qvectors.h b/Common/DataModel/Qvectors.h index 2185e1bb7c2..423c2648e89 100644 --- a/Common/DataModel/Qvectors.h +++ b/Common/DataModel/Qvectors.h @@ -43,12 +43,12 @@ DECLARE_SOA_COLUMN(QvecFT0MReVec, qvecFT0MReVec, std::vector); DECLARE_SOA_COLUMN(QvecFT0MImVec, qvecFT0MImVec, std::vector); DECLARE_SOA_COLUMN(QvecFV0AReVec, qvecFV0AReVec, std::vector); DECLARE_SOA_COLUMN(QvecFV0AImVec, qvecFV0AImVec, std::vector); -DECLARE_SOA_COLUMN(QvecBPosReVec, qvecBPosReVec, std::vector); -DECLARE_SOA_COLUMN(QvecBPosImVec, qvecBPosImVec, std::vector); -DECLARE_SOA_COLUMN(QvecBNegReVec, qvecBNegReVec, std::vector); -DECLARE_SOA_COLUMN(QvecBNegImVec, qvecBNegImVec, std::vector); -DECLARE_SOA_COLUMN(QvecBTotReVec, qvecBTotReVec, std::vector); -DECLARE_SOA_COLUMN(QvecBTotImVec, qvecBTotImVec, std::vector); +DECLARE_SOA_COLUMN(QvecTPCposReVec, qvecTPCposReVec, std::vector); +DECLARE_SOA_COLUMN(QvecTPCposImVec, qvecTPCposImVec, std::vector); +DECLARE_SOA_COLUMN(QvecTPCnegReVec, qvecTPCnegReVec, std::vector); +DECLARE_SOA_COLUMN(QvecTPCnegImVec, qvecTPCnegImVec, std::vector); +DECLARE_SOA_COLUMN(QvecTPCallReVec, qvecTPCallReVec, std::vector); +DECLARE_SOA_COLUMN(QvecTPCallImVec, qvecTPCallImVec, std::vector); DECLARE_SOA_COLUMN(QvecFT0CRe, qvecFT0CRe, float); DECLARE_SOA_COLUMN(QvecFT0CIm, qvecFT0CIm, float); @@ -58,6 +58,32 @@ DECLARE_SOA_COLUMN(QvecFT0MRe, qvecFT0MRe, float); DECLARE_SOA_COLUMN(QvecFT0MIm, qvecFT0MIm, float); DECLARE_SOA_COLUMN(QvecFV0ARe, qvecFV0ARe, float); DECLARE_SOA_COLUMN(QvecFV0AIm, qvecFV0AIm, float); +DECLARE_SOA_COLUMN(QvecTPCposRe, qvecTPCposRe, float); +DECLARE_SOA_COLUMN(QvecTPCposIm, qvecTPCposIm, float); +DECLARE_SOA_COLUMN(QvecTPCnegRe, qvecTPCnegRe, float); +DECLARE_SOA_COLUMN(QvecTPCnegIm, qvecTPCnegIm, float); +DECLARE_SOA_COLUMN(QvecTPCallRe, qvecTPCallRe, float); +DECLARE_SOA_COLUMN(QvecTPCallIm, qvecTPCallIm, float); + +DECLARE_SOA_COLUMN(SumAmplFT0C, sumAmplFT0C, float); +DECLARE_SOA_COLUMN(SumAmplFT0A, sumAmplFT0A, float); +DECLARE_SOA_COLUMN(SumAmplFT0M, sumAmplFT0M, float); +DECLARE_SOA_COLUMN(SumAmplFV0A, sumAmplFV0A, float); +DECLARE_SOA_COLUMN(NTrkTPCpos, nTrkTPCpos, int); +DECLARE_SOA_COLUMN(NTrkTPCneg, nTrkTPCneg, int); +DECLARE_SOA_COLUMN(NTrkTPCall, nTrkTPCall, int); +DECLARE_SOA_COLUMN(LabelsTPCpos, labelsTPCpos, std::vector); +DECLARE_SOA_COLUMN(LabelsTPCneg, labelsTPCneg, std::vector); +DECLARE_SOA_COLUMN(LabelsTPCall, labelsTPCall, std::vector); + +// Deprecated, will be removed in future after transition time // +DECLARE_SOA_COLUMN(QvecBPosReVec, qvecBPosReVec, std::vector); +DECLARE_SOA_COLUMN(QvecBPosImVec, qvecBPosImVec, std::vector); +DECLARE_SOA_COLUMN(QvecBNegReVec, qvecBNegReVec, std::vector); +DECLARE_SOA_COLUMN(QvecBNegImVec, qvecBNegImVec, std::vector); +DECLARE_SOA_COLUMN(QvecBTotReVec, qvecBTotReVec, std::vector); +DECLARE_SOA_COLUMN(QvecBTotImVec, qvecBTotImVec, std::vector); + DECLARE_SOA_COLUMN(QvecBPosRe, qvecBPosRe, float); DECLARE_SOA_COLUMN(QvecBPosIm, qvecBPosIm, float); DECLARE_SOA_COLUMN(QvecBNegRe, qvecBNegRe, float); @@ -65,16 +91,13 @@ DECLARE_SOA_COLUMN(QvecBNegIm, qvecBNegIm, float); DECLARE_SOA_COLUMN(QvecBTotRe, qvecBTotRe, float); DECLARE_SOA_COLUMN(QvecBTotIm, qvecBTotIm, float); -DECLARE_SOA_COLUMN(SumAmplFT0C, sumAmplFT0C, float); -DECLARE_SOA_COLUMN(SumAmplFT0A, sumAmplFT0A, float); -DECLARE_SOA_COLUMN(SumAmplFT0M, sumAmplFT0M, float); -DECLARE_SOA_COLUMN(SumAmplFV0A, sumAmplFV0A, float); DECLARE_SOA_COLUMN(NTrkBPos, nTrkBPos, int); DECLARE_SOA_COLUMN(NTrkBNeg, nTrkBNeg, int); DECLARE_SOA_COLUMN(NTrkBTot, nTrkBTot, int); DECLARE_SOA_COLUMN(LabelsBPos, labelsBPos, std::vector); DECLARE_SOA_COLUMN(LabelsBNeg, labelsBNeg, std::vector); DECLARE_SOA_COLUMN(LabelsBTot, labelsBTot, std::vector); +///////////////////////////////////////////////////////////////// } // namespace qvec DECLARE_SOA_TABLE(Qvectors, "AOD", "QVECTORDEVS", //! Table with all Qvectors. @@ -85,33 +108,51 @@ DECLARE_SOA_TABLE(QvectorFT0Cs, "AOD", "QVECTORSFT0C", qvec::IsCalibrated, qvec: DECLARE_SOA_TABLE(QvectorFT0As, "AOD", "QVECTORSFT0A", qvec::IsCalibrated, qvec::QvecFT0ARe, qvec::QvecFT0AIm, qvec::SumAmplFT0A); DECLARE_SOA_TABLE(QvectorFT0Ms, "AOD", "QVECTORSFT0M", qvec::IsCalibrated, qvec::QvecFT0MRe, qvec::QvecFT0MIm, qvec::SumAmplFT0M); DECLARE_SOA_TABLE(QvectorFV0As, "AOD", "QVECTORSFV0A", qvec::IsCalibrated, qvec::QvecFV0ARe, qvec::QvecFV0AIm, qvec::SumAmplFV0A); -DECLARE_SOA_TABLE(QvectorBPoss, "AOD", "QVECTORSBPOS", qvec::IsCalibrated, qvec::QvecBPosRe, qvec::QvecBPosIm, qvec::NTrkBPos, qvec::LabelsBPos); -DECLARE_SOA_TABLE(QvectorBNegs, "AOD", "QVECTORSBNEG", qvec::IsCalibrated, qvec::QvecBNegRe, qvec::QvecBNegIm, qvec::NTrkBNeg, qvec::LabelsBNeg); -DECLARE_SOA_TABLE(QvectorBTots, "AOD", "QVECTORSBTOT", qvec::IsCalibrated, qvec::QvecBTotRe, qvec::QvecBTotIm, qvec::NTrkBTot, qvec::LabelsBTot); +DECLARE_SOA_TABLE(QvectorTPCposs, "AOD", "QVECTORSTPCPOS", qvec::IsCalibrated, qvec::QvecTPCposRe, qvec::QvecTPCposIm, qvec::NTrkTPCpos, qvec::LabelsTPCpos); +DECLARE_SOA_TABLE(QvectorTPCnegs, "AOD", "QVECTORSTPCNEG", qvec::IsCalibrated, qvec::QvecTPCnegRe, qvec::QvecTPCnegIm, qvec::NTrkTPCneg, qvec::LabelsTPCneg); +DECLARE_SOA_TABLE(QvectorTPCalls, "AOD", "QVECTORSTPCALL", qvec::IsCalibrated, qvec::QvecTPCallRe, qvec::QvecTPCallIm, qvec::NTrkTPCall, qvec::LabelsTPCall); DECLARE_SOA_TABLE(QvectorFT0CVecs, "AOD", "QVECTORSFT0CVEC", qvec::IsCalibrated, qvec::QvecFT0CReVec, qvec::QvecFT0CImVec, qvec::SumAmplFT0C); DECLARE_SOA_TABLE(QvectorFT0AVecs, "AOD", "QVECTORSFT0AVEC", qvec::IsCalibrated, qvec::QvecFT0AReVec, qvec::QvecFT0AImVec, qvec::SumAmplFT0A); DECLARE_SOA_TABLE(QvectorFT0MVecs, "AOD", "QVECTORSFT0MVEC", qvec::IsCalibrated, qvec::QvecFT0MReVec, qvec::QvecFT0MImVec, qvec::SumAmplFT0M); DECLARE_SOA_TABLE(QvectorFV0AVecs, "AOD", "QVECTORSFV0AVEC", qvec::IsCalibrated, qvec::QvecFV0AReVec, qvec::QvecFV0AImVec, qvec::SumAmplFV0A); -DECLARE_SOA_TABLE(QvectorBPosVecs, "AOD", "QVECTORSBPOSVEC", qvec::IsCalibrated, qvec::QvecBPosReVec, qvec::QvecBPosImVec, qvec::NTrkBPos, qvec::LabelsBPos); -DECLARE_SOA_TABLE(QvectorBNegVecs, "AOD", "QVECTORSBNEGVEC", qvec::IsCalibrated, qvec::QvecBNegReVec, qvec::QvecBNegImVec, qvec::NTrkBNeg, qvec::LabelsBNeg); -DECLARE_SOA_TABLE(QvectorBTotVecs, "AOD", "QVECTORSBTOTVEC", qvec::IsCalibrated, qvec::QvecBTotReVec, qvec::QvecBTotImVec, qvec::NTrkBTot, qvec::LabelsBTot); +DECLARE_SOA_TABLE(QvectorTPCposVecs, "AOD", "QVECTORSTPCPVEC", qvec::IsCalibrated, qvec::QvecTPCposReVec, qvec::QvecTPCposImVec, qvec::NTrkTPCpos, qvec::LabelsTPCpos); +DECLARE_SOA_TABLE(QvectorTPCnegVecs, "AOD", "QVECTORSTPCNVEC", qvec::IsCalibrated, qvec::QvecTPCnegReVec, qvec::QvecTPCnegImVec, qvec::NTrkTPCneg, qvec::LabelsTPCneg); +DECLARE_SOA_TABLE(QvectorTPCallVecs, "AOD", "QVECTORSTPCAVEC", qvec::IsCalibrated, qvec::QvecTPCallReVec, qvec::QvecTPCallImVec, qvec::NTrkTPCall, qvec::LabelsTPCall); using QvectorFT0C = QvectorFT0Cs::iterator; using QvectorFT0A = QvectorFT0As::iterator; using QvectorFT0M = QvectorFT0Ms::iterator; using QvectorFV0A = QvectorFV0As::iterator; -using QvectorBPos = QvectorBPoss::iterator; -using QvectorBNeg = QvectorBNegs::iterator; -using QvectorBTot = QvectorBTots::iterator; +using QvectorTPCpos = QvectorTPCposs::iterator; +using QvectorTPCneg = QvectorTPCnegs::iterator; +using QvectorTPCall = QvectorTPCalls::iterator; using QvectorFT0CVec = QvectorFT0CVecs::iterator; using QvectorFT0AVec = QvectorFT0AVecs::iterator; using QvectorFT0MVec = QvectorFT0MVecs::iterator; using QvectorFV0AVec = QvectorFV0AVecs::iterator; +using QvectorTPCposVec = QvectorTPCposVecs::iterator; +using QvectorTPCnegVec = QvectorTPCnegVecs::iterator; +using QvectorTPCallVec = QvectorTPCallVecs::iterator; + +// Deprecated, will be removed in future after transition time // +DECLARE_SOA_TABLE(QvectorBPoss, "AOD", "QVECTORSBPOS", qvec::IsCalibrated, qvec::QvecBPosRe, qvec::QvecBPosIm, qvec::NTrkBPos, qvec::LabelsBPos); +DECLARE_SOA_TABLE(QvectorBNegs, "AOD", "QVECTORSBNEG", qvec::IsCalibrated, qvec::QvecBNegRe, qvec::QvecBNegIm, qvec::NTrkBNeg, qvec::LabelsBNeg); +DECLARE_SOA_TABLE(QvectorBTots, "AOD", "QVECTORSBTOT", qvec::IsCalibrated, qvec::QvecBTotRe, qvec::QvecBTotIm, qvec::NTrkBTot, qvec::LabelsBTot); + +DECLARE_SOA_TABLE(QvectorBPosVecs, "AOD", "QVECTORSBPOSVEC", qvec::IsCalibrated, qvec::QvecBPosReVec, qvec::QvecBPosImVec, qvec::NTrkBPos, qvec::LabelsBPos); +DECLARE_SOA_TABLE(QvectorBNegVecs, "AOD", "QVECTORSBNEGVEC", qvec::IsCalibrated, qvec::QvecBNegReVec, qvec::QvecBNegImVec, qvec::NTrkBNeg, qvec::LabelsBNeg); +DECLARE_SOA_TABLE(QvectorBTotVecs, "AOD", "QVECTORSBTOTVEC", qvec::IsCalibrated, qvec::QvecBTotReVec, qvec::QvecBTotImVec, qvec::NTrkBTot, qvec::LabelsBTot); + +using QvectorBPos = QvectorBPoss::iterator; +using QvectorBNeg = QvectorBNegs::iterator; +using QvectorBTot = QvectorBTots::iterator; + using QvectorBPosVec = QvectorBPosVecs::iterator; using QvectorBNegVec = QvectorBNegVecs::iterator; using QvectorBTotVec = QvectorBTotVecs::iterator; +///////////////////////////////////////////////////////////////// } // namespace o2::aod diff --git a/Common/DataModel/ZDCInterCalib.h b/Common/DataModel/ZDCInterCalib.h new file mode 100644 index 00000000000..5ab722452af --- /dev/null +++ b/Common/DataModel/ZDCInterCalib.h @@ -0,0 +1,46 @@ +// Copyright 2019-2020 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. +#ifndef COMMON_DATAMODEL_ZDCINTERCALIB_H_ +#define COMMON_DATAMODEL_ZDCINTERCALIB_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace znoutput +{ +DECLARE_SOA_COLUMN(pmcZNA, ZNAcommonPM, float); //! PMC ZNA +DECLARE_SOA_COLUMN(pm1ZNA, ZNAPM1, float); //! PM1 ZNA +DECLARE_SOA_COLUMN(pm2ZNA, ZNAPM2, float); //! PM2 ZNA +DECLARE_SOA_COLUMN(pm3ZNA, ZNAPM3, float); //! PM3 ZNA +DECLARE_SOA_COLUMN(pm4ZNA, ZNAPM4, float); //! PM4 ZNA +DECLARE_SOA_COLUMN(pmcZNC, ZNCcommonPM, float); //! PMC ZNC +DECLARE_SOA_COLUMN(pm1ZNC, ZNCPM1, float); //! PM1 ZNC +DECLARE_SOA_COLUMN(pm2ZNC, ZNCPM2, float); //! PM2 ZNC +DECLARE_SOA_COLUMN(pm3ZNC, ZNCPM3, float); //! PM3 ZNC +DECLARE_SOA_COLUMN(pm4ZNC, ZNCPM4, float); //! PM4 ZNC + +} // namespace znoutput + +DECLARE_SOA_TABLE(ZDCInterCalib, "AOD", "ZDCIC", o2::soa::Index<>, + znoutput::pmcZNA, + znoutput::pm1ZNA, + znoutput::pm2ZNA, + znoutput::pm3ZNA, + znoutput::pm4ZNA, + znoutput::pmcZNC, + znoutput::pm1ZNC, + znoutput::pm2ZNC, + znoutput::pm3ZNC, + znoutput::pm4ZNC); +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_ZDCINTERCALIB_H_ diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 7cd53628f18..1f8624206e6 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -112,3 +112,15 @@ o2physics_add_dpl_workflow(mftmchmatchingml O2::CCDB O2Physics::MLCore O2::ReconstructionDataFormats COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(match-mft-ft0 + SOURCES match-mft-ft0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + O2::ReconstructionDataFormats + O2::DetectorsBase O2::DetectorsCommonDataFormats + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(zdc-task-intercalib + SOURCES zdc-task-intercalib.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/Common/TableProducer/Converters/CMakeLists.txt b/Common/TableProducer/Converters/CMakeLists.txt index cbec8fc2d1e..e7b76fd1d42 100644 --- a/Common/TableProducer/Converters/CMakeLists.txt +++ b/Common/TableProducer/Converters/CMakeLists.txt @@ -39,11 +39,21 @@ o2physics_add_dpl_workflow(collision-converter PUBLIC_LINK_LIBRARIES COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(mccollision-converter + SOURCES mcCollisionConverter.cxx + PUBLIC_LINK_LIBRARIES + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(bc-converter SOURCES bcConverter.cxx PUBLIC_LINK_LIBRARIES O2::Framework COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(bc-flags-creator + SOURCES bcFlagsCreator.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(calo-label-converter SOURCES caloLabelConverter.cxx PUBLIC_LINK_LIBRARIES diff --git a/Common/TableProducer/Converters/bcFlagsCreator.cxx b/Common/TableProducer/Converters/bcFlagsCreator.cxx new file mode 100644 index 00000000000..8ac9d6e1516 --- /dev/null +++ b/Common/TableProducer/Converters/bcFlagsCreator.cxx @@ -0,0 +1,36 @@ +// Copyright 2019-2020 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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +using namespace o2; +using namespace o2::framework; + +// Creates an empty BCFlags for data that doesn't have it to be used seamlessly +// n.b. this will overwrite existing BCFlags, to be discussed if data in mixed condition +struct bcFlagsCreator { + Produces bcFlags; + + void process(aod::BCs const& bcTable) + { + for (auto& bc : bcTable) { + bcFlags(0); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGEM/PhotonMeson/TableProducer/converters/emeventsconverter.cxx b/Common/TableProducer/Converters/mcCollisionConverter.cxx similarity index 55% rename from PWGEM/PhotonMeson/TableProducer/converters/emeventsconverter.cxx rename to Common/TableProducer/Converters/mcCollisionConverter.cxx index ee3eca3e134..b965a092117 100644 --- a/PWGEM/PhotonMeson/TableProducer/converters/emeventsconverter.cxx +++ b/Common/TableProducer/Converters/mcCollisionConverter.cxx @@ -8,36 +8,28 @@ // 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. - #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" using namespace o2; using namespace o2::framework; -// Converts EMEvents version 000 to 001 -struct emeventsconverter { - Produces events_001; +struct mcCollisionConverter { + Produces mcCollisions_001; - void process(aod::EMEvents_000 const& events) + void process(aod::McCollisions_000 const& mcCollisionTable) { - for (auto& event : events) { - events_001( - event.collisionId(), - event.runNumber(), - 0, - event.sel8(), - event.alias_raw(), - event.selection_raw(), - 0, - event.ncollsPerBC(), - event.posX(), - event.posY(), - event.posZ(), - event.numContrib(), - 0 /*dummy occupancy value*/); + for (auto& mcCollision : mcCollisionTable) { + + // Repopulate new table + mcCollisions_001( + mcCollision.bcId(), + mcCollision.generatorsID(), + mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), + mcCollision.t(), mcCollision.weight(), + mcCollision.impactParameter(), + 0.0f); // dummy event plane, not available in _000 } } }; @@ -45,5 +37,6 @@ struct emeventsconverter { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"emevents-converter"})}; + adaptAnalysisTask(cfgc), + }; } diff --git a/Common/TableProducer/PID/pidTOFBase.cxx b/Common/TableProducer/PID/pidTOFBase.cxx index e82ea651304..f0f9722fc6b 100644 --- a/Common/TableProducer/PID/pidTOFBase.cxx +++ b/Common/TableProducer/PID/pidTOFBase.cxx @@ -46,16 +46,13 @@ float trackDistanceForGoodMatch = 999.f; float trackDistanceForGoodMatchLowMult = 999.f; int multiplicityThreshold = 0; using Run3Trks = o2::soa::Join; -using Run3Cols = o2::soa::Join; +using Run3Cols = aod::Collisions; bool isTrackGoodMatchForTOFPID(const Run3Trks::iterator& tr, const Run3Cols& /*ev*/) { if (!tr.hasTOF()) { return false; } - if (tr.has_collision() && tr.collision_as().multNTracksPVeta1() < multiplicityThreshold) { - return tr.tofChi2() < trackDistanceForGoodMatchLowMult; - } - return tr.tofChi2() < trackDistanceForGoodMatch; + return true; } /// Task to produce the TOF signal from the trackTime information diff --git a/Common/TableProducer/PID/pidTOFMerge.cxx b/Common/TableProducer/PID/pidTOFMerge.cxx index b6290e2ca8f..1dab71277ed 100644 --- a/Common/TableProducer/PID/pidTOFMerge.cxx +++ b/Common/TableProducer/PID/pidTOFMerge.cxx @@ -31,6 +31,7 @@ // O2Physics includes #include "TableHelper.h" #include "MetadataHelper.h" +#include "CollisionTypeHelper.h" #include "pidTOFBase.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" @@ -45,133 +46,224 @@ using namespace o2::track; MetadataHelper metadataInfo; +// Input data types +using Run3Trks = o2::soa::Join; +using Run3Cols = aod::Collisions; +using Run3TrksWtof = soa::Join; +using Run3TrksWtofWevTime = soa::Join; + +using EvTimeCollisions = soa::Join; +using EvTimeCollisionsFT0 = soa::Join; + +using Run2Trks = o2::soa::Join; +using Run2TrksWtofWevTime = soa::Join; + // Configuration common to all tasks -struct TOFCalibConfig : ConfigurableGroup { - Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; - Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; - Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; - Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; - Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; - - void inheritFromBaseTask(o2::framework::InitContext& initContext) +struct TOFCalibConfig { + template + void init(const CfgType& opt) { - if (!getTaskOptionValue(initContext, "tof-signal", "ccdb-url", url.value, true)) { - LOG(fatal) << "Could not get ccdb-url from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "ccdb-timestamp", timestamp.value, true)) { - LOG(fatal) << "Could not get ccdb-timestamp from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "paramFileName", paramFileName.value, true)) { - LOG(fatal) << "Could not get paramFileName from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "parametrizationPath", parametrizationPath.value, true)) { - LOG(fatal) << "Could not get parametrizationPath from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "passName", passName.value, true)) { - LOG(fatal) << "Could not get passName from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "timeShiftCCDBPath", timeShiftCCDBPath.value, true)) { - LOG(fatal) << "Could not get timeShiftCCDBPath from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "loadResponseFromCCDB", loadResponseFromCCDB.value, true)) { - LOG(fatal) << "Could not get loadResponseFromCCDB from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "fatalOnPassNotAvailable", fatalOnPassNotAvailable.value, true)) { - LOG(fatal) << "Could not get fatalOnPassNotAvailable from tof-signal task"; + mUrl = opt.cfgUrl.value; + mPathGrpLhcIf = opt.cfgPathGrpLhcIf.value; + mTimestamp = opt.cfgTimestamp.value; + mTimeShiftCCDBPathPos = opt.cfgTimeShiftCCDBPathPos.value; + mTimeShiftCCDBPathNeg = opt.cfgTimeShiftCCDBPathNeg.value; + mParamFileName = opt.cfgParamFileName.value; + mParametrizationPath = opt.cfgParametrizationPath.value; + mReconstructionPass = opt.cfgReconstructionPass.value; + mLoadResponseFromCCDB = opt.cfgLoadResponseFromCCDB.value; + mFatalOnPassNotAvailable = opt.cfgFatalOnPassNotAvailable.value; + mEnableTimeDependentResponse = opt.cfgEnableTimeDependentResponse.value; + mCollisionSystem = opt.cfgCollisionSystem.value; + mAutoSetProcessFunctions = opt.cfgAutoSetProcessFunctions.value; + } + + template + void getCfg(o2::framework::InitContext& initContext, const std::string name, VType& v, const std::string task) + { + if (!getTaskOptionValue(initContext, task, name, v, true)) { + LOG(fatal) << "Could not get " << name << " from " << task << " task"; } } + void inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string task = "tof-signal") + { + mInitMode = 2; + getCfg(initContext, "ccdb-url", mUrl, task); + getCfg(initContext, "ccdb-path-grplhcif", mPathGrpLhcIf, task); + getCfg(initContext, "ccdb-timestamp", mTimestamp, task); + getCfg(initContext, "timeShiftCCDBPathPos", mTimeShiftCCDBPathPos, task); + getCfg(initContext, "timeShiftCCDBPathNeg", mTimeShiftCCDBPathPos, task); + getCfg(initContext, "paramFileName", mParamFileName, task); + getCfg(initContext, "parametrizationPath", mParametrizationPath, task); + getCfg(initContext, "reconstructionPass", mReconstructionPass, task); + getCfg(initContext, "loadResponseFromCCDB", mLoadResponseFromCCDB, task); + getCfg(initContext, "fatalOnPassNotAvailable", mFatalOnPassNotAvailable, task); + getCfg(initContext, "enableTimeDependentResponse", mEnableTimeDependentResponse, task); + getCfg(initContext, "collisionSystem", mCollisionSystem, task); + getCfg(initContext, "autoSetProcessFunctions", mAutoSetProcessFunctions, task); + } + // @brief Set up the configuration from the calibration object from the init function of the task template - void setUp(o2::pid::tof::TOFResoParamsV3& mRespParamsV3, CCDBObject ccdb) + void initSetup(o2::pid::tof::TOFResoParamsV3& mRespParamsV3, + CCDBObject ccdb) { + mInitMode = 1; // First we set the CCDB manager - ccdb->setURL(url.value); - ccdb->setTimestamp(timestamp.value); + ccdb->setURL(mUrl); + ccdb->setTimestamp(mTimestamp); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); // Not later than now objects ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); // Then the information about the metadata - if (passName.value == "metadata") { + if (mReconstructionPass == "metadata") { LOG(info) << "Getting pass from metadata"; if (metadataInfo.isMC()) { - passName.value = metadataInfo.get("AnchorPassName"); + mReconstructionPass = metadataInfo.get("AnchorPassName"); } else { - passName.value = metadataInfo.get("RecoPassName"); + mReconstructionPass = metadataInfo.get("RecoPassName"); } - LOG(info) << "Passed autodetect mode for pass. Taking '" << passName.value << "'"; + LOG(info) << "Passed autodetect mode for pass. Taking '" << mReconstructionPass << "'"; } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; + LOG(info) << "Using parameter collection, starting from pass '" << mReconstructionPass << "'"; - const std::string fname = paramFileName.value; + const std::string fname = mParamFileName; if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; + LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << mParametrizationPath; if (1) { o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); + paramCollection.loadParamFromFile(fname, mParametrizationPath); LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV3, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + if (!paramCollection.retrieveParameters(mRespParamsV3, mReconstructionPass)) { + if (mFatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); } } else { - mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(passName.value)); + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPass)); mRespParamsV3.printMomentumChargeShiftParameters(); } } else { - mRespParamsV3.loadParamFromFile(fname.data(), parametrizationPath.value); + mRespParamsV3.loadParamFromFile(fname.data(), mParametrizationPath); } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->template getForTimeStamp(parametrizationPath.value, timestamp.value); + } else if (mLoadResponseFromCCDB) { // Loading it from CCDB + LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << mParametrizationPath << " for timestamp " << mTimestamp; + o2::tof::ParameterCollection* paramCollection = ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp); paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV3, passName.value)) { // Attempt at loading the parameters with the pass defined - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPass)) { // Attempt at loading the parameters with the pass defined + if (mFatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); } } else { // Pass is available, load non standard parameters - mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(passName.value)); + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPass)); mRespParamsV3.printMomentumChargeShiftParameters(); } } + // Calibration object is defined mRespParamsV3.print(); - if (timeShiftCCDBPath.value != "") { - if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV3.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV3.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); + + // Loading additional calibration objects + if (mTimeShiftCCDBPathPos != "") { + if (mTimeShiftCCDBPathPos.find(".root") != std::string::npos) { + mRespParamsV3.setTimeShiftParameters(mTimeShiftCCDBPathPos, "ccdb_object", true); + } else { + if (mReconstructionPass == "") { + mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(mTimeShiftCCDBPathPos, mTimestamp), true); + } else { + std::map metadata; + metadata["RecoPassName"] = mReconstructionPass; + mRespParamsV3.setTimeShiftParameters(ccdb->template getSpecific(mTimeShiftCCDBPathPos, mTimestamp, metadata), true); + } + } + } + if (mTimeShiftCCDBPathNeg != "") { + if (mTimeShiftCCDBPathNeg.find(".root") != std::string::npos) { + mRespParamsV3.setTimeShiftParameters(mTimeShiftCCDBPathNeg, "ccdb_object", false); } else { - mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); - mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); + if (mReconstructionPass == "") { + mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(mTimeShiftCCDBPathNeg, mTimestamp), false); + } else { + std::map metadata; + metadata["RecoPassName"] = mReconstructionPass; + mRespParamsV3.setTimeShiftParameters(ccdb->template getSpecific(mTimeShiftCCDBPathNeg, mTimestamp, metadata), false); + } } } } + + template + void processSetup(o2::pid::tof::TOFResoParamsV3& mRespParamsV3, + CCDBObject ccdb, + const BcType& bc) + { + LOG(debug) << "Processing setup for run number " << bc.runNumber() << " from run " << mLastRunNumber; + // First we check if this run number was already processed + if (mLastRunNumber == bc.runNumber()) { + return; + } + mLastRunNumber = bc.runNumber(); + mTimestamp = bc.timestamp(); + + // Check the beam type + o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp(mPathGrpLhcIf, + mTimestamp); + if (mCollisionSystem == -1) { + mCollisionSystem = CollisionSystemType::getCollisionTypeFromGrp(grpo); + } else { + LOG(debug) << "Not setting collisions system as already set to " << mCollisionSystem << " " << CollisionSystemType::getCollisionSystemName(mCollisionSystem); + } + + if (!mEnableTimeDependentResponse) { + return; + } + LOG(debug) << "Updating parametrization from path '" << mParametrizationPath << "' and timestamp " << mTimestamp; + if (!ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp)->retrieveParameters(mRespParamsV3, mReconstructionPass)) { + if (mFatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + } + } + return; + } + + bool autoSetProcessFunctions() const { return mAutoSetProcessFunctions; } + int collisionSystem() const { return mCollisionSystem; } + + private: + int mLastRunNumber = -1; // Last run number for which the calibration was loaded + int mInitMode = 0; // 0: no init, 1: init, 2: inherit + + // Configurable options + std::string mUrl; + std::string mPathGrpLhcIf; + int64_t mTimestamp; + std::string mTimeShiftCCDBPathPos; + std::string mTimeShiftCCDBPathNeg; + std::string mParamFileName; + std::string mParametrizationPath; + std::string mReconstructionPass; + bool mLoadResponseFromCCDB; + bool mFatalOnPassNotAvailable; + bool mEnableTimeDependentResponse; + int mCollisionSystem; + bool mAutoSetProcessFunctions; }; // Part 1 TOF signal definition /// Selection criteria for tracks used for TOF event time -float trackDistanceForGoodMatch = 999.f; -float trackDistanceForGoodMatchLowMult = 999.f; -int multiplicityThreshold = 0; -using Run3Trks = o2::soa::Join; -using Run3Cols = o2::soa::Join; -bool isTrackGoodMatchForTOFPID(const Run3Trks::iterator& tr, const Run3Cols& /*ev*/) +bool isTrackGoodMatchForTOFPID(const Run3Trks::iterator& tr) { if (!tr.hasTOF()) { return false; } - if (tr.has_collision() && tr.collision_as().multNTracksPVeta1() < multiplicityThreshold) { - return tr.tofChi2() < trackDistanceForGoodMatchLowMult; - } - return tr.tofChi2() < trackDistanceForGoodMatch; + return true; } /// Task to produce the TOF signal from the trackTime information @@ -182,16 +274,33 @@ struct tofSignal { // Running flags bool enableTableTOFSignal = false; // Flag to check if the TOF signal table is requested or not bool enableTablepidTOFFlags = false; // Flag to check if the TOF signal flags table is requested or not - TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration - Configurable distanceForGoodMatch{"distanceForGoodMatch", 999.f, "Maximum distance to consider a good match"}; - Configurable distanceForGoodMatchLowMult{"distanceForGoodMatchLowMult", 999.f, "Maximum distance to consider a good match for low multiplicity events"}; - Configurable multThreshold{"multThreshold", 0, "Multiplicity threshold to consider a low multiplicity event"}; // Output histograms Configurable enableQaHistograms{"enableQaHistograms", false, "Flag to enable the QA histograms"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // Detector response and input parameters + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + Service ccdb; + struct : ConfigurableGroup { + Configurable cfgUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfgPathGrpLhcIf{"ccdb-path-grplhcif", "GLO/Config/GRPLHCIF", "Path on the CCDB for the GRPLHCIF object"}; + Configurable cfgTimestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + Configurable cfgTimeShiftCCDBPathPos{"timeShiftCCDBPathPos", "", "Path of the TOF time shift vs eta for pos. tracks. If empty none is taken"}; + Configurable cfgTimeShiftCCDBPathNeg{"timeShiftCCDBPathNeg", "", "Path of the TOF time shift vs eta for neg. tracks. If empty none is taken"}; + Configurable cfgParamFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; + Configurable cfgParametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; + Configurable cfgReconstructionPass{"reconstructionPass", "", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}}; + Configurable cfgLoadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; + Configurable cfgFatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; + Configurable cfgEnableTimeDependentResponse{"enableTimeDependentResponse", false, "Flag to use the collision timestamp to fetch the PID Response"}; + Configurable cfgCollisionSystem{"collisionSystem", -1, "Collision system: -1 (autoset), 0 (pp), 1 (PbPb), 2 (XeXe), 3 (pPb)"}; + Configurable cfgAutoSetProcessFunctions{"autoSetProcessFunctions", true, "Flag to autodetect the process functions to use"}; + } cfg; // Configurables (only defined here and inherited from other tasks) + + TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration void init(o2::framework::InitContext& initContext) { + mTOFCalibConfig.init(cfg); // Checking that the table is requested in the workflow and enabling it enableTableTOFSignal = isTableRequiredInWorkflow(initContext, "TOFSignal"); if (enableTableTOFSignal) { @@ -207,11 +316,14 @@ struct tofSignal { LOG(info) << "No table or process is enabled. Disabling task"; return; } - if (metadataInfo.isFullyDefined() && !doprocessRun2 && !doprocessRun3) { // Check if the metadata is initialized (only if not forced from the workflow configuration) - if (metadataInfo.isRun3()) { - doprocessRun3.value = true; - } else { - doprocessRun2.value = false; + if (mTOFCalibConfig.autoSetProcessFunctions()) { + LOG(info) << "Autodetecting process functions"; + if (metadataInfo.isFullyDefined() && !doprocessRun2 && !doprocessRun3) { // Check if the metadata is initialized (only if not forced from the workflow configuration) + if (metadataInfo.isRun3()) { + doprocessRun3.value = true; + } else { + doprocessRun2.value = false; + } } } @@ -222,11 +334,7 @@ struct tofSignal { if (!doprocessRun2 && !doprocessRun3) { LOG(fatal) << "Neither processRun2 nor processRun3 are enabled. Pick one of the two"; } - - trackDistanceForGoodMatch = distanceForGoodMatch; - trackDistanceForGoodMatchLowMult = distanceForGoodMatchLowMult; - multiplicityThreshold = multThreshold; - LOG(info) << "Configuring selections for good match: " << trackDistanceForGoodMatch << " low mult " << trackDistanceForGoodMatchLowMult << " mult. threshold " << multiplicityThreshold; + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); // Getting the parametrization parameters if (!enableQaHistograms) { return; } @@ -239,7 +347,7 @@ struct tofSignal { /// Dummy process function for BCs, needed in case both Run2 and Run3 process functions are disabled void process(aod::BCs const&) {} - void processRun3(Run3Trks const& tracks, Run3Cols const& collisions) + void processRun3(Run3Trks const& tracks) { if (!enableTableTOFSignal) { return; @@ -248,26 +356,25 @@ struct tofSignal { if (enableTablepidTOFFlags) { tableFlags.reserve(tracks.size()); } - for (auto& t : tracks) { - const auto s = o2::pid::tof::TOFSignal::GetTOFSignal(t); + for (auto& trk : tracks) { + const float& sig = o2::pid::tof::TOFSignal::GetTOFSignal(trk); if (enableQaHistograms) { - histos.fill(HIST("tofSignal"), s); + histos.fill(HIST("tofSignal"), sig); } - table(s); + table(sig); if (!enableTablepidTOFFlags) { continue; } - const auto b = isTrackGoodMatchForTOFPID(t, collisions); + const auto& b = isTrackGoodMatchForTOFPID(trk); if (enableQaHistograms) { - histos.fill(HIST("goodForPIDFlags"), s); + histos.fill(HIST("goodForPIDFlags"), sig); } tableFlags(b); } } PROCESS_SWITCH(tofSignal, processRun3, "Process Run3 data i.e. input is TrackIU. Set to false to autodetect from metadata.", false); - using TrksRun2 = o2::soa::Join; - void processRun2(TrksRun2 const& tracks) + void processRun2(Run2Trks const& tracks) { if (!enableTableTOFSignal) { return; @@ -276,8 +383,8 @@ struct tofSignal { if (enableTablepidTOFFlags) { tableFlags.reserve(tracks.size()); } - for (auto& t : tracks) { - table(o2::pid::tof::TOFSignal::GetTOFSignal(t)); + for (auto& trk : tracks) { + table(o2::pid::tof::TOFSignal::GetTOFSignal(trk)); if (!enableTablepidTOFFlags) { continue; } @@ -293,7 +400,11 @@ float trackSampleMaxMomentum = 2.f; template bool filterForTOFEventTime(const trackType& tr) { - return (tr.hasTOF() && tr.p() > trackSampleMinMomentum && tr.p() < trackSampleMaxMomentum && (tr.trackType() == o2::aod::track::TrackTypeEnum::Track || tr.trackType() == o2::aod::track::TrackTypeEnum::TrackIU)); + return (tr.hasTOF() && + tr.p() > trackSampleMinMomentum && tr.p() < trackSampleMaxMomentum && + tr.hasITS() && + tr.hasTPC() && + (tr.trackType() == o2::aod::track::TrackTypeEnum::Track || tr.trackType() == o2::aod::track::TrackTypeEnum::TrackIU)); } // accept all /// Specialization of TOF event time maker @@ -334,10 +445,13 @@ struct tofEventTime { Configurable maxMomentum{"maxMomentum", 2.0f, "Maximum momentum to select track sample for TOF event time"}; Configurable maxEvTimeTOF{"maxEvTimeTOF", 100000.0f, "Maximum value of the TOF event time"}; Configurable sel8TOFEvTime{"sel8TOFEvTime", false, "Flag to compute the ev. time only for events that pass the sel8 ev. selection"}; + Configurable mComputeEvTimeWithTOF{"computeEvTimeWithTOF", -1, "Compute ev. time with TOF. -1 (autoset), 0 no, 1 yes"}; + Configurable mComputeEvTimeWithFT0{"computeEvTimeWithFT0", -1, "Compute ev. time with FT0. -1 (autoset), 0 no, 1 yes"}; Configurable maxNtracksInSet{"maxNtracksInSet", 10, "Size of the set to consider for the TOF ev. time computation"}; void init(o2::framework::InitContext& initContext) { + mTOFCalibConfig.inheritFromBaseTask(initContext); // Checking that the table is requested in the workflow and enabling it enableTableTOFEvTime = isTableRequiredInWorkflow(initContext, "TOFEvTime"); @@ -356,8 +470,24 @@ struct tofEventTime { return; } - if (metadataInfo.isFullyDefined() && metadataInfo.isRun3() && doprocessRun2) { - LOG(fatal) << "Run2 process function is enabled but the metadata says it is Run3"; + if (mTOFCalibConfig.autoSetProcessFunctions()) { + LOG(info) << "Autodetecting process functions"; + if (metadataInfo.isFullyDefined()) { + if (metadataInfo.isRun3()) { + doprocessRun3.value = true; + } else { + doprocessRun2.value = true; + } + } + } + + if (metadataInfo.isFullyDefined()) { + if (metadataInfo.isRun3() && doprocessRun2) { + LOG(fatal) << "Run2 process function is enabled but the metadata says it is Run3"; + } + if (!metadataInfo.isRun3() && doprocessRun3) { + LOG(fatal) << "Run3 process function is enabled but the metadata says it is Run2"; + } } trackSampleMinMomentum = minMomentum; @@ -369,16 +499,8 @@ struct tofEventTime { LOGF(info, "Enabling process function: processRun2"); nEnabled++; } - if (doprocessNoFT0 == true) { - LOGF(info, "Enabling process function: processNoFT0"); - nEnabled++; - } - if (doprocessFT0 == true) { - LOGF(info, "Enabling process function: processFT0"); - nEnabled++; - } - if (doprocessOnlyFT0 == true) { - LOGF(info, "Enabling process function: processOnlyFT0"); + if (doprocessRun3 == true) { + LOGF(info, "Enabling process function: processRun3"); nEnabled++; } if (nEnabled > 1) { @@ -388,7 +510,7 @@ struct tofEventTime { if (sel8TOFEvTime.value == true) { LOG(info) << "TOF event time will be computed for collisions that pass the event selection only!"; } - mTOFCalibConfig.setUp(mRespParamsV3, ccdb); // Getting the parametrization parameters + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); // Getting the parametrization parameters o2::tof::eventTimeContainer::setMaxNtracksInSet(maxNtracksInSet.value); o2::tof::eventTimeContainer::printConfig(); @@ -418,210 +540,213 @@ struct tofEventTime { tableEvTime(t.collision().collisionTime() * 1000.f, t.collision().collisionTimeRes() * 1000.f); } } - PROCESS_SWITCH(tofEventTime, processRun2, "Process with Run2 data", false); + PROCESS_SWITCH(tofEventTime, processRun2, "Process with Run2 data", true); /// /// Process function to prepare the event for each track on Run 3 data without the FT0 - using TrksEvTime = soa::Join; // Define slice per collision - Preslice perCollision = aod::track::collisionId; + Preslice perCollision = aod::track::collisionId; template - using ResponseImplementationEvTime = o2::pid::tof::ExpTimes; - using EvTimeCollisions = soa::Join; - void processNoFT0(TrksEvTime const& tracks, - EvTimeCollisions const&) + using ResponseImplementationEvTime = o2::pid::tof::ExpTimes; + void processRun3(Run3TrksWtof& tracks, + aod::FT0s const&, + EvTimeCollisionsFT0 const&, + aod::BCsWithTimestamps const&) { if (!enableTableTOFEvTime) { return; } + LOG(debug) << "Processing Run3 data for TOF event time"; tableEvTime.reserve(tracks.size()); tableFlags.reserve(tracks.size()); if (enableTableEvTimeTOFOnly) { tableEvTimeTOFOnly.reserve(tracks.size()); } - - int lastCollisionId = -1; // Last collision ID analysed - for (auto const& t : tracks) { // Loop on collisions - if (!t.has_collision() || ((sel8TOFEvTime.value == true) && !t.collision_as().sel8())) { // Track was not assigned, cannot compute event time or event did not pass the event selection - tableFlags(0); - tableEvTime(0.f, 999.f); - if (enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly((uint8_t)0, 0.f, 0.f, -1); - } + bool calibUpdated = false; + for (auto const& track : tracks) { // Loop on all tracks + if (!track.has_collision()) { // Skipping tracks without collisions continue; } - if (t.collisionId() == lastCollisionId) { // Event time from this collision is already in the table + const auto& coll = track.collision_as(); + if (!coll.has_bc()) { continue; } - /// Create new table for the tracks in a collision - lastCollisionId = t.collisionId(); /// Cache last collision ID - - const auto& tracksInCollision = tracks.sliceBy(perCollision, lastCollisionId); - - // First make table for event time - const auto evTimeTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV3, diamond); - int nGoodTracksForTOF = 0; - float et = evTimeTOF.mEventTime; - float erret = evTimeTOF.mEventTimeError; + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, coll.bc_as()); // Update the calibration parameters + calibUpdated = true; + break; + } - for (auto const& trk : tracksInCollision) { // Loop on Tracks - if constexpr (removeTOFEvTimeBias) { - evTimeTOF.removeBias(trk, nGoodTracksForTOF, et, erret, 2); - } - uint8_t flags = 0; - if (erret < errDiamond && (maxEvTimeTOF <= 0.f || abs(et) < maxEvTimeTOF)) { - flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeTOF; - } else { - et = 0.f; - erret = errDiamond; - } - tableFlags(flags); - tableEvTime(et, erret); - if (enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly((uint8_t)filterForTOFEventTime(trk), et, erret, evTimeTOF.mEventTimeMultiplicity); + // Autoset the processing mode for the event time computation + if (calibUpdated) { + if (mComputeEvTimeWithTOF == -1 || mComputeEvTimeWithFT0 == -1) { + switch (mTOFCalibConfig.collisionSystem()) { + case CollisionSystemType::kCollSyspp: // pp + mComputeEvTimeWithTOF.value = ((mComputeEvTimeWithTOF == -1) ? 0 : mComputeEvTimeWithTOF.value); + mComputeEvTimeWithFT0.value = ((mComputeEvTimeWithFT0 == -1) ? 1 : mComputeEvTimeWithFT0.value); + break; + case CollisionSystemType::kCollSysPbPb: // PbPb + mComputeEvTimeWithTOF.value = ((mComputeEvTimeWithTOF == -1) ? 1 : mComputeEvTimeWithTOF.value); + mComputeEvTimeWithFT0.value = ((mComputeEvTimeWithFT0 == -1) ? 0 : mComputeEvTimeWithFT0.value); + break; + default: + LOG(fatal) << "Collision system " << mTOFCalibConfig.collisionSystem() << " " << CollisionSystemType::getCollisionSystemName(mTOFCalibConfig.collisionSystem()) << " not supported for TOF event time computation"; + break; } } + } else { + LOG(warning) << "Calibration not updated on " << tracks.size() << " tracks !!"; } - } - PROCESS_SWITCH(tofEventTime, processNoFT0, "Process without FT0", false); + LOG(debug) << "Running on " << CollisionSystemType::getCollisionSystemName(mTOFCalibConfig.collisionSystem()) << " mComputeEvTimeWithTOF " << mComputeEvTimeWithTOF.value << " mComputeEvTimeWithFT0 " << mComputeEvTimeWithFT0.value; - /// - /// Process function to prepare the event for each track on Run 3 data with the FT0 - using EvTimeCollisionsFT0 = soa::Join; - void processFT0(TrksEvTime& tracks, - aod::FT0s const&, - EvTimeCollisionsFT0 const&) - { - if (!enableTableTOFEvTime) { - return; - } - - tableEvTime.reserve(tracks.size()); - tableFlags.reserve(tracks.size()); - if (enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly.reserve(tracks.size()); - } - - int lastCollisionId = -1; // Last collision ID analysed - for (auto const& t : tracks) { // Loop on collisions - if (!t.has_collision() || ((sel8TOFEvTime.value == true) && !t.collision_as().sel8())) { // Track was not assigned, cannot compute event time or event did not pass the event selection - tableFlags(0); - tableEvTime(0.f, 999.f); - if (enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly((uint8_t)0, 0.f, 0.f, -1); + if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 1) { + int lastCollisionId = -1; // Last collision ID analysed + for (auto const& t : tracks) { // Loop on collisions + if (!t.has_collision() || ((sel8TOFEvTime.value == true) && !t.collision_as().sel8())) { // Track was not assigned, cannot compute event time or event did not pass the event selection + tableFlags(0); + tableEvTime(0.f, 999.f); + if (enableTableEvTimeTOFOnly) { + tableEvTimeTOFOnly((uint8_t)0, 0.f, 0.f, -1); + } + continue; } - continue; - } - if (t.collisionId() == lastCollisionId) { // Event time from this collision is already in the table - continue; - } - /// Create new table for the tracks in a collision - lastCollisionId = t.collisionId(); /// Cache last collision ID - - const auto& tracksInCollision = tracks.sliceBy(perCollision, lastCollisionId); - const auto& collision = t.collision_as(); - - // Compute the TOF event time - const auto evTimeTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV3, diamond); - - float t0AC[2] = {.0f, 999.f}; // Value and error of T0A or T0C or T0AC - float t0TOF[2] = {static_cast(evTimeTOF.mEventTime), static_cast(evTimeTOF.mEventTimeError)}; // Value and error of TOF - - uint8_t flags = 0; - int nGoodTracksForTOF = 0; - float eventTime = 0.f; - float sumOfWeights = 0.f; - float weight = 0.f; - - for (auto const& trk : tracksInCollision) { // Loop on Tracks - // Reset the flag - flags = 0; - // Reset the event time - eventTime = 0.f; - sumOfWeights = 0.f; - weight = 0.f; - // Remove the bias on TOF ev. time - if constexpr (removeTOFEvTimeBias) { - evTimeTOF.removeBias(trk, nGoodTracksForTOF, t0TOF[0], t0TOF[1], 2); + if (t.collisionId() == lastCollisionId) { // Event time from this collision is already in the table + continue; } - if (t0TOF[1] < errDiamond && (maxEvTimeTOF <= 0 || abs(t0TOF[0]) < maxEvTimeTOF)) { - flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeTOF; + /// Create new table for the tracks in a collision + lastCollisionId = t.collisionId(); /// Cache last collision ID - weight = 1.f / (t0TOF[1] * t0TOF[1]); - eventTime += t0TOF[0] * weight; - sumOfWeights += weight; - } + const auto& tracksInCollision = tracks.sliceBy(perCollision, lastCollisionId); + const auto& collision = t.collision_as(); - if (collision.has_foundFT0()) { // T0 measurement is available - // const auto& ft0 = collision.foundFT0(); - if (collision.t0ACValid()) { - t0AC[0] = collision.t0AC() * 1000.f; - t0AC[1] = collision.t0resolution() * 1000.f; - flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC; + // Compute the TOF event time + const auto evTimeMakerTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV3, diamond); + + float t0AC[2] = {.0f, 999.f}; // Value and error of T0A or T0C or T0AC + float t0TOF[2] = {static_cast(evTimeMakerTOF.mEventTime), static_cast(evTimeMakerTOF.mEventTimeError)}; // Value and error of TOF + + uint8_t flags = 0; + int nGoodTracksForTOF = 0; + float eventTime = 0.f; + float sumOfWeights = 0.f; + float weight = 0.f; + + for (auto const& trk : tracksInCollision) { // Loop on Tracks + // Reset the flag + flags = 0; + // Reset the event time + eventTime = 0.f; + sumOfWeights = 0.f; + weight = 0.f; + // Remove the bias on TOF ev. time + if constexpr (removeTOFEvTimeBias) { + evTimeMakerTOF.removeBias(trk, nGoodTracksForTOF, t0TOF[0], t0TOF[1], 2); } + if (t0TOF[1] < errDiamond && (maxEvTimeTOF <= 0 || abs(t0TOF[0]) < maxEvTimeTOF)) { + flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeTOF; - weight = 1.f / (t0AC[1] * t0AC[1]); - eventTime += t0AC[0] * weight; - sumOfWeights += weight; - } + weight = 1.f / (t0TOF[1] * t0TOF[1]); + eventTime += t0TOF[0] * weight; + sumOfWeights += weight; + } + + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + t0AC[0] = collision.t0AC() * 1000.f; + t0AC[1] = collision.t0resolution() * 1000.f; + flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC; + } + + weight = 1.f / (t0AC[1] * t0AC[1]); + eventTime += t0AC[0] * weight; + sumOfWeights += weight; + } - if (sumOfWeights < weightDiamond) { // avoiding sumOfWeights = 0 or worse that diamond - eventTime = 0; - sumOfWeights = weightDiamond; + if (sumOfWeights < weightDiamond) { // avoiding sumOfWeights = 0 or worse that diamond + eventTime = 0; + sumOfWeights = weightDiamond; + tableFlags(0); + } else { + tableFlags(flags); + } + tableEvTime(eventTime / sumOfWeights, sqrt(1. / sumOfWeights)); + if (enableTableEvTimeTOFOnly) { + tableEvTimeTOFOnly((uint8_t)filterForTOFEventTime(trk), t0TOF[0], t0TOF[1], evTimeMakerTOF.mEventTimeMultiplicity); + } + } + } + } else if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 0) { + int lastCollisionId = -1; // Last collision ID analysed + for (auto const& t : tracks) { // Loop on collisions + if (!t.has_collision() || ((sel8TOFEvTime.value == true) && !t.collision_as().sel8())) { // Track was not assigned, cannot compute event time or event did not pass the event selection tableFlags(0); - } else { - tableFlags(flags); + tableEvTime(0.f, 999.f); + if (enableTableEvTimeTOFOnly) { + tableEvTimeTOFOnly((uint8_t)0, 0.f, 0.f, -1); + } + continue; } - tableEvTime(eventTime / sumOfWeights, sqrt(1. / sumOfWeights)); - if (enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly((uint8_t)filterForTOFEventTime(trk), t0TOF[0], t0TOF[1], evTimeTOF.mEventTimeMultiplicity); + if (t.collisionId() == lastCollisionId) { // Event time from this collision is already in the table + continue; } - } - } - } - PROCESS_SWITCH(tofEventTime, processFT0, "Process with FT0", false); + /// Create new table for the tracks in a collision + lastCollisionId = t.collisionId(); /// Cache last collision ID - /// - /// Process function to prepare the event for each track on Run 3 data with only the FT0 - void processOnlyFT0(TrksEvTime& tracks, - aod::FT0s const&, - EvTimeCollisionsFT0 const&) - { - if (!enableTableTOFEvTime) { - return; - } + const auto& tracksInCollision = tracks.sliceBy(perCollision, lastCollisionId); - tableEvTime.reserve(tracks.size()); - tableFlags.reserve(tracks.size()); - if (!enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly.reserve(tracks.size()); - } + // First make table for event time + const auto evTimeMakerTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV3, diamond); + int nGoodTracksForTOF = 0; + float et = evTimeMakerTOF.mEventTime; + float erret = evTimeMakerTOF.mEventTimeError; - for (auto const& t : tracks) { // Loop on collisions - if (enableTableEvTimeTOFOnly) { - tableEvTimeTOFOnly((uint8_t)0, 0.f, 0.f, -1); - } - if (!t.has_collision()) { // Track was not assigned, cannot compute event time - tableFlags(0); - tableEvTime(0.f, 999.f); - continue; + for (auto const& trk : tracksInCollision) { // Loop on Tracks + if constexpr (removeTOFEvTimeBias) { + evTimeMakerTOF.removeBias(trk, nGoodTracksForTOF, et, erret, 2); + } + uint8_t flags = 0; + if (erret < errDiamond && (maxEvTimeTOF <= 0.f || abs(et) < maxEvTimeTOF)) { + flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeTOF; + } else { + et = 0.f; + erret = errDiamond; + } + tableFlags(flags); + tableEvTime(et, erret); + if (enableTableEvTimeTOFOnly) { + tableEvTimeTOFOnly((uint8_t)filterForTOFEventTime(trk), et, erret, evTimeMakerTOF.mEventTimeMultiplicity); + } + } } - const auto& collision = t.collision_as(); - - if (collision.has_foundFT0()) { // T0 measurement is available - // const auto& ft0 = collision.foundFT0(); - if (collision.t0ACValid()) { - tableFlags(o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC); - tableEvTime(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + } else if (mComputeEvTimeWithTOF == 0 && mComputeEvTimeWithFT0 == 1) { + for (auto const& t : tracks) { // Loop on collisions + if (enableTableEvTimeTOFOnly) { + tableEvTimeTOFOnly((uint8_t)0, 0.f, 0.f, -1); + } + if (!t.has_collision()) { // Track was not assigned, cannot compute event time + tableFlags(0); + tableEvTime(0.f, 999.f); continue; } + const auto& collision = t.collision_as(); + + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + tableFlags(o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC); + tableEvTime(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + continue; + } + } + tableFlags(0); + tableEvTime(0.f, 999.f); } - tableFlags(0); - tableEvTime(0.f, 999.f); + } else { + LOG(fatal) << "Invalid configuration for TOF event time computation"; } } - PROCESS_SWITCH(tofEventTime, processOnlyFT0, "Process only with FT0", false); + PROCESS_SWITCH(tofEventTime, processRun3, "Process the Run3 data", true); }; // Part 3 Nsigma computation @@ -676,9 +801,7 @@ struct tofPidMerge { o2::pid::tof::TOFResoParamsV3 mRespParamsV3; Service ccdb; TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration - // Configurable inheritFromBaseTask{"inheritFromBaseTask", true, "Flag to iherit all common configurables from the TOF base task"}; Configurable enableQaHistograms{"enableQaHistograms", false, "Flag to enable the QA histograms"}; - Configurable enableTimeDependentResponse{"enableTimeDependentResponse", false, "Flag to use the collision timestamp to fetch the PID Response"}; // Configuration flags to include and exclude particle hypotheses Configurable> enableParticle{"enableParticle", @@ -696,6 +819,7 @@ struct tofPidMerge { std::vector mEnabledParticlesFull; // Vector of enabled PID hypotheses to loop on when making full tables void init(o2::framework::InitContext& initContext) { + mTOFCalibConfig.inheritFromBaseTask(initContext); // Checking the tables are requested in the workflow and enabling them for (int i = 0; i < nSpecies; i++) { // First checking tiny @@ -714,10 +838,24 @@ struct tofPidMerge { } if (mEnabledParticlesFull.size() == 0 && mEnabledParticles.size() == 0) { LOG(info) << "No PID tables are required, disabling the task"; - doprocessData.value = false; + doprocessRun3.value = false; + doprocessRun2.value = false; return; + } else if (doprocessRun3.value == false && doprocessRun2.value == false) { + LOG(fatal) << "PID tables are required but process data is disabled. Please enable it"; + } + if (doprocessRun3.value == true && doprocessRun2.value == true) { + LOG(fatal) << "Both processRun2 and processRun3 are enabled. Pick one of the two"; + } + if (metadataInfo.isFullyDefined()) { + if (metadataInfo.isRun3() && doprocessRun2) { + LOG(fatal) << "Run2 process function is enabled but the metadata says it is Run3"; + } + if (!metadataInfo.isRun3() && doprocessRun3) { + LOG(fatal) << "Run3 process function is enabled but the metadata says it is Run2"; + } } - mTOFCalibConfig.setUp(mRespParamsV3, ccdb); // Getting the parametrization parameters + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); // Getting the parametrization parameters // Printing enabled tables and enabling QA histograms if needed LOG(info) << "++ Enabled tables:"; @@ -905,10 +1043,11 @@ struct tofPidMerge { void process(aod::BCs const&) {} - using Trks = soa::Join; template - using ResponseImplementation = o2::pid::tof::ExpTimes; - void processData(Trks const& tracks, aod::Collisions const&, aod::BCsWithTimestamps const&) + using ResponseImplementation = o2::pid::tof::ExpTimes; + void processRun3(Run3TrksWtofWevTime const& tracks, + Run3Cols const&, + aod::BCsWithTimestamps const&) { constexpr auto responseEl = ResponseImplementation(); constexpr auto responseMu = ResponseImplementation(); @@ -924,17 +1063,183 @@ struct tofPidMerge { if (!track.has_collision()) { // Skipping tracks without collisions continue; } - mTOFCalibConfig.timestamp.value = track.collision().bc_as().timestamp(); - if (enableTimeDependentResponse) { - LOG(debug) << "Updating parametrization from path '" << mTOFCalibConfig.parametrizationPath.value << "' and timestamp " << mTOFCalibConfig.timestamp.value; - if (!ccdb->getForTimeStamp(mTOFCalibConfig.parametrizationPath.value, mTOFCalibConfig.timestamp.value)->retrieveParameters(mRespParamsV3, mTOFCalibConfig.passName.value)) { - if (mTOFCalibConfig.fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mTOFCalibConfig.passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mTOFCalibConfig.passName.value.data()); + const auto& coll = track.collision(); + if (!coll.has_bc()) { + continue; + } + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, coll.bc_as()); // Update the calibration parameters + break; + } + + for (auto const& pidId : mEnabledParticles) { + reserveTable(pidId, tracks.size(), false); + } + + for (auto const& pidId : mEnabledParticlesFull) { + reserveTable(pidId, tracks.size(), true); + } + + float resolution = 1.f; // Last resolution assigned + float nsigma = 0; + for (auto const& trk : tracks) { // Loop on all tracks + if (!trk.has_collision()) { // Track was not assigned, cannot compute NSigma (no event time) -> filling with empty table + for (auto const& pidId : mEnabledParticles) { + makeTableEmpty(pidId, false); + } + for (auto const& pidId : mEnabledParticlesFull) { + makeTableEmpty(pidId, true); + } + continue; + } + + for (auto const& pidId : mEnabledParticles) { // Loop on enabled particle hypotheses + switch (pidId) { + case idxEl: { + nsigma = responseEl.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDEl); + break; } + case idxMu: { + nsigma = responseMu.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDMu); + break; + } + case idxPi: { + nsigma = responsePi.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDPi); + break; + } + case idxKa: { + nsigma = responseKa.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDKa); + break; + } + case idxPr: { + nsigma = responsePr.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDPr); + break; + } + case idxDe: { + nsigma = responseDe.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDDe); + break; + } + case idxTr: { + nsigma = responseTr.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDTr); + break; + } + case idxHe: { + nsigma = responseHe.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDHe); + break; + } + case idxAl: { + nsigma = responseAl.GetSeparation(mRespParamsV3, trk); + aod::pidutils::packInTable(nsigma, tablePIDAl); + break; + } + default: + LOG(fatal) << "Wrong particle ID for standard tables"; + break; } + if (enableQaHistograms) { + hnsigma[pidId]->Fill(trk.p(), nsigma); + } + } + for (auto const& pidId : mEnabledParticlesFull) { // Loop on enabled particle hypotheses with full tables + switch (pidId) { + case idxEl: { + resolution = responseEl.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseEl.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullEl(resolution, nsigma); + break; + } + case idxMu: { + resolution = responseMu.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseMu.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullMu(resolution, nsigma); + break; + } + case idxPi: { + resolution = responsePi.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responsePi.GetSeparation(mRespParamsV3, trk); + tablePIDFullPi(resolution, nsigma); + break; + } + case idxKa: { + resolution = responseKa.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseKa.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullKa(resolution, nsigma); + break; + } + case idxPr: { + resolution = responsePr.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responsePr.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullPr(resolution, nsigma); + break; + } + case idxDe: { + resolution = responseDe.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseDe.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullDe(resolution, nsigma); + break; + } + case idxTr: { + resolution = responseTr.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseTr.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullTr(resolution, nsigma); + break; + } + case idxHe: { + resolution = responseHe.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseHe.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullHe(resolution, nsigma); + break; + } + case idxAl: { + resolution = responseAl.GetExpectedSigma(mRespParamsV3, trk); + nsigma = responseAl.GetSeparation(mRespParamsV3, trk, resolution); + tablePIDFullAl(resolution, nsigma); + break; + } + default: + LOG(fatal) << "Wrong particle ID for full tables"; + break; + } + if (enableQaHistograms) { + hnsigmaFull[pidId]->Fill(trk.p(), nsigma); + } + } + } + } + PROCESS_SWITCH(tofPidMerge, processRun3, "Produce tables. Set to off if the tables are not required", true); + + template + using ResponseImplementationRun2 = o2::pid::tof::ExpTimes; + void processRun2(Run2TrksWtofWevTime const& tracks, + Run3Cols const&, + aod::BCsWithTimestamps const&) + { + constexpr auto responseEl = ResponseImplementationRun2(); + constexpr auto responseMu = ResponseImplementationRun2(); + constexpr auto responsePi = ResponseImplementationRun2(); + constexpr auto responseKa = ResponseImplementationRun2(); + constexpr auto responsePr = ResponseImplementationRun2(); + constexpr auto responseDe = ResponseImplementationRun2(); + constexpr auto responseTr = ResponseImplementationRun2(); + constexpr auto responseHe = ResponseImplementationRun2(); + constexpr auto responseAl = ResponseImplementationRun2(); + + for (auto const& track : tracks) { // Loop on all tracks + if (!track.has_collision()) { // Skipping tracks without collisions + continue; + } + const auto& coll = track.collision(); + if (!coll.has_bc()) { + continue; } + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, coll.bc_as()); // Update the calibration parameters break; } @@ -1080,7 +1385,7 @@ struct tofPidMerge { } } } - PROCESS_SWITCH(tofPidMerge, processData, "Process data i.e. input is TrackIU", false); + PROCESS_SWITCH(tofPidMerge, processRun2, "Produce tables. Set to off if the tables are not required", false); }; // Part 4 Beta and TOF mass computation @@ -1099,17 +1404,22 @@ struct tofPidBeta { bool enableTableMass = false; void init(o2::framework::InitContext& initContext) { + mTOFCalibConfig.inheritFromBaseTask(initContext); enableTableBeta = isTableRequiredInWorkflow(initContext, "pidTOFbeta"); enableTableMass = isTableRequiredInWorkflow(initContext, "pidTOFmass"); if (!enableTableBeta && !enableTableMass && !doprocessRun2 && !doprocessRun3) { LOG(info) << "No table or process is enabled. Disabling task"; return; } - if (metadataInfo.isFullyDefined()) { - if (metadataInfo.isRun3()) { - doprocessRun3.value = true; - } else { - doprocessRun2.value = true; + + if (mTOFCalibConfig.autoSetProcessFunctions()) { + LOG(info) << "Autodetecting process functions"; + if (metadataInfo.isFullyDefined()) { + if (metadataInfo.isRun3()) { + doprocessRun3.value = true; + } else { + doprocessRun2.value = true; + } } } @@ -1117,14 +1427,13 @@ struct tofPidBeta { if (!enableTOFParams) { return; } - mTOFCalibConfig.setUp(mRespParamsV3, ccdb); // Getting the parametrization parameters + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); // Getting the parametrization parameters } void process(aod::BCs const&) {} - using TrksRun2 = soa::Join; - o2::pid::tof::Beta responseBetaRun2; - void processRun2(TrksRun2 const& tracks) + o2::pid::tof::Beta responseBetaRun2; + void processRun2(Run2TrksWtofWevTime const& tracks) { if (!enableTableBeta && !enableTableMass) { return; @@ -1138,18 +1447,17 @@ struct tofPidBeta { } if (enableTableMass) { if (enableTOFParams) { - tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk.tofExpMom() / (1.f + trk.sign() * mRespParamsV3.getMomentumChargeShift(trk.eta())), beta)); + tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk.tofExpMom() / (1.f + trk.sign() * mRespParamsV3.getMomentumChargeShift(trk.eta())), beta)); } else { - tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk, beta)); + tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk, beta)); } } } } - PROCESS_SWITCH(tofPidBeta, processRun2, "Process Run3 data i.e. input is TrackIU. If false, taken from metadata automatically", false); + PROCESS_SWITCH(tofPidBeta, processRun2, "Process Run3 data i.e. input is TrackIU. If false, taken from metadata automatically", true); - using Trks = soa::Join; - o2::pid::tof::Beta responseBeta; - void processRun3(Trks const& tracks) + o2::pid::tof::Beta responseBeta; + void processRun3(Run3TrksWtofWevTime const& tracks) { if (!enableTableBeta && !enableTableMass) { return; @@ -1164,14 +1472,14 @@ struct tofPidBeta { } if (enableTableMass) { if (enableTOFParams) { - tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk.tofExpMom() / (1.f + trk.sign() * mRespParamsV3.getMomentumChargeShift(trk.eta())), beta)); + tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk.tofExpMom() / (1.f + trk.sign() * mRespParamsV3.getMomentumChargeShift(trk.eta())), beta)); } else { - tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk, beta)); + tablePIDTOFMass(o2::pid::tof::TOFMass::GetTOFMass(trk, beta)); } } } } - PROCESS_SWITCH(tofPidBeta, processRun3, "Process Run3 data i.e. input is TrackIU. If false, taken from metadata automatically", false); + PROCESS_SWITCH(tofPidBeta, processRun3, "Process Run3 data i.e. input is TrackIU. If false, taken from metadata automatically", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/Common/TableProducer/centralityTable.cxx b/Common/TableProducer/centralityTable.cxx index 871978a851c..439ed0aad29 100644 --- a/Common/TableProducer/centralityTable.cxx +++ b/Common/TableProducer/centralityTable.cxx @@ -23,13 +23,15 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" - +#include "MetadataHelper.h" #include "TableHelper.h" #include "TList.h" using namespace o2; using namespace o2::framework; +MetadataHelper metadataInfo; // Metadata helper + static constexpr int kCentRun2V0Ms = 0; static constexpr int kCentRun2V0As = 1; static constexpr int kCentRun2SPDTrks = 2; @@ -76,12 +78,15 @@ struct CentralityTable { Configurable> enabledTables{"enabledTables", {defaultParameters[0], nTables, nParameters, tableNames, parameterNames}, "Produce tables depending on needs. Values different than -1 override the automatic setup: the corresponding table can be set off (0) or on (1)"}; - Configurable ccdbUrl{"ccdburl", "http://alice-ccdb.cern.ch", "The CCDB endpoint url address"}; - Configurable ccdbPath{"ccdbpath", "Centrality/Estimators", "The CCDB path for centrality/multiplicity information"}; - Configurable genName{"genname", "", "Genearator name: HIJING, PYTHIA8, ... Default: \"\""}; - Configurable doNotCrashOnNull{"doNotCrashOnNull", false, {"Option to not crash on null and instead fill required tables with dummy info"}}; + struct : ConfigurableGroup { + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "The CCDB endpoint url address"}; + Configurable ccdbPath{"ccdbpath", "Centrality/Estimators", "The CCDB path for centrality/multiplicity information"}; + Configurable genName{"genname", "", "Genearator name: HIJING, PYTHIA8, ... Default: \"\""}; + Configurable doNotCrashOnNull{"doNotCrashOnNull", false, {"Option to not crash on null and instead fill required tables with dummy info"}}; + Configurable reconstructionPass{"reconstructionPass", "", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}}; + } ccdbConfig; + Configurable embedINELgtZEROselection{"embedINELgtZEROselection", false, {"Option to do percentile 100.5 if not INELgtZERO"}}; - Configurable fatalizeMultCalibSanity{"fatalizeMultCalibSanity", false, {"Option to do fatalize the sanity check on the multiplicity calibration"}}; Configurable produceHistograms{"produceHistograms", false, {"Option to produce debug histograms"}}; ConfigurableAxis binsPercentile{"binsPercentile", {VARIABLE_WIDTH, 0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.011, 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018, 0.019, 0.02, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.029, 0.03, 0.031, 0.032, 0.033, 0.034, 0.035, 0.036, 0.037, 0.038, 0.039, 0.04, 0.041, 0.042, 0.043, 0.044, 0.045, 0.046, 0.047, 0.048, 0.049, 0.05, 0.051, 0.052, 0.053, 0.054, 0.055, 0.056, 0.057, 0.058, 0.059, 0.06, 0.061, 0.062, 0.063, 0.064, 0.065, 0.066, 0.067, 0.068, 0.069, 0.07, 0.071, 0.072, 0.073, 0.074, 0.075, 0.076, 0.077, 0.078, 0.079, 0.08, 0.081, 0.082, 0.083, 0.084, 0.085, 0.086, 0.087, 0.088, 0.089, 0.09, 0.091, 0.092, 0.093, 0.094, 0.095, 0.096, 0.097, 0.098, 0.099, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0, 99.0, 100.0}, "Binning of the percentile axis"}; @@ -208,7 +213,7 @@ struct CentralityTable { doprocessRun3.value = false; } - ccdb->setURL(ccdbUrl); + ccdb->setURL(ccdbConfig.ccdburl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); @@ -233,6 +238,7 @@ struct CentralityTable { histos.addClone("FT0C/", "sel8FT0C/"); histos.addClone("FT0A/", "sel8FT0A/"); + histos.print(); listCalib.setObject(new TList); } @@ -244,7 +250,18 @@ struct CentralityTable { auto bc = collision.bc_as(); if (bc.runNumber() != mRunNumber) { LOGF(debug, "timestamp=%llu", bc.timestamp()); - TList* callst = ccdb->getForTimeStamp(ccdbPath, bc.timestamp()); + TList* callst = nullptr; + if (ccdbConfig.reconstructionPass.value == "") { + callst = ccdb->getForTimeStamp(ccdbConfig.ccdbPath, bc.timestamp()); + } else if (ccdbConfig.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = ccdbConfig.reconstructionPass.value; + callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + } Run2V0MInfo.mCalibrationStored = false; Run2V0AInfo.mCalibrationStored = false; @@ -266,9 +283,9 @@ struct CentralityTable { Run2V0MInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); Run2V0MInfo.mhVtxAmpCorrV0C = getccdb("hVtx_fAmplitude_V0C_Normalized"); Run2V0MInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0M"); - Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", genName->c_str()).Data()); + Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", ccdbConfig.genName->c_str()).Data()); if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) && (Run2V0MInfo.mhMultSelCalib != nullptr)) { - if (genName->length() != 0) { + if (ccdbConfig.genName->length() != 0) { if (Run2V0MInfo.mMCScale != nullptr) { for (int ixpar = 0; ixpar < 6; ++ixpar) { Run2V0MInfo.mMCScalePars[ixpar] = Run2V0MInfo.mMCScale->GetParameter(ixpar); @@ -337,7 +354,7 @@ struct CentralityTable { mRunNumber = bc.runNumber(); } } else { - if (!doNotCrashOnNull) { // default behaviour: crash + if (!ccdbConfig.doNotCrashOnNull) { // default behaviour: crash LOGF(fatal, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } else { // only if asked: continue filling with non-valid values (105) LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); @@ -457,7 +474,29 @@ struct CentralityTable { auto bc = collision.template bc_as(); if (bc.runNumber() != mRunNumber) { LOGF(info, "timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber()); - TList* callst = ccdb->getForTimeStamp(ccdbPath, bc.timestamp()); + TList* callst = nullptr; + // Check if the ccdb path is a root file + if (ccdbConfig.ccdbPath.value.find(".root") != std::string::npos) { + TFile f(ccdbConfig.ccdbPath.value.c_str(), "READ"); + f.GetObject(ccdbConfig.reconstructionPass.value.c_str(), callst); + if (!callst) { + f.ls(); + LOG(fatal) << "No calibration list " << ccdbConfig.reconstructionPass.value << " found in the file " << ccdbConfig.ccdbPath.value; + } + } else { + if (ccdbConfig.reconstructionPass.value == "") { + callst = ccdb->getForTimeStamp(ccdbConfig.ccdbPath, bc.timestamp()); + } else if (ccdbConfig.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = ccdbConfig.reconstructionPass.value; + callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + } + } + FV0AInfo.mCalibrationStored = false; FT0MInfo.mCalibrationStored = false; FT0AInfo.mCalibrationStored = false; @@ -494,22 +533,22 @@ struct CentralityTable { for (auto const& table : mEnabledTables) { switch (table) { case kCentFV0As: - getccdb(FV0AInfo, genName); + getccdb(FV0AInfo, ccdbConfig.genName); break; case kCentFT0Ms: - getccdb(FT0MInfo, genName); + getccdb(FT0MInfo, ccdbConfig.genName); break; case kCentFT0As: - getccdb(FT0AInfo, genName); + getccdb(FT0AInfo, ccdbConfig.genName); break; case kCentFT0Cs: - getccdb(FT0CInfo, genName); + getccdb(FT0CInfo, ccdbConfig.genName); break; case kCentFDDMs: - getccdb(FDDMInfo, genName); + getccdb(FDDMInfo, ccdbConfig.genName); break; case kCentNTPVs: - getccdb(NTPVInfo, genName); + getccdb(NTPVInfo, ccdbConfig.genName); break; default: LOGF(fatal, "Table %d not supported in Run3", table); @@ -518,7 +557,7 @@ struct CentralityTable { } mRunNumber = bc.runNumber(); } else { - if (!doNotCrashOnNull) { // default behaviour: crash + if (!ccdbConfig.doNotCrashOnNull) { // default behaviour: crash LOGF(fatal, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } else { // only if asked: continue filling with non-valid values (105) LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); @@ -585,11 +624,11 @@ struct CentralityTable { if (produceHistograms.value) { histos.fill(HIST("FT0A/percentile"), perC); histos.fill(HIST("FT0A/percentilevsPV"), perC, collision.multNTracksPV()); - histos.fill(HIST("FT0A/MultvsPV"), collision.multZeqFT0A(), collision.multNTracksPV()); + histos.fill(HIST("FT0A/MultvsPV"), collision.multZeqFT0A() + collision.multZeqFT0C(), collision.multNTracksPV()); if (collision.sel8()) { histos.fill(HIST("sel8FT0A/percentile"), perC); histos.fill(HIST("sel8FT0A/percentilevsPV"), perC, collision.multNTracksPV()); - histos.fill(HIST("sel8FT0A/MultvsPV"), collision.multZeqFT0A(), collision.multNTracksPV()); + histos.fill(HIST("sel8FT0A/MultvsPV"), collision.multZeqFT0A() + collision.multZeqFT0C(), collision.multNTracksPV()); } } } @@ -600,11 +639,11 @@ struct CentralityTable { if (produceHistograms.value) { histos.fill(HIST("FT0C/percentile"), perC); histos.fill(HIST("FT0C/percentilevsPV"), perC, collision.multNTracksPV()); - histos.fill(HIST("FT0C/MultvsPV"), collision.multZeqFT0C(), collision.multNTracksPV()); + histos.fill(HIST("FT0C/MultvsPV"), collision.multZeqFT0A() + collision.multZeqFT0C(), collision.multNTracksPV()); if (collision.sel8()) { histos.fill(HIST("sel8FT0C/percentile"), perC); histos.fill(HIST("sel8FT0C/percentilevsPV"), perC, collision.multNTracksPV()); - histos.fill(HIST("sel8FT0C/MultvsPV"), collision.multZeqFT0C(), collision.multNTracksPV()); + histos.fill(HIST("sel8FT0C/MultvsPV"), collision.multZeqFT0A() + collision.multZeqFT0C(), collision.multNTracksPV()); } } } @@ -646,4 +685,8 @@ struct CentralityTable { PROCESS_SWITCH(CentralityTable, processRun3FT0, "Provide Run3 calibrated centrality/multiplicity percentiles tables for FT0 only", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + metadataInfo.initMetadata(cfgc); + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index 466c60cd7b6..0801ee29a39 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -23,6 +23,7 @@ #include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsParameters/GRPECSObject.h" #include "ITSMFTBase/DPLAlpideParam.h" +#include "MetadataHelper.h" #include "TH1D.h" @@ -30,6 +31,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::aod::evsel; +MetadataHelper metadataInfo; // Metadata helper + using BCsWithRun2InfosTimestampsAndMatches = soa::Join; using BCsWithRun3Matchings = soa::Join; using BCsWithBcSelsRun2 = soa::Join; @@ -45,6 +48,7 @@ struct BcSelectionTask { Configurable confITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; Configurable confTimeFrameStartBorderMargin{"TimeFrameStartBorderMargin", -1, "Number of bcs to cut at the start of the Time Frame. Take from CCDB if -1"}; Configurable confTimeFrameEndBorderMargin{"TimeFrameEndBorderMargin", -1, "Number of bcs to cut at the end of the Time Frame. Take from CCDB if -1"}; + Configurable confCheckRunDurationLimits{"checkRunDurationLimits", false, "Check if the BCs are within the run duration limits"}; int lastRunNumber = -1; int64_t bcSOR = -1; // global bc of the start of the first orbit @@ -56,6 +60,15 @@ struct BcSelectionTask { void init(InitContext&) { + if (metadataInfo.isFullyDefined() && !doprocessRun2 && !doprocessRun3) { // Check if the metadata is initialized (only if not forced from the workflow configuration) + LOG(info) << "Autosetting the processing mode (Run2 or Run3) based on metadata"; + if (metadataInfo.isRun3()) { + doprocessRun3.value = true; + } else { + doprocessRun2.value = false; + } + } + // ccdb->setURL("http://ccdb-test.cern.ch:8080"); ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -69,6 +82,7 @@ struct BcSelectionTask { histos.add("hCounterTCEafterBCcuts", "", kTH1D, {{1, 0., 1.}}); histos.add("hCounterZEMafterBCcuts", "", kTH1D, {{1, 0., 1.}}); histos.add("hCounterZNCafterBCcuts", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterInvalidBCTimestamp", "", kTH1D, {{1, 0., 1.}}); histos.add("hLumiTVX", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); histos.add("hLumiTCE", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); histos.add("hLumiZEM", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); @@ -216,10 +230,14 @@ struct BcSelectionTask { bcsel.reserve(bcs.size()); // extract ITS time frame parameters - - int64_t ts = bcs.iteratorAt(0).timestamp(); + int run = bcs.iteratorAt(0).runNumber(); + auto timestamps = ccdb->getRunDuration(run, true); /// fatalise if timestamps are not found + int64_t sorTimestamp = timestamps.first; // timestamp of the SOR/SOX/STF in ms + int64_t eorTimestamp = timestamps.second; // timestamp of the EOR/EOX/ETF in ms + int64_t ts = eorTimestamp / 2 + sorTimestamp / 2; // timestamp of the middle of the run auto alppar = ccdb->getForTimeStamp>("ITS/Config/AlpideParam", ts); - + EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", ts); + TriggerAliases* aliases = ccdb->getForTimeStamp("EventSelection/TriggerAliases", ts); // map from GlobalBC to BcId needed to find triggerBc std::map mapGlobalBCtoBcId; for (auto& bc : bcs) { @@ -227,12 +245,10 @@ struct BcSelectionTask { } int triggerBcShift = confTriggerBcShift; if (confTriggerBcShift == 999) { - int run = bcs.iteratorAt(0).runNumber(); triggerBcShift = (run <= 526766 || (run >= 526886 && run <= 527237) || (run >= 527259 && run <= 527518) || run == 527523 || run == 527734 || run >= 534091) ? 0 : 294; } // extract run number and related information - int run = bcs.iteratorAt(0).runNumber(); if (run != lastRunNumber) { lastRunNumber = run; // do it only once if (run >= 500000) { // access CCDB for data or anchored MC only @@ -266,8 +282,6 @@ struct BcSelectionTask { // bc loop for (auto bc : bcs) { - EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); - TriggerAliases* aliases = ccdb->getForTimeStamp("EventSelection/TriggerAliases", bc.timestamp()); uint32_t alias{0}; // workaround for pp2022 (trigger info is shifted by -294 bcs) int32_t triggerBcId = mapGlobalBCtoBcId[bc.globalBC() + triggerBcShift]; @@ -410,6 +424,15 @@ struct BcSelectionTask { } } + if (bc.timestamp() < static_cast(sorTimestamp) || bc.timestamp() > static_cast(eorTimestamp)) { + histos.get(HIST("hCounterInvalidBCTimestamp"))->Fill(srun, 1); + if (confCheckRunDurationLimits.value) { + LOGF(warn, "Invalid BC timestamp: %d, run: %d, sor: %d, eor: %d", bc.timestamp(), run, sorTimestamp, eorTimestamp); + alias = 0u; + selection = 0u; + } + } + // Fill bc selection columns bcsel(alias, selection, foundFT0, foundFV0, foundFDD, foundZDC); } @@ -423,7 +446,7 @@ struct EventSelectionTask { Configurable syst{"syst", "PbPb", "pp, pPb, Pbp, PbPb, XeXe"}; // TODO determine from AOD metadata or from CCDB Configurable muonSelection{"muonSelection", 0, "0 - barrel, 1 - muon selection with pileup cuts, 2 - muon selection without pileup cuts"}; Configurable maxDiffZvtxFT0vsPV{"maxDiffZvtxFT0vsPV", 1., "maximum difference (in cm) between z-vertex from FT0 and PV"}; - Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; + Configurable isMC{"isMC", 0, "-1 - autoset, 0 - data, 1 - MC"}; // configurables for occupancy-based event selection Configurable confTimeIntervalForOccupancyCalculationMin{"TimeIntervalForOccupancyCalculationMin", -40, "Min time diff window for TPC occupancy calculation, us"}; Configurable confTimeIntervalForOccupancyCalculationMax{"TimeIntervalForOccupancyCalculationMax", 100, "Max time diff window for TPC occupancy calculation, us"}; @@ -460,6 +483,25 @@ struct EventSelectionTask { void init(InitContext&) { + if (metadataInfo.isFullyDefined()) { // Check if the metadata is initialized (only if not forced from the workflow configuration) + if (!doprocessRun2 && !doprocessRun3) { + LOG(info) << "Autosetting the processing mode (Run2 or Run3) based on metadata"; + if (metadataInfo.isRun3()) { + doprocessRun3.value = true; + } else { + doprocessRun2.value = false; + } + } + if (isMC == -1) { + LOG(info) << "Autosetting the MC mode based on metadata"; + if (metadataInfo.isMC()) { + isMC.value = 1; + } else { + isMC.value = 0; + } + } + } + // ccdb->setURL("http://ccdb-test.cern.ch:8080"); ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -481,7 +523,7 @@ struct EventSelectionTask { auto bc = col.bc_as(); EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); bool* applySelection = par->GetSelection(muonSelection); - if (isMC) { + if (isMC == 1) { applySelection[kIsBBZAC] = 0; applySelection[kNoV0MOnVsOfPileup] = 0; applySelection[kNoSPDOnVsOfPileup] = 0; @@ -537,7 +579,7 @@ struct EventSelectionTask { bool isINT1period = bc.runNumber() <= 136377 || (bc.runNumber() >= 144871 && bc.runNumber() <= 159582); // fill counters - if (isMC || (!isINT1period && bc.alias_bit(kINT7)) || (isINT1period && bc.alias_bit(kINT1))) { + if (isMC == 1 || (!isINT1period && bc.alias_bit(kINT7)) || (isINT1period && bc.alias_bit(kINT1))) { histos.get(HIST("hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); if ((!isINT1period && sel7) || (isINT1period && sel1)) { histos.get(HIST("hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); @@ -640,9 +682,7 @@ struct EventSelectionTask { int nITSTPCtracks = 0; int nTOFtracks = 0; int nTRDtracks = 0; - int nTRDnotTOFtracks = 0; double timeFromTOFtracks = 0; - double timeFromTRDtracks = 0; auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); for (auto& track : tracksGrouped) { if (!track.isPVContributor()) { @@ -651,22 +691,17 @@ struct EventSelectionTask { nITSTPCtracks += track.hasITS() && track.hasTPC(); nTOFtracks += track.hasTOF(); nTRDtracks += track.hasTRD(); - nTRDnotTOFtracks += track.hasTRD() && !track.hasTOF(); - // calculate average time using TOF and TRD tracks + // calculate average time using TOF tracks if (track.hasTOF()) { timeFromTOFtracks += track.trackTime(); - } else if (track.hasTRD()) { - timeFromTRDtracks += track.trackTime(); } + if (track.itsNCls() >= 5) nITS567cls++; } - LOGP(debug, "nContrib={} nITSTPCtracks={} nTOFtracks={} nTRDtracks={} nTRDnotTOFtracks={}", col.numContrib(), nITSTPCtracks, nTOFtracks, nTRDtracks, nTRDnotTOFtracks); + LOGP(debug, "nContrib={} nITSTPCtracks={} nTOFtracks={} nTRDtracks={}", col.numContrib(), nITSTPCtracks, nTOFtracks, nTRDtracks); - if (nTRDnotTOFtracks > 0) { - meanBC += TMath::Nint(timeFromTRDtracks / nTRDnotTOFtracks / bcNS); // assign collision bc using TRD-matched tracks - deltaBC = 0; // use precise bc from TRD-matched tracks - } else if (nTOFtracks > 0) { + if (nTOFtracks > 0) { meanBC += TMath::FloorNint(timeFromTOFtracks / nTOFtracks / bcNS); // assign collision bc using TOF-matched tracks deltaBC = 4; // use precise bc from TOF tracks with +/-4 bc margin } else if (nITSTPCtracks > 0) { @@ -819,8 +854,12 @@ struct EventSelectionTask { bool decisions[4]; for (int iCut = 0; iCut < 4; iCut++) { decisions[iCut] = true; - for (int iTime = 0; iTime < nTimeIntervals; iTime++) - decisions[iCut] *= (nITS567tracksInTimeBins[iTime] < coeffOccupInTimeBins[iCut] * confReferenceOccupanciesInTimeBins->at(iTime)); + for (int iTime = 0; iTime < nTimeIntervals; iTime++) { + if (nITS567tracksInTimeBins[iTime] >= coeffOccupInTimeBins[iCut] * confReferenceOccupanciesInTimeBins->at(iTime)) { + decisions[iCut] = false; + break; + } + } } vNoOccupStrictCuts[colIndex] = decisions[0]; vNoOccupMediumCuts[colIndex] = decisions[1]; @@ -892,6 +931,9 @@ struct EventSelectionTask { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + // Parse the metadata + metadataInfo.initMetadata(cfgc); + return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; diff --git a/Common/TableProducer/match-mft-ft0.cxx b/Common/TableProducer/match-mft-ft0.cxx new file mode 100644 index 00000000000..268548255cd --- /dev/null +++ b/Common/TableProducer/match-mft-ft0.cxx @@ -0,0 +1,554 @@ +// Copyright 2019-2020 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. + +// \file match-mft-ft0.cxx +// \author Sarah Herrmann +// +// \brief This code loops over every MFT tracks (except orphan tracks) and propagates +// them to the FT0-C, matching the signals in some BC to reduce track ambiguity +// It produces a table containing for each MFT track a list of BCs with an FT0C match +// called aod::BCofMFT +// \date 03/09/24 + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" + +#include "MathUtils/Utils.h" +#include "CommonConstants/LHCConstants.h" +#include "Common/Core/trackUtilities.h" //for getTrackPar() +#include "ReconstructionDataFormats/TrackFwd.h" //for propagate +// https://github.com/AliceO2Group/AliceO2/blob/dev/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +#include "CommonConstants/LHCConstants.h" +#include "Math/MatrixFunctions.h" +#include "Math/SMatrix.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" + +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "Field/MagneticField.h" +#include "TGeoGlobalMagField.h" + +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" + +#include "Common/DataModel/MatchMFTFT0.h" + +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix5 = ROOT::Math::SVector; + +using namespace o2; +using namespace o2::framework; + +// Creating a table BC to FT0 and filling it +struct bctoft0c { + Produces mf; + struct { + std::vector ft0ids; + } filler; + void process(aod::BCs::iterator const& bc, soa::SmallGroups const& ft0s) + { + filler.ft0ids.clear(); + for (auto const& ft0 : ft0s) { + filler.ft0ids.emplace_back(ft0.globalIndex()); + } + mf(bc.globalIndex(), filler.ft0ids); + } +}; + +using ExtBCs = soa::Join; + +template +T getCompatibleBCs(aod::AmbiguousMFTTrack const& atrack, aod::Collision const& collOrig, T const& bcs, int deltaBC) +{ + // this method is unused for now, MFTtracks with no collisions (orphan tracks) are not considered for the matching with FT0C + auto compBCs = atrack.bc_as(); // BC + info on FT0 + auto bcIter = compBCs.begin(); // first element of compBC + uint64_t firstBC = bcIter.globalBC(); + + bcIter.moveToEnd(); // does it move to the end or the next one after the end ? + --bcIter; // to avoid a seg fault + uint64_t lastBC = bcIter.globalBC(); // gives the last COMPATIBLE BC in compBCs + + auto bcIt = collOrig.bc_as(); + + int64_t minBCId = bcIt.globalIndex(); + auto minGlobalBC = bcIt.globalBC(); + + if (bcIt.globalBC() < firstBC + deltaBC) { + while (bcIt != bcs.end() && bcIt.globalBC() < firstBC + deltaBC) { + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + + ++bcIt; + } + if (bcIt == bcs.end()) { + --bcIt; + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + } + } else { + // here bcIt.globalBC() >= firstBC + deltaBC + + while (bcIt != bcs.begin() && bcIt.globalBC() > firstBC + deltaBC) { + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + + --bcIt; + } + } + + int64_t maxBCId = bcIt.globalIndex(); + auto maxGlobalBC = bcIt.globalBC(); + + while (bcIt != bcs.end() && bcIt.globalBC() < lastBC + deltaBC) { + maxBCId = bcIt.globalIndex(); + maxGlobalBC = bcIt.globalBC(); + + ++bcIt; + } + + if (bcIt != bcs.end() && maxBCId >= minBCId) { + T slice{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId + 1)}, (uint64_t)minBCId}; + bcs.copyIndexBindings(slice); + return slice; + } else { + T slice{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId)}, (uint64_t)minBCId}; + bcs.copyIndexBindings(slice); + return slice; + } +} + +template +T getCompatibleBCs(aod::MFTTracks::iterator const& track, aod::Collision const& collOrig, T const& bcs, int deltaBC) +{ + + // define firstBC and lastBC (globalBC of beginning and end of the range, when no shift is applied) + + auto bcIt = collOrig.bc_as(); + // auto timstp = bcIt.timestamp(); + + int64_t firstBC = bcIt.globalBC() + (track.trackTime() - track.trackTimeRes()) / o2::constants::lhc::LHCBunchSpacingNS; + int64_t lastBC = firstBC + 2 * track.trackTimeRes() / o2::constants::lhc::LHCBunchSpacingNS + 1; // to have a delta = 198 BC + + // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>> last-first %lld\n", lastBC-firstBC); + + // int collTimeResInBC = collOrig.collisionTimeRes()/o2::constants::lhc::LHCBunchSpacingNS; + + // int64_t collFirstBC = bcIt.globalBC() + (collOrig.collisionTime() - collOrig.collisionTimeRes())/o2::constants::lhc::LHCBunchSpacingNS; + // int64_t collLastBC = collFirstBC + 2*collOrig.collisionTimeRes()/o2::constants::lhc::LHCBunchSpacingNS +1; + + int64_t minBCId = bcIt.globalIndex(); + uint64_t minGlobalBC = bcIt.globalBC(); + + if ((int64_t)bcIt.globalBC() < firstBC + deltaBC) { + while (bcIt != bcs.end() && (int64_t)bcIt.globalBC() < firstBC + deltaBC) { + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + + ++bcIt; + } + if (bcIt == bcs.end()) { + --bcIt; + // allows to avoid bcIt==bcs.end() in the following + } + // minGlobalBC needs to be >= to firstBC+deltaBC + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + + } else { + // here bcIt.globalBC() >= firstBC + deltaBC + + while (bcIt != bcs.begin() && (int64_t)bcIt.globalBC() >= (int64_t)firstBC + deltaBC) { + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + --bcIt; + } + if (bcIt == bcs.begin() && (int64_t)bcIt.globalBC() >= (int64_t)firstBC + deltaBC) { + minBCId = bcIt.globalIndex(); + minGlobalBC = bcIt.globalBC(); + } + ++bcIt; // retrieve the pointer which gave minBCId and minGlobalBC + if (bcIt == bcs.end()) { + --bcIt; // go back if we got to the end of the list + } + } + + int64_t maxBCId = bcIt.globalIndex(); + uint64_t maxGlobalBC = bcIt.globalBC(); + + if ((int64_t)bcIt.globalBC() > (int64_t)lastBC + deltaBC) { + // the previous minimum is actually bigger than the right boundary + + if (bcIt != bcs.begin()) { + --bcIt; // let's check the previous element in the BC list + if ((int64_t)bcIt.globalBC() < (int64_t)firstBC + deltaBC) // if this previous element is smaller than the left boundary + { + // means that the slice of compatible BCs is empty + + T slice{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; + // bcs.copyIndexBindings(slice); REMOVED IT BECAUSE I DON'T KNOW WHAT IT DOES HERE + return slice; // returns an empty slice + } + } + } + + if ((int64_t)bcIt.globalBC() < (int64_t)firstBC + deltaBC) { + // the previous minimum is actually smaller than the right boundary + ++bcIt; + + if (bcIt != bcs.end() && ((int64_t)bcIt.globalBC() > (int64_t)lastBC + deltaBC)) { + // check the following element + + T slice{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; + // bcs.copyIndexBindings(slice); REMOVED IT BECAUSE I DON'T KNOW WHAT IT DOES HERE + return slice; // returns an empty slice + } + } + + while (bcIt != bcs.end() && (int64_t)bcIt.globalBC() <= (int64_t)lastBC + deltaBC) { + maxBCId = bcIt.globalIndex(); + maxGlobalBC = bcIt.globalBC(); + + ++bcIt; + } + + if (maxBCId < minBCId) { + if (bcIt == bcs.end()) { + printf("at the end of the bcs iterator %d\n", 1); + } + T slice{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; + // bcs.copyIndexBindings(slice); REMOVED IT BECAUSE I DON'T KNOW WHAT IT DOES HERE + return slice; // returns an empty slice + } + + T slice{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId + 1)}, (uint64_t)minBCId}; + bcs.copyIndexBindings(slice); + return slice; +} + +struct matchmftft0 { + Produces BcMft; + struct { + std::vector BCids; + } filler; + + Service ccdb; + + int runNumber = -1; + float Bz = 0; // Magnetic field for MFT + static constexpr double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT + int count = 0; + o2::parameters::GRPMagField* grpmag = nullptr; + + Configurable strictBCSel{"strictBCSel", false, "force the BC of the match to have FT0A&C signals"}; + Configurable shiftBC{"shiftBC", 0, "shift in BC wrt normal"}; // should be kept at zero except if the time-alignment MFT-FT0C must be redone + + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + + std::vector> channelCoord = {{103.2, 17.8, -813.1}, {76.9, 17.8, -815.9}, {103.1, 44.2, -812.1}, {76.8, 44.2, -814.9}, {103.2, 78.7, -810}, {76.8, 79, -812.9}, {103.2, 105, -807.1}, {76.8, 105.3, -810}, {43.2, 78.8, -815}, {43.2, 105.1, -812.1}, {16.8, 78.9, -815.9}, {16.8, 105.2, -813}, {-16.8, 105.2, -813}, {-16.8, 78.9, -815.9}, {-43.2, 105.1, -812.1}, {-43.2, 78.8, -815}, {-76.8, 105.3, -810}, {-76.8, 79, -812.9}, {-103.2, 105, -807.1}, {-103.2, 78.7, -810}, {-76.8, 44.2, -814.9}, {-103.1, 44.2, -812.1}, {-76.9, 17.8, -815.9}, {-103.2, 17.8, -813.1}, {-103.2, -17.8, -813.1}, {-76.9, -17.8, -815.9}, {-103.1, -44.2, -812.1}, {-76.8, -44.2, -814.9}, {-103.2, -78.7, -810}, {-76.8, -79, -812.9}, {-103.2, -105, -807.1}, {-76.8, -105.3, -810}, {-43.2, -78.8, -815}, {-43.2, -105.1, -812.1}, {-16.8, -78.9, -815.9}, {-16.8, -105.2, -813}, {16.8, -105.2, -813}, {16.8, -78.9, -815.9}, {43.2, -105.1, -812.1}, {43.2, -78.8, -815}, {76.8, -105.3, -810}, {76.8, -79, -812.9}, {103.2, -105, -807.1}, {103.2, -78.7, -810}, {76.8, -44.2, -814.9}, {103.1, -44.2, -812.1}, {76.9, -17.8, -815.9}, {103.2, -17.8, -813.1}, {163, 18.7, -804.1}, {137, 18.9, -808.9}, {163, 45.2, -803.1}, {137, 45.3, -807.9}, {163, 78.6, -800.1}, {137, 79.1, -804.9}, {163, 104.9, -797.2}, {137, 105.4, -801.9}, {103.4, 138, -802}, {102.9, 164, -797.2}, {77.1, 138, -804.9}, {76.6, 164, -800}, {43.3, 139, -807}, {43.2, 165, -802.1}, {16.9, 139, -807.9}, {16.7, 165, -803}, {-16.7, 165, -803}, {-16.9, 139, -807.9}, {-43.2, 165, -802.1}, {-43.3, 139, -807}, {-76.6, 164, -800}, {-77.1, 138, -804.9}, {-102.9, 164, -797.2}, {-103.4, 138, -802}, {-137, 105.4, -801.9}, {-163, 104.9, -797.2}, {-137, 79.1, -804.9}, {-163, 78.6, -800.1}, {-137, 45.3, -807.9}, {-163, 45.2, -803.1}, {-137, 18.9, -808.9}, {-163, 18.7, -804.1}, {-163, -18.7, -804.1}, {-137, -18.9, -808.9}, {-163, -45.2, -803.1}, {-137, -45.3, -807.9}, {-163, -78.6, -800.1}, {-137, -79.1, -804.9}, {-163, -104.9, -797.2}, {-137, -105.4, -801.9}, {-103.4, -138, -802}, {-102.9, -164, -797.2}, {-77.1, -138, -804.9}, {-76.6, -164, -800}, {-43.3, -139, -807}, {-43.2, -165, -802.1}, {-16.9, -139, -807.9}, {-16.7, -165, -803}, {16.7, -165, -803}, {16.9, -139, -807.9}, {43.2, -165, -802.1}, {43.3, -139, -807}, {76.6, -164, -800}, {77.1, -138, -804.9}, {102.9, -164, -797.2}, {103.4, -138, -802}, {137, -105.4, -801.9}, {163, -104.9, -797.2}, {137, -79.1, -804.9}, {163, -78.6, -800.1}, {137, -45.3, -807.9}, {163, -45.2, -803.1}, {137, -18.9, -808.9}, {163, -18.7, -804.1}}; + + HistogramRegistry registry{ + "registry", + {{"UnMatchedTracksXY", "; #it{x} (cm); #it{y} (cm);", {HistType::kTH2F, {{701, -35.05, 35.05}, {701, -35.05, 35.05}}}}, + {"MatchedTracksXY", "; #it{x} (cm); #it{y} (cm);", {HistType::kTH2F, {{701, -35.05, 35.05}, {701, -35.05, 35.05}}}}, + {"AllTracksXY", "; #it{x} (cm); #it{y} (cm);", {HistType::kTH2F, {{701, -35.05, 35.05}, {701, -35.05, 35.05}}}}, + {"DistChannelToProp", "; D (cm); #count", {HistType::kTH1D, {{101, 0, 100}}}}, + {"NchannelsPerBC", "; N_{channelC}; #count", {HistType::kTH1D, {{101, 0, 100}}}}, + {"NgoodBCperTrack", "; N_{goodBC}; #count", {HistType::kTH1D, {{11, 0, 10}}}}, + {"NgoodBCperTrackINDIV", "; N_{goodBC}; #count", {HistType::kTH1D, {{11, 0, 10}}}}, + {"NCompBCwFT0C", "; N_{compBC}; #count", {HistType::kTH1D, {{21, -0.5, 20.5}}}}, + {"NCompBCwFT0s", "; N_{compBC}; #count", {HistType::kTH1D, {{21, -0.5, 20.5}}}}, + {"DiffInBCINDIV", "; indivBC-firstBC (globalBC); #count", {HistType::kTH1I, {{199, 0, 199}}}}, + {"DiffInBC", "; goodBC-firstBC (globalBC); #count", {HistType::kTH1I, {{199, 0, 199}}}}}}; + + void init(InitContext const&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + void initCCDB(ExtBCs::iterator const& bc) + { + + if (runNumber == bc.runNumber()) { + return; + } + grpmag = ccdb->getForTimeStamp(grpmagPath, bc.timestamp()); + LOG(info) << "Setting magnetic field to current " << grpmag->getL3Current() + << " A for run " << bc.runNumber() + << " from its GRPMagField CCDB object"; + o2::base::Propagator::initFieldFromGRP(grpmag); // for some reason this is necessary for the next next line + runNumber = bc.runNumber(); + + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + + Bz = field->getBz(centerMFT); // gives error if the propagator is not initFielded + LOG(info) << "The field at the center of the MFT is Bz = " << Bz; + } + + bool isInFT0Acc(double x, double y) + { + // returns true if the propagated x and y positions are in an active zone of the FT0-C, false if they in a dead zone + + if ((abs(x) < 6.365) && (abs(y) < 6.555)) { + // track outside the FT0-C acceptance (in the central hole) + return false; + } + + if (((x > -12.75) && (x < -11.85)) || ((x > -6.55) && (x < -5.75)) || ((x > -0.35) && (x < 0.45)) || ((x > 5.75) && (x < 6.55)) || ((x > 11.85) && (x < 12.75))) { + // track outside the FT0-C acceptance (in the vertical line holes) + return false; + } + + if (((y > -12.95) && (y < -11.95)) || ((y > -6.65) && (y < -5.85)) || ((y > -0.55) && (y < 0.45)) || ((y > 5.75) && (y < 6.65)) || ((y > 11.95) && (y < 12.85))) { + // track outside the FT0-C acceptance (in the horizontal line holes) + return false; + } + + return true; + } + + void processMFT(aod::MFTTracks const& mfttracks, + aod::Collisions const&, ExtBCs const& bcs, + aod::FT0s const&) + { + initCCDB(bcs.begin()); + + int i = 0; // counts the number of channels having non-zero amplitude + // for a particular BC + double D = 0.0; // distance between (xe,ye,ze) and (xc,yc,zc) + double minD; + double globalMinD; + + for (auto& track : mfttracks) { + filler.BCids.clear(); + globalMinD = 999.; // minimum D for all BC + ExtBCs::iterator closestBC; // compatible BC with the D the smallest + // beware: there could be several BC with the same smallest D + // not a very useful variable + + if (!track.has_collision()) { + BcMft(track.globalIndex(), filler.BCids); // empty + continue; + } + auto collOrig = track.collision(); + + auto bcSlice = getCompatibleBCs(track, collOrig, bcs, shiftBC); + + // firstBC= global BC of the beginning of the ROF (shifted by shiftBC) + int64_t firstBC = collOrig.bc_as().globalBC() + (track.trackTime() - track.trackTimeRes()) / o2::constants::lhc::LHCBunchSpacingNS + shiftBC; + + bool rofHasBoth = false; // ROF with both FT0C and FT0A signal in the same BC + + std::vector v1; // Temporary null vector for the computation of the covariance matrix + SMatrix55 tcovs(v1.begin(), v1.end()); + SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); + + o2::track::TrackParCovFwd trackPar{track.z(), tpars, tcovs, track.chi2()}; + + // we propagate the MFT track to the mean z position of FT0-C + // getTrackPar() doesn't work because mft tracks don't have alpha + trackPar.propagateToZhelix(-82.6, Bz); // z in cm + + if (!isInFT0Acc(trackPar.getX(), trackPar.getY())) { + // track outside the FT0-C acceptance + BcMft(track.globalIndex(), filler.BCids); // empty + continue; + } + + std::vector goodBC; // contains the BCs matched with the current MFT track + int nCompBCwft0C = 0; + int nCompBCwft0s = 0; // Number of compatible BCs with FT0A AND C signals + + bool hasft0A = false; + bool hasft0C = false; + for (auto& bc : bcSlice) { + hasft0C = false; + hasft0A = false; + // printf("----------bcId %lld\n", bc.globalIndex()); + if (!bc.has_ft0s()) { + continue; + } + + auto ft0s = bc.ft0s(); + i = 0; // reinitialise + D = 0.0; + minD = 999.9; + for (auto const& ft0 : ft0s) { + // printf("---------ft0.bcId %d\n", ft0.bcId()); + if (ft0.channelA().size() > 0) { + // BC with signals in FT0A + hasft0A = true; + } + + if (ft0.channelC().size() > 0) { + hasft0C = true; + } + for (auto channelId : ft0.channelC()) { + + std::vector Xc = channelCoord[channelId]; //(xc,yc,zc) coordinates + // D in cm + D = sqrt(pow(Xc[0] * 0.1 - trackPar.getX(), 2) + pow(Xc[1] * 0.1 - trackPar.getY(), 2) + pow(Xc[2] * 0.1 - 1.87 - trackPar.getZ(), 2)); + // printf("----channelId %u, D %f, n %d\n", channelId, D, n);//should be between 96 and 207 + if (D < minD) { + minD = D; + } + + registry.fill(HIST("DistChannelToProp"), D); + } + + i += ft0.channelC().size(); + } + + registry.fill(HIST("NchannelsPerBC"), i); + if (hasft0C) { + nCompBCwft0C++; // number of compatible BCs that have ft0-C signal + } + + //----------------------- BC selection here ------------------------ + // if strictBCSel true we are only considering BC with signals from both FT0A and FT0C + if (!(hasft0A && hasft0C) && strictBCSel) { + continue; + // we go to the next BC + } + nCompBCwft0s++; + if (hasft0A && hasft0C) { + rofHasBoth = true; + } + + //----------------------- end of BC selection ------------------------ + + if (minD < 2) // 20 mm + { + goodBC.push_back(bc); // goodBC is a vector of bc + filler.BCids.emplace_back(bc.globalIndex()); + } + if (minD < globalMinD) { + globalMinD = minD; + closestBC = bc; + } + } + + if (!rofHasBoth) { + // there isn't a coincidence of FT0A and C inside the considered MFT ROF + // MFT track is probably noise, we don't select it + filler.BCids.clear(); + BcMft(track.globalIndex(), filler.BCids); // empty + continue; + } + registry.fill(HIST("NgoodBCperTrack"), goodBC.size()); + if (goodBC.size() == 0) { + registry.fill(HIST("UnMatchedTracksXY"), trackPar.getX(), trackPar.getY()); + } + if (goodBC.size() > 0) { + registry.fill(HIST("MatchedTracksXY"), trackPar.getX(), trackPar.getY()); + int64_t diff = goodBC[0].globalBC() - firstBC; + registry.fill(HIST("DiffInBC"), diff); + } + registry.fill(HIST("AllTracksXY"), trackPar.getX(), trackPar.getY()); + registry.fill(HIST("NCompBCwFT0C"), nCompBCwft0C); + registry.fill(HIST("NCompBCwFT0s"), nCompBCwft0s); + + if (nCompBCwft0s == 1) { + registry.fill(HIST("NgoodBCperTrackINDIV"), goodBC.size()); + + // position of the goodBC in the ROF for isolated colliding BCs + if (goodBC.size() > 0) { + int64_t diff = goodBC[0].globalBC() - firstBC; + registry.fill(HIST("DiffInBCINDIV"), diff); + } + } + + BcMft(track.globalIndex(), filler.BCids); + } // loop of mfttracks + } + PROCESS_SWITCH(matchmftft0, processMFT, "Process MFT tracks with collisions", true); +}; + +struct checkmatchinmc { + // checks if the matching works as expected in MC + // only doprocessMFTMCcheck==true if you are analysing MC + + HistogramRegistry registryMC{ + "registryMC", + {}}; + + void init(InitContext const&) + { + if (doprocessMFTMCcheck) { + registryMC.add({"TrackIsMatched", "; isMFTTrackMatched; #count", {HistType::kTH1I, {{2, 0, 2}}}}); + registryMC.add({"DiffInBCTrue", "; goodBC-trueBC (globalBC); #count", {HistType::kTH1I, {{800, -400, 400}}}}); + registryMC.add({"TrueBCAmongMatched", "; isTrueBCAmongMatchedOnes; #count", {HistType::kTH1D, {{2, 0, 2}}}}); + } + } + + using MFTTracksLabeledWithFT0 = soa::Join; + + void processMFTMCcheck(MFTTracksLabeledWithFT0 const& mfttracks, + aod::McCollisions const&, ExtBCs const&, aod::McParticles const&) + { + + for (auto& mfttrack : mfttracks) { + + if (!mfttrack.has_bcs()) // mft tracks having a match in FT0-C + { + registryMC.fill(HIST("TrackIsMatched"), 0); + continue; + } + + registryMC.fill(HIST("TrackIsMatched"), 1); // around 50% of all MFT tracks are matched with FT0-C in data + // around 90% of MFT tracks falling in the active FT0-C regions are matched + if (!mfttrack.has_mcParticle()) { + continue; + } + + o2::aod::McParticle particle = mfttrack.mcParticle(); + int64_t trueMFTBC = particle.mcCollision().bc_as().globalBC(); + ; + bool isTrueBCAmongMatchedOnes = false; + + for (auto& bc : mfttrack.bcs_as()) { // + int64_t bcDiffTrue = bc.globalBC() - trueMFTBC; // difference between the muon's BC and the MFT track's BC + registryMC.fill(HIST("DiffInBCTrue"), bcDiffTrue); + if (bcDiffTrue == 0) { + isTrueBCAmongMatchedOnes = true; + } + } + if (isTrueBCAmongMatchedOnes) { + registryMC.fill(HIST("TrueBCAmongMatched"), 1); + } else { + registryMC.fill(HIST("TrueBCAmongMatched"), 0); + } + } + } + PROCESS_SWITCH(checkmatchinmc, processMFTMCcheck, "Process MFT tracks and check matching with MC information", false); + + void processDummy(aod::Collisions const&) + { + // do nothing + } + PROCESS_SWITCH(checkmatchinmc, processDummy, "Do nothing if not MC", true); +}; + +WorkflowSpec + defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/Common/TableProducer/multiplicityExtraTable.cxx b/Common/TableProducer/multiplicityExtraTable.cxx index cc37a39e34b..6a6bc1a76a8 100644 --- a/Common/TableProducer/multiplicityExtraTable.cxx +++ b/Common/TableProducer/multiplicityExtraTable.cxx @@ -30,12 +30,16 @@ using BCPattern = std::bitset; const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; struct MultiplicityExtraTable { - Produces multBC; + Produces multBC; Produces multNeigh; + Produces mult2bc; + Produces bc2mult; + // Allow for downscaling of BC table for less space use in derived data Configurable bcDownscaleFactor{"bcDownscaleFactor", 2, "Downscale factor for BC table (0: save nothing, 1: save all)"}; Configurable minFT0CforBCTable{"minFT0CforBCTable", 25.0f, "Minimum FT0C amplitude to fill BC table to reduce data"}; + Configurable saveOnlyBCsWithCollisions{"saveOnlyBCsWithCollisions", true, "save only BCs with collisions in them"}; // needed for downscale unsigned int randomSeed = 0; @@ -59,117 +63,180 @@ struct MultiplicityExtraTable { using BCsWithRun3Matchings = soa::Join; - void processBCs(BCsWithRun3Matchings::iterator const& bc, aod::FV0As const&, aod::FT0s const&, aod::FDDs const&, aod::Zdcs const&) + void processBCs(soa::Join const& bcs, aod::FV0As const&, aod::FT0s const&, aod::FDDs const&, aod::Zdcs const&, soa::Join const& collisions) { - // downscale if requested to do so - if (bcDownscaleFactor < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > bcDownscaleFactor) { - return; + //+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ + // determine saved BCs and corresponding new BC table index + std::vector bcHasCollision(bcs.size()); + std::vector newBCindex(bcs.size()); + std::vector bc2multArray(bcs.size()); + int atIndex = 0; + for (const auto& bc : bcs) { + bcHasCollision[bc.globalIndex()] = false; + newBCindex[bc.globalIndex()] = -1; + bc2multArray[bc.globalIndex()] = -1; } - bool Tvx = false; - bool isFV0OrA = false; - float multFT0C = 0.f; - float multFT0A = 0.f; - float multFV0A = 0.f; - float multFDDA = 0.f; - float multFDDC = 0.f; - - // ZDC amplitudes - float multZEM1 = -1.f; - float multZEM2 = -1.f; - float multZNA = -1.f; - float multZNC = -1.f; - float multZPA = -1.f; - float multZPC = -1.f; - - uint8_t multFT0TriggerBits = 0; - uint8_t multFV0TriggerBits = 0; - uint8_t multFDDTriggerBits = 0; - uint64_t multBCTriggerMask = bc.triggerMask(); - - // initialize - from Arvind - newRunNumber = bc.runNumber(); - int localBC = bc.globalBC() % nBCsPerOrbit; - - if (newRunNumber != oldRunNumber) { - auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, newRunNumber); - auto ts = soreor.first; - - LOG(info) << " newRunNumber " << newRunNumber << " time stamp " << ts; - oldRunNumber = newRunNumber; - auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); - CollidingBunch = grplhcif->getBunchFilling().getBCPattern(); - } // new run number - - bool collidingBC = CollidingBunch.test(localBC); - - if (bc.has_ft0()) { - auto ft0 = bc.ft0(); - std::bitset<8> triggers = ft0.triggerMask(); - Tvx = triggers[o2::fit::Triggers::bitVertex]; - multFT0TriggerBits = static_cast(triggers.to_ulong()); - - // calculate T0 charge - for (auto amplitude : ft0.amplitudeA()) { - multFT0A += amplitude; - } - for (auto amplitude : ft0.amplitudeC()) { - multFT0C += amplitude; - } - } else { - multFT0A = -999.0f; - multFT0C = -999.0f; + //+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ + // tag BCs that have a collision (from evsel foundBC) + for (const auto& collision : collisions) { + bcHasCollision[collision.foundBCId()] = true; } - if (bc.has_fv0a()) { - auto fv0 = bc.fv0a(); - std::bitset<8> fV0Triggers = fv0.triggerMask(); - multFV0TriggerBits = static_cast(fV0Triggers.to_ulong()); + //+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ - for (auto amplitude : fv0.amplitude()) { - multFV0A += amplitude; + for (const auto& bc : bcs) { + // downscale if requested to do so + if (bcDownscaleFactor < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > bcDownscaleFactor) { + continue; } - isFV0OrA = fV0Triggers[o2::fit::Triggers::bitA]; - } else { - multFV0A = -999.0f; - } - if (bc.has_fdd()) { - auto fdd = bc.fdd(); - std::bitset<8> fFDDTriggers = fdd.triggerMask(); - multFDDTriggerBits = static_cast(fFDDTriggers.to_ulong()); + float multFT0C = 0.f; + if (bc.has_ft0()) { + auto ft0 = bc.ft0(); + for (auto amplitude : ft0.amplitudeC()) { + multFT0C += amplitude; + } + } else { + multFT0C = -999.0f; + } - for (auto amplitude : fdd.chargeA()) { - multFDDA += amplitude; + if (multFT0C < minFT0CforBCTable) { + continue; // skip this event } - for (auto amplitude : fdd.chargeC()) { - multFDDC += amplitude; + + if (saveOnlyBCsWithCollisions && !bcHasCollision[bc.globalIndex()]) { + continue; // skip if no collision is assigned to this BC (from evSel assignment) } - } else { - multFDDA = -999.0f; - multFDDC = -999.0f; - } - if (bc.has_zdc()) { - multZNA = bc.zdc().amplitudeZNA(); - multZNC = bc.zdc().amplitudeZNC(); - multZEM1 = bc.zdc().amplitudeZEM1(); - multZEM2 = bc.zdc().amplitudeZEM2(); - multZPA = bc.zdc().amplitudeZPA(); - multZPC = bc.zdc().amplitudeZPC(); - } else { - multZNA = -999.f; - multZNC = -999.f; - multZEM1 = -999.f; - multZEM2 = -999.f; - multZPA = -999.f; - multZPC = -999.f; + newBCindex[bc.globalIndex()] = atIndex++; } + //+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ - if (multFT0C < minFT0CforBCTable) { - return; // skip this event + //+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ + // interlink: collision -> valid BC, BC -> collision + for (const auto& collision : collisions) { + mult2bc(newBCindex[collision.foundBCId()]); + bc2multArray[collision.foundBCId()] = collision.globalIndex(); } + //+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ - multBC(multFT0A, multFT0C, multFV0A, multFDDA, multFDDC, multZNA, multZNC, multZEM1, multZEM2, multZPA, multZPC, Tvx, isFV0OrA, multFV0TriggerBits, multFT0TriggerBits, multFDDTriggerBits, multBCTriggerMask, collidingBC); + for (const auto& bc : bcs) { + if (newBCindex[bc.globalIndex()] < 0) { + continue; // don't keep if low mult or downsampled out + } + + bool Tvx = false; + bool isFV0OrA = false; + float multFT0C = 0.f; + float multFT0A = 0.f; + float multFV0A = 0.f; + float multFDDA = 0.f; + float multFDDC = 0.f; + + // ZDC amplitudes + float multZEM1 = -1.f; + float multZEM2 = -1.f; + float multZNA = -1.f; + float multZNC = -1.f; + float multZPA = -1.f; + float multZPC = -1.f; + + float posZFT0 = -1e+3; + bool posZFT0valid = false; + + uint8_t multFT0TriggerBits = 0; + uint8_t multFV0TriggerBits = 0; + uint8_t multFDDTriggerBits = 0; + uint64_t multBCTriggerMask = bc.triggerMask(); + + // initialize - from Arvind + newRunNumber = bc.runNumber(); + int localBC = bc.globalBC() % nBCsPerOrbit; + + if (newRunNumber != oldRunNumber) { + auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, newRunNumber); + auto ts = soreor.first; + + LOG(info) << " newRunNumber " << newRunNumber << " time stamp " << ts; + oldRunNumber = newRunNumber; + auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); + CollidingBunch = grplhcif->getBunchFilling().getBCPattern(); + } // new run number + + bool collidingBC = CollidingBunch.test(localBC); + + if (bc.has_ft0()) { + const auto& ft0 = bc.ft0(); + std::bitset<8> triggers = ft0.triggerMask(); + Tvx = triggers[o2::fit::Triggers::bitVertex]; + multFT0TriggerBits = static_cast(triggers.to_ulong()); + + // calculate T0 charge + for (auto amplitude : ft0.amplitudeA()) { + multFT0A += amplitude; + } + for (auto amplitude : ft0.amplitudeC()) { + multFT0C += amplitude; + } + posZFT0 = ft0.posZ(); + posZFT0valid = ft0.isValidTime(); + } else { + multFT0A = -999.0f; + multFT0C = -999.0f; + } + if (bc.has_fv0a()) { + auto fv0 = bc.fv0a(); + std::bitset<8> fV0Triggers = fv0.triggerMask(); + multFV0TriggerBits = static_cast(fV0Triggers.to_ulong()); + + for (auto amplitude : fv0.amplitude()) { + multFV0A += amplitude; + } + isFV0OrA = fV0Triggers[o2::fit::Triggers::bitA]; + } else { + multFV0A = -999.0f; + } + + if (bc.has_fdd()) { + auto fdd = bc.fdd(); + std::bitset<8> fFDDTriggers = fdd.triggerMask(); + multFDDTriggerBits = static_cast(fFDDTriggers.to_ulong()); + + for (auto amplitude : fdd.chargeA()) { + multFDDA += amplitude; + } + for (auto amplitude : fdd.chargeC()) { + multFDDC += amplitude; + } + } else { + multFDDA = -999.0f; + multFDDC = -999.0f; + } + + if (bc.has_zdc()) { + multZNA = bc.zdc().amplitudeZNA(); + multZNC = bc.zdc().amplitudeZNC(); + multZEM1 = bc.zdc().amplitudeZEM1(); + multZEM2 = bc.zdc().amplitudeZEM2(); + multZPA = bc.zdc().amplitudeZPA(); + multZPC = bc.zdc().amplitudeZPC(); + } else { + multZNA = -999.f; + multZNC = -999.f; + multZEM1 = -999.f; + multZEM2 = -999.f; + multZPA = -999.f; + multZPC = -999.f; + } + + bc2mult(bc2multArray[bc.globalIndex()]); + multBC( + multFT0A, multFT0C, posZFT0, posZFT0valid, multFV0A, + multFDDA, multFDDC, multZNA, multZNC, multZEM1, + multZEM2, multZPA, multZPC, Tvx, isFV0OrA, + multFV0TriggerBits, multFT0TriggerBits, multFDDTriggerBits, multBCTriggerMask, collidingBC, + bc.flags()); + } } void processCollisionNeighbors(aod::Collisions const& collisions) diff --git a/Common/TableProducer/multiplicityTable.cxx b/Common/TableProducer/multiplicityTable.cxx index baf9ab6eb4b..5b7d69c4fc8 100644 --- a/Common/TableProducer/multiplicityTable.cxx +++ b/Common/TableProducer/multiplicityTable.cxx @@ -43,7 +43,7 @@ static constexpr int kFV0MultZeqs = 9; static constexpr int kFT0MultZeqs = 10; static constexpr int kFDDMultZeqs = 11; static constexpr int kPVMultZeqs = 12; -static constexpr int kMultsExtraMC = 13; +static constexpr int kMultMCExtras = 13; static constexpr int nTables = 14; // Checking that the Zeq tables are after the normal ones @@ -66,7 +66,7 @@ static const std::vector tableNames{"FV0Mults", // 0 "FT0MultZeqs", // 10 "FDDMultZeqs", // 11 "PVMultZeqs", // 12 - "MultsExtraMC"}; // 13 + "MultMCExtras"}; // 13 static const std::vector parameterNames{"Enable"}; static const int defaultParameters[nTables][nParameters]{{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}}; @@ -85,7 +85,8 @@ struct MultiplicityTable { Produces tableFT0Zeqs; // 10 Produces tableFDDZeqs; // 11 Produces tablePVZeqs; // 12 - Produces tableExtraMc; // 13 + Produces tableExtraMc; // 13 + Produces tableExtraMult2MCExtras; Produces multsGlobal; // Not accounted for, produced based on process function processGlobalTrackingCounters // For vertex-Z corrections in calibration @@ -109,8 +110,12 @@ struct MultiplicityTable { {defaultParameters[0], nTables, nParameters, tableNames, parameterNames}, "Produce tables depending on needs. Values different than -1 override the automatic setup: the corresponding table can be set off (0) or on (1)"}; - Configurable ccdbUrl{"ccdburl", "http://alice-ccdb.cern.ch", "The CCDB endpoint url address"}; - Configurable ccdbPath{"ccdbpath", "Centrality/Calibration", "The CCDB path for centrality/multiplicity information"}; + struct : ConfigurableGroup { + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "The CCDB endpoint url address"}; + Configurable ccdbPath{"ccdbpath", "Centrality/Calibration", "The CCDB path for centrality/multiplicity information"}; + Configurable reconstructionPass{"reconstructionPass", "", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}}; + } ccdbConfig; + Configurable produceHistograms{"produceHistograms", false, {"Option to produce debug histograms"}}; int mRunNumber; @@ -159,10 +164,10 @@ struct MultiplicityTable { } } // Handle the custom cases. - if (tEnabled[kMultsExtraMC]) { - if (enabledTables->get(tableNames[kMultsExtraMC].c_str(), "Enable") == -1) { + if (tEnabled[kMultMCExtras]) { + if (enabledTables->get(tableNames[kMultMCExtras].c_str(), "Enable") == -1) { doprocessMC.value = true; - LOG(info) << "Enabling MC processing due to " << tableNames[kMultsExtraMC] << " table being enabled."; + LOG(info) << "Enabling MC processing due to " << tableNames[kMultMCExtras] << " table being enabled."; } } @@ -195,7 +200,7 @@ struct MultiplicityTable { hVtxZFDDC = nullptr; hVtxZNTracks = nullptr; - ccdb->setURL(ccdbUrl); + ccdb->setURL(ccdbConfig.ccdburl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); // don't fatal, please - exception is caught explicitly (as it should) @@ -274,14 +279,15 @@ struct MultiplicityTable { tablePv(multNContribs, multNContribsEta1, multNContribsEtaHalf); } - using Run3Tracks = soa::Join; - Partition tracksIUWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); - Partition pvAllContribTracksIU = ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); - Partition pvContribTracksIU = (nabs(aod::track::eta) < 0.8f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); - Partition pvContribTracksIUEta1 = (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); - Partition pvContribTracksIUEtaHalf = (nabs(aod::track::eta) < 0.5f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + using Run3TracksIU = soa::Join; + Partition tracksIUWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + Partition pvAllContribTracksIU = ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + Partition pvContribTracksIU = (nabs(aod::track::eta) < 0.8f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + Partition pvContribTracksIUEta1 = (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + Partition pvContribTracksIUEtaHalf = (nabs(aod::track::eta) < 0.5f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + void processRun3(soa::Join const& collisions, - Run3Tracks const&, + Run3TracksIU const&, BCsWithRun3Matchings const&, aod::Zdcs const&, aod::FV0As const&, @@ -330,7 +336,7 @@ struct MultiplicityTable { case kPVMultZeqs: // Equalized multiplicity for PV tablePVZeqs.reserve(collisions.size()); break; - case kMultsExtraMC: // MC extra information (nothing to do in the data) + case kMultMCExtras: // MC extra information (nothing to do in the data) break; default: LOG(fatal) << "Unknown table requested: " << i; @@ -372,7 +378,18 @@ struct MultiplicityTable { if (doVertexZeq > 0) { if (bc.runNumber() != mRunNumber) { mRunNumber = bc.runNumber(); // mark this run as at least tried - lCalibObjects = ccdb->getForTimeStamp(ccdbPath, bc.timestamp()); + if (ccdbConfig.reconstructionPass.value == "") { + lCalibObjects = ccdb->getForTimeStamp(ccdbConfig.ccdbPath, bc.timestamp()); + } else if (ccdbConfig.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + lCalibObjects = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = ccdbConfig.reconstructionPass.value; + lCalibObjects = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + } + if (lCalibObjects) { if (produceHistograms) { listCalib->Add(lCalibObjects->Clone(Form("%i", bc.runNumber()))); @@ -499,11 +516,14 @@ struct MultiplicityTable { const auto& tracksThisCollision = pvContribTracksIUEta1.sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); multNContribsEta1 = tracksThisCollision.size(); for (auto track : tracksThisCollision) { - if (std::abs(track.eta()) < 0.8) + if (std::abs(track.eta()) < 0.8) { multNContribs++; - if (std::abs(track.eta()) < 0.5) + } + if (std::abs(track.eta()) < 0.5) { multNContribsEtaHalf++; + } } + tablePv(multNContribs, multNContribsEta1, multNContribsEtaHalf); LOGF(debug, "multNContribs=%i, multNContribsEta1=%i, multNContribsEtaHalf=%i", multNContribs, multNContribsEta1, multNContribsEtaHalf); } break; @@ -548,7 +568,7 @@ struct MultiplicityTable { tableExtra(collision.numContrib(), collision.chi2(), collision.collisionTimeRes(), mRunNumber, collision.posZ(), collision.sel8(), nHasITS, nHasTPC, nHasTOF, nHasTRD, nITSonly, nTPConly, nITSTPC, - nAllTracksTPCOnly, nAllTracksITSTPC, bcNumber, collision.trackOccupancyInTimeRange()); + nAllTracksTPCOnly, nAllTracksITSTPC, collision.trackOccupancyInTimeRange(), collision.flags()); } break; case kMultSelections: // Multiplicity selections { @@ -590,7 +610,7 @@ struct MultiplicityTable { } tablePVZeqs(multZeqNContribs); } break; - case kMultsExtraMC: // MC only (nothing to do) + case kMultMCExtras: // MC only (nothing to do) { } break; default: // Default @@ -608,7 +628,7 @@ struct MultiplicityTable { Filter mcParticleFilter = (aod::mcparticle::eta < 4.9f) && (aod::mcparticle::eta > -3.3f); using mcParticlesFiltered = soa::Filtered; - void processMC(aod::McCollision const&, mcParticlesFiltered const& mcParticles) + void processMC(aod::McCollision const& mcCollision, mcParticlesFiltered const& mcParticles) { int multFT0A = 0; int multFT0C = 0; @@ -643,23 +663,57 @@ struct MultiplicityTable { if (3.5 < mcPart.eta() && mcPart.eta() < 4.9) multFT0A++; } - tableExtraMc(multFT0A, multFT0C, multBarrelEta05, multBarrelEta08, multBarrelEta10); + tableExtraMc(multFT0A, multFT0C, multBarrelEta05, multBarrelEta08, multBarrelEta10, mcCollision.posZ()); + } + + void processMC2Mults(soa::Join::iterator const& collision) + { + tableExtraMult2MCExtras(collision.mcCollisionId()); // interlink } - void processGlobalTrackingCounters(aod::Collision const&, - soa::Join const& tracks) + Configurable min_pt_globaltrack{"min_pt_globaltrack", 0.15, "min. pT for global tracks"}; + Configurable max_pt_globaltrack{"max_pt_globaltrack", 1e+10, "max. pT for global tracks"}; + Configurable min_ncluster_its_globaltrack{"min_ncluster_its_globaltrack", 5, "min. number of ITS clusters for global tracks"}; + Configurable min_ncluster_itsib_globaltrack{"min_ncluster_itsib_globaltrack", 1, "min. number of ITSib clusters for global tracks"}; + + using Run3Tracks = soa::Join; + Partition pvContribGlobalTracksEta1 = (min_pt_globaltrack < aod::track::pt && aod::track::pt < max_pt_globaltrack) && (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor) && requireQualityTracksInFilter(); + + void processGlobalTrackingCounters(aod::Collision const& collision, soa::Join const& tracksIU, Run3Tracks const&) { // counter from Igor int nGlobalTracks = 0; - for (auto& track : tracks) { + int multNContribsEta05_kGlobalTrackWoDCA = 0; + int multNContribsEta08_kGlobalTrackWoDCA = 0; + int multNContribsEta10_kGlobalTrackWoDCA = 0; + + auto pvContribGlobalTracksEta1_per_collision = pvContribGlobalTracksEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + for (auto& track : pvContribGlobalTracksEta1_per_collision) { + if (track.itsNCls() < min_ncluster_its_globaltrack || track.itsNClsInnerBarrel() < min_ncluster_itsib_globaltrack) { + continue; + } + multNContribsEta10_kGlobalTrackWoDCA++; + + if (std::abs(track.eta()) < 0.8) { + multNContribsEta08_kGlobalTrackWoDCA++; + } + if (std::abs(track.eta()) < 0.5) { + multNContribsEta05_kGlobalTrackWoDCA++; + } + } + + for (auto& track : tracksIU) { if (fabs(track.eta()) < 0.8 && track.tpcNClsFound() >= 80 && track.tpcNClsCrossedRows() >= 100) { if (track.isGlobalTrack()) { nGlobalTracks++; } } } - multsGlobal(nGlobalTracks); + + LOGF(debug, "nGlobalTracks = %d, multNContribsEta08_kGlobalTrackWoDCA = %d, multNContribsEta10_kGlobalTrackWoDCA = %d, multNContribsEta05_kGlobalTrackWoDCA = %d", nGlobalTracks, multNContribsEta08_kGlobalTrackWoDCA, multNContribsEta10_kGlobalTrackWoDCA, multNContribsEta05_kGlobalTrackWoDCA); + + multsGlobal(nGlobalTracks, multNContribsEta08_kGlobalTrackWoDCA, multNContribsEta10_kGlobalTrackWoDCA, multNContribsEta05_kGlobalTrackWoDCA); } // Process switches @@ -667,6 +721,7 @@ struct MultiplicityTable { PROCESS_SWITCH(MultiplicityTable, processRun3, "Produce Run 3 multiplicity tables", true); PROCESS_SWITCH(MultiplicityTable, processGlobalTrackingCounters, "Produce Run 3 global counters", false); PROCESS_SWITCH(MultiplicityTable, processMC, "Produce MC multiplicity tables", false); + PROCESS_SWITCH(MultiplicityTable, processMC2Mults, "Produce MC -> Mult map", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx index 93fe2ff7ca1..c878b78b988 100644 --- a/Common/TableProducer/qVectorsTable.cxx +++ b/Common/TableProducer/qVectorsTable.cxx @@ -59,9 +59,9 @@ struct qVectorsTable { kFT0A = 1, kFT0M, kFV0A, - kBPos, - kBNeg, - kBTot + kTPCpos, + kTPCneg, + kTPCall }; // Configurables. @@ -80,6 +80,7 @@ struct qVectorsTable { Configurable cfgMaxPtOnTPC{"cfgMaxPtOnTPC", 5., "maximum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"}; Configurable cfgCorrLevel{"cfgCorrLevel", 4, "calibration step: 0 = no corr, 1 = gain corr, 2 = rectr, 3 = twist, 4 = full"}; Configurable> cfgnMods{"cfgnMods", {2, 3}, "Modulation of interest"}; + Configurable cfgMaxCentrality{"cfgMaxCentrality", 100.f, "max. centrality for Q vector calibration"}; Configurable cfgGainEqPath{"cfgGainEqPath", "Users/j/junlee/Qvector/GainEq", "CCDB path for gain equalization constants"}; Configurable cfgQvecCalibPath{"cfgQvecCalibPath", "Analysis/EventPlane/QVecCorrections", "CCDB pasth for Q-vecteor calibration constants"}; @@ -90,9 +91,9 @@ struct qVectorsTable { Configurable cfgUseFT0A{"cfgUseFT0A", false, "Initial value for using FT0A. By default obtained from DataModel."}; Configurable cfgUseFT0M{"cfgUseFT0M", false, "Initial value for using FT0M. By default obtained from DataModel."}; Configurable cfgUseFV0A{"cfgUseFV0A", false, "Initial value for using FV0A. By default obtained from DataModel."}; - Configurable cfgUseBPos{"cfgUseBPos", false, "Initial value for using BPos. By default obtained from DataModel."}; - Configurable cfgUseBNeg{"cfgUseBNeg", false, "Initial value for using BNeg. By default obtained from DataModel."}; - Configurable cfgUseBTot{"cfgUseBTot", false, "Initial value for using BTot. By default obtained from DataModel."}; + Configurable cfgUseTPCpos{"cfgUseTPCpos", false, "Initial value for using TPCpos. By default obtained from DataModel."}; + Configurable cfgUseTPCneg{"cfgUseTPCneg", false, "Initial value for using TPCneg. By default obtained from DataModel."}; + Configurable cfgUseTPCall{"cfgUseTPCall", false, "Initial value for using TPCall. By default obtained from DataModel."}; // Table. Produces qVector; @@ -100,17 +101,17 @@ struct qVectorsTable { Produces qVectorFT0A; Produces qVectorFT0M; Produces qVectorFV0A; - Produces qVectorBPos; - Produces qVectorBNeg; - Produces qVectorBTot; + Produces qVectorTPCpos; + Produces qVectorTPCneg; + Produces qVectorTPCall; Produces qVectorFT0CVec; Produces qVectorFT0AVec; Produces qVectorFT0MVec; Produces qVectorFV0AVec; - Produces qVectorBPosVec; - Produces qVectorBNegVec; - Produces qVectorBTotVec; + Produces qVectorTPCposVec; + Produces qVectorTPCnegVec; + Produces qVectorTPCallVec; std::vector FT0RelGainConst{}; std::vector FV0RelGainConst{}; @@ -133,10 +134,27 @@ struct qVectorsTable { std::vector objQvec{}; + // Deprecated, will be removed in future after transition time // + Configurable cfgUseBPos{"cfgUseBPos", false, "Initial value for using BPos. By default obtained from DataModel."}; + Configurable cfgUseBNeg{"cfgUseBNeg", false, "Initial value for using BNeg. By default obtained from DataModel."}; + Configurable cfgUseBTot{"cfgUseBTot", false, "Initial value for using BTot. By default obtained from DataModel."}; + + Produces qVectorBPos; + Produces qVectorBNeg; + Produces qVectorBTot; + + Produces qVectorBPosVec; + Produces qVectorBNegVec; + Produces qVectorBTotVec; + ///////////////////////////////////////////////////////////////// + std::unordered_map useDetector = { {"QvectorBTots", cfgUseBTot}, {"QvectorBNegs", cfgUseBNeg}, {"QvectorBPoss", cfgUseBPos}, + {"QvectorTPCalls", cfgUseTPCall}, + {"QvectorTPCnegs", cfgUseTPCneg}, + {"QvectorTPCposs", cfgUseTPCpos}, {"QvectorFV0As", cfgUseFV0A}, {"QvectorFT0Ms", cfgUseFT0M}, {"QvectorFT0As", cfgUseFT0A}, @@ -156,7 +174,8 @@ struct qVectorsTable { goto allDetectorsInUse; // Added to break from nested loop if all detectors are in use. } for (auto det : useDetector) { - if (input.matcher.binding == det.first) { + std::string table_name_with_vector = det.first; // for replacing s with Vecs at the end. + if (input.matcher.binding == det.first || input.matcher.binding == table_name_with_vector.replace(table_name_with_vector.size() - 1, 1, "Vecs")) { useDetector[det.first.data()] = true; LOGF(info, Form("Using detector: %s.", det.first.data())); } @@ -219,7 +238,7 @@ struct qVectorsTable { } objQvec.clear(); - for (auto i = 0; i < cfgnMods->size(); i++) { + for (std::size_t i = 0; i < cfgnMods->size(); i++) { int ind = cfgnMods->at(i); fullPath = cfgQvecCalibPath; fullPath += "/v"; @@ -281,15 +300,15 @@ struct qVectorsTable { } template - void CalQvec(const Nmode nmode, const CollType& coll, const TrackType& track, std::vector& QvecRe, std::vector& QvecIm, std::vector& QvecAmp, std::vector& TrkBPosLabel, std::vector& TrkBNegLabel, std::vector& TrkBTotLabel) + void CalQvec(const Nmode nmode, const CollType& coll, const TrackType& track, std::vector& QvecRe, std::vector& QvecIm, std::vector& QvecAmp, std::vector& TrkTPCposLabel, std::vector& TrkTPCnegLabel, std::vector& TrkTPCallLabel) { float qVectFT0A[2] = {0.}; float qVectFT0C[2] = {0.}; float qVectFT0M[2] = {0.}; float qVectFV0A[2] = {0.}; - float qVectBPos[2] = {0.}; - float qVectBNeg[2] = {0.}; - float qVectBTot[2] = {0.}; + float qVectTPCpos[2] = {0.}; + float qVectTPCneg[2] = {0.}; + float qVectTPCall[2] = {0.}; TComplex QvecDet(0); TComplex QvecFT0M(0); @@ -392,56 +411,59 @@ struct qVectorsTable { qVectFV0A[1] = -999.; } - int nTrkBPos = 0; - int nTrkBNeg = 0; - int nTrkBTot = 0; + int nTrkTPCpos = 0; + int nTrkTPCneg = 0; + int nTrkTPCall = 0; for (auto& trk : track) { if (!SelTrack(trk)) { continue; } histosQA.fill(HIST("ChTracks"), trk.pt(), trk.eta(), trk.phi(), cent); - if (std::abs(trk.eta()) < 0.1 || std::abs(trk.eta()) > 0.8) { + if (std::abs(trk.eta()) > 0.8) { + continue; + } + qVectTPCall[0] += trk.pt() * std::cos(trk.phi() * nmode); + qVectTPCall[1] += trk.pt() * std::sin(trk.phi() * nmode); + TrkTPCallLabel.push_back(trk.globalIndex()); + nTrkTPCall++; + if (std::abs(trk.eta()) < 0.1) { continue; } - if (trk.eta() > 0 && useDetector["QvectorBPoss"]) { - qVectBPos[0] += trk.pt() * std::cos(trk.phi() * nmode); - qVectBPos[1] += trk.pt() * std::sin(trk.phi() * nmode); - TrkBPosLabel.push_back(trk.globalIndex()); - nTrkBPos++; - } else if (trk.eta() < 0 && useDetector["QvectorBNegs"]) { - qVectBNeg[0] += trk.pt() * std::cos(trk.phi() * nmode); - qVectBNeg[1] += trk.pt() * std::sin(trk.phi() * nmode); - TrkBNegLabel.push_back(trk.globalIndex()); - nTrkBNeg++; + if (trk.eta() > 0 && (useDetector["QvectorTPCposs"] || useDetector["QvectorBPoss"])) { + qVectTPCpos[0] += trk.pt() * std::cos(trk.phi() * nmode); + qVectTPCpos[1] += trk.pt() * std::sin(trk.phi() * nmode); + TrkTPCposLabel.push_back(trk.globalIndex()); + nTrkTPCpos++; + } else if (trk.eta() < 0 && (useDetector["QvectorTPCnegs"] || useDetector["QvectorBNegs"])) { + qVectTPCneg[0] += trk.pt() * std::cos(trk.phi() * nmode); + qVectTPCneg[1] += trk.pt() * std::sin(trk.phi() * nmode); + TrkTPCnegLabel.push_back(trk.globalIndex()); + nTrkTPCneg++; } - qVectBTot[0] += trk.pt() * std::cos(trk.phi() * nmode); - qVectBTot[1] += trk.pt() * std::sin(trk.phi() * nmode); - TrkBTotLabel.push_back(trk.globalIndex()); - nTrkBTot++; } - if (nTrkBPos > 0) { - qVectBPos[0] /= nTrkBPos; - qVectBPos[1] /= nTrkBPos; + if (nTrkTPCpos > 0) { + qVectTPCpos[0] /= nTrkTPCpos; + qVectTPCpos[1] /= nTrkTPCpos; } else { - qVectBPos[0] = 999.; - qVectBPos[1] = 999.; + qVectTPCpos[0] = 999.; + qVectTPCpos[1] = 999.; } - if (nTrkBNeg > 0) { - qVectBNeg[0] /= nTrkBNeg; - qVectBNeg[1] /= nTrkBNeg; + if (nTrkTPCneg > 0) { + qVectTPCneg[0] /= nTrkTPCneg; + qVectTPCneg[1] /= nTrkTPCneg; } else { - qVectBNeg[0] = 999.; - qVectBNeg[1] = 999.; + qVectTPCneg[0] = 999.; + qVectTPCneg[1] = 999.; } - if (nTrkBTot > 0) { - qVectBTot[0] /= nTrkBTot; - qVectBTot[1] /= nTrkBTot; + if (nTrkTPCall > 0) { + qVectTPCall[0] /= nTrkTPCall; + qVectTPCall[1] /= nTrkTPCall; } else { - qVectBTot[0] = 999.; - qVectBTot[1] = 999.; + qVectTPCall[0] = 999.; + qVectTPCall[1] = 999.; } for (auto i{0u}; i < 4; i++) { @@ -461,32 +483,32 @@ struct qVectorsTable { QvecIm.push_back(qVectFV0A[1]); } for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectBPos[0]); - QvecIm.push_back(qVectBPos[1]); + QvecRe.push_back(qVectTPCpos[0]); + QvecIm.push_back(qVectTPCpos[1]); } for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectBNeg[0]); - QvecIm.push_back(qVectBNeg[1]); + QvecRe.push_back(qVectTPCneg[0]); + QvecIm.push_back(qVectTPCneg[1]); } for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectBTot[0]); - QvecIm.push_back(qVectBTot[1]); + QvecRe.push_back(qVectTPCall[0]); + QvecIm.push_back(qVectTPCall[1]); } QvecAmp.push_back(sumAmplFT0C); QvecAmp.push_back(sumAmplFT0A); QvecAmp.push_back(sumAmplFT0M); QvecAmp.push_back(sumAmplFV0A); - QvecAmp.push_back(static_cast(nTrkBPos)); - QvecAmp.push_back(static_cast(nTrkBNeg)); - QvecAmp.push_back(static_cast(nTrkBTot)); + QvecAmp.push_back(static_cast(nTrkTPCpos)); + QvecAmp.push_back(static_cast(nTrkTPCneg)); + QvecAmp.push_back(static_cast(nTrkTPCall)); } void process(MyCollisions::iterator const& coll, aod::BCsWithTimestamps const&, aod::FT0s const&, aod::FV0As const&, MyTracks const& tracks) { - std::vector TrkBPosLabel{}; - std::vector TrkBNegLabel{}; - std::vector TrkBTotLabel{}; + std::vector TrkTPCposLabel{}; + std::vector TrkTPCnegLabel{}; + std::vector TrkTPCallLabel{}; std::vector qvecRe{}; std::vector qvecIm{}; std::vector qvecAmp{}; @@ -499,12 +521,12 @@ struct qVectorsTable { std::vector qvecImFT0M{}; std::vector qvecReFV0A{}; std::vector qvecImFV0A{}; - std::vector qvecReBPos{}; - std::vector qvecImBPos{}; - std::vector qvecReBNeg{}; - std::vector qvecImBNeg{}; - std::vector qvecReBTot{}; - std::vector qvecImBTot{}; + std::vector qvecReTPCpos{}; + std::vector qvecImTPCpos{}; + std::vector qvecReTPCneg{}; + std::vector qvecImTPCneg{}; + std::vector qvecReTPCall{}; + std::vector qvecImTPCall{}; auto bc = coll.bc_as(); int currentRun = bc.runNumber(); @@ -518,46 +540,46 @@ struct qVectorsTable { coll.centFV0A()}; cent = centAllEstim[cfgCentEsti]; bool IsCalibrated = true; - if (cent < 0. || cent > 80.) { + if (cent < 0. || cent > cfgMaxCentrality) { cent = 110.; IsCalibrated = false; } - for (auto id = 0; id < cfgnMods->size(); id++) { + for (std::size_t id = 0; id < cfgnMods->size(); id++) { int ind = cfgnMods->at(id); - CalQvec(ind, coll, tracks, qvecRe, qvecIm, qvecAmp, TrkBPosLabel, TrkBNegLabel, TrkBTotLabel); - if (cent < 80) { - for (auto i{0u}; i < 6; i++) { - helperEP.DoRecenter(qvecRe[(kBTot + 1) * 4 * id + i * 4 + 1], qvecIm[(kBTot + 1) * 4 * id + i * 4 + 1], + CalQvec(ind, coll, tracks, qvecRe, qvecIm, qvecAmp, TrkTPCposLabel, TrkTPCnegLabel, TrkTPCallLabel); + if (cent < cfgMaxCentrality) { + for (auto i{0u}; i < kTPCall + 1; i++) { + helperEP.DoRecenter(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 1], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 1], objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 1, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 2, i + 1)); - helperEP.DoRecenter(qvecRe[(kBTot + 1) * 4 * id + i * 4 + 2], qvecIm[(kBTot + 1) * 4 * id + i * 4 + 2], + helperEP.DoRecenter(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 2], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 2], objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 1, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 2, i + 1)); - helperEP.DoTwist(qvecRe[(kBTot + 1) * 4 * id + i * 4 + 2], qvecIm[(kBTot + 1) * 4 * id + i * 4 + 2], + helperEP.DoTwist(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 2], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 2], objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 3, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 4, i + 1)); - helperEP.DoRecenter(qvecRe[(kBTot + 1) * 4 * id + i * 4 + 3], qvecIm[(kBTot + 1) * 4 * id + i * 4 + 3], + helperEP.DoRecenter(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 3], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 3], objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 1, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 2, i + 1)); - helperEP.DoTwist(qvecRe[(kBTot + 1) * 4 * id + i * 4 + 3], qvecIm[(kBTot + 1) * 4 * id + i * 4 + 3], + helperEP.DoTwist(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 3], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 3], objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 3, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 4, i + 1)); - helperEP.DoRescale(qvecRe[(kBTot + 1) * 4 * id + i * 4 + 3], qvecIm[(kBTot + 1) * 4 * id + i * 4 + 3], + helperEP.DoRescale(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 3], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 3], objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 5, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 6, i + 1)); } } int CorrLevel = cfgCorrLevel == 0 ? 0 : cfgCorrLevel - 1; - qvecReFT0C.push_back(qvecRe[(kBTot + 1) * 4 * id + kFT0C * 4 + CorrLevel]); - qvecImFT0C.push_back(qvecIm[(kBTot + 1) * 4 * id + kFT0C * 4 + CorrLevel]); - qvecReFT0A.push_back(qvecRe[(kBTot + 1) * 4 * id + kFT0A * 4 + CorrLevel]); - qvecImFT0A.push_back(qvecIm[(kBTot + 1) * 4 * id + kFT0A * 4 + CorrLevel]); - qvecReFT0M.push_back(qvecRe[(kBTot + 1) * 4 * id + kFT0M * 4 + CorrLevel]); - qvecImFT0M.push_back(qvecIm[(kBTot + 1) * 4 * id + kFT0M * 4 + CorrLevel]); - qvecReFV0A.push_back(qvecRe[(kBTot + 1) * 4 * id + kFV0A * 4 + CorrLevel]); - qvecImFV0A.push_back(qvecIm[(kBTot + 1) * 4 * id + kFV0A * 4 + CorrLevel]); - qvecReBPos.push_back(qvecRe[(kBTot + 1) * 4 * id + kBPos * 4 + CorrLevel]); - qvecImBPos.push_back(qvecIm[(kBTot + 1) * 4 * id + kBPos * 4 + CorrLevel]); - qvecReBNeg.push_back(qvecRe[(kBTot + 1) * 4 * id + kBNeg * 4 + CorrLevel]); - qvecImBNeg.push_back(qvecIm[(kBTot + 1) * 4 * id + kBNeg * 4 + CorrLevel]); - qvecReBTot.push_back(qvecRe[(kBTot + 1) * 4 * id + kBTot * 4 + CorrLevel]); - qvecImBTot.push_back(qvecIm[(kBTot + 1) * 4 * id + kBTot * 4 + CorrLevel]); + qvecReFT0C.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + CorrLevel]); + qvecImFT0C.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + CorrLevel]); + qvecReFT0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + CorrLevel]); + qvecImFT0A.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + CorrLevel]); + qvecReFT0M.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + CorrLevel]); + qvecImFT0M.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + CorrLevel]); + qvecReFV0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + CorrLevel]); + qvecImFV0A.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + CorrLevel]); + qvecReTPCpos.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + CorrLevel]); + qvecImTPCpos.push_back(qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + CorrLevel]); + qvecReTPCneg.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + CorrLevel]); + qvecImTPCneg.push_back(qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + CorrLevel]); + qvecReTPCall.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + CorrLevel]); + qvecImTPCall.push_back(qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + CorrLevel]); } // Fill the columns of the Qvectors table. @@ -570,20 +592,34 @@ struct qVectorsTable { qVectorFT0M(IsCalibrated, qvecReFT0M.at(0), qvecImFT0M.at(0), qvecAmp[kFT0M]); if (useDetector["QvectorFV0As"]) qVectorFV0A(IsCalibrated, qvecReFV0A.at(0), qvecImFV0A.at(0), qvecAmp[kFV0A]); - if (useDetector["QvectorBPoss"]) - qVectorBPos(IsCalibrated, qvecReBPos.at(0), qvecImBPos.at(0), qvecAmp[kBPos], TrkBPosLabel); - if (useDetector["QvectorBNegs"]) - qVectorBNeg(IsCalibrated, qvecReBNeg.at(0), qvecImBNeg.at(0), qvecAmp[kBNeg], TrkBNegLabel); - if (useDetector["QvectorBTots"]) - qVectorBTot(IsCalibrated, qvecReBTot.at(0), qvecImBTot.at(0), qvecAmp[kBTot], TrkBTotLabel); + if (useDetector["QvectorTPCposs"]) + qVectorTPCpos(IsCalibrated, qvecReTPCpos.at(0), qvecImTPCpos.at(0), qvecAmp[kTPCpos], TrkTPCposLabel); + if (useDetector["QvectorTPCnegs"]) + qVectorTPCneg(IsCalibrated, qvecReTPCneg.at(0), qvecImTPCneg.at(0), qvecAmp[kTPCneg], TrkTPCnegLabel); + if (useDetector["QvectorTPCalls"]) + qVectorTPCall(IsCalibrated, qvecReTPCall.at(0), qvecImTPCall.at(0), qvecAmp[kTPCall], TrkTPCallLabel); qVectorFT0CVec(IsCalibrated, qvecReFT0C, qvecImFT0C, qvecAmp[kFT0C]); qVectorFT0AVec(IsCalibrated, qvecReFT0A, qvecImFT0A, qvecAmp[kFT0A]); qVectorFT0MVec(IsCalibrated, qvecReFT0M, qvecImFT0M, qvecAmp[kFT0M]); qVectorFV0AVec(IsCalibrated, qvecReFV0A, qvecImFV0A, qvecAmp[kFV0A]); - qVectorBPosVec(IsCalibrated, qvecReBPos, qvecImBPos, qvecAmp[kBPos], TrkBPosLabel); - qVectorBNegVec(IsCalibrated, qvecReBNeg, qvecImBNeg, qvecAmp[kBNeg], TrkBNegLabel); - qVectorBTotVec(IsCalibrated, qvecReBTot, qvecImBTot, qvecAmp[kBTot], TrkBTotLabel); + qVectorTPCposVec(IsCalibrated, qvecReTPCpos, qvecImTPCpos, qvecAmp[kTPCpos], TrkTPCposLabel); + qVectorTPCnegVec(IsCalibrated, qvecReTPCneg, qvecImTPCneg, qvecAmp[kTPCneg], TrkTPCnegLabel); + qVectorTPCallVec(IsCalibrated, qvecReTPCall, qvecImTPCall, qvecAmp[kTPCall], TrkTPCallLabel); + + // Deprecated, will be removed in future after transition time // + if (useDetector["QvectorBPoss"]) + qVectorBPos(IsCalibrated, qvecReTPCpos.at(0), qvecImTPCpos.at(0), qvecAmp[kTPCpos], TrkTPCposLabel); + if (useDetector["QvectorBNegs"]) + qVectorBNeg(IsCalibrated, qvecReTPCneg.at(0), qvecImTPCneg.at(0), qvecAmp[kTPCneg], TrkTPCnegLabel); + if (useDetector["QvectorBTots"]) + qVectorBTot(IsCalibrated, qvecReTPCall.at(0), qvecImTPCall.at(0), qvecAmp[kTPCall], TrkTPCallLabel); + + qVectorBPosVec(IsCalibrated, qvecReTPCpos, qvecImTPCpos, qvecAmp[kTPCpos], TrkTPCposLabel); + qVectorBNegVec(IsCalibrated, qvecReTPCneg, qvecImTPCneg, qvecAmp[kTPCneg], TrkTPCnegLabel); + qVectorBTotVec(IsCalibrated, qvecReTPCall, qvecImTPCall, qvecAmp[kTPCall], TrkTPCallLabel); + ///////////////////////////////////////////////////////////////// + } // End process. }; diff --git a/Common/TableProducer/timestamp.cxx b/Common/TableProducer/timestamp.cxx index c108bf32713..e3d37f7129b 100644 --- a/Common/TableProducer/timestamp.cxx +++ b/Common/TableProducer/timestamp.cxx @@ -23,25 +23,31 @@ #include "CCDB/BasicCCDBManager.h" #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsRaw/HBFUtils.h" +#include "MetadataHelper.h" using namespace o2::framework; using namespace o2::header; using namespace o2; +MetadataHelper metadataInfo; // Metadata helper + struct TimestampTask { Produces timestampTable; /// Table with SOR timestamps produced by the task Service ccdb; /// CCDB manager to access orbit-reset timestamp o2::ccdb::CcdbApi ccdb_api; /// API to access CCDB headers + Configurable fatalOnInvalidTimestamp{"fatalOnInvalidTimestamp", false, "Generate fatal error for invalid timestamps"}; std::map mapRunToOrbitReset; /// Cache of orbit reset timestamps + std::map> mapRunToRunDuration; /// Cache of run duration timestamps int lastRunNumber = 0; /// Last run number processed int64_t orbitResetTimestamp = 0; /// Orbit-reset timestamp in us + std::pair runDuration; /// Pair of SOR and EOR timestamps // Configurables Configurable verbose{"verbose", false, "verbose mode"}; Configurable rct_path{"rct-path", "RCT/Info/RunInformation", "path to the ccdb RCT objects for the SOR timestamps"}; Configurable orbit_reset_path{"orbit-reset-path", "CTP/Calib/OrbitReset", "path to the ccdb orbit-reset objects"}; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB database"}; - Configurable isRun2MC{"isRun2MC", false, "Running mode: enable only for Run 2 MC. Timestamps are set to SOR timestamp"}; + Configurable isRun2MC{"isRun2MC", -1, "Running mode: enable only for Run 2 MC. Timestamps are set to SOR timestamp. Default: -1 (autoset from metadata) 0 (Standard) 1 (Run 2 MC)"}; void init(o2::framework::InitContext&) { @@ -51,6 +57,14 @@ struct TimestampTask { if (!ccdb_api.isHostReachable()) { LOGF(fatal, "CCDB host %s is not reacheable, cannot go forward", url.value.data()); } + if (isRun2MC.value == -1) { + if ((!metadataInfo.isRun3()) && metadataInfo.isMC()) { + isRun2MC.value = 1; + LOG(info) << "Autosetting the Run2 MC mode based on metadata"; + } else { + isRun2MC.value = 0; + } + } } void process(aod::BC const& bc) @@ -64,14 +78,15 @@ struct TimestampTask { } else if (mapRunToOrbitReset.count(runNumber)) { // The run number was already requested before: getting it from cache! LOGF(debug, "Getting orbit-reset timestamp from cache"); orbitResetTimestamp = mapRunToOrbitReset[runNumber]; + runDuration = mapRunToRunDuration[runNumber]; } else { // The run was not requested before: need to acccess CCDB! LOGF(debug, "Getting start-of-run and end-of-run timestamps from CCDB"); - auto timestamps = ccdb->getRunDuration(runNumber, true); /// fatalise if timestamps are not found - int64_t sorTimestamp = timestamps.first; // timestamp of the SOR in ms - int64_t eorTimestamp = timestamps.second; // timestamp of the EOR in ms + runDuration = ccdb->getRunDuration(runNumber, true); /// fatalise if timestamps are not found + int64_t sorTimestamp = runDuration.first; // timestamp of the SOR/SOX/STF in ms + int64_t eorTimestamp = runDuration.second; // timestamp of the EOR/EOX/ETF in ms - bool isUnanchoredRun3MC = runNumber >= 300000 && runNumber < 500000; - if (isRun2MC || isUnanchoredRun3MC) { + const bool isUnanchoredRun3MC = runNumber >= 300000 && runNumber < 500000; + if (isRun2MC.value == 1 || isUnanchoredRun3MC) { // isRun2MC: bc/orbit distributions are not simulated in Run2 MC. All bcs are set to 0. // isUnanchoredRun3MC: assuming orbit-reset is done in the beginning of each run // Setting orbit-reset timestamp to start-of-run timestamp @@ -83,7 +98,7 @@ struct TimestampTask { } else { // sometimes orbit is reset after SOR. Using EOR timestamps for orbitReset query is more reliable LOGF(debug, "Getting orbit-reset timestamp using end-of-run timestamp from CCDB"); - auto ctp = ccdb->getForTimeStamp>(orbit_reset_path.value.data(), eorTimestamp); + auto ctp = ccdb->getForTimeStamp>(orbit_reset_path.value.data(), eorTimestamp / 2 + sorTimestamp / 2); orbitResetTimestamp = (*ctp)[0]; } @@ -93,18 +108,29 @@ struct TimestampTask { if (!check.second) { LOGF(fatal, "Run number %i already existed with a orbit-reset timestamp of %llu", runNumber, check.first->second); } - LOGF(info, "Add new run number %i with orbit-reset timestamp %llu to cache", runNumber, orbitResetTimestamp); + mapRunToRunDuration[runNumber] = runDuration; + LOGF(info, "Add new run number %i with orbit-reset timestamp %llu, SOR: %llu, EOR: %llu to cache", runNumber, orbitResetTimestamp, runDuration.first, runDuration.second); } if (verbose.value) { LOGF(info, "Orbit-reset timestamp for run number %i found: %llu us", runNumber, orbitResetTimestamp); } - - timestampTable((orbitResetTimestamp + int64_t(bc.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000); // us -> ms + int64_t timestamp{(orbitResetTimestamp + int64_t(bc.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000}; // us -> ms + if (timestamp < runDuration.first || timestamp > runDuration.second) { + if (fatalOnInvalidTimestamp.value) { + LOGF(fatal, "Timestamp %llu us is out of run duration [%llu, %llu] ms", timestamp, runDuration.first, runDuration.second); + } else { + LOGF(debug, "Timestamp %llu us is out of run duration [%llu, %llu] ms", timestamp, runDuration.first, runDuration.second); + } + } + timestampTable(timestamp); } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + // Parse the metadata + metadataInfo.initMetadata(cfgc); + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/Common/TableProducer/zdc-task-intercalib.cxx b/Common/TableProducer/zdc-task-intercalib.cxx new file mode 100644 index 00000000000..62596ee1f43 --- /dev/null +++ b/Common/TableProducer/zdc-task-intercalib.cxx @@ -0,0 +1,154 @@ +// Copyright 2019-2020 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. +/// +/// \brief Task for ZDC tower inter-calibration +/// \author chiara.oppedisano@cern.ch +// Minimal example to run this task: +// export OPTIONS="-b --configuration json://config.json --aod-file AO2D.root" +// o2-analysis-timestamp ${OPTIONS} | +// o2-analysis-event-selection ${OPTIONS} | +// o2-analysis-track-propagation ${OPTIONS} | +// o2-analysis-mm-zdc-task-intercalib ${OPTIONS} + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/ZDCInterCalib.h" + +#include "TH1F.h" +#include "TH2F.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::evsel; + +constexpr double kVeryNegative = -1.e12; +constexpr int ndet = 2; +constexpr int npar = 6; +static double mSum[ndet][npar][npar]; +static double mAdd[npar][npar]; + +using BCsRun3 = soa::Join; +using ColEvSels = soa::Join; + +struct zdcInterCalib { + + Produces zTab; + + // Configurable parameters + // + Configurable nBins{"nBins", 400, "n bins"}; + Configurable MaxZN{"MaxZN", 399.5, "Max ZN signal"}; + // + HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + registry.add("ZNApmc", "ZNApmc; ZNA PMC; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNCpmc", "ZNCpmc; ZNC PMC; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNApm1", "ZNApm1; ZNA PM1; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNApm2", "ZNApm2; ZNA PM2; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNApm3", "ZNApm3; ZNA PM3; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNApm4", "ZNApm4; ZNA PM4; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNCpm1", "ZNCpm1; ZNC PM1; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNCpm2", "ZNCpm2; ZNC PM2; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNCpm3", "ZNCpm3; ZNC PM3; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNCpm4", "ZNCpm4; ZNC PM4; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNAsumq", "ZNAsumq; ZNA uncalib. sum PMQ; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + registry.add("ZNCsumq", "ZNCsumq; ZNC uncalib. sum PMQ; Entries", {HistType::kTH1F, {{nBins, -0.5, MaxZN}}}); + } + + void process(ColEvSels const& cols, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) + { + // collision-based event selection + for (auto& collision : cols) { + const auto& foundBC = collision.foundBC_as(); + if (foundBC.has_zdc()) { + const auto& zdc = foundBC.zdc(); + + // To assure that ZN have a genuine signal (tagged by the relative TDC) + // we can check that the amplitude is >0 or that ADC is NOT very negative (-inf) + // If this is not the case, signals are set to kVeryNegative values + double pmcZNC = zdc.energyCommonZNC(); + double pmcZNA = zdc.energyCommonZNA(); + // + // double tdcZNC = zdc.zdc.timeZNC(); + // double tdcZNA = zdc.zdc.timeZNA(); + // + bool isZNChit = true, isZNAhit = true; + if (pmcZNC < kVeryNegative) { + pmcZNC = kVeryNegative; + isZNChit = false; + } + if (pmcZNA < kVeryNegative) { + pmcZNA = kVeryNegative; + isZNAhit = false; + } + // + double sumZNC = 0; + double sumZNA = 0; + double pmqZNC[4] = { + 0, + 0, + 0, + 0, + }; + double pmqZNA[4] = { + 0, + 0, + 0, + 0, + }; + // + if (isZNChit) { + for (int it = 0; it < 4; it++) { + pmqZNC[it] = (zdc.energySectorZNC())[it]; + sumZNC += pmqZNC[it]; + } + registry.get(HIST("ZNCpmc"))->Fill(pmcZNC); + registry.get(HIST("ZNCpm1"))->Fill(pmqZNC[0]); + registry.get(HIST("ZNCpm2"))->Fill(pmqZNC[1]); + registry.get(HIST("ZNCpm3"))->Fill(pmqZNC[2]); + registry.get(HIST("ZNCpm4"))->Fill(pmqZNC[3]); + registry.get(HIST("ZNCsumq"))->Fill(sumZNC); + } + if (isZNAhit) { + for (int it = 0; it < 4; it++) { + pmqZNA[it] = (zdc.energySectorZNA())[it]; + sumZNA += pmqZNA[it]; + } + // + registry.get(HIST("ZNApmc"))->Fill(pmcZNA); + registry.get(HIST("ZNApm1"))->Fill(pmqZNA[0]); + registry.get(HIST("ZNApm2"))->Fill(pmqZNA[1]); + registry.get(HIST("ZNApm3"))->Fill(pmqZNA[2]); + registry.get(HIST("ZNApm4"))->Fill(pmqZNA[3]); + registry.get(HIST("ZNAsumq"))->Fill(sumZNA); + } + if (isZNAhit || isZNChit) + zTab(pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3]); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/Tasks/centralityStudy.cxx b/Common/Tasks/centralityStudy.cxx index 399b0f5c208..1ba72958a37 100644 --- a/Common/Tasks/centralityStudy.cxx +++ b/Common/Tasks/centralityStudy.cxx @@ -181,7 +181,7 @@ struct centralityStudy { if constexpr (requires { collision.centFT0C(); }) { // process FT0C centrality plots histos.fill(HIST("hNContribsVsCentrality"), collision.centFT0C(), collision.multPVTotalContributors()); - histos.fill(HIST("hNITSTPCTracksVsCentrality"), collision.centFT0C(), collision.multNTracksITSOnly()); + histos.fill(HIST("hNITSTPCTracksVsCentrality"), collision.centFT0C(), collision.multNTracksITSTPC()); histos.fill(HIST("hNITSOnlyTracksVsCentrality"), collision.centFT0C(), collision.multNTracksITSOnly()); histos.fill(HIST("hNGlobalTracksVsCentrality"), collision.centFT0C(), collision.multNTracksGlobal()); histos.fill(HIST("hPVChi2VsCentrality"), collision.centFT0C(), collision.multPVChi2()); @@ -203,7 +203,7 @@ struct centralityStudy { genericProcessCollision(collision); } - void processBCs(aod::MultsBC::iterator const& multbc) + void processBCs(aod::MultBCs::iterator const& multbc) { // process BCs, calculate FT0C distribution // conditionals suggested by FIT team (Jacek O. et al) diff --git a/Common/Tasks/multiplicityQa.cxx b/Common/Tasks/multiplicityQa.cxx index 72fc827606a..3bf0f769b79 100644 --- a/Common/Tasks/multiplicityQa.cxx +++ b/Common/Tasks/multiplicityQa.cxx @@ -402,7 +402,7 @@ struct MultiplicityQa { histos.fill(HIST("multiplicityQa/h2dFT0MVsNchT0M"), nchFT0, biggestFT0); } - void processFIT(aod::MultsBC const& multsdebug) + void processFIT(aod::MultBCs const& multsdebug) { for (auto& mult : multsdebug) { histos.fill(HIST("multiplicityQa/hIsolatedFT0A"), mult.multBCFT0A()); diff --git a/Common/Tasks/qVectorsCorrection.cxx b/Common/Tasks/qVectorsCorrection.cxx index bdb2d537fbf..bc9c555e154 100644 --- a/Common/Tasks/qVectorsCorrection.cxx +++ b/Common/Tasks/qVectorsCorrection.cxx @@ -25,6 +25,7 @@ #include #include #include +#include // o2Physics includes. #include "Framework/AnalysisDataModel.h" @@ -37,7 +38,11 @@ #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/TrackSelection.h" + +#include "CommonConstants/PhysicsConstants.h" // o2 includes. @@ -45,6 +50,7 @@ using namespace o2; using namespace o2::framework; using MyCollisions = soa::Join; +using MyTracks = soa::Join; struct qVectorsCorrection { // No correction = recenter, recentered Qvectors = twist, twisted Qvectors = rescale. @@ -55,16 +61,38 @@ struct qVectorsCorrection { // as TDirectoryFile. HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - Configurable cfgnMod{"cfgnMod", 2, "Modulation of interest"}; + Configurable> cfgnMods{"cfgnMods", {2, 3}, "Modulation of interest"}; Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; - Configurable cfgRefAName{"cfgRefAName", "BPos", "The name of detector for reference A"}; - Configurable cfgRefBName{"cfgRefBName", "BNeg", "The name of detector for reference B"}; + Configurable cfgRefAName{"cfgRefAName", "TPCpos", "The name of detector for reference A"}; + Configurable cfgRefBName{"cfgRefBName", "TPCneg", "The name of detector for reference B"}; Configurable cfgAddEvtSel{"cfgAddEvtSel", true, "event selection"}; - ConfigurableAxis cfgaxisQvecF{"cfgaxisQvecF", {100, -1, 1}, ""}; + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "total qvector number"}; + Configurable cfgNbinsEP{"cfgNbinsEP", 360, "nbins for EP histograms"}; + + Configurable cfgQAAll{"cfgQAAll", false, "draw all q-vector steps"}; + Configurable cfgQAFinal{"cfgQAFinal", false, "draw final q-vector steps"}; + Configurable cfgQAFlowStudy{"cfgQAFlowStudy", false, "configurable for flow study"}; + Configurable cfgQAOccupancyStudy{"cfgQAOccupancyStudy", false, "configurable for occupancy study"}; + + Configurable cfgMinPt{"cfgMinPt", 0.15, "Minimum transverse momentum for charged track"}; + Configurable cfgMaxEta{"cfgMaxEta", 0.8, "Maximum pseudorapidiy for charged track"}; + Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.1, "Maximum transverse DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 1.0, "Maximum longitudinal DCA"}; + + Configurable cfgMaxOccupancy{"cfgMaxOccupancy", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgMinOccupancy{"cfgMinOccupancy", 0, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + + ConfigurableAxis cfgaxisQvecF{"cfgaxisQvecF", {300, -1, 1}, ""}; ConfigurableAxis cfgaxisQvec{"cfgaxisQvec", {100, -3, 3}, ""}; - ConfigurableAxis cfgaxisCent{"cfgaxisCent", {90, 0, 90}, ""}; + ConfigurableAxis cfgaxisCent{"cfgaxisCent", {100, 0, 100}, ""}; + + ConfigurableAxis cfgaxiscos{"cfgaxiscos", {102, -1.02, 1.02}, ""}; + ConfigurableAxis cfgaxispt{"cfgaxispt", {100, 0, 10}, ""}; + ConfigurableAxis cfgaxisCentMerged{"cfgaxisCentMerged", {20, 0, 100}, ""}; + ConfigurableAxis cfgaxisAzimuth{"cfgaxisAzimuth", {72, 0, 2.0 * constants::math::PI}, ""}; + ConfigurableAxis cfgaxisOccupancy{"cfgaxisOccupancy", {VARIABLE_WIDTH, -1, 0, 100, 500, 1000, 2000, 3000, 4000, 5000, 10000, 99999}, ""}; // Helper variables. EventPlaneHelper helperEP; @@ -76,6 +104,9 @@ struct qVectorsCorrection { template int GetDetId(const T& name) { + if (name.value == "BPos" || name.value == "BNeg" || name.value == "BTot") { + LOGF(warning, "Using deprecated label: %s. Please use TPCpos, TPCneg, TPCall instead.", name.value); + } if (name.value == "FT0C") { return 0; } else if (name.value == "FT0A") { @@ -84,15 +115,40 @@ struct qVectorsCorrection { return 2; } else if (name.value == "FV0A") { return 3; - } else if (name.value == "BPos") { + } else if (name.value == "TPCpos" || name.value == "BPos") { return 4; - } else if (name.value == "BNeg") { + } else if (name.value == "TPCneg" || name.value == "BNeg") { return 5; + } else if (name.value == "TPCall" || name.value == "BTot") { + return 6; } else { return 0; } } + template + bool SelTrack(const TrackType track) + { + if (track.pt() < 0.15) + return false; + if (!track.passedITSNCls()) + return false; + if (!track.passedITSChi2NDF()) + return false; + if (!track.passedITSHits()) + return false; + if (!track.passedTPCCrossedRowsOverNCls()) + return false; + if (!track.passedTPCChi2NDF()) + return false; + if (!track.passedDCAxy()) + return false; + if (!track.passedDCAz()) + return false; + + return true; + } + void init(InitContext const&) { DetId = GetDetId(cfgDetName); @@ -100,7 +156,7 @@ struct qVectorsCorrection { RefBId = GetDetId(cfgRefBName); if (DetId == RefAId || DetId == RefBId || RefAId == RefBId) { - LOGF(info, "Wrong detector configuration \n The FT0C will be used to get Q-Vector \n The BPos and BNeg will be used as reference systems"); + LOGF(info, "Wrong detector configuration \n The FT0C will be used to get Q-Vector \n The TPCpos and TPCneg will be used as reference systems"); DetId = 0; RefAId = 4; RefBId = 5; @@ -110,95 +166,378 @@ struct qVectorsCorrection { AxisSpec axisCent{cfgaxisCent, "centrality"}; AxisSpec axisQvec{cfgaxisQvec, "Q"}; AxisSpec axisQvecF{cfgaxisQvecF, "Q"}; - AxisSpec axisEvtPl{360, -constants::math::PI, constants::math::PI}; + AxisSpec axisEvtPl{cfgNbinsEP, -constants::math::PI, constants::math::PI}; + + AxisSpec axisCos{cfgaxiscos, "angle function"}; + AxisSpec axisPt{cfgaxispt, "trasverse momentum"}; + AxisSpec axisCentMerged{cfgaxisCentMerged, "merged centrality"}; + AxisSpec axisAzimuth{cfgaxisAzimuth, "relative azimuthal angle"}; + AxisSpec axisOccupancy{cfgaxisOccupancy, "Occupancy"}; histosQA.add("histCentFull", "Centrality distribution for valid events", HistType::kTH1F, {axisCent}); - histosQA.add("histQvecUncor", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRectr", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecTwist", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecFinal", "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); + for (uint i = 0; i < cfgnMods->size(); i++) { + histosQA.add(Form("histQvecUncorV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRefAUncorV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRefBUncorV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefAUncor", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefARectr", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefATwist", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefAFinal", "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); + histosQA.add(Form("histEvtPlUncorV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRefAUncorV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRefBUncorV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histQvecRefBUncor", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefBRectr", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefBTwist", "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add("histQvecRefBFinal", "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); + if (cfgQAOccupancyStudy) { + histosQA.add(Form("histQvecOccUncorV%d", cfgnMods->at(i)), "", {HistType::kTHnSparseF, {axisQvecF, axisQvecF, axisCent, axisOccupancy}}); + histosQA.add(Form("histQvecRefAOccUncorV%d", cfgnMods->at(i)), "", {HistType::kTHnSparseF, {axisQvecF, axisQvecF, axisCent, axisOccupancy}}); + histosQA.add(Form("histQvecRefBOccUncorV%d", cfgnMods->at(i)), "", {HistType::kTHnSparseF, {axisQvecF, axisQvecF, axisCent, axisOccupancy}}); + } - histosQA.add("histEvtPlUncor", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRectr", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlTwist", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlFinal", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + if (cfgQAFinal) { + histosQA.add(Form("histQvecFinalV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); + histosQA.add(Form("histQvecRefAFinalV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); + histosQA.add(Form("histQvecRefBFinalV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); - histosQA.add("histEvtPlRefAUncor", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRefARectr", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRefATwist", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRefAFinal", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + if (cfgQAOccupancyStudy) { + histosQA.add(Form("histQvecOccFinalV%d", cfgnMods->at(i)), "", {HistType::kTHnSparseF, {axisQvecF, axisQvecF, axisCent, axisOccupancy}}); + histosQA.add(Form("histQvecRefAOccFinalV%d", cfgnMods->at(i)), "", {HistType::kTHnSparseF, {axisQvecF, axisQvecF, axisCent, axisOccupancy}}); + histosQA.add(Form("histQvecRefBOccFinalV%d", cfgnMods->at(i)), "", {HistType::kTHnSparseF, {axisQvecF, axisQvecF, axisCent, axisOccupancy}}); + } - histosQA.add("histEvtPlRefBUncor", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRefBRectr", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRefBTwist", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRefBFinal", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histQvecRes_SigRefAV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRes_SigRefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRes_RefARefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisQvecF, axisCent}}); - histosQA.add("histEvtPlRes_SigRefA", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRes_SigRefB", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add("histEvtPlRes_RefARefB", "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlFinalV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRefAFinalV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRefBFinalV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - } // End void init(InitContext const&) + histosQA.add(Form("histEvtPlRes_SigRefAV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRes_SigRefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRes_RefARefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - // Definition of all the needed template functions. - template - void fillHistosQvec(const T& vec) - { - if (vec.qvecAmp()[DetId] > 1e-8) { - histosQA.fill(HIST("histQvecUncor"), vec.qvecRe()[DetId * 4], vec.qvecIm()[DetId * 4], vec.cent()); - histosQA.fill(HIST("histQvecRectr"), vec.qvecRe()[DetId * 4 + 1], vec.qvecIm()[DetId * 4 + 1], vec.cent()); - histosQA.fill(HIST("histQvecTwist"), vec.qvecRe()[DetId * 4 + 2], vec.qvecIm()[DetId * 4 + 2], vec.cent()); - histosQA.fill(HIST("histQvecFinal"), vec.qvecRe()[DetId * 4 + 3], vec.qvecIm()[DetId * 4 + 3], vec.cent()); - - histosQA.fill(HIST("histEvtPlUncor"), helperEP.GetEventPlane(vec.qvecRe()[DetId * 4], vec.qvecIm()[DetId * 4], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRectr"), helperEP.GetEventPlane(vec.qvecRe()[DetId * 4 + 1], vec.qvecIm()[DetId * 4 + 1], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlTwist"), helperEP.GetEventPlane(vec.qvecRe()[DetId * 4 + 2], vec.qvecIm()[DetId * 4 + 2], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlFinal"), helperEP.GetEventPlane(vec.qvecRe()[DetId * 4 + 3], vec.qvecIm()[DetId * 4 + 3], cfgnMod), vec.cent()); - } + histosQA.add(Form("hist_EP_cos_Det_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("hist_EP_sin_Det_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("hist_EP_azimuth_Det_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisAzimuth}}); - if (vec.qvecAmp()[RefAId] > 1e-8) { - histosQA.fill(HIST("histQvecRefAUncor"), vec.qvecRe()[RefAId * 4], vec.qvecIm()[RefAId * 4], vec.cent()); - histosQA.fill(HIST("histQvecRefARectr"), vec.qvecRe()[RefAId * 4 + 1], vec.qvecIm()[RefAId * 4 + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefATwist"), vec.qvecRe()[RefAId * 4 + 2], vec.qvecIm()[RefAId * 4 + 2], vec.cent()); - histosQA.fill(HIST("histQvecRefAFinal"), vec.qvecRe()[RefAId * 4 + 3], vec.qvecIm()[RefAId * 4 + 3], vec.cent()); + histosQA.add(Form("hist_EP_cos_RefA_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("hist_EP_sin_RefA_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("hist_EP_azimuth_RefA_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisAzimuth}}); - histosQA.fill(HIST("histEvtPlRefAUncor"), helperEP.GetEventPlane(vec.qvecRe()[RefAId * 4], vec.qvecIm()[RefAId * 4], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRefARectr"), helperEP.GetEventPlane(vec.qvecRe()[RefAId * 4 + 1], vec.qvecIm()[RefAId * 4 + 1], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRefATwist"), helperEP.GetEventPlane(vec.qvecRe()[RefAId * 4 + 2], vec.qvecIm()[RefAId * 4 + 2], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinal"), helperEP.GetEventPlane(vec.qvecRe()[RefAId * 4 + 3], vec.qvecIm()[RefAId * 4 + 3], cfgnMod), vec.cent()); - } + histosQA.add(Form("hist_EP_cos_RefB_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("hist_EP_sin_RefB_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("hist_EP_azimuth_RefB_v%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisAzimuth}}); - if (vec.qvecAmp()[RefBId] > 1e-8) { - histosQA.fill(HIST("histQvecRefBUncor"), vec.qvecRe()[RefBId * 4], vec.qvecIm()[RefBId * 4], vec.cent()); - histosQA.fill(HIST("histQvecRefBRectr"), vec.qvecRe()[RefBId * 4 + 1], vec.qvecIm()[RefBId * 4 + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefBTwist"), vec.qvecRe()[RefBId * 4 + 2], vec.qvecIm()[RefBId * 4 + 2], vec.cent()); - histosQA.fill(HIST("histQvecRefBFinal"), vec.qvecRe()[RefBId * 4 + 3], vec.qvecIm()[RefBId * 4 + 3], vec.cent()); + if (cfgQAAll) { + histosQA.add(Form("histQvecRectrV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecTwistV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.fill(HIST("histEvtPlRefBUncor"), helperEP.GetEventPlane(vec.qvecRe()[RefBId * 4], vec.qvecIm()[RefBId * 4], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRefBRectr"), helperEP.GetEventPlane(vec.qvecRe()[RefBId * 4 + 1], vec.qvecIm()[RefBId * 4 + 1], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRefBTwist"), helperEP.GetEventPlane(vec.qvecRe()[RefBId * 4 + 2], vec.qvecIm()[RefBId * 4 + 2], cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinal"), helperEP.GetEventPlane(vec.qvecRe()[RefBId * 4 + 3], vec.qvecIm()[RefBId * 4 + 3], cfgnMod), vec.cent()); + histosQA.add(Form("histQvecRefARectrV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRefATwistV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + + histosQA.add(Form("histQvecRefBRectrV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRefBTwistV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + + histosQA.add(Form("histEvtPlRectrV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlTwistV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + + histosQA.add(Form("histEvtPlRefARectrV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRefATwistV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + + histosQA.add(Form("histEvtPlRefBRectrV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRefBTwistV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + } + } } + } // End void init(InitContext const&) - if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8) { - histosQA.fill(HIST("histEvtPlRes_SigRefA"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetId * 4 + 3], vec.qvecIm()[DetId * 4 + 3], cfgnMod), helperEP.GetEventPlane(vec.qvecRe()[RefAId * 4 + 3], vec.qvecIm()[RefAId * 4 + 3], cfgnMod), cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefB"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetId * 4 + 3], vec.qvecIm()[DetId * 4 + 3], cfgnMod), helperEP.GetEventPlane(vec.qvecRe()[RefBId * 4 + 3], vec.qvecIm()[RefBId * 4 + 3], cfgnMod), cfgnMod), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefB"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAId * 4 + 3], vec.qvecIm()[RefAId * 4 + 3], cfgnMod), helperEP.GetEventPlane(vec.qvecRe()[RefBId * 4 + 3], vec.qvecIm()[RefBId * 4 + 3], cfgnMod), cfgnMod), vec.cent()); + template + void fillHistosFlow(const CollType& coll, const TrackType& track, int nmode) + { + if (coll.qvecAmp()[DetId] < 1e-8 || coll.qvecAmp()[RefAId] < 1e-8 || coll.qvecAmp()[RefBId] < 1e-8) { + return; + } + int DetInd = DetId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int RefAInd = RefAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int RefBInd = RefBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + for (auto& trk : track) { + if (!SelTrack(trk)) { + continue; + } + + if (std::abs(trk.eta()) > 0.8) { + continue; + } + + if (nmode == 2) { + histosQA.fill(HIST("hist_EP_cos_Det_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_Det_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_Det_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + + histosQA.fill(HIST("hist_EP_cos_RefA_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_RefA_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_RefA_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + + histosQA.fill(HIST("hist_EP_cos_RefB_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_RefB_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_RefB_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + } else if (nmode == 3) { + histosQA.fill(HIST("hist_EP_cos_Det_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_Det_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_Det_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + + histosQA.fill(HIST("hist_EP_cos_RefA_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_RefA_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_RefA_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + + histosQA.fill(HIST("hist_EP_cos_RefB_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_RefB_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_RefB_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + } else if (nmode == 4) { + histosQA.fill(HIST("hist_EP_cos_Det_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_Det_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_Det_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + + histosQA.fill(HIST("hist_EP_cos_RefA_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_RefA_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_RefA_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + + histosQA.fill(HIST("hist_EP_cos_RefB_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_sin_RefB_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_azimuth_RefB_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + } } } - void process(MyCollisions::iterator const& qVec) + // Definition of all the needed template functions. + template + void fillHistosQvec(const T& vec, int nmode) + { + int DetInd = DetId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int RefAInd = RefAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int RefBInd = RefBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + if (nmode == 2) { + if (vec.qvecAmp()[DetId] > 1e-8) { + histosQA.fill(HIST("histQvecUncorV2"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent()); + histosQA.fill(HIST("histEvtPlUncorV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecOccUncorV2"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecFinalV2"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecOccFinalV2"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRectrV2"), vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecTwistV2"), vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRectrV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlTwistV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[RefAId] > 1e-8) { + histosQA.fill(HIST("histQvecRefAUncorV2"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent()); + histosQA.fill(HIST("histEvtPlRefAUncorV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefAOccUncorV2"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecRefAFinalV2"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlRefAFinalV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefAOccFinalV2"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRefARectrV2"), vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecRefATwistV2"), vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRefARectrV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefATwistV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[RefBId] > 1e-8) { + histosQA.fill(HIST("histQvecRefBUncorV2"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent()); + histosQA.fill(HIST("histEvtPlRefBUncorV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefBOccUncorV2"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecRefBFinalV2"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlRefBFinalV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefBOccFinalV2"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRefBRectrV2"), vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecRefBTwistV2"), vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRefBRectrV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefBTwistV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8 && cfgQAFinal) { + histosQA.fill(HIST("histQvecRes_SigRefAV2"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefAInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefAInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_SigRefBV2"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_RefARefBV2"), vec.qvecRe()[RefAInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[RefAInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + } + } else if (nmode == 3) { + if (vec.qvecAmp()[DetId] > 1e-8) { + histosQA.fill(HIST("histQvecUncorV3"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent()); + histosQA.fill(HIST("histEvtPlUncorV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecOccUncorV3"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecOccFinalV3"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + histosQA.fill(HIST("histQvecFinalV3"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), vec.cent()); + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRectrV3"), vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecTwistV3"), vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRectrV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlTwistV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[RefAId] > 1e-8) { + histosQA.fill(HIST("histQvecRefAUncorV3"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent()); + histosQA.fill(HIST("histEvtPlRefAUncorV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefAOccUncorV3"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecRefAFinalV3"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlRefAFinalV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefAOccFinalV3"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRefARectrV3"), vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecRefATwistV3"), vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRefARectrV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefATwistV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[RefBId] > 1e-8) { + histosQA.fill(HIST("histQvecRefBUncorV3"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent()); + histosQA.fill(HIST("histEvtPlRefBUncorV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefBOccUncorV3"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecRefBFinalV3"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlRefBFinalV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefBOccFinalV3"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRefBRectrV3"), vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecRefBTwistV3"), vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRefBRectrV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefBTwistV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8 && cfgQAFinal) { + histosQA.fill(HIST("histQvecRes_SigRefAV3"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefAInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefAInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_SigRefBV3"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_RefARefBV3"), vec.qvecRe()[RefAInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[RefAInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + } + } else if (nmode == 4) { + if (vec.qvecAmp()[DetId] > 1e-8) { + histosQA.fill(HIST("histQvecUncorV4"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent()); + histosQA.fill(HIST("histEvtPlUncorV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecOccUncorV4"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecFinalV4"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlFinalV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecOccFinalV4"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRectrV4"), vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecTwistV4"), vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRectrV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlTwistV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[RefAId] > 1e-8) { + histosQA.fill(HIST("histQvecRefAUncorV4"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent()); + histosQA.fill(HIST("histEvtPlRefAUncorV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefAOccUncorV4"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecRefAFinalV4"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlRefAFinalV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefAOccFinalV4"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRefARectrV4"), vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecRefATwistV4"), vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRefARectrV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefATwistV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[RefBId] > 1e-8) { + histosQA.fill(HIST("histQvecRefBUncorV4"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent()); + histosQA.fill(HIST("histEvtPlRefBUncorV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefBOccUncorV4"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAFinal) { + histosQA.fill(HIST("histQvecRefBFinalV4"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histEvtPlRefBFinalV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), vec.cent()); + if (cfgQAOccupancyStudy) { + histosQA.fill(HIST("histQvecRefBOccFinalV4"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + } + if (cfgQAAll) { + histosQA.fill(HIST("histQvecRefBRectrV4"), vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], vec.cent()); + histosQA.fill(HIST("histQvecRefBTwistV4"), vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], vec.cent()); + + histosQA.fill(HIST("histEvtPlRefBRectrV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefBTwistV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], nmode), vec.cent()); + } + } + } + if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8 && cfgQAFinal) { + histosQA.fill(HIST("histQvecRes_SigRefAV4"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefAInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefAInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_SigRefBV4"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_RefARefBV4"), vec.qvecRe()[RefAInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[RefAInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + } + } + } + void process(MyCollisions::iterator const& qVec, MyTracks const& tracks) { histosQA.fill(HIST("histCentFull"), qVec.cent()); if (cfgAddEvtSel && (!qVec.sel8() || @@ -206,7 +545,16 @@ struct qVectorsCorrection { !qVec.selection_bit(aod::evsel::kNoSameBunchPileup))) { return; } - fillHistosQvec(qVec); + if (cfgAddEvtSel && (qVec.trackOccupancyInTimeRange() > cfgMaxOccupancy || qVec.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + return; + } + + for (uint i = 0; i < cfgnMods->size(); i++) { + fillHistosQvec(qVec, cfgnMods->at(i)); + if (cfgQAFinal && cfgQAFlowStudy) { + fillHistosFlow(qVec, tracks, cfgnMods->at(i)); + } + } } // End void process(...) }; diff --git a/Common/Tools/Multiplicity/multCalibrator.cxx b/Common/Tools/Multiplicity/multCalibrator.cxx index 51306f91160..e9931c0389f 100644 --- a/Common/Tools/Multiplicity/multCalibrator.cxx +++ b/Common/Tools/Multiplicity/multCalibrator.cxx @@ -40,7 +40,7 @@ multCalibrator::multCalibrator() : TNamed(), fInputFileName("AnalysisResults.root"), fOutputFileName("CCDB-objects.root"), fAnchorPointValue(-1), - fAnchorPointPercentage(90), + fAnchorPointPercentage(100), fCalibHists(0x0), fPrecisionHistogram(0x0) { diff --git a/Common/Tools/TrackTuner.h b/Common/Tools/TrackTuner.h index 0d5d8452c68..617c2602c97 100644 --- a/Common/Tools/TrackTuner.h +++ b/Common/Tools/TrackTuner.h @@ -586,7 +586,7 @@ struct TrackTuner { double trackParDcaZTuned = trackParDcaZMC + deltaDcaZTuned; // double dd0rpo=d0rpo-d0rpmc; - double deltaDcaXY = trackParDcaXYRec - trackParDcaXYMC; + double deltaDcaXY = trackParDcaXYRec - trackParDcaXYMC - dcaXYMeanMC; // double dd0rpn=dd0rpo*(sd0rpo>0. ? (sd0rpn/sd0rpo) : 1.); double deltaDcaXYTuned = deltaDcaXY * (dcaXYResMC > 0. ? (dcaXYResData / dcaXYResMC) : 1.); @@ -600,7 +600,7 @@ struct TrackTuner { if (debugInfo) { LOG(info) << dcaZResMC << ", " << dcaZResData << ", diff(DcaZ - DcaZMC): " << deltaDcaZ << ", diff upgraded: " << deltaDcaZTuned << ", DcaZ Data : " << trackParDcaZTuned; - LOG(info) << dcaXYResMC << ", " << dcaXYResData << ", diff(DcaY - DcaYMC): " << deltaDcaXY << ", diff upgraded: " << deltaDcaXYTuned << ", DcaY Data :" << trackParDcaXYTuned; + LOG(info) << dcaXYResMC << ", " << dcaXYResData << ", " << dcaXYMeanMC << ", diff(DcaY - DcaYMC - dcaXYMeanMC): " << deltaDcaXY << ", diff upgraded: " << deltaDcaXYTuned << ", DcaY Data :" << trackParDcaXYTuned; } // option mimic data // ---------------------- diff --git a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx index 8d3e170d17b..b41bc1faef4 100644 --- a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx +++ b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx @@ -25,6 +25,7 @@ #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" #include "TH1F.h" #include "TH2F.h" @@ -36,7 +37,8 @@ using namespace o2::aod::evsel; using BCsRun2 = soa::Join; using BCsRun3 = soa::Join; -using ColEvSels = soa::Join; +// using ColEvSels = soa::Join; +using ColEvSels = soa::Join; using FullTracksIU = soa::Join; struct DetectorOccupancyQaTask { @@ -47,7 +49,8 @@ struct DetectorOccupancyQaTask { Configurable confOccupancyHistCoeffNbins2D{"HistCoeffNbins2D", 1., "Coefficient for nBins in occupancy 2D histos"}; Configurable confOccupancyHistCoeffNbins3D{"HistCoeffNbins3D", 1., "Coefficient for nBins in occupancy 3D histos"}; Configurable confCoeffMaxNtracksThisEvent{"CoeffMaxNtracksThisEvent", 1., "Coefficient for max nTracks or FT0 ampl in histos in a given event"}; - Configurable confFlagApplyROFborderCut{"UseROFborderCut", true, "Use ROF border cut for a current event"}; + Configurable confFlagApplyROFborderCut{"ApplyROFborderCut", true, "Use ROF border cut for a current event"}; + Configurable confFlagApplyTFborderCut{"ApplyTFborderCut", true, "Use TF border cut for a current event"}; Configurable confFlagWhichTimeRange{"FlagWhichTimeRange", 0, "Whicn time range for occupancy calculation: 0 - symmetric, 1 - only past, 2 - only future"}; Configurable confFlagUseGlobalTracks{"FlagUseGlobalTracks", 0, "For small time bins, use global tracks counter instead of ITSTPC tracks"}; @@ -68,10 +71,13 @@ struct DetectorOccupancyQaTask { Configurable confAddTracksVsFwdHistos{"AddTracksVsFwdHistos", true, "0 - add histograms, 1 - skip"}; Configurable nBinsTracks{"nBinsTracks", 400, "N bins in n tracks histo"}; Configurable nMaxTracks{"nMaxTracks", 8000, "N max in n tracks histo"}; - Configurable nMaxGlobalTracks{"nMaxGlobalTracks", 4000, "N max in n tracks histo"}; + Configurable nMaxGlobalTracks{"nMaxGlobalTracks", 3000, "N max in n tracks histo"}; Configurable nBinsMultFwd{"nBinsMultFwd", 400, "N bins in mult fwd histo"}; Configurable nMaxMultFwd{"nMaxMultFwd", 200000, "N max in mult fwd histo"}; + Configurable nBinsOccupancy{"nBinsOccupancy", 150, "N bins for occupancy axis"}; + Configurable nMaxOccupancy{"nMaxOccupancy", 15000, "N for max of the occupancy axis"}; + uint64_t minGlobalBC = 0; Service ccdb; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -99,6 +105,17 @@ struct DetectorOccupancyQaTask { double kMaxOccup = confOccupancyHistCoeffNtracksForOccupancy; double kMaxThisEv = confCoeffMaxNtracksThisEvent; + AxisSpec axisBC{3601, -0.5, 3600.5, "bc"}; + histos.add("h2D_diff_FoundBC_vs_BC", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_multAbove10", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_multAbove20", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_multAbove50", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_multAbove100", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_hasTOF", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_hasTRD", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_hasTOF_multAbove10", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + histos.add("h2D_diff_FoundBC_vs_BC_hasTRD_multAbove10", "", kTH2D, {axisBC, {201, -100.5, 100.5, "foundBC-BC"}}); + if (confAddBasicQAhistos) { int nMax1D = kMaxThisEv * 8000; histos.add("hNumITS567tracksPerCollision", ";n tracks;n events", kTH1D, {{nMax1D, -0.5, nMax1D - 0.5}}); @@ -158,9 +175,13 @@ struct DetectorOccupancyQaTask { // QA of occupancy-based event selection histos.add("hOccupancy", "", kTH1D, {{15002, -1.5, 15000.5}}); + AxisSpec axisOccupancy{nBinsOccupancy, 0., nMaxOccupancy, "occupancy (n ITS tracks weighted)"}; + AxisSpec axisCentrality{100, 0, 100, "centrality, %"}; + histos.add("hCentrVsOccupancy", "hCentrVsOccupancy", kTH2F, {axisCentrality, axisOccupancy}); + if (confAddTracksVsFwdHistos) { AxisSpec axisNtracks{nBinsTracks, -0.5, nMaxTracks - 0.5, "n tracks"}; - AxisSpec axisNtracksGlobal{nMaxGlobalTracks, -0.5, nMaxGlobalTracks - 0.5, "n tracks"}; + AxisSpec axisNtracksGlobal{nBinsTracks, -0.5, nMaxGlobalTracks - 0.5, "n tracks"}; AxisSpec axisMultFw{nBinsMultFwd, 0., static_cast(nMaxMultFwd), "mult Fwd"}; histos.add("nTracksPV_vs_V0A_kNoHighOccupancyAgressive", "nTracksPV_vs_V0A_kNoHighOccupancyAgressive", kTH2F, {axisMultFw, axisNtracks}); @@ -200,6 +221,35 @@ struct DetectorOccupancyQaTask { histos.add("nTracksGlobal_vs_V0A_occup_Minus1", "nTracksGlobal_vs_V0A_occup_Minus1", kTH2F, {axisMultFw, axisNtracksGlobal}); histos.add("nTracksGlobal_vs_V0A_AntiNoCollInTimeRangeStandard", "nTracksGlobal_vs_V0A_AntiNoCollInTimeRangeStandard", kTH2F, {axisMultFw, axisNtracksGlobal}); histos.add("nTracksGlobal_vs_V0A_AntiNoCollInTimeRangeNarrow", "nTracksGlobal_vs_V0A_AntiNoCollInTimeRangeNarrow", kTH2F, {axisMultFw, axisNtracksGlobal}); + + histos.add("nTracksGlobal_vs_nPV_kNoHighOccupancyAgressive", "nTracksGlobal_vs_nPV_kNoHighOccupancyAgressive", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_kNoHighOccupancyStrict", "nTracksGlobal_vs_nPV_kNoHighOccupancyStrict", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_kNoHighOccupancyMedium", "nTracksGlobal_vs_nPV_kNoHighOccupancyMedium", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_kNoHighOccupancyRelaxed", "nTracksGlobal_vs_nPV_kNoHighOccupancyRelaxed", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_kNoHighOccupancyGentle", "nTracksGlobal_vs_nPV_kNoHighOccupancyGentle", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_kNoCollInTimeRangeStandard", "nTracksGlobal_vs_nPV_kNoCollInTimeRangeStandard", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_kNoCollInTimeRangeNarrow", "nTracksGlobal_vs_nPV_kNoCollInTimeRangeNarrow", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_250", "nTracksGlobal_vs_nPV_occup_0_250", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_500", "nTracksGlobal_vs_nPV_occup_0_500", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_750", "nTracksGlobal_vs_nPV_occup_0_750", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_2000", "nTracksGlobal_vs_nPV_occup_0_2000", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeStandard", "nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeStandard", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeNarrow", "nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeNarrow", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_noOccupSel", "nTracksGlobal_vs_nPV_noOccupSel", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeStandard_extraCuts", "nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeStandard_extraCuts", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_0_2000_kNoCollInTimeRangeStandard_extraCuts", "nTracksGlobal_vs_nPV_occup_0_2000_kNoCollInTimeRangeStandard_extraCuts", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_ABOVE_750", "nTracksGlobal_vs_nPV_occup_ABOVE_750", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_occup_Minus1", "nTracksGlobal_vs_nPV_occup_Minus1", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeStandard", "nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeStandard", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeNarrow", "nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeNarrow", kTH2F, {axisNtracks, axisNtracksGlobal}); + + histos.add("nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts", "nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts", kTH2F, {axisNtracks, axisNtracksGlobal}); + histos.add("nTracksGlobal_vs_nPV_QA_after_TFborderCut", "nTracksGlobal_vs_nPV_QA_after_TFborderCut", kTH2F, {axisNtracks, axisNtracksGlobal}); + + // 3D histograms with occupancy axis + histos.add("nTracksGlobal_vs_nPV_vs_occup_pure", "nTracksGlobal_vs_nPV_vs_occup_pure", kTH3F, {axisNtracks, axisNtracksGlobal, axisOccupancy}); + histos.add("nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeStandard", "nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeStandard", kTH3F, {axisNtracks, axisNtracksGlobal, axisOccupancy}); + histos.add("nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeNarrow", "nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeNarrow", kTH3F, {axisNtracks, axisNtracksGlobal, axisOccupancy}); } } @@ -274,6 +324,7 @@ struct DetectorOccupancyQaTask { int nITSTPCtracks = 0; int nITSTPCtracksPtEtaCuts = 0; int nTOFtracks = 0; + int nTRDtracks = 0; auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); for (auto& track : tracksGrouped) { if (!track.isPVContributor()) { @@ -283,6 +334,7 @@ struct DetectorOccupancyQaTask { nITS567cls++; nITSTPCtracks += track.hasITS() && track.hasTPC(); nTOFtracks += track.hasTOF(); + nTRDtracks += track.hasTRD(); if (track.pt() < confCutPtMinThisEvent || track.pt() > confCutPtMaxThisEvent) continue; @@ -324,6 +376,33 @@ struct DetectorOccupancyQaTask { vIsFullInfoForOccupancy[colIndex] = ((bcInTF - 300) * bcNS > timeWinOccupancyCalcNS) && ((nBCsPerTF - 4000 - bcInTF) * bcNS > timeWinOccupancyCalcNS) ? true : false; LOGP(debug, "### check bcInTF cut: colIndex={} bcInTF={} vIsFullInfoForOccupancy={}", colIndex, bcInTF, static_cast(vIsFullInfoForOccupancy[colIndex])); + + // additional QA: + if (col.selection_bit(kNoTimeFrameBorder) && col.selection_bit(kNoITSROFrameBorder)) { + auto bcFoundId = bc.globalBC() % 3564; + auto bcNonFound = col.bc_as(); + auto bcNonFoundId = bcNonFound.globalBC() % 3564; + int64_t diffFoundBC_vs_BC = (int64_t)bcFoundId - (int64_t)bcNonFoundId; + histos.fill(HIST("h2D_diff_FoundBC_vs_BC"), bcNonFoundId, diffFoundBC_vs_BC); + if (nITS567cls > 10) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_multAbove10"), bcNonFoundId, diffFoundBC_vs_BC); + if (nITS567cls > 20) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_multAbove20"), bcNonFoundId, diffFoundBC_vs_BC); + if (nITS567cls > 50) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_multAbove50"), bcNonFoundId, diffFoundBC_vs_BC); + if (nITS567cls > 100) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_multAbove100"), bcNonFoundId, diffFoundBC_vs_BC); + + if (nTOFtracks > 0) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_hasTOF"), bcNonFoundId, diffFoundBC_vs_BC); + if (nTRDtracks > 0) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_hasTRD"), bcNonFoundId, diffFoundBC_vs_BC); + + if (nITS567cls > 10 && nTOFtracks > 0) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_hasTOF_multAbove10"), bcNonFoundId, diffFoundBC_vs_BC); + if (nITS567cls > 10 && nTRDtracks > 0) + histos.fill(HIST("h2D_diff_FoundBC_vs_BC_hasTRD_multAbove10"), bcNonFoundId, diffFoundBC_vs_BC); + } } // find for each collision all collisions within the defined time window @@ -401,6 +480,10 @@ struct DetectorOccupancyQaTask { if (col.posZ() < confCutVertZMinThisEvent || col.posZ() > confCutVertZMaxThisEvent) continue; + // skip if collision is close to TF border + if (confFlagApplyTFborderCut && !col.selection_bit(kNoTimeFrameBorder)) + continue; + // skip if collision is close to ROF border if (confFlagApplyROFborderCut && !col.selection_bit(kNoITSROFrameBorder)) continue; @@ -535,16 +618,15 @@ struct DetectorOccupancyQaTask { // ### occupancy event selection QA for (auto& col : cols) { - if (!col.sel8()) { + // if (!col.sel8()) { + // continue; + // } + if (!col.selection_bit(kIsTriggerTVX)) continue; - } - - int occupancy = col.trackOccupancyInTimeRange(); - histos.fill(HIST("hOccupancy"), occupancy); - if (!confAddTracksVsFwdHistos) { + // cut on vZ for a given collision + if (col.posZ() < confCutVertZMinThisEvent || col.posZ() > confCutVertZMaxThisEvent) continue; - } auto multV0A = col.multFV0A(); // auto multT0A = col.multFT0A(); @@ -554,87 +636,148 @@ struct DetectorOccupancyQaTask { auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); for (auto& track : tracksGrouped) { - if (!track.isPVContributor()) { + if (!track.isPVContributor()) + continue; + if (track.pt() < confCutPtMinThisEvent || track.pt() > confCutPtMaxThisEvent) + continue; + if (track.eta() < confCutEtaMinTracksThisEvent || track.eta() > confCutEtaMaxTracksThisEvent) + continue; + if (track.itsNCls() < 5) continue; - } nPV++; - if (track.isGlobalTrack()) + + if (track.isGlobalTrack() && track.tpcNClsFound() >= confCutMinTPCcls) nGlobalTracks++; } + if (confAddTracksVsFwdHistos) + histos.fill(HIST("nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts"), nPV, nGlobalTracks); + + // skip if collision is close to TF border + if (confFlagApplyTFborderCut && !col.selection_bit(kNoTimeFrameBorder)) + continue; + + if (confAddTracksVsFwdHistos) + histos.fill(HIST("nTracksGlobal_vs_nPV_QA_after_TFborderCut"), nPV, nGlobalTracks); + + // skip if collision is close to ROF border + if (confFlagApplyROFborderCut && !col.selection_bit(kNoITSROFrameBorder)) + continue; + + int occupancy = col.trackOccupancyInTimeRange(); + histos.fill(HIST("hOccupancy"), occupancy); + + auto t0cCentr = col.centFT0C(); + histos.fill(HIST("hCentrVsOccupancy"), t0cCentr, occupancy); + + if (!confAddTracksVsFwdHistos) { + continue; + } + // nPV tracks vs fwd amplitude histos.fill(HIST("nTracksPV_vs_V0A_noOccupSel"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_noOccupSel"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_noOccupSel"), nPV, nGlobalTracks); + + if (occupancy >= 0) + histos.fill(HIST("nTracksGlobal_vs_nPV_vs_occup_pure"), nPV, nGlobalTracks, occupancy); if (col.selection_bit(o2::aod::evsel::kNoHighOccupancyAgressive)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoHighOccupancyAgressive"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoHighOccupancyAgressive"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoHighOccupancyAgressive"), nPV, nGlobalTracks); } if (col.selection_bit(o2::aod::evsel::kNoHighOccupancyStrict)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoHighOccupancyStrict"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoHighOccupancyStrict"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoHighOccupancyStrict"), nPV, nGlobalTracks); } if (col.selection_bit(o2::aod::evsel::kNoHighOccupancyMedium)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoHighOccupancyMedium"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoHighOccupancyMedium"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoHighOccupancyMedium"), nPV, nGlobalTracks); } if (col.selection_bit(o2::aod::evsel::kNoHighOccupancyRelaxed)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoHighOccupancyRelaxed"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoHighOccupancyRelaxed"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoHighOccupancyRelaxed"), nPV, nGlobalTracks); } if (col.selection_bit(o2::aod::evsel::kNoHighOccupancyGentle)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoHighOccupancyGentle"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoHighOccupancyGentle"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoHighOccupancyGentle"), nPV, nGlobalTracks); } if (col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoCollInTimeRangeStandard"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoCollInTimeRangeStandard"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoCollInTimeRangeStandard"), nPV, nGlobalTracks); + if (occupancy >= 0) + histos.fill(HIST("nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeStandard"), nPV, nGlobalTracks, occupancy); } if (col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { histos.fill(HIST("nTracksPV_vs_V0A_kNoCollInTimeRangeNarrow"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoCollInTimeRangeNarrow"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_kNoCollInTimeRangeNarrow"), nPV, nGlobalTracks); + if (occupancy >= 0) + histos.fill(HIST("nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeNarrow"), nPV, nGlobalTracks, occupancy); } if (occupancy >= 0 && occupancy < 250) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_250"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_0_250"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_250"), nPV, nGlobalTracks); } if (occupancy >= 0 && occupancy < 500) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_500"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_0_500"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_500"), nPV, nGlobalTracks); } if (occupancy >= 0 && occupancy < 750) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_750"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_0_750"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_750"), nPV, nGlobalTracks); + } + if (occupancy >= 0 && occupancy < 2000) { + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_2000"), nPV, nGlobalTracks); } if (occupancy >= 0 && occupancy < 500 && col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_500_kNoCollInTimeRangeStandard"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_0_500_kNoCollInTimeRangeStandard"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeStandard"), nPV, nGlobalTracks); } if (occupancy >= 0 && occupancy < 500 && col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_500_kNoCollInTimeRangeNarrow"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_0_500_kNoCollInTimeRangeNarrow"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeNarrow"), nPV, nGlobalTracks); } if (occupancy >= 0 && occupancy < 500 && col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) && col.selection_bit(kNoSameBunchPileup) && col.selection_bit(kIsGoodZvtxFT0vsPV)) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_500_kNoCollInTimeRangeStandard_extraCuts"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_0_500_kNoCollInTimeRangeStandard_extraCuts"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_500_kNoCollInTimeRangeStandard_extraCuts"), nPV, nGlobalTracks); + } + if (occupancy >= 0 && occupancy < 2000 && col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) && col.selection_bit(kNoSameBunchPileup) && col.selection_bit(kIsGoodZvtxFT0vsPV)) { + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_0_2000_kNoCollInTimeRangeStandard_extraCuts"), nPV, nGlobalTracks); } // more checks if (occupancy >= 750) { histos.fill(HIST("nTracksPV_vs_V0A_occup_ABOVE_750"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_ABOVE_750"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_ABOVE_750"), nPV, nGlobalTracks); } if (occupancy == -1) { histos.fill(HIST("nTracksPV_vs_V0A_occup_Minus1"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_occup_Minus1"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_occup_Minus1"), nPV, nGlobalTracks); } if (!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { histos.fill(HIST("nTracksPV_vs_V0A_AntiNoCollInTimeRangeStandard"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_AntiNoCollInTimeRangeStandard"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeStandard"), nPV, nGlobalTracks); } if (!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { histos.fill(HIST("nTracksPV_vs_V0A_AntiNoCollInTimeRangeNarrow"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_AntiNoCollInTimeRangeNarrow"), multV0A, nGlobalTracks); + histos.fill(HIST("nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeNarrow"), nPV, nGlobalTracks); } } } diff --git a/DPG/Tasks/AOTEvent/rofBorderQa.cxx b/DPG/Tasks/AOTEvent/rofBorderQa.cxx index 6f5f8a876e9..83f704960b6 100644 --- a/DPG/Tasks/AOTEvent/rofBorderQa.cxx +++ b/DPG/Tasks/AOTEvent/rofBorderQa.cxx @@ -211,7 +211,7 @@ struct RofBorderQaTask { Colls::iterator const& collision, aod::FT0s const&, BCsRun3 const& bcs, - aod::Origins const& origins, + aod::Origins const& /*origins*/, soa::Join + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ + +namespace variables_table // declaration of columns to create +{ +DECLARE_SOA_COLUMN(ChAngle, chAngle, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(MomentumHMPID, momentumHMPID, float); +DECLARE_SOA_COLUMN(MomentumTrack, momentumTrack, float); +DECLARE_SOA_COLUMN(Xtrack, xtrack, float); +DECLARE_SOA_COLUMN(Ytrack, ytrack, float); +DECLARE_SOA_COLUMN(Xmip, xmip, float); +DECLARE_SOA_COLUMN(Ymip, ymip, float); +DECLARE_SOA_COLUMN(Nphotons, nphotons, float); +DECLARE_SOA_COLUMN(ChargeMIP, chargeMIP, float); +DECLARE_SOA_COLUMN(ClusterSize, clustersize, float); +DECLARE_SOA_COLUMN(Chamber, chamber, float); +DECLARE_SOA_COLUMN(Photons_charge, photons_charge, float); + +DECLARE_SOA_COLUMN(EtaTrack, etatrack, float); +DECLARE_SOA_COLUMN(PhiTrack, phitrack, float); + +DECLARE_SOA_COLUMN(ITSNcluster, itsNcluster, float); +DECLARE_SOA_COLUMN(TPCNcluster, tpcNcluster, float); +DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, float); +DECLARE_SOA_COLUMN(TPCchi2, tpcChi2, float); +DECLARE_SOA_COLUMN(ITSchi2, itsChi2, float); + +DECLARE_SOA_COLUMN(DCAxy, dcaxy, float); +DECLARE_SOA_COLUMN(DCAz, dcaz, float); + +DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNsigmaPi, float); +DECLARE_SOA_COLUMN(TOFNSigmaPi, tofNsigmaPi, float); +DECLARE_SOA_COLUMN(TPCNSigmaKa, tpcNsigmaKa, float); +DECLARE_SOA_COLUMN(TOFNSigmaKa, tofNsigmaKa, float); +DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNsigmaPr, float); +DECLARE_SOA_COLUMN(TOFNSigmaPr, tofNsigmaPr, float); +DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNsigmaDe, float); +DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNsigmaDe, float); + +} // namespace variables_table + +DECLARE_SOA_TABLE(HMPID_analysis, "AOD", "HMPIDANALYSIS", + variables_table::ChAngle, variables_table::Phi, variables_table::Eta, variables_table::MomentumHMPID, + variables_table::MomentumTrack, variables_table::Xtrack, variables_table::Ytrack, variables_table::Xmip, + variables_table::Ymip, variables_table::Nphotons, variables_table::ChargeMIP, variables_table::ClusterSize, + variables_table::Chamber, variables_table::Photons_charge, variables_table::EtaTrack, variables_table::PhiTrack, + variables_table::ITSNcluster, variables_table::TPCNcluster, variables_table::TPCNClsCrossedRows, + variables_table::TPCchi2, variables_table::ITSchi2, variables_table::DCAxy, variables_table::DCAz, + variables_table::TPCNSigmaPi, variables_table::TOFNSigmaPi, variables_table::TPCNSigmaKa, variables_table::TOFNSigmaKa, + variables_table::TPCNSigmaPr, variables_table::TOFNSigmaPr, variables_table::TPCNSigmaDe, variables_table::TOFNSigmaDe); +} // namespace o2::aod + +struct pidHmpidAnalysis { + + Produces HMPID_analysis; + + // using TrackCandidates = soa::Join; + + using CollisionCandidates = o2::soa::Join; + + using TrackCandidates = soa::Join; + + void process(const aod::HMPIDs& hmpids, + TrackCandidates const&, + CollisionCandidates const&) + { + + for (const auto& t : hmpids) { + if (t.track_as().isGlobalTrack() != (uint8_t) true) { + continue; + } + + const auto& track = t.track_as(); + + if (!track.hasITS() || !track.hasTPC() || !track.hasTOF()) { + continue; + } + + /////FILL TABLE + HMPID_analysis(t.hmpidSignal(), t.track_as().phi(), t.track_as().eta(), t.hmpidMom(), + track.p(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), + t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, t.hmpidClusSize() / 1000000, + *t.hmpidPhotsCharge(), track.eta(), track.phi(), track.itsNCls(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), + track.tpcChi2NCl(), track.itsChi2NCl(), track.dcaXY(), track.dcaZ(), + track.tpcNSigmaPi(), track.tofNSigmaPi(), track.tpcNSigmaKa(), track.tofNSigmaKa(), + track.tpcNSigmaPr(), track.tofNSigmaPr(), track.tpcNSigmaDe(), track.tofNSigmaDe()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) { return WorkflowSpec{adaptAnalysisTask(cfg)}; } diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/qaHMPID.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/qaHMPID.cxx index aff95a901dd..e4a7b370f55 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/qaHMPID.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/qaHMPID.cxx @@ -14,16 +14,74 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "ReconstructionDataFormats/TrackParametrization.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" +#include "ReconstructionDataFormats/PID.h" +#include "Common/Core/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" #include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +namespace o2::aod +{ + +namespace variables_table // declaration of columns to create +{ +DECLARE_SOA_COLUMN(ChAngle, chAngle, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(MomHMPID, momMPID, float); +DECLARE_SOA_COLUMN(MomTrackX, momTrackX, float); +DECLARE_SOA_COLUMN(MomTrackY, momTrackY, float); +DECLARE_SOA_COLUMN(MomTrackZ, momTrackZ, float); +DECLARE_SOA_COLUMN(Xtrack, xtrack, float); +DECLARE_SOA_COLUMN(Ytrack, ytrack, float); +DECLARE_SOA_COLUMN(Xmip, xmip, float); +DECLARE_SOA_COLUMN(Ymip, ymip, float); +DECLARE_SOA_COLUMN(Nphotons, nphotons, float); +DECLARE_SOA_COLUMN(ChargeMIP, chargeMIP, float); +DECLARE_SOA_COLUMN(ClusterSize, clustersize, float); +DECLARE_SOA_COLUMN(Chamber, chamber, float); +DECLARE_SOA_COLUMN(Photons_charge, photons_charge, float); + +DECLARE_SOA_COLUMN(EtaTrack, etatrack, float); +DECLARE_SOA_COLUMN(PhiTrack, phitrack, float); + +DECLARE_SOA_COLUMN(ITSNcluster, itsNcluster, float); +DECLARE_SOA_COLUMN(TPCNcluster, tpcNcluster, float); +DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, float); +DECLARE_SOA_COLUMN(TPCchi2, tpcChi2, float); +DECLARE_SOA_COLUMN(ITSchi2, itsChi2, float); + +DECLARE_SOA_COLUMN(DCAxy, dcaxy, float); +DECLARE_SOA_COLUMN(DCAz, dcaz, float); + +} // namespace variables_table + +DECLARE_SOA_TABLE(HMPID_analysis, "AOD", "HMPIDANALYSIS", + variables_table::ChAngle, variables_table::Phi, variables_table::Eta, variables_table::MomHMPID, + variables_table::MomTrackX, variables_table::MomTrackY, variables_table::MomTrackZ, + variables_table::Xtrack, variables_table::Ytrack, variables_table::Xmip, + variables_table::Ymip, variables_table::Nphotons, variables_table::ChargeMIP, variables_table::ClusterSize, + variables_table::Chamber, variables_table::Photons_charge, variables_table::EtaTrack, variables_table::PhiTrack, + variables_table::ITSNcluster, variables_table::TPCNcluster, variables_table::TPCNClsCrossedRows, + variables_table::TPCchi2, variables_table::ITSchi2, variables_table::DCAxy, variables_table::DCAz); +} // namespace o2::aod + struct pidHmpidQa { + + Produces HMPID_analysis; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable nBinsP{"nBinsP", 500, "Number of momentum bins"}; Configurable minP{"minP", 0.01f, "Minimum momentum plotted (GeV/c)"}; @@ -73,21 +131,31 @@ struct pidHmpidQa { void process(const aod::HMPIDs& hmpids, const TrackCandidates& /*tracks*/, const aod::Collisions& /*colls*/) + { for (const auto& t : hmpids) { if (t.track_as().isGlobalTrack() != (uint8_t) true) { continue; } - if (abs(t.track_as().dcaXY()) > maxDCA) { + + const auto& track = t.track_as(); + + if (!track.hasITS() || !track.hasTPC() || !track.hasTOF()) { continue; } + HMPID_analysis(t.hmpidSignal(), t.track_as().phi(), t.track_as().eta(), t.hmpidMom(), + track.px(), track.py(), track.pz(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), + t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, t.hmpidClusSize() / 1000000, + *t.hmpidPhotsCharge(), track.eta(), track.phi(), track.itsNCls(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), + track.tpcChi2NCl(), track.itsChi2NCl(), track.dcaXY(), track.dcaZ()); + histos.fill(HIST("hmpidSignal"), t.hmpidSignal()); histos.fill(HIST("PhivsEta"), t.track_as().eta(), t.track_as().phi()); histos.fill(HIST("hmpidMomvsTrackMom"), t.track_as().p(), abs(t.hmpidMom())); histos.fill(HIST("hmpidCkovvsMom"), abs(t.hmpidMom()), t.hmpidSignal()); - histos.fill(HIST("hmpidXTrack"), t.hmpidYTrack()); + histos.fill(HIST("hmpidXTrack"), t.hmpidXTrack()); histos.fill(HIST("hmpidYTrack"), t.hmpidYTrack()); histos.fill(HIST("hmpidXMip"), t.hmpidXMip()); histos.fill(HIST("hmpidYMip"), t.hmpidYMip()); diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx index a550dfbd120..fe928c0ddc3 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx @@ -48,6 +48,8 @@ struct tofPidBetaQa { ConfigurableAxis tofBetaBins{"tofBetaBins", {4000, 0, 2.f}, "Binning in the TOF beta plot"}; ConfigurableAxis trackLengthBins{"trackLengthBins", {100, 0, 1000.f}, "Binning in track length plot"}; Configurable requireGoodMatchTracks{"requireGoodMatchTracks", false, "Require good match tracks"}; + Configurable mMaxTOFChi2{"maxTOFChi2", 3.f, "Maximum TOF Chi2"}; + Configurable mEtaWindow{"etaWindow", 0.8f, "Window in eta for tracks"}; void init(o2::framework::InitContext&) { @@ -61,7 +63,7 @@ struct tofPidBetaQa { const AxisSpec lAxis{trackLengthBins, "Track length (cm)"}; const AxisSpec tofChi2Axis{1000, 0, 20, "TOF residual (cm)"}; const AxisSpec ptResoAxis{100, 0, 0.1, "#sigma_{#it{p}_{T}}"}; - const AxisSpec pAxisPosNeg{2 * nBinsP, -maxP, maxP, "#it{p}/z (GeV/#it{c})"}; + const AxisSpec pAxisPosNeg{2 * nBinsP, -maxP, maxP, "signed #it{p} (GeV/#it{c})"}; AxisSpec ptAxis{nBinsP, minP, maxP, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec pAxis{nBinsP, minP, maxP, "#it{p} (GeV/#it{c})"}; if (logAxis) { @@ -126,51 +128,51 @@ struct tofPidBetaQa { // TOF beta if (splitSignalPerCharge) { - histos.add("tofbeta/inclusive", "", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); + histos.add("tofbeta/inclusive", "", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); if (splitSignalPerEvTime) { - histos.add("tofbeta/EvTimeTOF", "Ev. Time TOF", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); + histos.add("tofbeta/EvTimeTOF", "Ev. Time TOF", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); } if (splitTrdTracks) { - histos.add("tofbeta/trd/inclusive", "(hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); + histos.add("tofbeta/trd/inclusive", "(hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); if (splitSignalPerEvTime) { - histos.add("tofbeta/trd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/trd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/trd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/trd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); + histos.add("tofbeta/trd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/trd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/trd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/trd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); } - histos.add("tofbeta/notrd/inclusive", "(hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); + histos.add("tofbeta/notrd/inclusive", "(hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); if (splitSignalPerEvTime) { - histos.add("tofbeta/notrd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/notrd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/notrd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); - histos.add("tofbeta/notrd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH3F, {pAxisPosNeg, betaAxis, chargeAxis}); + histos.add("tofbeta/notrd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/notrd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/notrd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); + histos.add("tofbeta/notrd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH3F, {pAxis, betaAxis, chargeAxis}); } } } else { - histos.add("tofbeta/inclusive", "", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/inclusive", "", HistType::kTH2F, {pAxisPosNeg, betaAxis}); if (splitSignalPerEvTime) { - histos.add("tofbeta/EvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxisPosNeg, betaAxis}); } if (splitTrdTracks) { - histos.add("tofbeta/trd/inclusive", "(hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/trd/inclusive", "(hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); if (splitSignalPerEvTime) { - histos.add("tofbeta/trd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/trd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/trd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/trd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/trd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/trd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/trd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/trd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); } - histos.add("tofbeta/notrd/inclusive", "(hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/notrd/inclusive", "(hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); if (splitSignalPerEvTime) { - histos.add("tofbeta/notrd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/notrd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/notrd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/notrd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/notrd/EvTimeTOF", "Ev. Time TOF (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/notrd/EvTimeTOFOnly", "Ev. Time TOF Only (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/notrd/EvTimeT0AC", "Ev. Time T0AC (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); + histos.add("tofbeta/notrd/EvTimeT0ACOnly", "Ev. Time T0AC Only (hasTRD)", HistType::kTH2F, {pAxisPosNeg, betaAxis}); } } } @@ -193,7 +195,7 @@ struct tofPidBetaQa { h->GetXaxis()->SetBinLabel(1, "Tracks read"); h->GetXaxis()->SetBinLabel(2, "hasTOF"); h->GetXaxis()->SetBinLabel(3, "isGlobalTrack"); - h->GetXaxis()->SetBinLabel(4, "goodTOFMatch"); + h->GetXaxis()->SetBinLabel(4, TString::Format("TOF chi2 < %.2f", mMaxTOFChi2.value)); } Filter eventFilter = (applyEvSel.node() == 0) || @@ -205,6 +207,7 @@ struct tofPidBetaQa { ((trackSelection.node() == 3) && requireGlobalTrackWoDCAInFilter()) || ((trackSelection.node() == 4) && requireQualityTracksInFilter()) || ((trackSelection.node() == 5) && requireInAcceptanceTracksInFilter()); + Filter etaFilter = (nabs(o2::aod::track::eta) < mEtaWindow); using CollisionCandidate = soa::Filtered>::iterator; using TrackCandidates = soa::Join mMaxTOFChi2) { // Skipping tracks with large Chi2 continue; } histos.fill(HIST("event/trackselection"), 4.f); @@ -327,24 +330,25 @@ struct tofPidBetaQa { } } } else { - histos.fill(HIST("tofmass/notrd/inclusive"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/notrd/inclusive"), track.p(), track.beta()); + const float signedp = track.p() * track.sign(); + histos.fill(HIST("tofmass/notrd/inclusive"), signedp, track.mass()); + histos.fill(HIST("tofbeta/notrd/inclusive"), signedp, track.beta()); if (splitSignalPerEvTime) { if (track.isEvTimeTOF()) { - histos.fill(HIST("tofmass/notrd/EvTimeTOF"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/notrd/EvTimeTOF"), track.p(), track.beta()); + histos.fill(HIST("tofmass/notrd/EvTimeTOF"), signedp, track.mass()); + histos.fill(HIST("tofbeta/notrd/EvTimeTOF"), signedp, track.beta()); } if (track.isEvTimeTOF() && !track.isEvTimeT0AC()) { - histos.fill(HIST("tofmass/notrd/EvTimeTOFOnly"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/notrd/EvTimeTOFOnly"), track.p(), track.beta()); + histos.fill(HIST("tofmass/notrd/EvTimeTOFOnly"), signedp, track.mass()); + histos.fill(HIST("tofbeta/notrd/EvTimeTOFOnly"), signedp, track.beta()); } if (track.isEvTimeT0AC()) { - histos.fill(HIST("tofmass/notrd/EvTimeT0AC"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/notrd/EvTimeT0AC"), track.p(), track.beta()); + histos.fill(HIST("tofmass/notrd/EvTimeT0AC"), signedp, track.mass()); + histos.fill(HIST("tofbeta/notrd/EvTimeT0AC"), signedp, track.beta()); } if (track.isEvTimeT0AC() && !track.isEvTimeTOF()) { - histos.fill(HIST("tofmass/notrd/EvTimeT0ACOnly"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/notrd/EvTimeT0ACOnly"), track.p(), track.beta()); + histos.fill(HIST("tofmass/notrd/EvTimeT0ACOnly"), signedp, track.mass()); + histos.fill(HIST("tofbeta/notrd/EvTimeT0ACOnly"), signedp, track.beta()); } } } @@ -384,24 +388,25 @@ struct tofPidBetaQa { } } } else { - histos.fill(HIST("tofmass/trd/inclusive"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/trd/inclusive"), track.p(), track.beta()); + const float signedp = track.p() * track.sign(); + histos.fill(HIST("tofmass/trd/inclusive"), signedp, track.mass()); + histos.fill(HIST("tofbeta/trd/inclusive"), signedp, track.beta()); if (splitSignalPerEvTime) { if (track.isEvTimeTOF()) { - histos.fill(HIST("tofmass/trd/EvTimeTOF"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/trd/EvTimeTOF"), track.p(), track.beta()); + histos.fill(HIST("tofmass/trd/EvTimeTOF"), signedp, track.mass()); + histos.fill(HIST("tofbeta/trd/EvTimeTOF"), signedp, track.beta()); } if (track.isEvTimeTOF() && !track.isEvTimeT0AC()) { - histos.fill(HIST("tofmass/trd/EvTimeTOFOnly"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/trd/EvTimeTOFOnly"), track.p(), track.beta()); + histos.fill(HIST("tofmass/trd/EvTimeTOFOnly"), signedp, track.mass()); + histos.fill(HIST("tofbeta/trd/EvTimeTOFOnly"), signedp, track.beta()); } if (track.isEvTimeT0AC()) { - histos.fill(HIST("tofmass/trd/EvTimeT0AC"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/trd/EvTimeT0AC"), track.p(), track.beta()); + histos.fill(HIST("tofmass/trd/EvTimeT0AC"), signedp, track.mass()); + histos.fill(HIST("tofbeta/trd/EvTimeT0AC"), signedp, track.beta()); } if (track.isEvTimeT0AC() && !track.isEvTimeTOF()) { - histos.fill(HIST("tofmass/trd/EvTimeT0ACOnly"), track.p(), track.mass()); - histos.fill(HIST("tofbeta/trd/EvTimeT0ACOnly"), track.p(), track.beta()); + histos.fill(HIST("tofmass/trd/EvTimeT0ACOnly"), signedp, track.mass()); + histos.fill(HIST("tofbeta/trd/EvTimeT0ACOnly"), signedp, track.beta()); } } } @@ -410,7 +415,4 @@ struct tofPidBetaQa { } }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx index 9895afab68a..e5ca7df21cc 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx @@ -28,6 +28,7 @@ #include "Common/TableProducer/PID/pidTOFBase.h" #include "Framework/runDataProcessing.h" #include "CommonConstants/LHCConstants.h" +#include "DataFormatsFT0/Digit.h" using namespace o2; using namespace o2::framework; @@ -68,166 +69,170 @@ struct tofPidCollisionTimeQa { const AxisSpec deltaAxis{1000, -10000, 10000, "t-t_{ev}-t_{exp}(#pi) (ps)"}; const AxisSpec lengthAxis{1000, 0, 600, "Track length (cm)"}; - auto h = histos.add("eventSelection", "eventSelection", kTH1F, {{10, 0, 10, "Cut passed"}}); - h->GetXaxis()->SetBinLabel(1, "Events read"); - h->GetXaxis()->SetBinLabel(2, "Event selection"); - h->GetXaxis()->SetBinLabel(3, "#sigma_{Ev. time} < 200 ps"); - h->GetXaxis()->SetBinLabel(4, "#sigma_{Ev. time} > 200 ps"); - h = histos.add("trackSelection", "trackSelection", kTH1F, {{10, 0, 10, "Cut passed"}}); - h->GetXaxis()->SetBinLabel(1, "Tracks read"); - h->GetXaxis()->SetBinLabel(2, "Track selection"); - h->GetXaxis()->SetBinLabel(3, "hasITS"); - h->GetXaxis()->SetBinLabel(4, "hasTPC"); - h->GetXaxis()->SetBinLabel(5, "hasTOF"); - histos.add("deltaEvTimeTOFT0A", "deltaEvTimeTOFT0A", kTH1F, {evTimeDeltaAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0A} (ps)"); - histos.add("deltaEvTimeTOFT0C", "deltaEvTimeTOFT0C", kTH1F, {evTimeDeltaAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0C} (ps)"); - histos.add("deltaEvTimeTOFT0AC", "deltaEvTimeTOFT0AC", kTH1F, {evTimeDeltaAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0AC} (ps)"); - auto h2 = histos.add("deltaEvTimeTOFT0AvsT0C", "deltaEvTimeTOFT0AvsT0C", kTH2F, {evTimeDeltaAxis, evTimeDeltaAxis}); - h2->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0A} (ps)"); - h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0C} (ps)"); - h2 = histos.add("deltaEvTimeTOFT0AvsTOF", "deltaEvTimeTOFT0AvsTOF", kTH2F, {evTimeAxis, evTimeDeltaAxis}); - h2->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); - h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0A} (ps)"); - h2 = histos.add("deltaEvTimeTOFT0CvsTOF", "deltaEvTimeTOFT0CvsTOF", kTH2F, {evTimeAxis, evTimeDeltaAxis}); - h2->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); - h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0C} (ps)"); - h2 = histos.add("deltaEvTimeTOFT0ACvsTOF", "deltaEvTimeTOFT0ACvsTOF", kTH2F, {evTimeAxis, evTimeDeltaAxis}); - h2->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); - h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0AC} (ps)"); - - histos.add("eventTime", "eventTime", kTH1F, {evTimeAxis}); - histos.add("eventTimeReso", "eventTimeReso", kTH1F, {evTimeResoAxis}); - histos.add("eventTimeVsMult", "eventTimeVsMult", kTH2F, {multAxis, evTimeAxis}); - histos.add("eventTimeResoVsMult", "eventTimeResoVsMult", kTH2F, {multAxis, evTimeResoAxis}); - - histos.add("eventTimeTOFMult", "eventTimeTOFMult", kTH1F, {multAxis}); - histos.add("eventTimeTOF", "eventTimeTOF", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); - histos.add("eventTimeTOFReso", "eventTimeTOFReso", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} resolution (ps)"); - histos.add("eventTimeTOFVsMult", "eventTimeTOFVsMult", kTH2F, {multAxis, evTimeAxis})->GetYaxis()->SetTitle("Ev. time_{TOF} (ps)"); - histos.add("eventTimeTOFResoVsMult", "eventTimeTOFResoVsMult", kTH2F, {multAxis, evTimeResoAxis})->GetYaxis()->SetTitle("Ev. time_{TOF} resolution (ps)"); - - histos.add("eventTimeT0A", "eventTimeT0A", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("T0A event time (ps)"); - histos.add("eventTimeT0C", "eventTimeT0C", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("T0C event time (ps)"); - histos.add("eventTimeT0AC", "eventTimeT0AC", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("T0AC event time (ps)"); - histos.add("eventTimeT0ACReso", "eventTimeT0ACReso", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("T0AC event time resolution (ps)"); - - histos.add("collisionTime", "collisionTime", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("Collision time (ps)"); - histos.add("collisionTimeRes", "collisionTimeRes", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("Collision time resolution (ps)"); - - histos.add("tracks/p", "p", kTH1F, {pAxis}); - histos.add("tracks/pt", "pt", kTH1F, {ptAxis}); - histos.add("tracks/length", "length", kTH1F, {lengthAxis}); - - histos.add("deltaVsMult/pi", Form("pi %.2f < #it{p} < %.2f", minPReso.value, maxPReso.value), kTH2F, {multAxis, deltaAxis}); - histos.add("deltaVsReso/pi", Form("pi %.2f < #it{p} < %.2f", minPReso.value, maxPReso.value), kTH2F, {evTimeResoAxis, deltaAxis}); - - histos.add("tofbeta/inclusive", "", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeT0AOnly", "Ev. Time T0A Only", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeT0COnly", "Ev. Time T0A Only", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("tofbeta/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxis, betaAxis}); - - histos.add("tofmass/inclusive", "", HistType::kTH2F, {pAxis, massAxis}); - histos.add("tofmass/EvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxis, massAxis}); - histos.add("tofmass/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxis, massAxis}); - histos.add("tofmass/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxis, massAxis}); - histos.add("tofmass/EvTimeT0AOnly", "Ev. Time T0A Only", HistType::kTH2F, {pAxis, massAxis}); - histos.add("tofmass/EvTimeT0COnly", "Ev. Time T0C Only", HistType::kTH2F, {pAxis, massAxis}); - histos.add("tofmass/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxis, massAxis}); - - if (enableDebug) { - histos.add("withtof/p", "p", kTH1F, {pAxis}); - histos.add("withtof/pt", "pt", kTH1F, {ptAxis}); - histos.add("withtof/length", "length", kTH1F, {lengthAxis}); - histos.add("withtof/tofSignal", "tofSignal", kTH1F, {tofSignalAxis}); - histos.add("withtof/beta", "beta", kTH2F, {pAxis, betaAxis}); - histos.add("withtof/delta", "delta", kTH2F, {pAxis, deltaAxis}); - histos.add("withtof/expP", "expP", kTH2F, {pAxis, pAxis}); - histos.add("withtof/mass", "mass", kTH1F, {massAxis}); - histos.add("withtof/tofSignalPerCollision", "tofSignalPerCollision", kTH2S, {collisionAxis, tofSignalAxis}); - - histos.add("goodreso/p", "p", kTH1F, {pAxis}); - histos.add("goodreso/pt", "pt", kTH1F, {ptAxis}); - histos.add("goodreso/ptden", "ptden", kTH1F, {ptAxis}); - histos.add("goodreso/length", "length", kTH1F, {lengthAxis}); - histos.add("goodreso/tofSignal", "tofSignal", kTH1F, {tofSignalAxis}); - histos.add("goodreso/beta", "beta", kTH2F, {pAxis, betaAxis}); - histos.add("goodreso/delta", "delta", kTH2F, {pAxis, deltaAxis}); - histos.add("goodreso/expP", "expP", kTH2F, {pAxis, pAxis}); - histos.add("goodreso/mass", "mass", kTH1F, {massAxis}); - histos.add("goodreso/tofSignalPerCollision", "tofSignalPerCollision", kTH2S, {collisionAxis, tofSignalAxis}); - - histos.add("badreso/p", "p", kTH1F, {pAxis}); - histos.add("badreso/pt", "pt", kTH1F, {ptAxis}); - histos.add("badreso/ptden", "ptden", kTH1F, {ptAxis}); - histos.add("badreso/length", "length", kTH1F, {lengthAxis}); - histos.add("badreso/tofSignal", "tofSignal", kTH1F, {tofSignalAxis}); - histos.add("badreso/beta", "beta", kTH2F, {pAxis, betaAxis}); - histos.add("badreso/delta", "delta", kTH2F, {pAxis, deltaAxis}); - histos.add("badreso/expP", "expP", kTH2F, {pAxis, pAxis}); - histos.add("badreso/mass", "mass", kTH1F, {massAxis}); - histos.add("badreso/tofSignalPerCollision", "tofSignalPerCollision", kTH2S, {collisionAxis, tofSignalAxis}); - - histos.add("goodforevtime/tofSignal", "tofSignal", kTH1F, {tofSignalAxis}); - histos.add("goodforevtime/p", "p", kTH1F, {pAxis}); - histos.add("goodforevtime/pt", "pt", kTH1F, {ptAxis}); - histos.add("goodforevtime/length", "length", kTH1F, {lengthAxis}); - histos.add("goodforevtime/beta", "beta", kTH2F, {pAxis, betaAxis}); - histos.add("goodforevtime/delta", "delta", kTH2F, {pAxis, deltaAxis}); - histos.add("goodforevtime/expP", "expP", kTH2F, {pAxis, pAxis}); - histos.add("goodforevtime/mass", "mass", kTH1F, {massAxis}); - histos.add("goodforevtime/tofSignalPerCollision", "tofSignalPerCollision", kTH2S, {collisionAxis, tofSignalAxis}); - - histos.add("withqualitycuts/p", "p", kTH1F, {pAxis}); - histos.add("withqualitycuts/pt", "pt", kTH1F, {ptAxis}); - histos.add("withqualitycuts/length", "length", kTH1F, {lengthAxis}); - histos.add("withqualitycuts/mass", "mass", kTH1F, {massAxis}); - } + if (doprocessData) { + auto h = histos.add("eventSelection", "eventSelection", kTH1F, {{10, 0, 10, "Cut passed"}}); + h->GetXaxis()->SetBinLabel(1, "Events read"); + h->GetXaxis()->SetBinLabel(2, "Event selection"); + h->GetXaxis()->SetBinLabel(3, "#sigma_{Ev. time} < 200 ps"); + h->GetXaxis()->SetBinLabel(4, "#sigma_{Ev. time} > 200 ps"); + h = histos.add("trackSelection", "trackSelection", kTH1F, {{10, 0, 10, "Cut passed"}}); + h->GetXaxis()->SetBinLabel(1, "Tracks read"); + h->GetXaxis()->SetBinLabel(2, "Track selection"); + h->GetXaxis()->SetBinLabel(3, "hasITS"); + h->GetXaxis()->SetBinLabel(4, "hasTPC"); + h->GetXaxis()->SetBinLabel(5, "hasTOF"); + histos.add("deltaEvTimeTOFT0A", "deltaEvTimeTOFT0A", kTH1F, {evTimeDeltaAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0A} (ps)"); + histos.add("deltaEvTimeTOFT0C", "deltaEvTimeTOFT0C", kTH1F, {evTimeDeltaAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0C} (ps)"); + histos.add("deltaEvTimeTOFT0AC", "deltaEvTimeTOFT0AC", kTH1F, {evTimeDeltaAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0AC} (ps)"); + auto h2 = histos.add("deltaEvTimeTOFT0AvsT0C", "deltaEvTimeTOFT0AvsT0C", kTH2F, {evTimeDeltaAxis, evTimeDeltaAxis}); + h2->GetXaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0A} (ps)"); + h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0C} (ps)"); + h2 = histos.add("deltaEvTimeTOFT0AvsTOF", "deltaEvTimeTOFT0AvsTOF", kTH2F, {evTimeAxis, evTimeDeltaAxis}); + h2->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); + h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0A} (ps)"); + h2 = histos.add("deltaEvTimeTOFT0CvsTOF", "deltaEvTimeTOFT0CvsTOF", kTH2F, {evTimeAxis, evTimeDeltaAxis}); + h2->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); + h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0C} (ps)"); + h2 = histos.add("deltaEvTimeTOFT0ACvsTOF", "deltaEvTimeTOFT0ACvsTOF", kTH2F, {evTimeAxis, evTimeDeltaAxis}); + h2->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); + h2->GetYaxis()->SetTitle("Ev. time_{TOF} - Ev. time_{T0AC} (ps)"); + + histos.add("eventTime", "eventTime", kTH1F, {evTimeAxis}); + histos.add("eventTimeReso", "eventTimeReso", kTH1F, {evTimeResoAxis}); + histos.add("eventTimeVsMult", "eventTimeVsMult", kTH2F, {multAxis, evTimeAxis}); + histos.add("eventTimeResoVsMult", "eventTimeResoVsMult", kTH2F, {multAxis, evTimeResoAxis}); + + histos.add("eventTimeTOFMult", "eventTimeTOFMult", kTH1F, {multAxis}); + histos.add("eventTimeTOF", "eventTimeTOF", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} (ps)"); + histos.add("eventTimeTOFReso", "eventTimeTOFReso", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("Ev. time_{TOF} resolution (ps)"); + histos.add("eventTimeTOFVsMult", "eventTimeTOFVsMult", kTH2F, {multAxis, evTimeAxis})->GetYaxis()->SetTitle("Ev. time_{TOF} (ps)"); + histos.add("eventTimeTOFResoVsMult", "eventTimeTOFResoVsMult", kTH2F, {multAxis, evTimeResoAxis})->GetYaxis()->SetTitle("Ev. time_{TOF} resolution (ps)"); + + histos.add("eventTimeT0A", "eventTimeT0A", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("T0A event time (ps)"); + histos.add("eventTimeT0C", "eventTimeT0C", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("T0C event time (ps)"); + histos.add("eventTimeT0AC", "eventTimeT0AC", kTH1F, {evTimeAxis})->GetXaxis()->SetTitle("T0AC event time (ps)"); + histos.add("eventTimeT0ACReso", "eventTimeT0ACReso", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("T0AC event time resolution (ps)"); + + histos.add("collisionTime", "collisionTime", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("Collision time (ps)"); + histos.add("collisionTimeRes", "collisionTimeRes", kTH1F, {evTimeResoAxis})->GetXaxis()->SetTitle("Collision time resolution (ps)"); + + histos.add("tracks/p", "p", kTH1F, {pAxis}); + histos.add("tracks/pt", "pt", kTH1F, {ptAxis}); + histos.add("tracks/length", "length", kTH1F, {lengthAxis}); + + histos.add("deltaVsMult/pi", Form("pi %.2f < #it{p} < %.2f", minPReso.value, maxPReso.value), kTH2F, {multAxis, deltaAxis}); + histos.add("deltaVsReso/pi", Form("pi %.2f < #it{p} < %.2f", minPReso.value, maxPReso.value), kTH2F, {evTimeResoAxis, deltaAxis}); + + histos.add("tofbeta/inclusive", "", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeT0AOnly", "Ev. Time T0A Only", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeT0COnly", "Ev. Time T0A Only", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("tofbeta/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxis, betaAxis}); + + histos.add("tofmass/inclusive", "", HistType::kTH2F, {pAxis, massAxis}); + histos.add("tofmass/EvTimeTOF", "Ev. Time TOF", HistType::kTH2F, {pAxis, massAxis}); + histos.add("tofmass/EvTimeTOFOnly", "Ev. Time TOF Only", HistType::kTH2F, {pAxis, massAxis}); + histos.add("tofmass/EvTimeT0AC", "Ev. Time T0AC", HistType::kTH2F, {pAxis, massAxis}); + histos.add("tofmass/EvTimeT0AOnly", "Ev. Time T0A Only", HistType::kTH2F, {pAxis, massAxis}); + histos.add("tofmass/EvTimeT0COnly", "Ev. Time T0C Only", HistType::kTH2F, {pAxis, massAxis}); + histos.add("tofmass/EvTimeT0ACOnly", "Ev. Time T0AC Only", HistType::kTH2F, {pAxis, massAxis}); + if (enableDebug) { + histos.add("withtof/p", "p", kTH1F, {pAxis}); + histos.add("withtof/pt", "pt", kTH1F, {ptAxis}); + histos.add("withtof/length", "length", kTH1F, {lengthAxis}); + histos.add("withtof/tofSignal", "tofSignal", kTH1F, {tofSignalAxis}); + histos.add("withtof/beta", "beta", kTH2F, {pAxis, betaAxis}); + histos.add("withtof/delta", "delta", kTH2F, {pAxis, deltaAxis}); + histos.add("withtof/expP", "expP", kTH2F, {pAxis, pAxis}); + histos.add("withtof/mass", "mass", kTH1F, {massAxis}); + histos.add("withtof/tofSignalPerCollision", "tofSignalPerCollision", kTH2S, {collisionAxis, tofSignalAxis}); + + histos.addClone("withtof/", "goodreso/"); + histos.addClone("withtof/", "badreso/"); + histos.addClone("withtof/", "goodforevtime/"); + histos.addClone("withtof/", "withqualitycuts/"); + } - listEfficiency.setObject(new THashList); - auto makeEfficiency = [&](TString effname, TString efftitle) { - listEfficiency->Add(new TEfficiency(effname, efftitle + ";TOF multiplicity;Efficiency", nBinsMultiplicity, 0, rangeMultiplicity)); - }; + listEfficiency.setObject(new THashList); + auto makeEfficiency = [&](TString effname, TString efftitle) { + listEfficiency->Add(new TEfficiency(effname, efftitle + ";TOF multiplicity;Efficiency", nBinsMultiplicity, 0, rangeMultiplicity)); + }; - makeEfficiency("effTOFEvTime", "Efficiency of the TOF Event Time"); - makeEfficiency("effT0ACEvTime", "Efficiency of the T0AC Event Time"); - makeEfficiency("effTOFT0ACEvTime", "Efficiency of the TOF+T0AC Event Time"); - makeEfficiency("effT0AEvTime", "Efficiency of the T0A Event Time"); - makeEfficiency("effT0CEvTime", "Efficiency of the T0C Event Time"); + makeEfficiency("effTOFEvTime", "Efficiency of the TOF Event Time"); + makeEfficiency("effT0ACEvTime", "Efficiency of the T0AC Event Time"); + makeEfficiency("effTOFT0ACEvTime", "Efficiency of the TOF+T0AC Event Time"); + makeEfficiency("effT0AEvTime", "Efficiency of the T0A Event Time"); + makeEfficiency("effT0CEvTime", "Efficiency of the T0C Event Time"); + } if (!doprocessMC) { return; } const AxisSpec diffAxis{1000, -1000, 1000, "Difference"}; - histos.add("MC/diff", "", HistType::kTH1F, {diffAxis}); + histos.add("MC/diff/All", "All", HistType::kTH1F, {diffAxis})->GetXaxis()->SetTitle("t^{MC}_{ev}-t^{All}_{ev} (ps)"); + histos.add("MC/diff/FT0", "FT0", HistType::kTH1F, {diffAxis})->GetXaxis()->SetTitle("t^{MC}_{ev}-t_{FT0}_{ev} (ps)"); + histos.add("MC/diff/TOF", "TOF", HistType::kTH1F, {diffAxis})->GetXaxis()->SetTitle("t^{MC}_{ev}-t_{TOF}_{ev} (ps)"); + + histos.add("MC/diffvsZ/All", "All", HistType::kTH2F, {diffAxis, {100, -20, 20}})->GetXaxis()->SetTitle("t^{MC}_{ev}-t^{All}_{ev}_{ev} (ps)"); + histos.add("MC/diffvsZ/FT0", "FT0", HistType::kTH2F, {diffAxis, {100, -20, 20}})->GetXaxis()->SetTitle("t^{MC}_{ev}-t_{FT0}_{ev} (ps)"); + histos.add("MC/diffvsZ/TOF", "TOF", HistType::kTH2F, {diffAxis, {100, -20, 20}})->GetXaxis()->SetTitle("t^{MC}_{ev}-t_{TOF}_{ev} (ps)"); // pion - histos.add("MC/pdg211/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/pdgNeg211/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/prm/pdg211/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/prm/pdgNeg211/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); + histos.add("MC/particle/pdg211/all/particleDiff", "particleDiff", HistType::kTH2F, {ptAxis, diffAxis})->GetYaxis()->SetTitle("t^{MC}_{ev}-t^{part}_{MC} (ps)"); + histos.add("MC/particle/pdg211/all/delta", "delta", HistType::kTH2F, {ptAxis, diffAxis})->GetYaxis()->SetTitle("t_{TOF}-t^{MC}_{ev}-t_{exp} (ps)"); + histos.add("MC/particle/pdg211/all/deltaTRD", "deltaTRD", HistType::kTH2F, {ptAxis, diffAxis})->GetYaxis()->SetTitle("t_{TOF}-t^{MC}_{ev}-t_{exp} (ps)"); + histos.add("MC/particle/pdg211/all/deltaNoTRD", "deltaNoTRD", HistType::kTH2F, {ptAxis, diffAxis})->GetYaxis()->SetTitle("t_{TOF}-t^{MC}_{ev}-t_{exp} (ps)"); + histos.addClone("MC/particle/pdg211/all/", "MC/particle/pdg211/prm/"); + + histos.addClone("MC/particle/pdg211/", "MC/particle/pdgNeg211/"); + // kaon - histos.add("MC/pdg321/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/pdgNeg321/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/prm/pdg321/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/prm/pdgNeg321/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); + histos.addClone("MC/particle/pdg211/", "MC/particle/pdg321/"); + histos.addClone("MC/particle/pdg211/", "MC/particle/pdgNeg321/"); // proton - histos.add("MC/pdg2212/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/pdgNeg2212/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/prm/pdg2212/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - histos.add("MC/prm/pdgNeg2212/particleDiff", "", HistType::kTH2F, {pAxis, diffAxis}); - - histos.add("MC/t", "", HistType::kTH1F, {{1000, -1000, 1000, "MC time"}}); + histos.addClone("MC/particle/pdg211/", "MC/particle/pdg2212/"); + histos.addClone("MC/particle/pdg211/", "MC/particle/pdgNeg2212/"); + + const AxisSpec mcTimeAxis{1000, -1000, 1000, "MC coll time (ps)"}; + + histos.add("MC/CollisionTime/eventtimeMC", "", HistType::kTH1F, {mcTimeAxis}); + histos.add("MC/CollisionTime/All", "", HistType::kTH1F, {mcTimeAxis})->GetXaxis()->SetTitle("All (ps)"); + histos.add("MC/CollisionTime/FT0", "", HistType::kTH1F, {mcTimeAxis})->GetXaxis()->SetTitle("FT0 (ps)"); + histos.add("MC/CollisionTime/TOF", "", HistType::kTH1F, {mcTimeAxis})->GetXaxis()->SetTitle("TOF (ps)"); + histos.add("MC/CollisionTime/eventtimeMCvsAll", "", HistType::kTH2F, {mcTimeAxis, mcTimeAxis})->GetYaxis()->SetTitle("All (ps)"); + histos.add("MC/CollisionTime/eventtimeMCvsFT0", "", HistType::kTH2F, {mcTimeAxis, mcTimeAxis})->GetYaxis()->SetTitle("FT0 (ps)"); + histos.add("MC/CollisionTime/eventtimeMCvsTOF", "", HistType::kTH2F, {mcTimeAxis, mcTimeAxis})->GetYaxis()->SetTitle("TOF (ps)"); + + const AxisSpec axisBCID{o2::constants::lhc::LHCMaxBunches, -0.5, -0.5 + o2::constants::lhc::LHCMaxBunches, "BC ID in orbit"}; + const AxisSpec axisBCIDMC{o2::constants::lhc::LHCMaxBunches, -0.5, -0.5 + o2::constants::lhc::LHCMaxBunches, "MC BC ID in orbit"}; + + histos.add("collisions/Reco/BCvsMCBC", "BC vs MC BC", kTH2D, {axisBCID, axisBCIDMC}); + histos.add("collisions/Reco/FoundBCvsMCBC", "Found BC vs MC BC", kTH2D, {axisBCID, axisBCIDMC})->GetXaxis()->SetTitle("Found BC ID in orbit"); + histos.add("collisions/Reco/FoundBCvsBC", "Found BC vs MC BC", kTH2D, {axisBCID, axisBCID})->GetXaxis()->SetTitle("Found BC ID in orbit"); + histos.add("collisions/Reco/bcMinusfoundBc", "bcMinusfoundBc", kTH1D, {{1600, -1000, 1000, "bc - foundBc (ns)"}}); + histos.add("collisions/Reco/bcMinusfoundBcRatio", "bcMinusfoundBcRatio", kTH1D, {{1600, -40, 40, "(bc - foundBc)/collisionTimeRes"}}); + histos.add("collisions/Reco/bcMinusMcBc", "bcMinusMcBc", kTH1D, {{1600, -1000, 1000, "bc - mcBc (ns)"}}); + histos.add("collisions/Reco/foundbcMinusMcBc", "foundbcMinusMcBc", kTH1D, {{1600, -1000, 1000, "foundBc - mcBc (ns)"}}); + histos.add("collisions/Reco/bcMinusMcBcRatio", "bcMinusMcBcRatio", kTH1D, {{1600, -40, 40, "(bc - mcBc)/collisionTimeRes"}}); + histos.add("collisions/Reco/foundbcMinusMcBcRatio", "foundbcMinusMcBcRatio", kTH1D, {{1600, -40, 40, "(foundBc-mcBc)/collisionTimeRes"}}); + + histos.add("ft0/FT0AMinusFT0ACorrected", "", kTH1D, {{1600, -1000, 1000, "FT0A - FT0A_{corr} (ps)"}}); + histos.add("ft0/FT0CMinusFT0CCorrected", "", kTH1D, {{1600, -1000, 1000, "FT0C - FT0C_{corr} (ps)"}}); + histos.add("ft0/FT0ACMinusFT0ACCorrected", "", kTH1D, {{1600, -1000, 1000, "FT0AC - FT0AC_{corr} (ps)"}}); + histos.add("ft0/diffPosZ", "", kTH1D, {{100, -10, 10, "z_{mc} - z_{FT0} (cm)"}}); } - using Trks = soa::Join; + using Trks = soa::Join; + using TrksData = soa::Join; using EvTimeCollisions = soa::Join; // Define slice per collision Preslice perCollision = aod::track::collisionId; - void processData(Trks const& tracks, EvTimeCollisions const&) + void processData(TrksData const& tracks, EvTimeCollisions const&) { static int ncolls = 0; int lastCollisionId = -1; // Last collision ID analysed @@ -330,17 +335,17 @@ struct tofPidCollisionTimeQa { histos.fill(HIST("trackSelection"), 4.5f); // Recompute quantities with event times - const float& betaTOF = trk.evTimeTOFMult() > 1 ? o2::pid::tof::Beta::GetBeta(trk, trk.evTimeTOF()) : 999.f; - const float& betaT0A = collision.t0ACorrectedValid() ? o2::pid::tof::Beta::GetBeta(trk, collision.t0ACorrected() * 1000.f) : 999.f; - const float& betaT0C = collision.t0CCorrectedValid() ? o2::pid::tof::Beta::GetBeta(trk, collision.t0CCorrected() * 1000.f) : 999.f; - const float& betaT0AC = collision.t0ACValid() ? o2::pid::tof::Beta::GetBeta(trk, collision.t0AC() * 1000.f) : 999.f; + const float& betaTOF = trk.evTimeTOFMult() > 1 ? o2::pid::tof::Beta::GetBeta(trk, trk.evTimeTOF()) : 999.f; + const float& betaT0A = collision.t0ACorrectedValid() ? o2::pid::tof::Beta::GetBeta(trk, collision.t0ACorrected() * 1000.f) : 999.f; + const float& betaT0C = collision.t0CCorrectedValid() ? o2::pid::tof::Beta::GetBeta(trk, collision.t0CCorrected() * 1000.f) : 999.f; + const float& betaT0AC = collision.t0ACValid() ? o2::pid::tof::Beta::GetBeta(trk, collision.t0AC() * 1000.f) : 999.f; - const float& massTOF = trk.evTimeTOFMult() > 1 ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaTOF) : 999.f; - const float& massT0A = collision.t0ACorrectedValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0A) : 999.f; - const float& massT0C = collision.t0CCorrectedValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0C) : 999.f; - const float& massT0AC = collision.t0ACValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0AC) : 999.f; + const float& massTOF = trk.evTimeTOFMult() > 1 ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaTOF) : 999.f; + const float& massT0A = collision.t0ACorrectedValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0A) : 999.f; + const float& massT0C = collision.t0CCorrectedValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0C) : 999.f; + const float& massT0AC = collision.t0ACValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0AC) : 999.f; - const float& deltaPi = trk.tofSignal() - trk.tofEvTime() - o2::pid::tof::ExpTimes::GetExpectedSignal(trk); + const float& deltaPi = trk.tofSignal() - trk.tofEvTime() - o2::pid::tof::ExpTimes::GetExpectedSignal(trk); histos.fill(HIST("tofbeta/inclusive"), trk.p(), trk.beta()); histos.fill(HIST("tofmass/inclusive"), trk.p(), trk.mass()); @@ -435,80 +440,165 @@ struct tofPidCollisionTimeQa { EvTimeCollisionsMC const&, aod::McParticles const&, aod::BCs const&, + aod::FT0s const&, aod::McCollisions const&) { // static int ncolls = 0; int lastCollisionId = -1; // Last collision ID analysed - for (auto& t : tracks) { - if (!t.has_collision()) { // Track was not assigned to a collision - continue; - } else if (t.collisionId() == lastCollisionId) { // Event was already processed + for (auto& trk : tracks) { + if (!trk.has_collision()) { // Track was not assigned to a collision continue; } - lastCollisionId = t.collisionId(); /// Cache last collision ID - const auto& collision = t.collision_as(); + const auto& collision = trk.collision_as(); if (!collision.has_mcCollision()) { continue; } const auto& collisionMC = collision.mcCollision_as(); - // timeInBCNS + bc2ns(); - const auto& mcBC = collisionMC.bc(); - // bc* o2::constants::lhc::LHCBunchSpacingNS + orbit* o2::constants::lhc::LHCOrbitNS; - // int64_t(mcBC.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) - const int64_t bcMCtime = static_cast((collisionMC.t() + 2.f) / o2::constants::lhc::LHCBunchSpacingNS); - const float eventtimeMC = collisionMC.t() - bcMCtime * o2::constants::lhc::LHCBunchSpacingNS; - LOG(info) << mcBC.globalBC() - bcMCtime << " MC collision time: " << eventtimeMC << " collision time: " << collision.collisionTime() << " TOF event time: " << t.tofEvTime(); - histos.fill(HIST("MC/t"), eventtimeMC); - histos.fill(HIST("MC/diff"), eventtimeMC - t.tofEvTime()); - if (!t.has_mcParticle()) { + const float eventtimeMC = collisionMC.t() * 1000.f; + + if (trk.has_mcParticle()) { + const auto& particle = trk.mcParticle(); + const auto& mcCollTimeMinusFormationTime = particle.vt() - collisionMC.t(); + const auto& mcTOFvalue = trk.tofSignal() - eventtimeMC - trk.tofExpTimePi(); + LOG(debug) << "Track " << particle.vt() << " vs " << eventtimeMC; + switch (particle.pdgCode()) { + case 211: + histos.fill(HIST("MC/particle/pdg211/all/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + histos.fill(HIST("MC/particle/pdg211/all/delta"), particle.pt(), mcTOFvalue); + if (trk.hasTRD()) { + histos.fill(HIST("MC/particle/pdg211/all/deltaTRD"), particle.pt(), mcTOFvalue); + } else { + histos.fill(HIST("MC/particle/pdg211/all/deltaNoTRD"), particle.pt(), mcTOFvalue); + } + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("MC/particle/pdg211/prm/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + } + break; + case -211: + histos.fill(HIST("MC/particle/pdgNeg211/all/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + histos.fill(HIST("MC/particle/pdgNeg211/all/delta"), particle.pt(), mcTOFvalue); + histos.fill(HIST("MC/particle/pdgNeg211/all/delta"), particle.pt(), mcTOFvalue); + if (trk.hasTRD()) { + histos.fill(HIST("MC/particle/pdgNeg211/all/deltaTRD"), particle.pt(), mcTOFvalue); + } else { + histos.fill(HIST("MC/particle/pdgNeg211/all/deltaNoTRD"), particle.pt(), mcTOFvalue); + } + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("MC/particle/pdgNeg211/prm/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + } + break; + case 321: + histos.fill(HIST("MC/particle/pdg321/all/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("MC/particle/pdg321/prm/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + } + break; + case -321: + histos.fill(HIST("MC/particle/pdgNeg321/all/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("MC/particle/pdgNeg321/prm/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + } + break; + case 2212: + histos.fill(HIST("MC/particle/pdg2212/all/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("MC/particle/pdg2212/prm/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + } + break; + case -2212: + histos.fill(HIST("MC/particle/pdgNeg2212/all/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("MC/particle/pdgNeg2212/prm/particleDiff"), particle.pt(), mcCollTimeMinusFormationTime); + } + break; + default: + break; + } + } + + if (trk.collisionId() == lastCollisionId) { // Event was already processed continue; } - const auto& particle = t.mcParticle(); - LOG(info) << "Track " << particle.vt() << " vs " << eventtimeMC; - switch (particle.pdgCode()) { - case 211: - histos.fill(HIST("MC/pdg211/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - if (particle.isPhysicalPrimary()) { - histos.fill(HIST("MC/prm/pdg211/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - } - break; - case -211: - histos.fill(HIST("MC/pdgNeg211/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - if (particle.isPhysicalPrimary()) { - histos.fill(HIST("MC/prm/pdgNeg211/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - } - break; - case 321: - histos.fill(HIST("MC/pdg321/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - if (particle.isPhysicalPrimary()) { - histos.fill(HIST("MC/prm/pdg321/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - } - break; - case -321: - histos.fill(HIST("MC/pdgNeg321/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - if (particle.isPhysicalPrimary()) { - histos.fill(HIST("MC/prm/pdgNeg321/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - } - break; - case 2212: - histos.fill(HIST("MC/pdg2212/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - if (particle.isPhysicalPrimary()) { - histos.fill(HIST("MC/prm/pdg2212/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - } - break; - case -2212: - histos.fill(HIST("MC/pdgNeg2212/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - if (particle.isPhysicalPrimary()) { - histos.fill(HIST("MC/prm/pdgNeg2212/particleDiff"), particle.pt(), collisionMC.t() - particle.vt()); - } - break; - default: - break; + lastCollisionId = trk.collisionId(); /// Cache last collision ID + + float t0AC[2] = {0.f, 0.f}; + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + t0AC[0] = collision.t0AC() * 1000.f; + t0AC[1] = collision.t0resolution() * 1000.f; + } + + float t0A = 1e10; + float t0C = 1e10; + + constexpr float dummyTime = 30.; // Due to HW limitations time can be only within range (-25,25) ns, dummy time is around 32 ns + if (collision.has_foundFT0()) { // Get the non corrected FT0AC + const auto& ft0 = collision.foundFT0(); + const std::bitset<8>& triggers = ft0.triggerMask(); + const bool ora = triggers[o2::ft0::Triggers::bitA]; + const bool orc = triggers[o2::ft0::Triggers::bitC]; + if (ora && ft0.timeA() < dummyTime) { + t0A = ft0.timeA(); + } + if (orc && ft0.timeC() < dummyTime) { + t0C = ft0.timeC(); + } + if (ft0.isValidTime()) { + histos.fill(HIST("ft0/diffPosZ"), ft0.posZ() - collisionMC.posZ()); + } + } + if (collision.t0ACorrectedValid()) { + histos.fill(HIST("ft0/FT0AMinusFT0ACorrected"), (t0A - collision.t0ACorrected()) * 1000.f); } + if (collision.t0CCorrectedValid()) { + histos.fill(HIST("ft0/FT0CMinusFT0CCorrected"), (t0C - collision.t0CCorrected()) * 1000.f); + } + if (collision.t0ACValid()) { + histos.fill(HIST("ft0/FT0ACMinusFT0ACCorrected"), (0.5 * (t0A + t0C) - collision.t0AC()) * 1000.f); + } + + const auto& recoBC = collision.bc(); + const auto& foundBC = collision.foundBC(); + const auto& mcBC = collisionMC.bc(); + + const auto& recoBCid = recoBC.globalBC() % o2::constants::lhc::LHCMaxBunches; + const auto& mcBCid = mcBC.globalBC() % o2::constants::lhc::LHCMaxBunches; + const auto& foundBCid = foundBC.globalBC() % o2::constants::lhc::LHCMaxBunches; + const int diffRecoFoundBC = foundBC.globalBC() - recoBC.globalBC(); + const int diffRecoMCBC = recoBC.globalBC() - mcBC.globalBC(); + const int diffFoundMCBC = foundBC.globalBC() - mcBC.globalBC(); + histos.fill(HIST("collisions/Reco/BCvsMCBC"), recoBCid, mcBCid); + histos.fill(HIST("collisions/Reco/FoundBCvsMCBC"), foundBCid, mcBCid); + histos.fill(HIST("collisions/Reco/FoundBCvsBC"), foundBCid, recoBCid); + histos.fill(HIST("collisions/Reco/bcMinusMcBc"), (diffRecoMCBC)*o2::constants::lhc::LHCBunchSpacingNS); + histos.fill(HIST("collisions/Reco/foundbcMinusMcBc"), (diffFoundMCBC)*o2::constants::lhc::LHCBunchSpacingNS); + histos.fill(HIST("collisions/Reco/bcMinusfoundBc"), (diffRecoFoundBC)*o2::constants::lhc::LHCBunchSpacingNS); + histos.fill(HIST("collisions/Reco/bcMinusfoundBcRatio"), (diffRecoFoundBC)*o2::constants::lhc::LHCBunchSpacingNS / collision.collisionTimeRes()); + histos.fill(HIST("collisions/Reco/foundbcMinusMcBcRatio"), (diffFoundMCBC)*o2::constants::lhc::LHCBunchSpacingNS / collision.collisionTimeRes()); + histos.fill(HIST("collisions/Reco/bcMinusMcBcRatio"), (diffRecoMCBC)*o2::constants::lhc::LHCBunchSpacingNS / collision.collisionTimeRes()); + + // timeInBCNS + bc2ns(); + // bc* o2::constants::lhc::LHCBunchSpacingNS + orbit* o2::constants::lhc::LHCOrbitNS; + // int64_t(mcBC.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) + + histos.fill(HIST("MC/CollisionTime/eventtimeMC"), eventtimeMC); + histos.fill(HIST("MC/CollisionTime/All"), trk.tofEvTime()); + histos.fill(HIST("MC/CollisionTime/FT0"), t0AC[0]); + histos.fill(HIST("MC/CollisionTime/TOF"), trk.evTimeTOF()); + histos.fill(HIST("MC/CollisionTime/eventtimeMCvsAll"), eventtimeMC, trk.tofEvTime()); + histos.fill(HIST("MC/CollisionTime/eventtimeMCvsFT0"), eventtimeMC, t0AC[0]); + histos.fill(HIST("MC/CollisionTime/eventtimeMCvsTOF"), eventtimeMC, trk.evTimeTOF()); + + histos.fill(HIST("MC/diff/All"), eventtimeMC - trk.tofEvTime()); + histos.fill(HIST("MC/diff/FT0"), eventtimeMC - t0AC[0]); + histos.fill(HIST("MC/diff/TOF"), eventtimeMC - trk.evTimeTOF()); + histos.fill(HIST("MC/diffvsZ/All"), eventtimeMC - trk.tofEvTime(), collisionMC.posZ()); + histos.fill(HIST("MC/diffvsZ/FT0"), eventtimeMC - t0AC[0], collisionMC.posZ()); + histos.fill(HIST("MC/diffvsZ/TOF"), eventtimeMC - trk.evTimeTOF(), collisionMC.posZ()); } } - PROCESS_SWITCH(tofPidCollisionTimeQa, processMC, "Process MC", true); + PROCESS_SWITCH(tofPidCollisionTimeQa, processMC, "Process MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx index bbae2f60cd5..bc80df4b71a 100644 --- a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx +++ b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx @@ -281,7 +281,7 @@ struct tpcPidQaSignal { void processNoEvSel(soa::Filtered const& tracks, aod::Collisions const& collisions) { histos.fill(HIST("event/evsel"), 1, collisions.size()); - LOG(info) << "Processing " << collisions.size() << " collisions with " << tracks.size() << " tracks"; + LOG(debug) << "Processing " << collisions.size() << " collisions with " << tracks.size() << " tracks"; processTracks(tracks); } PROCESS_SWITCH(tpcPidQaSignal, processNoEvSel, "Process without event selection", true); @@ -290,7 +290,7 @@ struct tpcPidQaSignal { void processMoreTrkSel(soa::Filtered> const& tracks, aod::Collisions const& collisions) { histos.fill(HIST("event/evsel"), 1, collisions.size()); - LOG(info) << "Processing " << collisions.size() << " collisions with " << tracks.size() << " tracks"; + LOG(debug) << "Processing " << collisions.size() << " collisions with " << tracks.size() << " tracks"; processTracks(tracks); } PROCESS_SWITCH(tpcPidQaSignal, processMoreTrkSel, "Process without event selection", false); diff --git a/DPG/Tasks/AOTTrack/qaDcaMC.cxx b/DPG/Tasks/AOTTrack/qaDcaMC.cxx index 14078e0745f..4054c59b33a 100644 --- a/DPG/Tasks/AOTTrack/qaDcaMC.cxx +++ b/DPG/Tasks/AOTTrack/qaDcaMC.cxx @@ -68,38 +68,20 @@ static constexpr const char* chargeNames[nSpecies] = {"pos_pdg", "neg_pdg"}; static constexpr int PDGs[nSpecies] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton, 1000010020, 1000010030, 1000020030, 1000020040}; // Histograms -static constexpr int nHistograms = nSpecies * 2; - // Pt -static constexpr std::string_view hPtStr[nHistograms] = {"MC/el/pos_pdg/dcaxy/pt/str", "MC/mu/pos_pdg/dcaxy/pt/str", "MC/pi/pos_pdg/dcaxy/pt/str", - "MC/ka/pos_pdg/dcaxy/pt/str", "MC/pr/pos_pdg/dcaxy/pt/str", "MC/de/pos_pdg/dcaxy/pt/str", - "MC/tr/pos_pdg/dcaxy/pt/str", "MC/he/pos_pdg/dcaxy/pt/str", "MC/al/pos_pdg/dcaxy/pt/str", - "MC/el/neg_pdg/dcaxy/pt/str", "MC/mu/neg_pdg/dcaxy/pt/str", "MC/pi/neg_pdg/dcaxy/pt/str", - "MC/ka/neg_pdg/dcaxy/pt/str", "MC/pr/neg_pdg/dcaxy/pt/str", "MC/de/neg_pdg/dcaxy/pt/str", - "MC/tr/neg_pdg/dcaxy/pt/str", "MC/he/neg_pdg/dcaxy/pt/str", "MC/al/neg_pdg/dcaxy/pt/str"}; -static constexpr std::string_view hPtMat[nHistograms] = {"MC/el/pos_pdg/dcaxy/pt/mat", "MC/mu/pos_pdg/dcaxy/pt/mat", "MC/pi/pos_pdg/dcaxy/pt/mat", - "MC/ka/pos_pdg/dcaxy/pt/mat", "MC/pr/pos_pdg/dcaxy/pt/mat", "MC/de/pos_pdg/dcaxy/pt/mat", - "MC/tr/pos_pdg/dcaxy/pt/mat", "MC/he/pos_pdg/dcaxy/pt/mat", "MC/al/pos_pdg/dcaxy/pt/mat", - "MC/el/neg_pdg/dcaxy/pt/mat", "MC/mu/neg_pdg/dcaxy/pt/mat", "MC/pi/neg_pdg/dcaxy/pt/mat", - "MC/ka/neg_pdg/dcaxy/pt/mat", "MC/pr/neg_pdg/dcaxy/pt/mat", "MC/de/neg_pdg/dcaxy/pt/mat", - "MC/tr/neg_pdg/dcaxy/pt/mat", "MC/he/neg_pdg/dcaxy/pt/mat", "MC/al/neg_pdg/dcaxy/pt/mat"}; -static constexpr std::string_view hPtMatSM[nHistograms] = {"MC/el/pos_pdg/dcaxy/pt/sm", "MC/mu/pos_pdg/dcaxy/pt/sm", "MC/pi/pos_pdg/dcaxy/pt/sm", - "MC/ka/pos_pdg/dcaxy/pt/sm", "MC/pr/pos_pdg/dcaxy/pt/sm", "MC/de/pos_pdg/dcaxy/pt/sm", - "MC/tr/pos_pdg/dcaxy/pt/sm", "MC/he/pos_pdg/dcaxy/pt/sm", "MC/al/pos_pdg/dcaxy/pt/sm", - "MC/el/neg_pdg/dcaxy/pt/sm", "MC/mu/neg_pdg/dcaxy/pt/sm", "MC/pi/neg_pdg/dcaxy/pt/sm", - "MC/ka/neg_pdg/dcaxy/pt/sm", "MC/pr/neg_pdg/dcaxy/pt/sm", "MC/de/neg_pdg/dcaxy/pt/sm", - "MC/tr/neg_pdg/dcaxy/pt/sm", "MC/he/neg_pdg/dcaxy/pt/sm", "MC/al/neg_pdg/dcaxy/pt/sm"}; -static constexpr std::string_view hPtMatSM1Dau[nHistograms] = {"MC/el/pos_pdg/dcaxy/pt/sm1dau", "MC/mu/pos_pdg/dcaxy/pt/sm1dau", "MC/pi/pos_pdg/dcaxy/pt/sm1dau", - "MC/ka/pos_pdg/dcaxy/pt/sm1dau", "MC/pr/pos_pdg/dcaxy/pt/sm1dau", "MC/de/pos_pdg/dcaxy/pt/sm1dau", - "MC/tr/pos_pdg/dcaxy/pt/sm1dau", "MC/he/pos_pdg/dcaxy/pt/sm1dau", "MC/al/pos_pdg/dcaxy/pt/sm1dau", - "MC/el/neg_pdg/dcaxy/pt/sm1dau", "MC/mu/neg_pdg/dcaxy/pt/sm1dau", "MC/pi/neg_pdg/dcaxy/pt/sm1dau", - "MC/ka/neg_pdg/dcaxy/pt/sm1dau", "MC/pr/neg_pdg/dcaxy/pt/sm1dau", "MC/de/neg_pdg/dcaxy/pt/sm1dau", - "MC/tr/neg_pdg/dcaxy/pt/sm1dau", "MC/he/neg_pdg/dcaxy/pt/sm1dau", "MC/al/neg_pdg/dcaxy/pt/sm1dau"}; std::array, nCharges>, nSpecies> hPtPrm; +std::array, nCharges>, nSpecies> hPtStr; +std::array, nCharges>, nSpecies> hPtMat; +std::array, nCharges>, nSpecies> hPtMatSM; +std::array, nCharges>, nSpecies> hPtMatSM1Dau; +std::array, nCharges>, nSpecies> hPtMotherOfPDG1; +std::array, nCharges>, nSpecies> hPtMotherOfPDG2; +std::array, nCharges>, nSpecies> hPtMotherOfPDG3; struct QaDcaMc { // Track/particle selection Configurable maxProdRadius{"maxProdRadius", 9999.f, "Maximum production radius of the particle under study"}; + Configurable motherPDG{"motherPDG", 0, "PDG code of the mother particle"}; // Charge selection Configurable doPositivePDG{"doPositivePDG", false, "Flag to fill histograms for positive PDG codes."}; Configurable doNegativePDG{"doNegativePDG", false, "Flag to fill histograms for negative PDG codes."}; @@ -115,8 +97,10 @@ struct QaDcaMc { Configurable doAl{"do-al", false, "Flag to run with the PDG code of helium 4"}; // Track only selection, options to select only specific tracks Configurable minNClustersITS{"minNClustersITS", -1, "Minimum required number of ITS clusters"}; + Configurable enableTrackSelection{"enableTrackSelection", true, "Enable the track selection"}; // Event selection + Configurable enableEventSelection{"enableEventSelection", true, "Enable the event selection"}; Configurable nMinNumberOfContributors{"nMinNumberOfContributors", 2, "Minimum required number of contributors to the primary vertex"}; Configurable vertexZMin{"vertex-z-min", -10.f, "Minimum position of the generated vertez in Z (cm)"}; Configurable vertexZMax{"vertex-z-max", 10.f, "Maximum position of the generated vertez in Z (cm)"}; @@ -126,13 +110,12 @@ struct QaDcaMc { ConfigurableAxis etaBins{"etaBins", {200, -3.f, 3.f}, "Eta binning"}; ConfigurableAxis phiBins{"phiBins", {200, 0.f, 6.284f}, "Phi binning"}; ConfigurableAxis yBins{"yBins", {200, -0.5f, 0.5f}, "Y binning"}; - ConfigurableAxis dcaBins{"dcaBins", {2000, -1.f, 1.f}, "DCA binning"}; + ConfigurableAxis dcaBinsxy{"dcaBinsxy", {500, -1.f, 1.f}, "DCAxy binning"}; + ConfigurableAxis dcaBinsz{"dcaBinsz", {100, -0.1f, 0.1f}, "DCAz binning"}; Configurable doPVContributorCut{"doPVContributorCut", false, "Select tracks used for primary vertex recostruction (isPVContributor)"}; // Histograms HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry histosPosPdg{"HistosPosPdg", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry histosNegPdg{"HistosNegPdg", {}, OutputObjHandlingPolicy::AnalysisObject}; static const char* particleName(int pdgSign, o2::track::PID::ID id) { @@ -167,8 +150,8 @@ struct QaDcaMc { const AxisSpec axisEta{etaBins, "#it{#eta}"}; const AxisSpec axisY{yBins, "#it{y}"}; const AxisSpec axisPhi{phiBins, "#it{#varphi} (rad)"}; - const AxisSpec axisDCAxy{dcaBins, "DCA_{xy} (cm)"}; - const AxisSpec axisDCAz{dcaBins, "DCA_{z} (cm)"}; + const AxisSpec axisDCAxy{dcaBinsxy, "DCA_{xy} (cm)"}; + const AxisSpec axisDCAz{dcaBinsz, "DCA_{z} (cm)"}; const char* partName = particleName(pdgSign, id); LOG(info) << "Preparing histograms for particle: " << partName << " pdgSign " << pdgSign; @@ -179,18 +162,17 @@ struct QaDcaMc { yMin, yMax, phiMin, phiMax); - const int histogramIndex = id + pdgSign * nSpecies; - HistogramRegistry* registry = &histosPosPdg; - if (pdgSign == 1) { - registry = &histosNegPdg; + hPtPrm[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/prm", particleNames[id], chargeNames[pdgSign]), "DCA Prm. " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + hPtStr[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/str", particleNames[id], chargeNames[pdgSign]), "DCA Str. " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + hPtMat[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/mat", particleNames[id], chargeNames[pdgSign]), "DCA Mat. " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + hPtMatSM[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/sm", particleNames[id], chargeNames[pdgSign]), "DCA Mat. SM " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + hPtMatSM1Dau[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/sm1dau", particleNames[id], chargeNames[pdgSign]), "DCA Mat. SM 1 Dau " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + if (motherPDG.value != 0) { + hPtMotherOfPDG1[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/motherpdg1", particleNames[id], chargeNames[pdgSign]), "DCA mother pdg " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + hPtMotherOfPDG2[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/motherpdg2", particleNames[id], chargeNames[pdgSign]), "DCA mother pdg " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); + hPtMotherOfPDG3[id][pdgSign] = histos.add(Form("MC/%s/%s/dcaxyz/pt/motherpdg3", particleNames[id], chargeNames[pdgSign]), "DCA mother pdg " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); } - hPtPrm[id][pdgSign] = registry->add(Form("MC/%s/%s/dcaxy/pt/prm", particleNames[id], chargeNames[pdgSign]), "DCA Prm. " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); - registry->add(hPtStr[histogramIndex].data(), "DCA Str. " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); - registry->add(hPtMat[histogramIndex].data(), "DCA Mat. " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); - registry->add(hPtMatSM[histogramIndex].data(), "DCA Mat. SM " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); - registry->add(hPtMatSM1Dau[histogramIndex].data(), "DCA Mat. SM " + tagPt, kTH3F, {axisPt, axisDCAxy, axisDCAz}); - LOG(info) << "Done with making histograms for particle: " << partName; } @@ -235,6 +217,8 @@ struct QaDcaMc { makeMCHistograms(doHe); makeMCHistograms(doAl); }); + + histos.print(); } // Selection cuts defined from the binning @@ -324,13 +308,6 @@ struct QaDcaMc { } } - HistogramRegistry* h = &histosPosPdg; - if constexpr (pdgSign == 1) { - h = &histosNegPdg; - } - - constexpr int histogramIndex = id + pdgSign * nSpecies; - LOG(debug) << "fillMCTrackHistograms for pdgSign '" << pdgSign << "' and id '" << static_cast(id) << "' " << particleName(pdgSign, id) << " with index " << histogramIndex; const o2::aod::McParticles::iterator& mcParticle = track.mcParticle(); if (!isPdgSelected(mcParticle)) { // Selecting PDG code @@ -339,17 +316,42 @@ struct QaDcaMc { histos.fill(HIST("MC/trackSelection"), trkCutIdxN + id); + if (motherPDG.value != 0) { + int motherPdgCounter = 0; + if (mcParticle.has_mothers()) { + const auto& mothers = mcParticle.mothers_as(); + for (const auto& mother : mothers) { + if (!mother.has_mothers()) { + continue; + } + const auto& mothers2 = mother.mothers_as(); + for (const auto& mother2 : mothers2) { + if (abs(mother2.pdgCode()) == motherPDG.value) { + motherPdgCounter++; + } + } + } + } + if (motherPdgCounter == 1) { + hPtMotherOfPDG1[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); + } else if (motherPdgCounter == 2) { + hPtMotherOfPDG2[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); + } else if (motherPdgCounter > 0) { + hPtMotherOfPDG3[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); + } + } + if (isPhysicalPrimary(mcParticle)) { hPtPrm[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); } else if (mcParticle.getProcess() == 4) { // Particle decay - h->fill(HIST(hPtStr[histogramIndex]), mcParticle.pt(), track.dcaXY(), track.dcaZ()); + hPtStr[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); } else { // Material - h->fill(HIST(hPtMat[histogramIndex]), mcParticle.pt(), track.dcaXY(), track.dcaZ()); + hPtMat[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); if (mcParticle.has_mothers()) { if (mcParticle.mothers_as()[0].pdgCode() == mcParticle.pdgCode()) { - h->fill(HIST(hPtMatSM[histogramIndex]), mcParticle.pt(), track.dcaXY(), track.dcaZ()); + hPtMatSM[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); if (mcParticle.mothers_as().size() == 1) { - h->fill(HIST(hPtMatSM[histogramIndex]), mcParticle.pt(), track.dcaXY(), track.dcaZ()); + hPtMatSM1Dau[id][pdgSign]->Fill(mcParticle.pt(), track.dcaXY(), track.dcaZ()); } } } @@ -362,6 +364,9 @@ struct QaDcaMc { if constexpr (doFillHistograms) { histos.fill(HIST("eventSelection"), 1); } + if (!enableEventSelection.value) { + return true; + } if (!collision.sel8()) { return false; } @@ -470,6 +475,10 @@ struct QaDcaMc { histos.fill(HIST("MC/fakeTrackNoiseHits"), 0.5); return false; } + if (!enableTrackSelection.value) { + return true; + } + if constexpr (doFillHisto) { histos.fill(countingHisto, trkCutIdxHasMcPart); // Tracks with particles (i.e. no fakes) } diff --git a/DPG/Tasks/AOTTrack/qaEfficiency.cxx b/DPG/Tasks/AOTTrack/qaEfficiency.cxx index 53390217d00..0e1c023fc6e 100644 --- a/DPG/Tasks/AOTTrack/qaEfficiency.cxx +++ b/DPG/Tasks/AOTTrack/qaEfficiency.cxx @@ -59,7 +59,8 @@ static constexpr int trkCutIdxPassedITSPartial = 18; static constexpr int trkCutIdxPassedTPCPartial = 19; static constexpr int trkCutIdxPassedTOFPartial = 20; static constexpr int trkCutIdxPassedGlobal = 21; -static constexpr int trkCutIdxN = 22; +static constexpr int trkCutSameColl = 22; +static constexpr int trkCutIdxN = 23; // Particle information static constexpr int nSpecies = o2::track::PID::NIDs; // One per PDG @@ -67,8 +68,8 @@ static constexpr int nCharges = 2; static constexpr int nParticles = nSpecies * nCharges; static constexpr const char* particleTitle[nParticles] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha", "e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; -static constexpr int PDGs[nParticles] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton, 1000010020, 1000010030, 1000020030, 1000020040, - -kElectron, -kMuonMinus, -kPiPlus, -kKPlus, -kProton, -1000010020, -1000010030, -1000020030, -1000020040}; +static constexpr int PDGs[nParticles] = {11, 13, 211, 321, 2212, 1000010020, 1000010030, 1000020030, 1000020040, + -11, -13, -211, -321, -2212, -1000010020, -1000010030, -1000020030, -1000020040}; // Histograms @@ -106,6 +107,12 @@ std::array, nParticles> hPtTrkItsTpcMat; std::array, nParticles> hPtItsTpcTofMat; std::array, nParticles> hPtGeneratedMat; +// Pt for tertiaries from secondary weak decay +std::array, nParticles> hPtItsTpcTer; +std::array, nParticles> hPtTrkItsTpcTer; +std::array, nParticles> hPtItsTpcTofTer; +std::array, nParticles> hPtGeneratedTer; + // P std::array, nParticles> hPItsTpc; std::array, nParticles> hPTrkItsTpc; @@ -146,9 +153,30 @@ std::array, nParticles> hPtEtaItsTpc; std::array, nParticles> hPtEtaTrkItsTpc; std::array, nParticles> hPtEtaItsTpcTof; std::array, nParticles> hPtEtaGenerated; +// 2D Pt vs Radius +std::array, nParticles> hPtRadiusItsTpc; +std::array, nParticles> hPtRadiusTrkItsTpc; +std::array, nParticles> hPtRadiusItsTpcTof; +std::array, nParticles> hPtRadiusGenerated; + +std::array, nParticles> hPtRadiusItsTpcPrm; +std::array, nParticles> hPtRadiusTrkItsTpcPrm; +std::array, nParticles> hPtRadiusItsTpcTofPrm; +std::array, nParticles> hPtRadiusGeneratedPrm; + +std::array, nParticles> hPtRadiusItsTpcStr; +std::array, nParticles> hPtRadiusTrkItsTpcStr; +std::array, nParticles> hPtRadiusItsTpcTofStr; +std::array, nParticles> hPtRadiusGeneratedStr; + +std::array, nParticles> hPtRadiusItsTpcTer; +std::array, nParticles> hPtRadiusTrkItsTpcTer; +std::array, nParticles> hPtRadiusItsTpcTofTer; +std::array, nParticles> hPtRadiusGeneratedTer; struct QaEfficiency { // Track/particle selection + Configurable numSameCollision{"numSameCollision", false, "Flag to ask that the numerator is in the same collision as the denominator"}; Configurable noFakesHits{"noFakesHits", false, "Flag to reject tracks that have fake hits"}; Configurable skipEventsWithoutTPCTracks{"skipEventsWithoutTPCTracks", false, "Flag to reject events that have no tracks reconstructed in the TPC"}; Configurable maxProdRadius{"maxProdRadius", 9999.f, "Maximum production radius of the particle under study"}; @@ -185,9 +213,11 @@ struct QaEfficiency { ConfigurableAxis etaBins{"etaBins", {200, -3.f, 3.f}, "Eta binning"}; ConfigurableAxis phiBins{"phiBins", {200, 0.f, 6.284f}, "Phi binning"}; ConfigurableAxis yBins{"yBins", {200, -0.5f, 0.5f}, "Y binning"}; + ConfigurableAxis radiusBins{"radiusBins", {200, 0.f, 100.f}, "Radius binning"}; // Task configuration Configurable makeEff{"make-eff", false, "Flag to produce the efficiency with TEfficiency"}; Configurable doPtEta{"doPtEta", false, "Flag to produce the efficiency vs pT and Eta"}; + Configurable doPtRadius{"doPtRadius", false, "Flag to produce the efficiency vs pT and Radius"}; Configurable applyEvSel{"applyEvSel", 0, "Flag to apply event selection: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; // Custom track cuts for debug purposes TrackSelection customTrackCuts; @@ -215,6 +245,11 @@ struct QaEfficiency { OutputObj listEfficiencyMC{"EfficiencyMC"}; OutputObj listEfficiencyData{"EfficiencyData"}; + using CollisionCandidates = o2::soa::Join; + using CollisionCandidatesMC = o2::soa::Join; + using TrackCandidates = o2::soa::Join; + using TrackCandidatesMC = o2::soa::Join; + // Histograms HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -255,6 +290,7 @@ struct QaEfficiency { const AxisSpec axisEta{etaBins, "#it{#eta}"}; const AxisSpec axisY{yBins, "#it{y}"}; const AxisSpec axisPhi{phiBins, "#it{#varphi} (rad)"}; + const AxisSpec axisRadius{radiusBins, "Radius (cm)"}; const char* partName = particleName(pdgSign, id); LOG(info) << "Preparing histograms for particle: " << partName << " pdgSign " << pdgSign; @@ -287,7 +323,6 @@ struct QaEfficiency { partName, phiMin, phiMax, yMin, yMax); - const int histogramIndex = id + pdgSign * nSpecies; // Pt @@ -318,6 +353,12 @@ struct QaEfficiency { hPtItsTpcTofStr[histogramIndex] = histos.add(Form("MC/pdg%i/pt/str/its_tpc_tof", PDGs[histogramIndex]), "ITS-TPC-TOF tracks (from weak decays) " + tagPt, kTH1D, {axisPt}); hPtGeneratedStr[histogramIndex] = histos.add(Form("MC/pdg%i/pt/str/generated", PDGs[histogramIndex]), "Generated (from weak decays) " + tagPt, kTH1D, {axisPt}); + // Ter + hPtItsTpcTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks (from secondary weak decays) " + tagPt, kTH1D, {axisPt}); + hPtTrkItsTpcTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/trk/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks (reco from secondary weak decays) " + tagPt, kTH1D, {axisPt}); + hPtItsTpcTofTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/its_tpc_tof", PDGs[histogramIndex]), "ITS-TPC-TOF tracks (from secondary weak decays) " + tagPt, kTH1D, {axisPt}); + hPtGeneratedTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/generated", PDGs[histogramIndex]), "Generated (from secondary weak decays) " + tagPt, kTH1D, {axisPt}); + // Mat hPtItsTpcMat[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mat/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks (from material)" + tagPt, kTH1D, {axisPt}); hPtTrkItsTpcMat[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mat/trk/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks (reco from material) " + tagPt, kTH1D, {axisPt}); @@ -366,6 +407,24 @@ struct QaEfficiency { hPtEtaGenerated[histogramIndex] = histos.add(Form("MC/pdg%i/pt/asd", PDGs[histogramIndex]), "Generated " + tagPtEta, kTH2D, {axisPt, axisEta}); } + if (doPtRadius) { + hPtRadiusItsTpc[histogramIndex] = histos.add(Form("MC/pdg%i/pt/radius/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusItsTpcTof[histogramIndex] = histos.add(Form("MC/pdg%i/pt/radius/its_tpc_tof", PDGs[histogramIndex]), "ITS-TPC-TOF tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusGenerated[histogramIndex] = histos.add(Form("MC/pdg%i/pt/radius/generated", PDGs[histogramIndex]), "Generated " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + + hPtRadiusItsTpcPrm[histogramIndex] = histos.add(Form("MC/pdg%i/pt/prm/radius/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusItsTpcTofPrm[histogramIndex] = histos.add(Form("MC/pdg%i/pt/prm/radius/its_tpc_tof", PDGs[histogramIndex]), "ITS-TPC-TOF tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusGeneratedPrm[histogramIndex] = histos.add(Form("MC/pdg%i/pt/prm/radius/generated", PDGs[histogramIndex]), "Generated " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + + hPtRadiusItsTpcStr[histogramIndex] = histos.add(Form("MC/pdg%i/pt/str/radius/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusItsTpcTofStr[histogramIndex] = histos.add(Form("MC/pdg%i/pt/str/radius/its_tpc_tof", PDGs[histogramIndex]), "ITS-TPC-TOF tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusGeneratedStr[histogramIndex] = histos.add(Form("MC/pdg%i/pt/str/radius/generated", PDGs[histogramIndex]), "Generated " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + + hPtRadiusItsTpcTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/radius/its_tpc", PDGs[histogramIndex]), "ITS-TPC tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusItsTpcTofTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/radius/its_tpc_tof", PDGs[histogramIndex]), "ITS-TPC-TOF tracks " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + hPtRadiusGeneratedTer[histogramIndex] = histos.add(Form("MC/pdg%i/pt/ter/radius/generated", PDGs[histogramIndex]), "Generated " + tagPt + " vs Radius", kTH2D, {axisPt, axisRadius}); + } + LOG(info) << "Done with making histograms for particle: " << partName; } @@ -430,17 +489,19 @@ struct QaEfficiency { makeEfficiency("ITS-TPC_vsPt_Prm_Trk", hPtTrkItsTpcPrm[histogramIndex]); makeEfficiency("ITS-TPC-TOF_vsPt_Prm", hPtItsTpcTofPrm[histogramIndex]); makeEfficiency("ITS-TPC-TOF_vsPt_Prm_Trk", hPtTrkItsTpcTofPrm[histogramIndex]); - makeEfficiency("ITS-TPC_vsPt_Prm_RecoEv", hPtItsTpcPrm[histogramIndex]); makeEfficiency("ITS-TPC_vsPt_Str", hPtItsTpcStr[histogramIndex]); makeEfficiency("ITS-TPC_vsPt_Str_Trk", hPtTrkItsTpcStr[histogramIndex]); makeEfficiency("ITS-TPC-TOF_vsPt_Str", hPtItsTpcTofStr[histogramIndex]); - makeEfficiency("ITS-TPC_vsPt_Mat", hPtItsTpcMat[histogramIndex]); makeEfficiency("ITS-TPC_vsPt_Mat_Trk", hPtTrkItsTpcMat[histogramIndex]); makeEfficiency("ITS-TPC-TOF_vsPt_Mat", hPtItsTpcTofMat[histogramIndex]); + makeEfficiency("ITS-TPC_vsPt_Ter", hPtItsTpcTer[histogramIndex]); + makeEfficiency("ITS-TPC_vsPt_Ter_Trk", hPtTrkItsTpcTer[histogramIndex]); + makeEfficiency("ITS-TPC-TOF_vsPt_Ter", hPtItsTpcTofTer[histogramIndex]); + makeEfficiency("ITS-TPC_vsP", hPItsTpc[histogramIndex]); makeEfficiency("ITS-TPC_vsP_Trk", hPTrkItsTpc[histogramIndex]); makeEfficiency("ITS-TPC-TOF_vsP", hPItsTpcTof[histogramIndex]); @@ -478,6 +539,16 @@ struct QaEfficiency { makeEfficiency2D("ITS-TPC_vsPt_vsEta_Trk", hPtEtaTrkItsTpc[histogramIndex]); makeEfficiency2D("ITS-TPC-TOF_vsPt_vsEta", hPtEtaItsTpcTof[histogramIndex]); } + if (doPtRadius) { + makeEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpc[histogramIndex]); + makeEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTof[histogramIndex]); + makeEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpcPrm[histogramIndex]); + makeEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTofPrm[histogramIndex]); + makeEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpcStr[histogramIndex]); + makeEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTofStr[histogramIndex]); + makeEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpcTer[histogramIndex]); + makeEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTofTer[histogramIndex]); + } LOG(info) << "Done with making histograms for particle: " << partName << " for efficiencies"; } @@ -537,6 +608,7 @@ struct QaEfficiency { default: LOG(fatal) << "Can't interpret track asked selection " << globalTrackSelection; } + h->GetXaxis()->SetBinLabel(trkCutSameColl, "passedSameColl"); for (int i = 0; i < nSpecies; i++) { h->GetXaxis()->SetBinLabel(trkCutIdxN + i, Form("Passed PDG %i %s", PDGs[i], particleTitle[i])); @@ -883,18 +955,13 @@ struct QaEfficiency { } } - template - bool isPdgSelected(const o2::aod::McParticles::iterator& mcParticle) + template + bool isPdgSelected(const particleType& mcParticle) { static_assert(pdgSign == 0 || pdgSign == 1); static_assert(id > 0 || id < nSpecies); - - // Selecting a specific PDG - if constexpr (pdgSign == 0) { - return mcParticle.pdgCode() == PDGs[id]; - } else { - return mcParticle.pdgCode() == -PDGs[id]; - } + constexpr int index = id + pdgSign * nSpecies; + return mcParticle.pdgCode() == PDGs[index]; } bool isPhysicalPrimary(const o2::aod::McParticles::iterator& mcParticle) @@ -906,9 +973,20 @@ struct QaEfficiency { } return mcParticle.isPhysicalPrimary(); } - - template - void fillMCTrackHistograms(const trackType& track, const bool doMakeHistograms) + bool isFinal(const o2::aod::McParticles::iterator& mcParticle) + { + if (!mcParticle.has_daughters() && !mcParticle.isPhysicalPrimary() && mcParticle.getProcess() == 4) { + auto mothers = mcParticle.mothers_as(); + for (const auto& mother : mothers) { + if (!mother.isPhysicalPrimary() && mother.getProcess() == 4) { + return true; + } + } + } + return false; // Otherwise, not considered a tertiary particle + } + template + void fillMCTrackHistograms(const TrackCandidatesMC::iterator& track, const bool doMakeHistograms) { static_assert(pdgSign == 0 || pdgSign == 1); if (!doMakeHistograms) { @@ -924,10 +1002,20 @@ struct QaEfficiency { return; } } - constexpr int histogramIndex = id + pdgSign * nSpecies; LOG(debug) << "fillMCTrackHistograms for pdgSign '" << pdgSign << "' and id '" << static_cast(id) << "' " << particleName(pdgSign, id) << " with index " << histogramIndex; const o2::aod::McParticles::iterator& mcParticle = track.mcParticle(); + const CollisionCandidatesMC::iterator& collision = track.collision_as(); + float radius = std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy()); + if (numSameCollision) { + if (!collision.has_mcCollision()) { + return; + } + if (mcParticle.mcCollision().globalIndex() != collision.mcCollision().globalIndex()) { + return; + } + } + histos.fill(HIST("MC/trackSelection"), trkCutSameColl); if (!isPdgSelected(mcParticle)) { // Selecting PDG code return; @@ -960,6 +1048,12 @@ struct QaEfficiency { hPtEtaItsTpcTof[histogramIndex]->Fill(mcParticle.pt(), mcParticle.eta()); } } + if (doPtRadius) { + hPtRadiusItsTpc[histogramIndex]->Fill(mcParticle.pt(), radius); + if (passedTOF) { + hPtRadiusItsTpcTof[histogramIndex]->Fill(mcParticle.pt(), radius); + } + } } if (passedITS && passedTOF) { hPtItsTof[histogramIndex]->Fill(mcParticle.pt()); @@ -997,6 +1091,12 @@ struct QaEfficiency { hEtaItsTpcTofPrm[histogramIndex]->Fill(mcParticle.eta()); hPhiItsTpcTofPrm[histogramIndex]->Fill(mcParticle.phi()); } + if (doPtRadius) { + hPtRadiusItsTpcPrm[histogramIndex]->Fill(mcParticle.pt(), radius); + if (passedTOF) { + hPtRadiusItsTpcTofPrm[histogramIndex]->Fill(mcParticle.pt(), radius); + } + } } } else if (mcParticle.getProcess() == 4) { // Particle decay // Checking mothers @@ -1022,6 +1122,27 @@ struct QaEfficiency { if (passedTOF) { hPtItsTpcTofStr[histogramIndex]->Fill(mcParticle.pt()); } + if (doPtRadius) { + hPtRadiusItsTpcStr[histogramIndex]->Fill(mcParticle.pt(), radius); + if (passedTOF) { + hPtRadiusItsTpcTofStr[histogramIndex]->Fill(mcParticle.pt(), radius); + } + } + } + if (isFinal(mcParticle)) { + if (passedITS && passedTPC && motherIsAccepted) { + hPtItsTpcTer[histogramIndex]->Fill(mcParticle.pt()); + hPtTrkItsTpcTer[histogramIndex]->Fill(track.pt()); + if (passedTOF) { + hPtItsTpcTofTer[histogramIndex]->Fill(mcParticle.pt()); + } + if (doPtRadius) { + hPtRadiusItsTpcTer[histogramIndex]->Fill(mcParticle.pt(), radius); + if (passedTOF) { + hPtRadiusItsTpcTofTer[histogramIndex]->Fill(mcParticle.pt(), radius); + } + } + } } } else { // Material if (passedITS && passedTPC) { @@ -1054,6 +1175,7 @@ struct QaEfficiency { constexpr int histogramIndex = id + pdgSign * nSpecies; LOG(debug) << "fillMCParticleHistograms for pdgSign '" << pdgSign << "' and id '" << static_cast(id) << "' " << particleName(pdgSign, id) << " with index " << histogramIndex; + float radius = std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy()); if (!isPdgSelected(mcParticle)) { // Selecting PDG code return; } @@ -1073,6 +1195,9 @@ struct QaEfficiency { hPtGeneratedPrm[histogramIndex]->Fill(mcParticle.pt()); hEtaGeneratedPrm[histogramIndex]->Fill(mcParticle.eta()); hPhiGeneratedPrm[histogramIndex]->Fill(mcParticle.phi()); + if (doPtRadius) { + hPtRadiusGeneratedPrm[histogramIndex]->Fill(mcParticle.pt(), radius); + } } else { if (mcParticle.getProcess() == 4) { // Particle decay // Checking mothers @@ -1094,18 +1219,29 @@ struct QaEfficiency { } if (motherIsAccepted) { hPtGeneratedStr[histogramIndex]->Fill(mcParticle.pt()); + if (doPtRadius) { + hPtRadiusGeneratedStr[histogramIndex]->Fill(mcParticle.pt(), radius); + } + if (isFinal(mcParticle)) { + hPtGeneratedTer[histogramIndex]->Fill(mcParticle.pt()); + if (doPtRadius) { + hPtRadiusGeneratedTer[histogramIndex]->Fill(mcParticle.pt(), radius); + } + } } } else { // Material hPtGeneratedMat[histogramIndex]->Fill(mcParticle.pt()); } } - hEtaGenerated[histogramIndex]->Fill(mcParticle.eta()); hYGenerated[histogramIndex]->Fill(mcParticle.y()); hPhiGenerated[histogramIndex]->Fill(mcParticle.phi()); if (doPtEta) { hPtEtaGenerated[histogramIndex]->Fill(mcParticle.pt(), mcParticle.eta()); } + if (doPtRadius) { + hPtRadiusGenerated[histogramIndex]->Fill(mcParticle.pt(), radius); + } } template @@ -1178,6 +1314,10 @@ struct QaEfficiency { doFillEfficiency("ITS-TPC_vsPt_Mat_Trk", hPtTrkItsTpcMat[histogramIndex], hPtGeneratedMat[histogramIndex]); doFillEfficiency("ITS-TPC-TOF_vsPt_Mat", hPtItsTpcTofMat[histogramIndex], hPtGeneratedMat[histogramIndex]); + doFillEfficiency("ITS-TPC_vsPt_Ter", hPtItsTpcTer[histogramIndex], hPtGeneratedTer[histogramIndex]); + doFillEfficiency("ITS-TPC_vsPt_Ter_Trk", hPtTrkItsTpcTer[histogramIndex], hPtGeneratedTer[histogramIndex]); + doFillEfficiency("ITS-TPC-TOF_vsPt_Ter", hPtItsTpcTofTer[histogramIndex], hPtGeneratedTer[histogramIndex]); + doFillEfficiency("ITS-TPC_vsP", hPItsTpc[histogramIndex], hPGenerated[histogramIndex]); doFillEfficiency("ITS-TPC_vsP_Trk", hPTrkItsTpc[histogramIndex], hPGenerated[histogramIndex]); doFillEfficiency("ITS-TPC-TOF_vsP", hPItsTpcTof[histogramIndex], hPGenerated[histogramIndex]); @@ -1218,8 +1358,18 @@ struct QaEfficiency { fillEfficiency2D("ITS-TPC_vsPt_vsEta", hPtEtaItsTpc[histogramIndex], hPtEtaGenerated[histogramIndex]); fillEfficiency2D("ITS-TPC_vsPt_vsEta_Trk", hPtEtaTrkItsTpc[histogramIndex], hPtEtaGenerated[histogramIndex]); fillEfficiency2D("ITS-TPC-TOF_vsPt_vsEta", hPtEtaItsTpcTof[histogramIndex], hPtEtaGenerated[histogramIndex]); + if (!doPtRadius) { + return; + } + fillEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpc[histogramIndex], hPtRadiusGenerated[histogramIndex]); + fillEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTof[histogramIndex], hPtRadiusGenerated[histogramIndex]); + fillEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpcPrm[histogramIndex], hPtRadiusGeneratedPrm[histogramIndex]); + fillEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTofPrm[histogramIndex], hPtRadiusGeneratedPrm[histogramIndex]); + fillEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpcStr[histogramIndex], hPtRadiusGeneratedStr[histogramIndex]); + fillEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTofStr[histogramIndex], hPtRadiusGeneratedStr[histogramIndex]); + fillEfficiency2D("ITS-TPC_vsPt_vsRadius", hPtRadiusItsTpcTer[histogramIndex], hPtRadiusGeneratedTer[histogramIndex]); + fillEfficiency2D("ITS-TPC-TOF_vsPt_vsRadius", hPtRadiusItsTpcTofTer[histogramIndex], hPtRadiusGeneratedTer[histogramIndex]); } - template bool isCollisionSelected(const CollType& collision) { @@ -1250,11 +1400,7 @@ struct QaEfficiency { } // Global process - using TrackCandidates = o2::soa::Join; - void process(o2::soa::Join::iterator const& collision) - { - isCollisionSelected(collision); - } + void process(CollisionCandidates::iterator const& collision) { isCollisionSelected(collision); } // Function to apply particle selection template @@ -1486,11 +1632,11 @@ struct QaEfficiency { SliceCache cache; Preslice perCollision = o2::aod::track::collisionId; Preslice perCollisionMc = o2::aod::mcparticle::mcCollisionId; - PresliceUnsorted> collPerCollMc = o2::aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted collPerCollMc = o2::aod::mccollisionlabel::mcCollisionId; void processMC(o2::aod::McCollisions const& mcCollisions, - // o2::soa::SmallGroups> const& collisions, - o2::soa::Join const& collisions, - o2::soa::Join const& tracks, + // o2::soa::SmallGroups const& collisions, + CollisionCandidatesMC const& collisions, + TrackCandidatesMC const& tracks, o2::aod::McParticles const& mcParticles) { @@ -1664,8 +1810,10 @@ struct QaEfficiency { // - considering also MC collisions without any reco. collision // - considering also tracks not associated to any collision // - ignoring the track-to-collision association - void processMCWithoutCollisions(o2::soa::Join const& tracks, o2::aod::Collisions const&, - o2::aod::McParticles const& mcParticles, o2::aod::McCollisions const&) + void processMCWithoutCollisions(TrackCandidatesMC const& tracks, + o2::aod::Collisions const&, + o2::aod::McParticles const& mcParticles, + o2::aod::McCollisions const&) { // Track loop for (const auto& track : tracks) { @@ -1751,7 +1899,7 @@ struct QaEfficiency { } PROCESS_SWITCH(QaEfficiency, processMCWithoutCollisions, "process MC without the collision association", false); - void processData(o2::soa::Join::iterator const& collision, + void processData(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) { @@ -1842,7 +1990,7 @@ struct QaEfficiency { } PROCESS_SWITCH(QaEfficiency, processData, "process data", true); - void processDataWithPID(o2::soa::Join::iterator const& collision, + void processDataWithPID(CollisionCandidates::iterator const& collision, o2::soa::Join const& tracks) { @@ -1935,8 +2083,7 @@ struct QaEfficiency { } PROCESS_SWITCH(QaEfficiency, processDataWithPID, "process data with PID", false); - void processHmpid(o2::soa::Join::iterator const& collision, - TrackCandidates const&, + void processHmpid(CollisionCandidates::iterator const& collision, TrackCandidates const&, o2::aod::HMPIDs const& hmpids) { diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.cxx b/DPG/Tasks/AOTTrack/qaEventTrack.cxx index afab3403224..bfd106f4b8b 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrack.cxx @@ -93,6 +93,13 @@ struct qaEventTrack { // options to check the track variables only for PV contributors Configurable checkOnlyPVContributor{"checkOnlyPVContributor", false, "check the track variables only for primary vertex contributors"}; + // options to force or not the presence of TRD (debug) + struct : ConfigurableGroup { + Configurable activateChecksTRD{"activateChecksTRD", false, "Activate the checks wityh TRD - force the track to have or not have TRD"}; + Configurable forceTRD{"forceTRD", false, "Force the track to have TRD"}; + Configurable forceNotTRD{"forceNotTRD", false, "Force the track not to have TRD"}; + } checksTRD; + // configurable binning of histograms ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 5.0, 10.0, 20.0, 50.0}, ""}; ConfigurableAxis binsInvPt{"binsInvPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 5.0, 10.0, 20.0, 50.0}, ""}; @@ -152,6 +159,13 @@ struct qaEventTrack { return; } + if (checksTRD.activateChecksTRD) { + std::array casesTRD = {checksTRD.forceTRD, checksTRD.forceNotTRD}; + if (std::accumulate(casesTRD.begin(), casesTRD.end(), 0) != 1) { + LOGP(fatal, "One and only one case between forceTRD and forceNotTRD can be true at a time. Fix it!"); + } + } + // // Next section setups overwrite of configurableAxis if overwriteAxisRangeForPbPb is used. // @@ -1498,6 +1512,17 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& if (!isSelectedTrack(track)) { continue; } + // TRD checks (debug) + if (checksTRD.activateChecksTRD) { + if (checksTRD.forceTRD && !track.hasTRD()) { + /// We want only tracks that match TRD, but the current one does not match it. Let's skip it. + continue; + } + if (checksTRD.forceNotTRD && track.hasTRD()) { + /// We want only tracks that do not match TRD, but the current one matches it. Let's skip it. + continue; + } + } // fill kinematic variables histos.fill(HIST("Tracks/Kine/pt"), track.pt()); if (track.sign() > 0) { diff --git a/DPG/Tasks/AOTTrack/qaFakeHits.cxx b/DPG/Tasks/AOTTrack/qaFakeHits.cxx new file mode 100644 index 00000000000..1da3a6a6674 --- /dev/null +++ b/DPG/Tasks/AOTTrack/qaFakeHits.cxx @@ -0,0 +1,254 @@ +// Copyright 2019-2020 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. + +/// +/// \file qaFakeHits.cxx +/// \author NicolĂČ Jacazio nicolo.jacazio@cern.ch +/// \since 2024-04-08 +/// \brief Task to analyze the fraction of the true and fake hits depending on where the fake hits are picked +/// + +// O2 includes +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StaticFor.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" + +using namespace o2::framework; +// Particle information +static constexpr int nSpecies = o2::track::PID::NIDs; // One per PDG +static constexpr int nCharges = 2; +static constexpr int nParticles = nSpecies * nCharges; +static constexpr const char* particleTitle[nParticles] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha", + "e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; +static constexpr int PDGs[nParticles] = {11, 13, 211, 321, 2212, 1000010020, 1000010030, 1000020030, 1000020040, + -11, -13, -211, -321, -2212, -1000010020, -1000010030, -1000020030, -1000020040}; +std::array, nParticles> hPtAll; +std::array, nParticles> hPtITS; +std::array, nParticles> hPtTPC; +std::array, nParticles> hPtTRD; +std::array, nParticles> hPtTOF; +std::array, nParticles> hPtOverall; + +struct QaFakeHits { + // Charge selection + Configurable doPositivePDG{"doPositivePDG", false, "Flag to fill histograms for positive PDG codes."}; + Configurable doNegativePDG{"doNegativePDG", false, "Flag to fill histograms for negative PDG codes."}; + // Particle only selection + Configurable doEl{"do-el", false, "Flag to run with the PDG code of electrons"}; + Configurable doMu{"do-mu", false, "Flag to run with the PDG code of muons"}; + Configurable doPi{"do-pi", false, "Flag to run with the PDG code of pions"}; + Configurable doKa{"do-ka", false, "Flag to run with the PDG code of kaons"}; + Configurable doPr{"do-pr", false, "Flag to run with the PDG code of protons"}; + Configurable doDe{"do-de", false, "Flag to run with the PDG code of deuterons"}; + Configurable doTr{"do-tr", false, "Flag to run with the PDG code of tritons"}; + Configurable doHe{"do-he", false, "Flag to run with the PDG code of helium 3"}; + Configurable doAl{"do-al", false, "Flag to run with the PDG code of helium 4"}; + // Track only selection, options to select only specific tracks + Configurable trackSelection{"trackSelection", true, "Local track selection"}; + Configurable globalTrackSelection{"globalTrackSelection", 0, "Global track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks, 6 -> custom track cuts via Configurable"}; + // Event selection + Configurable nMinNumberOfContributors{"nMinNumberOfContributors", 2, "Minimum required number of contributors to the primary vertex"}; + Configurable vertexZMin{"vertex-z-min", -10.f, "Minimum position of the generated vertez in Z (cm)"}; + Configurable vertexZMax{"vertex-z-max", 10.f, "Maximum position of the generated vertez in Z (cm)"}; + // Histogram configuration + ConfigurableAxis ptBins{"ptBins", {200, 0.f, 5.f}, "Pt binning"}; + // Histograms + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + static const char* particleName(int pdgSign, o2::track::PID::ID id) + { + if (pdgSign == 0) { // Positive PDG + return particleTitle[id]; + } + // Negative PDG + return particleTitle[id + o2::track::PID::NIDs]; + } + + void makeMCHistograms(const bool doMakeHistograms, + const int pdgSign, + o2::track::PID::ID id) + { + if (!doMakeHistograms) { + return; + } + + switch (pdgSign) { + case 0: // Positive + if (!doPositivePDG) { + return; + } + break; + case 1: // Negative + if (!doNegativePDG) { + return; + } + break; + default: + LOG(fatal) << "Can't interpret pdgSign " << pdgSign; + } + + const AxisSpec axisPt{ptBins, "#it{p}_{T} (GeV/#it{c})"}; + // const AxisSpec axisP{ptBins, "#it{p} (GeV/#it{c})"}; + // const AxisSpec axisEta{etaBins, "#it{#eta}"}; + // const AxisSpec axisY{yBins, "#it{y}"}; + // const AxisSpec axisPhi{phiBins, "#it{#varphi} (rad)"}; + + const char* partName = particleName(pdgSign, id); + LOG(info) << "Preparing histograms for particle: " << partName << " pdgSign " << pdgSign; + const int histogramIndex = id + pdgSign * nSpecies; + + const TString tagPt = Form("%s ", partName); + hPtAll[histogramIndex] = histos.add(Form("MC/pdg%i/pt/all", PDGs[histogramIndex]), "All tracks " + tagPt, kTH1D, {axisPt}); + hPtITS[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mismatched/its", PDGs[histogramIndex]), "ITS mismatch " + tagPt, kTH1D, {axisPt}); + hPtTPC[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mismatched/tpc", PDGs[histogramIndex]), "TPC mismatch " + tagPt, kTH1D, {axisPt}); + hPtTRD[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mismatched/trd", PDGs[histogramIndex]), "TRD mismatch " + tagPt, kTH1D, {axisPt}); + hPtTOF[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mismatched/tof", PDGs[histogramIndex]), "TOF mismatch " + tagPt, kTH1D, {axisPt}); + hPtOverall[histogramIndex] = histos.add(Form("MC/pdg%i/pt/mismatched/overall", PDGs[histogramIndex]), "Overall mismatch " + tagPt, kTH1D, {axisPt}); + + LOG(info) << "Done with particle: " << partName; + } + + void init(InitContext&) + { + for (int pdgSign = 0; pdgSign < 2; pdgSign++) { + makeMCHistograms(doEl, pdgSign, o2::track::PID::Electron); + makeMCHistograms(doMu, pdgSign, o2::track::PID::Muon); + makeMCHistograms(doPi, pdgSign, o2::track::PID::Pion); + makeMCHistograms(doKa, pdgSign, o2::track::PID::Kaon); + makeMCHistograms(doPr, pdgSign, o2::track::PID::Proton); + makeMCHistograms(doDe, pdgSign, o2::track::PID::Deuteron); + makeMCHistograms(doTr, pdgSign, o2::track::PID::Triton); + makeMCHistograms(doHe, pdgSign, o2::track::PID::Helium3); + makeMCHistograms(doAl, pdgSign, o2::track::PID::Alpha); + } + } + + template + bool isPdgSelected(const particleType& mcParticle) + { + static_assert(pdgSign == 0 || pdgSign == 1); + static_assert(id > 0 || id < nSpecies); + constexpr int index = id + pdgSign * nSpecies; + return mcParticle.pdgCode() == PDGs[index]; + } + + template + bool isMismatched(TrackType const& track, int layer) + { + return (track.mcMask() & 1 << layer); + } + + template + void fillMCTrackHistograms(const trackType& track, const bool doMakeHistograms) + { + static_assert(pdgSign == 0 || pdgSign == 1); + if (!doMakeHistograms) { + return; + } + + if constexpr (pdgSign == 0) { + if (!doPositivePDG) { + return; + } + } else { + if (!doNegativePDG) { + return; + } + } + + constexpr int histogramIndex = id + pdgSign * nSpecies; + LOG(debug) << "fillMCTrackHistograms for pdgSign '" << pdgSign << "' and id '" << static_cast(id) << "' " << particleName(pdgSign, id) << " with index " << histogramIndex; + if (!track.has_mcParticle()) { + return; + } + const auto& mcParticle = track.mcParticle(); + + if (!isPdgSelected(mcParticle)) { // Selecting PDG code + return; + } + if (!track.isGlobalTrack()) { + return; + } + hPtAll[histogramIndex]->Fill(mcParticle.pt()); + bool mismatchInITS = false; + for (int i = 0; i < 7; i++) { + if (isMismatched(track, i)) { + mismatchInITS = true; + break; + } + } + + bool mismatchInTPC = false; + for (int i = 7; i < 10; i++) { + if (isMismatched(track, i)) { + mismatchInTPC = true; + break; + } + } + const bool mismatchInTRD = isMismatched(track, 10); + const bool mismatchInTOF = isMismatched(track, 11); + const bool overallMismatch = isMismatched(track, 15); + + if (mismatchInITS) { + hPtITS[histogramIndex]->Fill(mcParticle.pt()); + } + if (mismatchInTPC) { + hPtTPC[histogramIndex]->Fill(mcParticle.pt()); + } + if (mismatchInTRD) { + hPtTRD[histogramIndex]->Fill(mcParticle.pt()); + } + if (mismatchInTOF) { + hPtTOF[histogramIndex]->Fill(mcParticle.pt()); + } + if (overallMismatch) { + hPtOverall[histogramIndex]->Fill(mcParticle.pt()); + } + } + + using TrackCandidates = o2::soa::Join; + using TrackCandidatesMC = o2::soa::Join; + + // MC process + void process(o2::aod::Collision const& /*collision*/, + o2::soa::Join const& tracks, + o2::aod::McCollisions const&, + o2::aod::McParticles const&) + { + // Track loop + for (const auto& track : tracks) { + static_for<0, 1>([&](auto pdgSign) { + fillMCTrackHistograms(track, doEl); + fillMCTrackHistograms(track, doMu); + fillMCTrackHistograms(track, doPi); + fillMCTrackHistograms(track, doKa); + fillMCTrackHistograms(track, doPr); + fillMCTrackHistograms(track, doDe); + fillMCTrackHistograms(track, doTr); + fillMCTrackHistograms(track, doHe); + fillMCTrackHistograms(track, doAl); + }); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/DPG/Tasks/AOTTrack/qaImpPar.cxx b/DPG/Tasks/AOTTrack/qaImpPar.cxx index 452e6448d70..e3467c2d65b 100644 --- a/DPG/Tasks/AOTTrack/qaImpPar.cxx +++ b/DPG/Tasks/AOTTrack/qaImpPar.cxx @@ -65,12 +65,16 @@ struct QaImpactPar { ConfigurableAxis binningPhi{"binningPhi", {24, 0.f, TMath::TwoPi()}, "Phi binning"}; ConfigurableAxis binningPDG{"binningPDG", {5, -1.5f, 3.5f}, "PDG species binning (-1: not matched, 0: unknown, 1: pi, 2: K, 3: p)"}; ConfigurableAxis binningCharge{"binningCharge", {2, -2.f, 2.f}, "charge binning (-1: negative; +1: positive)"}; + ConfigurableAxis binningIuPosX{"binningIuPosX", {100, -10.f, 10.f}, "Track IU x position"}; + ConfigurableAxis binningIuPosY{"binningIuPosY", {100, -10.f, 10.f}, "Track IU y position"}; + ConfigurableAxis binningIuPosZ{"binningIuPosZ", {100, -10.f, 10.f}, "Track IU z position"}; ConfigurableAxis binsNumPvContrib{"binsNumPvContrib", {200, 0, 200}, "Number of original PV contributors"}; Configurable keepOnlyPhysPrimary{"keepOnlyPhysPrimary", false, "Consider only phys. primary particles (MC)"}; Configurable keepOnlyPvContrib{"keepOnlyPvContrib", false, "Consider only PV contributor tracks"}; // Configurable numberContributorsMin{"numberContributorsMin", 0, "Minimum number of contributors for the primary vertex"}; Configurable useTriggerkINT7{"useTriggerkINT7", false, "Use kINT7 trigger"}; Configurable usesel8{"usesel8", true, "Use or not the sel8() (T0A & T0C) event selection"}; + Configurable addTrackIUinfo{"addTrackIUinfo", false, "Add track parameters at inner most update"}; Configurable trackSelection{"trackSelection", 1, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; Configurable zVtxMax{"zVtxMax", 10.f, "Maximum value for |z_vtx|"}; // Configurable keepOnlyGlobalTracks{"keepOnlyGlobalTracks", 1, "Keep only global tracks or not"}; @@ -154,11 +158,12 @@ struct QaImpactPar { void processData(o2::soa::Filtered::iterator& collision, const trackTable& tracksUnfiltered, const o2::soa::Filtered& tracks, + const o2::aod::TracksIU& tracksIU, o2::aod::BCsWithTimestamps const&) { /// here call the template processReco function auto bc = collision.bc_as(); - processReco(collision, tracksUnfiltered, tracks, 0, bc); + processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); } PROCESS_SWITCH(QaImpactPar, processData, "process data", true); @@ -168,13 +173,14 @@ struct QaImpactPar { void processMC(o2::soa::Filtered::iterator& collision, trackTable const& tracksUnfiltered, o2::soa::Filtered const& tracks, + const o2::aod::TracksIU& tracksIU, const o2::aod::McParticles& mcParticles, const o2::aod::McCollisions&, o2::aod::BCsWithTimestamps const&) { /// here call the template processReco function auto bc = collision.bc_as(); - processReco(collision, tracksUnfiltered, tracks, mcParticles, bc); + processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); } PROCESS_SWITCH(QaImpactPar, processMC, "process MC", false); @@ -256,6 +262,9 @@ struct QaImpactPar { const AxisSpec trackPtAxis{binningPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec trackEtaAxis{binningEta, "#it{#eta}"}; const AxisSpec trackPhiAxis{binningPhi, "#varphi"}; + const AxisSpec trackIUposXaxis{binningIuPosX, "x"}; + const AxisSpec trackIUposYaxis{binningIuPosY, "x"}; + const AxisSpec trackIUposZaxis{binningIuPosZ, "x"}; const AxisSpec trackImpParRPhiAxis{binningImpPar, "#it{d}_{r#it{#varphi}} (#mum)"}; const AxisSpec trackImpParZAxis{binningImpPar, "#it{d}_{z} (#mum)"}; const AxisSpec trackImpParRPhiPullsAxis{binningPulls, "#it{d}_{r#it{#varphi}} / #sigma(#it{d}_{r#it{#varphi}})"}; @@ -281,6 +290,10 @@ struct QaImpactPar { histograms.get(HIST("Reco/refitRun3"))->GetXaxis()->SetBinLabel(5, "hasTPC && hasITS"); histograms.add("Reco/h4ImpPar", "", kTHnSparseD, {trackPtAxis, trackImpParRPhiAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); histograms.add("Reco/h4ImpParZ", "", kTHnSparseD, {trackPtAxis, trackImpParZAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); + if (addTrackIUinfo) { + histograms.add("Reco/h4ImpParIU", "", kTHnSparseD, {trackPtAxis, trackImpParRPhiAxis, trackIUposXaxis, trackIUposYaxis, trackIUposZaxis}); + histograms.add("Reco/h4ImpParZIU", "", kTHnSparseD, {trackPtAxis, trackImpParZAxis, trackIUposXaxis, trackIUposYaxis, trackIUposZaxis}); + } // if(fEnablePulls && !doPVrefit) { // LOGF(fatal, ">>> dca errors not stored after track propagation at the moment. Use fEnablePulls only if doPVrefit!"); // } @@ -320,7 +333,7 @@ struct QaImpactPar { /// core template process function template void processReco(const C& collision, const trackTable& unfilteredTracks, const T& tracks, - const T_MC& /*mcParticles*/, + const o2::aod::TracksIU& tracksIU, const T_MC& /*mcParticles*/, o2::aod::BCsWithTimestamps::iterator const& bc) { constexpr float toMicrometers = 10000.f; // Conversion from [cm] to [mum] @@ -451,6 +464,9 @@ struct QaImpactPar { float tofNSigmaPion = -999.f; float tofNSigmaKaon = -999.f; float tofNSigmaProton = -999.f; + float trackIuPosX = -999.f; + float trackIuPosY = -999.f; + float trackIuPosZ = -999.f; int ntr = tracks.size(); int cnt = 0; for (const auto& track : tracks) { @@ -638,9 +654,24 @@ struct QaImpactPar { } } + /// retrive track position at inner most update + if (addTrackIUinfo) { + for (const auto& trackIU : tracksIU) { + if (trackIU.globalIndex() == track.globalIndex()) { + trackIuPosX = trackIU.x(); + trackIuPosY = trackIU.y(); + trackIuPosZ = trackIU.z(); + } + } + } + /// all tracks histograms.fill(HIST("Reco/h4ImpPar"), pt, impParRPhi, track.eta(), track.phi(), pdgIndex, track.sign(), collision.numContrib(), track.isPVContributor()); histograms.fill(HIST("Reco/h4ImpParZ"), pt, impParZ, track.eta(), track.phi(), pdgIndex, track.sign(), collision.numContrib(), track.isPVContributor()); + if (addTrackIUinfo) { + histograms.fill(HIST("Reco/h4ImpParIU"), pt, impParRPhi, trackIuPosX, trackIuPosY, trackIuPosZ); + histograms.fill(HIST("Reco/h4ImpParZIU"), pt, impParZ, trackIuPosX, trackIuPosY, trackIuPosZ); + } if (fEnablePulls) { histograms.fill(HIST("Reco/h4ImpParPulls"), pt, impParRPhi / impParRPhiSigma, track.eta(), track.phi(), pdgIndex, track.sign(), collision.numContrib(), track.isPVContributor()); histograms.fill(HIST("Reco/h4ImpParZPulls"), pt, impParZ / impParZSigma, track.eta(), track.phi(), pdgIndex, track.sign(), collision.numContrib(), track.isPVContributor()); diff --git a/DPG/Tasks/AOTTrack/qaMatchEff.cxx b/DPG/Tasks/AOTTrack/qaMatchEff.cxx index bdf8cb9c6de..086b1818364 100644 --- a/DPG/Tasks/AOTTrack/qaMatchEff.cxx +++ b/DPG/Tasks/AOTTrack/qaMatchEff.cxx @@ -76,6 +76,9 @@ struct qaMatchEff { Service ccdb; using BCsWithTimeStamp = soa::Join; + Configurable makethn{"makethn", false, "choose if produce thnsparse"}; + Configurable makehistos{"makehistos", true, "choose if produce histos"}; + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable enableMonitorVsTime{"enableMonitorVsTime", false, "Enable the storage of ITS-TPC matching efficiency vs. time"}; Configurable enableTHnSparseMonitorVsTime{"enableTHnSparseMonitorVsTime", false, "Enable the storage of ITS-TPC matching efficiency vs. time"}; @@ -87,10 +90,16 @@ struct qaMatchEff { Configurable isPbPb{"isPbPb", false, "Boolean to tag if the data is PbPb collisions. If false, it is pp"}; Configurable isEnableEventSelection{"isEnableEventSelection", true, "Boolean to switch the event selection on/off."}; Configurable isCentralityRequired{"isCentralityRequired", false, "Boolean to switch the centrality selection on/off."}; + Configurable isRejectNearByEvent{"isRejectNearByEvent", false, "Boolean to switch the rejection of near by events on/off."}; + Configurable isEnableOccupancyCut{"isEnableOccupancyCut", false, "Boolean to switch the occupancy cut on/off."}; struct : ConfigurableGroup { Configurable centralityMinCut{"centralityMinCut", 0.0f, "Minimum centrality"}; Configurable centralityMaxCut{"centralityMaxCut", 100.0f, "Maximum centrality"}; } centralityCuts; + struct : ConfigurableGroup { + Configurable minTracksInTimeRange{"minTracksInTimeRange", 0, "Minimum number of tracks in the time range"}; + Configurable maxTracksInTimeRange{"maxTracksInTimeRange", 999999, "Maximum number of tracks in the time range"}; + } occupancyCuts; // // Track selections Configurable isUseTPCinnerWallPt{"isUseTPCinnerWallPt", false, "Boolean to switch the usage of pt calculated at the inner wall of TPC on/off."}; @@ -114,6 +123,7 @@ struct qaMatchEff { Configurable etaMaxCut{"etaMaxCut", 2.0f, "Maximum pseudorapidity"}; } kineCuts; // + // // DCA and PID cuts Configurable> dcaMaxCut{"dcaMaxCut", {parTableDCA[0], nParDCA, nParVaDCA, parClassDCA, parNameDCA}, "Track DCA cuts"}; Configurable> nSigmaPID{"nSigmaPID", {parTablePID[0], nParPID, nParVaPID, parClassPID, parNamePID}, "PID nSigma cuts TPC and TOF"}; @@ -153,28 +163,26 @@ struct qaMatchEff { ConfigurableAxis posZBinsVsTime{"posZBinsVsTime", {2, -100, 100}, "posZ primary vertex binning for monitoring vs time"}; ConfigurableAxis tpcClstBinsVsTime{"tpcClstBinsVsTime", {40, 0, 160}, "TPC cluster binning for monitoring vs time"}; ConfigurableAxis itsClstBinsVsTime{"itsClstBinsVsTime", {9, 0, 9}, "ITS cluster binning for monitoring vs time"}; + // pdg codes vector + std::vector pdgChoice = {211, 213, 215, 217, 219, 221, 223, 321, 411, 521, 2212, 1114, 2214}; + // - AxisSpec axisPDG{pdgBins, 0, pdgBins + 1.000, "pdgclass"}; - // - AxisSpec axisPt{ptBins, "#it{p}_{T} (GeV/#it{c})"}; - // - AxisSpec axisX{XBins, "track x (cm)"}; + // Tracks selection object + TrackSelection cutObject; // - AxisSpec axisZ{ZBins, "track z (cm)"}; + // do you want pt comparison 2d's ? + Configurable makept2d{"makept2d", false, "choose if produce pt reco/TPC derived pt 2dims "}; // - AxisSpec axisQoPt{qoptBins, -20, 20, "#Q/it{p}_{T} (GeV/#it{c})^{-1}"}; + // common flags for PID + Configurable isPIDPionRequired{"isPIDPionRequired", false, "choose if apply pion PID"}; + Configurable isPIDKaonRequired{"isPIDKaonRequired", false, "choose if apply kaon PID"}; + Configurable isPIDProtonRequired{"isPIDProtonRequired", false, "choose if apply proton PID"}; // - AxisSpec axisEta{etaBins, kineCuts.etaMinCut, kineCuts.etaMaxCut, "#eta"}; - AxisSpec axisPhi{phiBins, 0.f, TwoPI, "#it{#varphi} (rad)"}; - AxisSpec axisDEta{etaBins, kineCuts.etaMinCut, kineCuts.etaMaxCut, "D#eta"}; - AxisSpec axisDPh{phiBins, -PI, PI, "D#it{#varphi} (rad)"}; - // pdg codes vector - std::vector pdgChoice = {211, 213, 215, 217, 219, 221, 223, 321, 411, 521, 2212, 1114, 2214}; + // limit for z position of primary vertex + Configurable zPrimVtxMax{"zPrimVtxax", 999.f, "Maximum asbolute value of z of primary vertex"}; // // configuration for THnSparse's // - Configurable makethn{"makethn", false, "choose if produce thnsparse"}; - Configurable makehistos{"makehistos", true, "choose if produce histos"}; ConfigurableAxis thnd0{"thnd0", {150, -3.0f, 3.0f}, "impact parameter in xy [cm]"}; ConfigurableAxis thndz{"thndz", {150, -10.0f, 10.0f}, "impact parameter in z [cm]"}; ConfigurableAxis thnPt{"thnPt", {80, 0.0f, 20.0f}, "pt [GeV/c]"}; @@ -186,31 +194,6 @@ struct qaMatchEff { // ConfigurableAxis thnITSclumap{"thnITSclumap", {128, -0.5f, 127.5f}, "ITS cluster map"}; // ConfigurableAxis thnTPCclu{"thnTPCclu", {81, -0.5f, 160.5f}, "TPC nclust found"}; ConfigurableAxis thnHasDet{"thnHasDet", {12, -0.5f, 11.5f}, "presence of ITS, TPC, TOF, TRD"}; - AxisSpec thnd0Axis{thnd0, "#it{d}_{r#it{#varphi}} [cm]"}; - AxisSpec thndzAxis{thndz, "#it{d}_{z} [cm]"}; - AxisSpec thnPtAxis{thnPt, "#it{p}_{T}^{reco} [GeV/#it{c}]"}; - AxisSpec thnPhiAxis{thnPhi, "#it{#phi}"}; - AxisSpec thnEtaAxis{thnEta, "#it{#eta}"}; - AxisSpec thnTypeAxis{thnType, "0:prim-1:sec-2:matsec"}; - AxisSpec thnSpecAxis{thnSpec, "particle ID"}; - AxisSpec thnSignAxis{thnSign, "track sign"}; - // AxisSpec thnITSclumapAxis{thnITSclumap, "ITS cluster map"}; - // AxisSpec thnTPCcluAxis{thnTPCclu, "TPC nclust found"}; - AxisSpec thnHasDetAxis{thnHasDet, "presence of ITS, TPC, TOF, TRD"}; - // - // Tracks selection object - TrackSelection cutObject; - // - // do you want pt comparison 2d's ? - Configurable makept2d{"makept2d", false, "choose if produce pt reco/TPC derived pt 2dims "}; - // - // common flags for PID - Configurable isPIDPionRequired{"isPIDPionRequired", false, "choose if apply pion PID"}; - Configurable isPIDKaonRequired{"isPIDKaonRequired", false, "choose if apply kaon PID"}; - Configurable isPIDProtonRequired{"isPIDProtonRequired", false, "choose if apply proton PID"}; - // - // limit for z position of primary vertex - Configurable zPrimVtxMax{"zPrimVtxax", 999.f, "Maximum asbolute value of z of primary vertex"}; // // // ****** BE VERY CAREFUL! -- FILTERS !!! ***** @@ -226,6 +209,8 @@ struct qaMatchEff { if (doDebug) LOG(info) << "===========================================>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> is it MC? = " << isitMC; // + // + // // let's know if it's MC or data if (isitMC) initMC(); @@ -316,6 +301,32 @@ struct qaMatchEff { { if (doDebug) LOGF(info, "*********************************************************** DATA ***************************************************"); + + // + const AxisSpec axisPDG{pdgBins, 0, pdgBins + 1.000, "pdgclass"}; + const AxisSpec axisPt{ptBins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisX{XBins, "track x (cm)"}; + const AxisSpec axisZ{ZBins, "track z (cm)"}; + const AxisSpec axisQoPt{qoptBins, -20, 20, "#Q/it{p}_{T} (GeV/#it{c})^{-1}"}; + const AxisSpec axisEta{etaBins, kineCuts.etaMinCut, kineCuts.etaMaxCut, "#eta"}; + const AxisSpec axisPhi{phiBins, 0.f, TwoPI, "#it{#varphi} (rad)"}; + const AxisSpec axisDEta{etaBins, kineCuts.etaMinCut, kineCuts.etaMaxCut, "D#eta"}; + const AxisSpec axisDPh{phiBins, -PI, PI, "D#it{#varphi} (rad)"}; + // + // configuration for THnSparse's + // + const AxisSpec thnd0Axis{thnd0, "#it{d}_{r#it{#varphi}} [cm]"}; + const AxisSpec thndzAxis{thndz, "#it{d}_{z} [cm]"}; + const AxisSpec thnPtAxis{thnPt, "#it{p}_{T}^{reco} [GeV/#it{c}]"}; + const AxisSpec thnPhiAxis{thnPhi, "#it{#phi}"}; + const AxisSpec thnEtaAxis{thnEta, "#it{#eta}"}; + const AxisSpec thnTypeAxis{thnType, "0:prim-1:sec-2:matsec"}; + const AxisSpec thnSpecAxis{thnSpec, "particle ID"}; + const AxisSpec thnSignAxis{thnSign, "track sign"}; + const AxisSpec thnHasDetAxis{thnHasDet, "presence of ITS, TPC, TOF, TRD"}; + // const AxisSpec thnITSclumapAxis{thnITSclumap, "ITS cluster map"}; + // const AxisSpec thnTPCcluAxis{thnTPCclu, "TPC nclust found"}; + // // // data histos // @@ -335,6 +346,7 @@ struct qaMatchEff { // histos.add("data/control/zDCA_tpcits", "DCA along z TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); // histos.add("data/control/xyDCA_tpcits", "DCA in x-y plane TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); histos.add("data/control/centrality", "Centrality distribution;centrality [%]", kTH1D, {{100, 0.0, 100.0}}, true); + histos.add("data/control/occupancy", "Number of tracks in time range;N_{tracks}", kTH1D, {{5000, 0.0, 50000.0}}, true); // // if (!makehistos) @@ -799,6 +811,31 @@ struct qaMatchEff { { if (doDebug) LOGF(info, " +++++++++++++++++++++++ MC ++++++++++++++++++++++++"); + // + const AxisSpec axisPDG{pdgBins, 0, pdgBins + 1.000, "pdgclass"}; + const AxisSpec axisPt{ptBins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisX{XBins, "track x (cm)"}; + const AxisSpec axisZ{ZBins, "track z (cm)"}; + const AxisSpec axisQoPt{qoptBins, -20, 20, "#Q/it{p}_{T} (GeV/#it{c})^{-1}"}; + const AxisSpec axisEta{etaBins, kineCuts.etaMinCut, kineCuts.etaMaxCut, "#eta"}; + const AxisSpec axisPhi{phiBins, 0.f, TwoPI, "#it{#varphi} (rad)"}; + const AxisSpec axisDEta{etaBins, kineCuts.etaMinCut, kineCuts.etaMaxCut, "D#eta"}; + const AxisSpec axisDPh{phiBins, -PI, PI, "D#it{#varphi} (rad)"}; + // + // + // configuration for THnSparse's + // + const AxisSpec thnd0Axis{thnd0, "#it{d}_{r#it{#varphi}} [cm]"}; + const AxisSpec thndzAxis{thndz, "#it{d}_{z} [cm]"}; + const AxisSpec thnPtAxis{thnPt, "#it{p}_{T}^{reco} [GeV/#it{c}]"}; + const AxisSpec thnPhiAxis{thnPhi, "#it{#phi}"}; + const AxisSpec thnEtaAxis{thnEta, "#it{#eta}"}; + const AxisSpec thnTypeAxis{thnType, "0:prim-1:sec-2:matsec"}; + const AxisSpec thnSpecAxis{thnSpec, "particle ID"}; + const AxisSpec thnSignAxis{thnSign, "track sign"}; + // const AxisSpec thnITSclumapAxis{thnITSclumap, "ITS cluster map"}; + // const AxisSpec thnTPCcluAxis{thnTPCclu, "TPC nclust found"}; + const AxisSpec thnHasDetAxis{thnHasDet, "presence of ITS, TPC, TOF, TRD"}; // // adding histos to the registry @@ -1421,6 +1458,9 @@ struct qaMatchEff { if constexpr (requires { coll.centFT0C(); }) { histos.fill(HIST("data/control/centrality"), coll.centFT0C()); } + if constexpr (requires { coll.trackOccupancyInTimeRange(); }) { + histos.fill(HIST("data/control/occupancy"), coll.trackOccupancyInTimeRange()); + } } return; } @@ -1584,18 +1624,18 @@ struct qaMatchEff { case 2212: specind = 4; break; - // case -11: - // specind = -1; - // break; - // case -211: - // specind = -2; - // break; - // case -321: - // specind = -3; - // break; - // case -2212: - // specind = -4; - // break; + // case -11: + // specind = -1; + // break; + // case -211: + // specind = -2; + // break; + // case -321: + // specind = -3; + // break; + // case -2212: + // specind = -4; + // break; default: specind = 0; } @@ -1614,11 +1654,9 @@ struct qaMatchEff { if (isKaon && isProton && !isPion) specind = 7; // maybe proton, maybe kaon if (isPion && isKaon && isProton) - specind = 9; // maybe pion, maybe kaon, maybe proton + specind = 8; // maybe pion, maybe kaon, maybe proton if (!isPion && !isKaon && !isProton) - specind = 1; // PID is NOT pion or kaon or proton - if (specind == 2 || specind == 3 || specind == 5) - specind = 10; // pions and kaons together + specind = 9; // PID is NOT pion or kaon or proton } // PID info for ThNSparse filling // @@ -1635,8 +1673,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1648,8 +1690,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1661,8 +1707,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1674,8 +1724,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1687,8 +1741,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1700,8 +1758,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1713,8 +1775,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1726,8 +1792,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1739,8 +1809,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1752,8 +1826,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -1765,8 +1843,12 @@ struct qaMatchEff { if (makethn) { if constexpr (IS_MC) { histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (siPDGCode == 211 || siPDGCode == 321) // pions and kaons together + histos.fill(HIST("MC/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } else { histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), specind, signOfTrack, hasdet); + if (specind == 2 || specind == 3 || specind == 5) // pions and kaons together + histos.fill(HIST("data/sparse/thnsforfrac"), track.dcaXY(), track.dcaZ(), trackPt, track.eta(), sayPrim, track.phi(), 10, signOfTrack, hasdet); } } } @@ -3303,7 +3385,8 @@ struct qaMatchEff { LOGF(info, "Event selection not passed, skipping..."); return; } - float centrality = collision.centFT0C(); + const float centrality = collision.centFT0C(); + const int occupancy = collision.trackOccupancyInTimeRange(); if (isCentralityRequired) { if (centrality < centralityCuts.centralityMinCut || centrality > centralityCuts.centralityMaxCut) { if (doDebug) @@ -3311,6 +3394,20 @@ struct qaMatchEff { return; } } + if (isRejectNearByEvent) { + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (doDebug) + LOGF(info, "Nearby event found, skipping..."); + return; + } + } + if (isEnableOccupancyCut) { + if (occupancy < occupancyCuts.minTracksInTimeRange || occupancy > occupancyCuts.maxTracksInTimeRange) { + if (doDebug) + LOGF(info, "Occupancy not in the range, skipping..."); + return; + } + } fillHistograms(tracks, tracks, bcs); // 2nd argument not used in this case fillGeneralHistos(collision); } diff --git a/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx b/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx index ca73e9006fd..3125f1e7c03 100644 --- a/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx +++ b/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx @@ -22,7 +22,9 @@ #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/TrackSelectionTables.h" +using namespace o2; using namespace o2::framework; +using namespace o2::framework::expressions; struct qaTrackSplitting { Configurable pdg{"pdg", 2212, "PDG code of the particle to be analysed"}; @@ -40,6 +42,14 @@ struct qaTrackSplitting { Configurable maxDcaXY{"maxDcaXY", 10000.f, "Additional cut on the maximum abs value of the DCA xy"}; Configurable maxDcaZ{"maxDcaZ", 2.f, "Additional cut on the maximum abs value of the DCA z"}; Configurable minTPCNClsFound{"minTPCNClsFound", 0.f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; + + Configurable windowEta{"windowEta", 0.f, "Position in eta of the window"}; + Configurable windowEtaWidth{"windowEtaWidth", 0.1f, "Width of the eta window"}; + Configurable windowPhi{"windowPhi", 0.785f, "Position in phi of the window"}; + Configurable windowPhiWidth{"windowPhiWidth", 0.1f, "Width of the phi window"}; + Configurable windowPt{"windowPt", 1.f, "Position in pt of the window"}; + Configurable windowPtWidth{"windowPtWidth", 0.1f, "Width of the pt window"}; + } cfgCustomTrackCuts; // Histograms @@ -51,6 +61,7 @@ struct qaTrackSplitting { histos.add("tracks", "tracsk", kTH1D, {{10, -0.5, 9.5, "Track selection"}}); histos.add("numberOfRecoed", "recoed", kTH1D, {{10, -0.5, 9.5, "Number of tracks associated to a particle"}}); histos.add("map", "map", kTH3D, {{100, -1, 1, "#Delta #eta"}, {100, -1, 1, "#Delta #varphi"}, {100, -1, 1, "#Delta #it{p}_{T}"}}); + histos.add("deltaPt", "deltaPt", kTH2D, {{100, 0, 5, "#it{p}_{T}"}, {100, -1, 1, "#Delta #it{p}_{T}"}}); histos.add("mapMC", "mapMC", kTH3D, {{100, -1, 1, "#Delta #eta"}, {100, -1, 1, "#Delta #varphi"}, {100, -1, 1, "#Delta #it{p}_{T}"}}); customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(cfgCustomTrackCuts.itsPattern); @@ -69,16 +80,46 @@ struct qaTrackSplitting { customTrackCuts.print(); } - // Global process - using TrackCandidates = o2::soa::Join; - void process(o2::soa::Join::iterator const& collision, - TrackCandidates const& tracks, - o2::aod::McParticles const&) + using CollisionCandidates = o2::soa::Join; + using TrackCandidates = o2::soa::Join; + Filter trackFilterEta = nabs(aod::track::eta - cfgCustomTrackCuts.windowEta) < cfgCustomTrackCuts.windowEtaWidth; + Filter trackFilterPhi = nabs(aod::track::phi - cfgCustomTrackCuts.windowPhi) < cfgCustomTrackCuts.windowPhiWidth; + Filter trackFilterITS = (aod::track::itsClusterSizes > (uint32_t)0); + Filter trackFilterTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + // Filter trackFilterType = (aod::track::TrackType == aod::track::Track); + // Filter filterPt = nabs(aod::track::pt - cfgCustomTrackCuts.windowPt) < cfgCustomTrackCuts.windowPtWidth; + void processData(CollisionCandidates const& collisions, + soa::Filtered const& filteredTracks) + { + for (const auto& coll1 : collisions) { + for (const auto& coll2 : collisions) { + if (coll1.globalIndex() == coll2.globalIndex()) { + continue; + } + for (const auto& track2 : filteredTracks) { + // Compute the delta in pT + for (const auto& track1 : filteredTracks) { + if (track1.globalIndex() == track2.globalIndex()) { + continue; + } + histos.fill(HIST("deltaPt"), track1.pt(), track1.pt() - track2.pt()); + } + } + } + } + } + PROCESS_SWITCH(qaTrackSplitting, processData, "Process Data", true); + + using CollisionCandidatesMC = soa::Join; + using TrackCandidatesMC = o2::soa::Join; + void processMC(CollisionCandidatesMC::iterator const& collision, + TrackCandidatesMC const& tracks, + o2::aod::McParticles const&) { if (!collision.sel8()) { return; } - typedef std::shared_ptr trkType; + typedef std::shared_ptr trkType; std::map> particleUsageCounter; for (auto track : tracks) { @@ -87,11 +128,12 @@ struct qaTrackSplitting { continue; } histos.fill(HIST("tracks"), 1); - if (track.mcParticle().pdgCode() != pdg) { + const auto& mcParticle = track.mcParticle(); + if (mcParticle.pdgCode() != pdg) { continue; } histos.fill(HIST("tracks"), 2); - if (!track.mcParticle().isPhysicalPrimary()) { + if (!mcParticle.isPhysicalPrimary()) { continue; } histos.fill(HIST("tracks"), 3); @@ -101,21 +143,28 @@ struct qaTrackSplitting { histos.fill(HIST("tracks"), 4); particleUsageCounter[track.mcParticleId()].push_back(std::make_shared(track)); } - for (const auto& [mcId, tracks] : particleUsageCounter) { - histos.fill(HIST("numberOfRecoed"), tracks.size()); - if (tracks.size() > 1) { + for (const auto& [mcId, tracksMatched] : particleUsageCounter) { + histos.fill(HIST("numberOfRecoed"), tracksMatched.size()); + if (tracksMatched.size() > 1) { bool isFirst = true; - for (const auto& track : tracks) { + for (const auto& track : tracksMatched) { if (isFirst) { isFirst = false; - histos.fill(HIST("mapMC"), track->eta() - track->mcParticle().eta(), track->phi() - track->mcParticle().phi(), track->pt() - track->mcParticle().pt()); + histos.fill(HIST("mapMC"), + track->eta() - track->mcParticle().eta(), + track->phi() - track->mcParticle().phi(), + track->pt() - track->mcParticle().pt()); continue; } - histos.fill(HIST("map"), track->eta() - tracks[0]->eta(), track->phi() - tracks[0]->phi(), track->pt() - tracks[0]->pt()); + histos.fill(HIST("map"), + track->eta() - tracksMatched[0]->eta(), + track->phi() - tracksMatched[0]->phi(), + track->pt() - tracksMatched[0]->pt()); } } } } + PROCESS_SWITCH(qaTrackSplitting, processMC, "Process MC", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx b/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx index 7bb4692131d..2d236ee0230 100644 --- a/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx +++ b/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx @@ -30,6 +30,7 @@ #include "Framework/runDataProcessing.h" #include "PWGHF/Utils/utilsAnalysis.h" #include "Tools/ML/MlResponse.h" +#include using namespace o2; using namespace o2::framework; @@ -60,7 +61,8 @@ enum SignalFlags : uint8_t { Bkg = 0, Prompt, NonPrompt, - Resonant + Resonant, + BkgFromNoHf }; static constexpr int nBinsPt = 7; @@ -187,7 +189,7 @@ struct TagTwoProngDisplacedVertices { Produces tagVarsTable; SliceCache cache; - Configurable fillTopoVarsTable{"fillTopoVarsTable", 0, "flag to fill tag table with topological variables (0 -> disabled, 1 -> signal only, 2 -> bkg only, 3 -> both)"}; + Configurable fillTopoVarsTable{"fillTopoVarsTable", 0, "flag to fill tag table with topological variables (0 -> disabled, 1 -> signal only, 2 -> bkg only, 3 -> bkg from no HF only, 4 -> all)"}; Configurable downsamplingForTopoVarTable{"downsamplingForTopoVarTable", 1.1, "fraction of tag candidates to downscale in filling table with topological variables"}; Configurable ptTagMaxForDownsampling{"ptTagMaxForDownsampling", 5., "maximum pT for downscaling of tag candidates in filling table with topological variables"}; Configurable applyTofPid{"applyTofPid", true, "flag to enable TOF PID selection"}; @@ -226,6 +228,8 @@ struct TagTwoProngDisplacedVertices { Configurable> onnxFileNamesDzeroFromDstar{"onnxFileNamesDzeroFromDstar", std::vector{"ModelHandler_onnx_DzeroToKPi.onnx"}, "ONNX file names for Kpi pairs from D0 <- D*+ decays"}; Configurable> onnxFileNamesDzeroKaKaFromDstar{"onnxFileNamesDzeroKaKaFromDstar", std::vector{"ModelHandler_onnx_DzeroToKK.onnx"}, "ONNX file names for KK pairs from D0 <- D*+ decays"}; // ML cuts + Configurable numMlClasses{"numMlClasses", 3, "Number of classes for the ML models"}; + Configurable> cutDirMl{"cutDirMl", std::vector{o2::cuts_ml::CutDirection::CutGreater, o2::cuts_ml::CutDirection::CutSmaller, o2::cuts_ml::CutDirection::CutSmaller}, "Whether to reject score values greater or smaller than the threshold"}; Configurable> mlCutsPiPiFromDplus{"mlCutsPiPiFromDplus", {aod::tagandprobe::mlCuts[0], aod::tagandprobe::nBinsPt, 3, aod::tagandprobe::labelsEmpty, aod::tagandprobe::labelsMlScores}, "ML Selections for pipi pairs from D+ decays"}; Configurable> mlCutsKaKaFromDsOrDplus{"mlCutsKaKaFromDsOrDplus", {aod::tagandprobe::mlCuts[0], aod::tagandprobe::nBinsPt, 3, aod::tagandprobe::labelsEmpty, aod::tagandprobe::labelsMlScores}, "ML Selections for KK pairs from Ds or D+ decays"}; Configurable> mlCutsDzeroFromDstar{"mlCutsDzeroFromDstar", {aod::tagandprobe::mlCuts[0], aod::tagandprobe::nBinsPt, 3, aod::tagandprobe::labelsEmpty, aod::tagandprobe::labelsMlScores}, "ML Selections for Kpi pairs from D0 <- D*+ decays"}; @@ -269,6 +273,10 @@ struct TagTwoProngDisplacedVertices { std::array, aod::tagandprobe::TagChannels::NTagChannels> topologicalCuts{}; std::array, aod::tagandprobe::TagChannels::NTagChannels> ptBinsForTopologicalCuts{}; + std::vector> hBkgMlScore{}; + std::vector> hPromptMlScore{}; + std::vector> hNonPromptMlScore{}; + std::vector> hDataMlScore{}; HistogramRegistry registry{"registry"}; @@ -302,6 +310,7 @@ struct TagTwoProngDisplacedVertices { const AxisSpec axisReflFlag{3, 0.5f, 3.5f}; const AxisSpec axisMassKaKa{200, constants::physics::MassPhi - 0.05f, constants::physics::MassPhi + 0.05f}; const AxisSpec axisMassKaPi{400, constants::physics::MassD0 - 0.2f, constants::physics::MassD0 + 0.2f}; + const AxisSpec axisMlScore{1000, 0.f, 1.f}; if (doprocessPiPiFromDplus || doprocessPiPiFromDplusMc) { registry.add("hMassPiPiVsPt", ";#it{p}_{T}(#pi#pi) (GeV/#it{c}); #it{M}(#pi#pi) (GeV/#it{c}^{2})", HistType::kTH2D, {axisPt, axisMassPiPi}); @@ -320,14 +329,27 @@ struct TagTwoProngDisplacedVertices { registry.add("hMassDzeroKaKaVsPt", ";#it{p}_{T}(K#pi) (GeV/#it{c}); #it{M}(K#pi) (GeV/#it{c}^{2})", HistType::kTH2D, {axisPt, axisMassKaPi}); } - const std::vector cutDirMl = {o2::cuts_ml::CutDirection::CutGreater, o2::cuts_ml::CutDirection::CutSmaller, o2::cuts_ml::CutDirection::CutSmaller}; + if (mlConfig.applyMlPiPiFromDplus || mlConfig.applyMlDzeroFromDstar || mlConfig.applyMlKaKaFromDsOrDplus || mlConfig.applyMlDzeroKaKaFromDstar) { + if (doprocessPiPiFromDplusMc || doprocessKaKaFromDsOrDplusMc || doprocessKaPiFromDstarMc) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hBkgMlScore.push_back(registry.add(Form("hBkgMlScore%d", iScore), Form(";#it{p}_{T}(tag) (GeV/#it{c});ML score %d; counts", iScore), HistType::kTH2D, {axisPt, axisMlScore})); + hPromptMlScore.push_back(registry.add(Form("hPromptMlScore%d", iScore), Form(";#it{p}_{T}(tag) (GeV/#it{c});ML score %d; counts", iScore), HistType::kTH2D, {axisPt, axisMlScore})); + hNonPromptMlScore.push_back(registry.add(Form("hNonPromptMlScore%d", iScore), Form(";#it{p}_{T}(tag) (GeV/#it{c});ML score %d; counts", iScore), HistType::kTH2D, {axisPt, axisMlScore})); + } + } else { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hDataMlScore.push_back(registry.add(Form("hMlScore%d", iScore), Form(";#it{p}_{T}(tag) (GeV/#it{c});ML score %d; counts", iScore), HistType::kTH2D, {axisPt, axisMlScore})); + } + } + } + const std::array, aod::tagandprobe::TagChannels::NTagChannels> mlCuts = {mlConfig.mlCutsPiPiFromDplus, mlConfig.mlCutsKaKaFromDsOrDplus, mlConfig.mlCutsDzeroFromDstar, mlConfig.mlCutsDzeroFromDstar, mlConfig.mlCutsDzeroKaKaFromDstar}; const std::array, aod::tagandprobe::TagChannels::NTagChannels> onnxFileNames = {mlConfig.onnxFileNamesPiPiFromDplus, mlConfig.onnxFileNamesKaKaFromDsOrDplus, mlConfig.onnxFileNamesDzeroFromDstar, mlConfig.onnxFileNamesDzeroFromDstar, mlConfig.onnxFileNamesDzeroKaKaFromDstar}; const std::array, aod::tagandprobe::TagChannels::NTagChannels> modelPathsCcdb = {mlConfig.modelPathsCcdbPiPiFromDplus, mlConfig.modelPathsCcdbKaKaFromDsOrDplus, mlConfig.modelPathsCcdbDzeroFromDstar, mlConfig.modelPathsCcdbDzeroFromDstar, mlConfig.modelPathsCcdbDzeroKaKaFromDstar}; applyMl = {mlConfig.applyMlPiPiFromDplus, mlConfig.applyMlKaKaFromDsOrDplus, mlConfig.applyMlDzeroFromDstar, mlConfig.applyMlDzeroFromDstar, mlConfig.applyMlDzeroKaKaFromDstar}; for (auto iChannel{0u}; iChannel < aod::tagandprobe::TagChannels::NTagChannels; ++iChannel) { if (applyMl[iChannel]) { - mlResponse[iChannel].configure(ptBinsForTopologicalCuts[iChannel], mlCuts[iChannel], cutDirMl, 3); + mlResponse[iChannel].configure(ptBinsForTopologicalCuts[iChannel], mlCuts[iChannel], mlConfig.cutDirMl, mlConfig.numMlClasses); if (mlConfig.loadMlModelsFromCcdb) { mlResponse[iChannel].setModelPathsCCDB(onnxFileNames[iChannel], ccdbApi, modelPathsCcdb[iChannel], mlConfig.timestampCcdbForMlModels); } else { @@ -397,7 +419,9 @@ struct TagTwoProngDisplacedVertices { } if (!firsTrack.has_mcParticle() || !secondTrack.has_mcParticle()) { - return BIT(aod::tagandprobe::SignalFlags::Bkg); + SETBIT(signalFlag, aod::tagandprobe::SignalFlags::Bkg); + SETBIT(signalFlag, aod::tagandprobe::SignalFlags::BkgFromNoHf); + return signalFlag; } else { auto firstMcTrack = firsTrack.template mcParticle_as(); auto secondMcTrack = secondTrack.template mcParticle_as(); @@ -469,7 +493,16 @@ struct TagTwoProngDisplacedVertices { return signalFlag; } - return BIT(aod::tagandprobe::SignalFlags::Bkg); + // if not signal, it must be background + SETBIT(signalFlag, aod::tagandprobe::SignalFlags::Bkg); + + auto originFirstTrack = RecoDecay::getCharmHadronOrigin(mcParticles, firstMcTrack, true); + auto originSecondTrack = RecoDecay::getCharmHadronOrigin(mcParticles, secondMcTrack, true); + if (originFirstTrack == RecoDecay::OriginType::None && originSecondTrack == RecoDecay::OriginType::None) { + SETBIT(signalFlag, aod::tagandprobe::SignalFlags::BkgFromNoHf); + } + + return signalFlag; } } @@ -655,9 +688,36 @@ struct TagTwoProngDisplacedVertices { continue; } + uint8_t isSignal{0u}; + int motherIdx{-1}; + if constexpr (doMc) { + isSignal = getTagOrigin(trackFirst, trackSecond, mcParticles, channel, pdgDecayMothers, pdgResonances, motherIdx); + } + std::vector mlScoresTag{}; if (applyMl[channel]) { - if (!mlResponse[channel].isSelectedMl(topoVars, ptTag, mlScoresTag)) { // for the time being all the topological variables used for all channels (decLen, decLenXy, normDecLen, normDecLenXy, cosp, cospXy, dcaXyTrack0, dcaXyTrack1, dcaProd) + bool isMlSelected = mlResponse[channel].isSelectedMl(topoVars, ptTag, mlScoresTag); + // we fill control histograms + if constexpr (doMc) { + if (TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Bkg)) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hBkgMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } else if (TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Prompt)) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hPromptMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } else if (TESTBIT(isSignal, aod::tagandprobe::SignalFlags::NonPrompt)) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hNonPromptMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } + } else { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hDataMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } + if (!isMlSelected) { // for the time being all the topological variables used for all channels (decLen, decLenXy, normDecLen, normDecLenXy, cosp, cospXy, dcaXyTrack0, dcaXyTrack1, dcaProd) continue; } } @@ -665,18 +725,14 @@ struct TagTwoProngDisplacedVertices { float invMass{std::sqrt(invMass2)}; registry.fill(HIST("hMassPiPiVsPt"), ptTag, invMass); // only channel with same sign tracks for the moment - uint8_t isSignal{0u}; - int motherIdx{-1}; - if constexpr (doMc) { - isSignal = getTagOrigin(trackFirst, trackSecond, mcParticles, channel, pdgDecayMothers, pdgResonances, motherIdx); - } - if (fillTopoVarsTable) { bool fillTable{true}; if (fillTopoVarsTable == 1 && !(TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Prompt) || TESTBIT(isSignal, aod::tagandprobe::SignalFlags::NonPrompt))) { // only signal fillTable = false; } else if (fillTopoVarsTable == 2 && !TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Bkg)) { // only background fillTable = false; + } else if (fillTopoVarsTable == 3 && !TESTBIT(isSignal, aod::tagandprobe::SignalFlags::BkgFromNoHf)) { // only background excluding tracks from other HF decays + fillTable = false; } float pseudoRndm = trackFirst.pt() * 1000. - (int64_t)(trackFirst.pt() * 1000); if (ptTag < ptTagMaxForDownsampling && pseudoRndm >= downsamplingForTopoVarTable) { @@ -755,9 +811,36 @@ struct TagTwoProngDisplacedVertices { continue; } + uint8_t isSignal{0u}; + int motherIdx{-1}; + if constexpr (doMc) { + isSignal = getTagOrigin(trackPos, trackNeg, mcParticles, channel, pdgDecayMothers, pdgResonances, motherIdx); + } + std::vector mlScoresTag{}; if (applyMl[channel]) { - if (!mlResponse[channel].isSelectedMl(topoVars, ptTag, mlScoresTag)) { // for the time being all the topological variables used for all channels (decLen, decLenXy, normDecLen, normDecLenXy, cosp, cospXy, dcaXyTrack0, dcaXyTrack1, dcaProd) + bool isMlSelected = mlResponse[channel].isSelectedMl(topoVars, ptTag, mlScoresTag); + // we fill control histograms + if constexpr (doMc) { + if (TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Bkg)) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hBkgMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } else if (TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Prompt)) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hPromptMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } else if (TESTBIT(isSignal, aod::tagandprobe::SignalFlags::NonPrompt)) { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hNonPromptMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } + } else { + for (int iScore{0}; iScore < mlConfig.numMlClasses; ++iScore) { + hDataMlScore.at(iScore)->Fill(ptTag, mlScoresTag.at(iScore)); + } + } + if (!isMlSelected) { // for the time being all the topological variables used for all channels (decLen, decLenXy, normDecLen, normDecLenXy, cosp, cospXy, dcaXyTrack0, dcaXyTrack1, dcaProd) continue; } } @@ -807,18 +890,14 @@ struct TagTwoProngDisplacedVertices { registry.fill(HIST("hMassDzeroKaKaVsPt"), ptTag, invMass); } - uint8_t isSignal{0u}; - int motherIdx{-1}; - if constexpr (doMc) { - isSignal = getTagOrigin(trackPos, trackNeg, mcParticles, channel, pdgDecayMothers, pdgResonances, motherIdx); - } - if (fillTopoVarsTable) { bool fillTable{true}; if (fillTopoVarsTable == 1 && !(TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Prompt) || TESTBIT(isSignal, aod::tagandprobe::SignalFlags::NonPrompt))) { // only signal fillTable = false; } else if (fillTopoVarsTable == 2 && !TESTBIT(isSignal, aod::tagandprobe::SignalFlags::Bkg)) { // only background fillTable = false; + } else if (fillTopoVarsTable == 3 && !TESTBIT(isSignal, aod::tagandprobe::SignalFlags::BkgFromNoHf)) { // only background excluding tracks from other HF decays + fillTable = false; } float pseudoRndm = trackPos.pt() * 1000. - (int64_t)(trackPos.pt() * 1000); if (ptTag < ptTagMaxForDownsampling && pseudoRndm >= downsamplingForTopoVarTable) { @@ -1070,8 +1149,20 @@ struct ProbeThirdTrack { Configurable> mlCutsKaKaFromDsOrDplus{"mlCutsKaKaFromDsOrDplus", {aod::tagandprobe::mlCuts[0], aod::tagandprobe::nBinsPt, 3, aod::tagandprobe::labelsEmpty, aod::tagandprobe::labelsMlScores}, "ML Selections for KK pairs from Ds or D+ decays"}; Configurable> mlCutsDzeroFromDstar{"mlCutsDzeroFromDstar", {aod::tagandprobe::mlCuts[0], aod::tagandprobe::nBinsPt, 3, aod::tagandprobe::labelsEmpty, aod::tagandprobe::labelsMlScores}, "ML Selections for Kpi pairs from D0 <- D*+ decays"}; } mlConfig; + Configurable ptCandMin{"ptCandMin", 0.f, "Minimum candidate pt for THnSparse filling"}; - Filter tagMcFilter = aod::tagandprobe::isSignal > 0; + ConfigurableAxis axisPtProbe{"axisPtProbe", {VARIABLE_WIDTH, 0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 12.f, 15.f, 20.f, 25.f, 30.f}, "Axis for pt Probe"}; + ConfigurableAxis axisPtTag{"axisPtTag", {VARIABLE_WIDTH, 0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 12.f, 15.f, 20.f, 25.f, 30.f}, "Axis for pt Tag"}; + ConfigurableAxis axisPtD{"axisPtD", {VARIABLE_WIDTH, 0.f, 0.5f, 1.f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.5f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.5f, 10.f, 11.f, 12.f, 14.f, 16.f, 20.f, 24.f, 36.f, 50.f}, "Axis for pt D"}; + ConfigurableAxis axisYD{"axisYD", {20, -1.f, 1.f}, "Axis for YD"}; + ConfigurableAxis axisEtaProbe{"axisEtaProbe", {20, -1.f, 1.f}, "Axis for Eta Probe"}; + ConfigurableAxis axisNumCrossRowTpc{"axisNumCrossRowTpc", {51, 49.5f, 100.5f}, "Axis for Number of CrossRowTpc"}; + ConfigurableAxis axisTpcChi2PerClus{"axisTpcChi2PerClus", {8, 2.f, 10.f}, "Axis for TpcChi2 Per Cluster"}; + ConfigurableAxis axisNumCluIts{"axisNumCluIts", {5, 2.5f, 7.5f}, "Axis for Number of Cluster ITS"}; + ConfigurableAxis axisPtMinTagdaught{"axisPtMinTagdaught", {10, 0.f, 1.f}, "Axis for Pt Min of Tag daughter"}; + ConfigurableAxis axisAbsEtaMaxTagdaught{"axisAbsEtaMaxTagdaught", {10, 0.f, 1.f}, "Axis for AbsEtaMax for Tag daughter"}; + + Filter tagMcFilter = aod::tagandprobe::isSignal > static_cast(0); using TracksWithDca = soa::Join; using TracksWithDcaMc = soa::Join; @@ -1098,8 +1189,11 @@ struct ProbeThirdTrack { std::array trackSelector{}; // define the track selectors std::array applyMl{}; + std::array minInvMass{}; + std::array maxInvMass{}; std::array, aod::tagandprobe::TrackTypes::NTrackTypes>, aod::tagandprobe::TagChannels::NTagChannels> histos{}; + std::array, aod::tagandprobe::TagChannels::NTagChannels> histosGen{}; HistogramRegistry registry{"registry"}; void init(InitContext&) @@ -1148,13 +1242,6 @@ struct ProbeThirdTrack { trackSelector[aod::tagandprobe::TrackTypes::GlobalWoDcaWoTpc].SetMaxChi2PerClusterITS(36.f); trackSelector[aod::tagandprobe::TrackTypes::GlobalWoDcaWoTpc].SetMaxDcaZ(2.f); - const AxisSpec axisPtProbe{{0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 12.f, 15.f, 20.f, 25.f, 30.f}}; - const AxisSpec axisPtTag{{0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 12.f, 15.f, 20.f, 25.f, 30.f}}; - const AxisSpec axisPtD{{0.f, 0.5f, 1.f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.5f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.5f, 10.f, 11.f, 12.f, 14.f, 16.f, 20.f, 24.f, 36.f, 50.f}}; - const AxisSpec axisEtaProbe{20, -1.f, 1.f}; - const AxisSpec axisNumCrossRowTpc{51, 49.5f, 100.5f}; - const AxisSpec axisTpcChi2PerClus{8, 2.f, 10.f}; - const AxisSpec axisNumCluIts{5, 2.5f, 7.5f}; std::array axisMass = {AxisSpec{225, 1.65f, 2.10f}, AxisSpec{225, 1.65f, 2.10f}, AxisSpec{350, 0.135f, 0.17f}, AxisSpec{350, 0.135f, 0.17f}, AxisSpec{350, 0.135f, 0.17f}}; std::array axisMassTag = {AxisSpec{125, 0.f, 2.5f}, AxisSpec{100, constants::physics::MassPhi - 0.05f, constants::physics::MassPhi + 0.05f}, AxisSpec{200, constants::physics::MassD0 - 0.2f, constants::physics::MassD0 + 0.2f}, AxisSpec{200, constants::physics::MassD0 - 0.2f, constants::physics::MassD0 + 0.2f}, AxisSpec{200, constants::physics::MassD0 - 0.2f, constants::physics::MassD0 + 0.2f}}; @@ -1166,9 +1253,14 @@ struct ProbeThirdTrack { histos[iChannel][iTrackType] = registry.add(Form("h%sVsPtProbeTag_%s", tagChannels[iChannel].data(), trackTypes[iTrackType].data()), "; #it{p}_{T}(D) (GeV/#it{c}); #it{p}_{T}(tag) (GeV/#it{c}); #it{p}_{T}(probe) (GeV/#it{c}); #it{p}_{T}^{TPC in}(probe) (GeV/#it{c}); #it{M}(D) (GeV/#it{c}^{2}); #it{M}(tag) (GeV/#it{c}^{2}); #it{#eta}(probe); #it{N}_{cross rows}^{TPC}(probe); #chi^{2}/#it{N}_{clusters}^{TPC}(probe); #it{N}_{clusters}^{ITS}(probe);", HistType::kTHnSparseF, {axisPtD, axisPtTag, axisPtProbe, axisPtProbe, axisMass[iChannel], axisMassTag[iChannel], axisEtaProbe, axisNumCrossRowTpc, axisTpcChi2PerClus, axisNumCluIts}); + auto invMassBins = axisMass[iChannel].binEdges; + minInvMass[iChannel] = invMassBins.front(); + maxInvMass[iChannel] = invMassBins.back(); } } - + for (int iChannel{0}; iChannel < aod::tagandprobe::TagChannels::NTagChannels; ++iChannel) { + histosGen[iChannel] = registry.add(Form("hGen%s", tagChannels[iChannel].data()), ";#it{p}_{T}(D_{parent}) (GeV/#it{c}); #it{y}(D_{parent});#it{p}_{T}(tag) (GeV/#it{c}); #it{y}(tag);#it{p}_{T}(probe) (GeV/#it{c}); #it{#eta}(probe);#it{p}_{T}^{min}(tag daughters);#it{#eta}_{max}(tag daughters)", HistType::kTHnSparseF, {axisPtD, axisYD, axisPtTag, axisYD, axisPtProbe, axisEtaProbe, axisPtMinTagdaught, axisAbsEtaMaxTagdaught}); + } applyMl = {mlConfig.applyMlPiPiFromDplus, mlConfig.applyMlKaKaFromDsOrDplus, mlConfig.applyMlDzeroFromDstar}; } @@ -1246,14 +1338,12 @@ struct ProbeThirdTrack { auto numItsCluTrackThird = trackThird.itsNCls(); float invMass{-1.f}, invMassTag{-1.f}, ptTag{-1.f}, ptD{-1.f}; computeInvariantMass(trackFirst, trackSecond, trackThird, channel, ptTag, invMassTag, ptD, invMass); - if constexpr (channel == aod::tagandprobe::TagChannels::DstarPlusToDzeroPi || channel == aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi) { - if (invMass > 0.17f) { - continue; - } - } else if constexpr (channel == aod::tagandprobe::TagChannels::DplusToKPiPi || channel == aod::tagandprobe::TagChannels::DsOrDplusToKKPi) { - if ((invMass < 1.65f || invMass > 2.10f)) { - continue; - } + if (invMass < minInvMass[channel] || invMass > maxInvMass[channel]) { + continue; + } + if (ptD < ptCandMin) { + /// candidate pt lower than the minimum allowed value, let's skip it + continue; } for (int iTrackType{0}; iTrackType < aod::tagandprobe::TrackTypes::NTrackTypes; ++iTrackType) { if (trackSelector[iTrackType].IsSelected(trackThird)) { @@ -1392,6 +1482,59 @@ struct ProbeThirdTrack { void processDummy(aod::Collisions const&) {} PROCESS_SWITCH(ProbeThirdTrack, processDummy, "Dummy process function that does nothing", false); + + void processGeneratedDstarToDzeroPi(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + { + + if (std::abs(mcCollision.posZ()) > 10.) + return; + std::array arrDstar = {kPiPlus, kKMinus, kPiPlus}; + int8_t* sign = nullptr; + std::vector listIndexDaughters; + float ptDzero = -1, yDzero = -999, ptSoftPion = -1, etaSoftPion = -999, ptminTagDaughers = 9999., etamaxTagDaugthers = 0.; + int indexProbe; + for (auto const& mcPart : mcParticles) { + // LOGP(info, "particle id: {}", mcPart.pdgCode()); + if (RecoDecay::isMatchedMCGen(mcParticles, mcPart, constants::physics::Pdg::kDStar, arrDstar, true, sign, 2, &listIndexDaughters)) { + // LOGP(info, "Selected particle id: {}", mcPart.pdgCode()); + ptDzero = -1; + yDzero = -999; + ptSoftPion = -1; + etaSoftPion = -999; + ptminTagDaughers = 9999.; + etamaxTagDaugthers = 0.; + indexProbe = -1; + for (auto const& iDaughtIndex : mcPart.daughtersIds()) { + // Printf("mcpart.daugthersIds, index: %d",idaughtindex); + auto mcPartDstarDaught = mcParticles.rawIteratorAt(iDaughtIndex - mcParticles.offset()); + if (std::abs(mcPartDstarDaught.pdgCode()) == constants::physics::Pdg::kD0) { + ptDzero = mcPartDstarDaught.pt(); + yDzero = mcPartDstarDaught.y(); + } else if (std::abs(mcPartDstarDaught.pdgCode()) == kPiPlus) { + ptSoftPion = mcPartDstarDaught.pt(); + etaSoftPion = mcPartDstarDaught.eta(); + indexProbe = iDaughtIndex; + } + } + for (auto const& idx : listIndexDaughters) { + // LOGP(info, "listIndexDaughters, index: {}", idx); + if (idx == indexProbe) { + continue; + } + auto mcPartDaught = mcParticles.rawIteratorAt(idx - mcParticles.offset()); + ptminTagDaughers = std::min(mcPartDaught.pt(), ptminTagDaughers); + etamaxTagDaugthers = std::max(std::abs(mcPartDaught.eta()), etamaxTagDaugthers); + } + // registry.fill(HIST(Form("hGen%s",tagChannels[aod::tagandprobe::DstarPlusToDzeroPi].data())), + if (mcPart.pdgCode() > 0) { + histosGen[aod::tagandprobe::DstarPlusToDzeroPi]->Fill(mcPart.pt(), mcPart.y(), ptDzero, yDzero, ptSoftPion, etaSoftPion, ptminTagDaughers, etamaxTagDaugthers); + } else { + histosGen[aod::tagandprobe::DstarMinusToDzeroBarPi]->Fill(mcPart.pt(), mcPart.y(), ptDzero, yDzero, ptSoftPion, etaSoftPion, ptminTagDaughers, etamaxTagDaugthers); + } + } + } + } + PROCESS_SWITCH(ProbeThirdTrack, processGeneratedDstarToDzeroPi, "Count generated particles", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/EventFiltering/CMakeLists.txt b/EventFiltering/CMakeLists.txt index 951f02f0930..31cd58f40ed 100644 --- a/EventFiltering/CMakeLists.txt +++ b/EventFiltering/CMakeLists.txt @@ -108,9 +108,10 @@ o2physics_add_dpl_workflow(lf-f1proton-filter COMPONENT_NAME Analysis) o2physics_add_library(EventFilteringUtils - SOURCES Zorro.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + SOURCES Zorro.cxx ZorroSummary.cxx + INSTALL_HEADERS ZorroHelper.h ZorroSummary.h + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore Arrow::arrow_shared) o2physics_target_root_dictionary(EventFilteringUtils - HEADERS Zorro.h + HEADERS ZorroHelper.h ZorroSummary.h LINKDEF EventFilteringUtilsLinkDef.h) \ No newline at end of file diff --git a/EventFiltering/EventFilteringUtilsLinkDef.h b/EventFiltering/EventFilteringUtilsLinkDef.h index e06cef4e78a..3f029b8aa9a 100644 --- a/EventFiltering/EventFilteringUtilsLinkDef.h +++ b/EventFiltering/EventFilteringUtilsLinkDef.h @@ -13,4 +13,6 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class std::vector < std::array < uint64_t, 2>> + ; +#pragma link C++ class ZorroHelper + ; +#pragma link C++ class ZorroSummary + ; +#pragma link C++ class std::vector < ZorroHelper> + ; diff --git a/EventFiltering/PWGCF/CFFilterAll.cxx b/EventFiltering/PWGCF/CFFilterAll.cxx index ca7b90fc0ca..80832e661b1 100644 --- a/EventFiltering/PWGCF/CFFilterAll.cxx +++ b/EventFiltering/PWGCF/CFFilterAll.cxx @@ -53,6 +53,7 @@ enum CFThreeBodyTriggers { kPPP, kPPL, kPLL, kLLL, + kPPPhi, kNThreeBodyTriggers }; enum CFTwoBodyTriggers { kPD, kLD, @@ -83,7 +84,7 @@ enum PIDLimits { kTPCMin, }; // For configurable tables -static const std::vector CFTriggerNamesALL{"ppp", "ppL", "pLL", "LLL", "pd", "Ld"}; +static const std::vector CFTriggerNamesALL{"ppp", "ppL", "pLL", "LLL", "ppPhi", "pd", "Ld"}; static const std::vector SpeciesNameAll{"Proton", "Deuteron", "Lambda"}; static const std::vector SpeciesName{"Proton", "Deuteron"}; static const std::vector SpeciesNameAnti{"AntiProton", "AntiDeuteron"}; @@ -97,17 +98,17 @@ static const std::vector PidCutsName{"TPC min", "TPC max", "TOF min static const std::vector PtCutsName{"Pt min (particle)", "Pt max (particle)", "Pt min (antiparticle)", "Pt max (antiparticle)", "P thres"}; static const std::vector MomCorCutsName{"Momemtum Correlation min", "Momemtum Correlation max"}; static const std::vector PIDForTrackingName{"Switch", "Momemtum Threshold"}; -static const std::vector ThreeBodyFilterNames{"PPP", "PPL", "PLL", "LLL"}; +static const std::vector ThreeBodyFilterNames{"PPP", "PPL", "PLL", "LLL", "PPPhi"}; static const std::vector TwoBodyFilterNames{"PD", "LD"}; -static const std::vector ParticleNames{"PPP", "aPaPaP", "PPL", "aPaPaL", "PLL", "aPaLaL", "LLL", "aLaLaL", "PD", "aPaD", "LD", "aLaD"}; +static const std::vector ParticleNames{"PPP", "aPaPaP", "PPL", "aPaPaL", "PLL", "aPaLaL", "LLL", "aLaLaL", "PPPhi", "aPaPPhi", "PD", "aPaD", "LD", "aLaD"}; static const int nPidRejection = 2; static const int nTracks = 2; static const int nPidAvg = 4; static const int nPidCutsDaughers = 2; static const int nPtCuts = 5; -static const int nAllTriggers = 6; -static const int nTriggerAllNames = 12; +static const int nAllTriggers = 7; +static const int nTriggerAllNames = 14; static const int nMomCorCuts = 2; static const float pidcutsTable[nTracks][kNPIDLimits]{ @@ -143,17 +144,17 @@ static const float ITSCutsTable[1][nTracks] = { {1, 1}}; static const float triggerSwitches[1][nAllTriggers]{ - {1, 1, 1, 1, 1, 1}}; + {1, 1, 1, 1, 1, 1, 1}}; static const float Q3Limits[1][kNThreeBodyTriggers]{ - {0.6f, 0.6f, 0.6f, 0.6f}}; + {0.6f, 0.6f, 0.6f, 0.6f, 0.6f}}; static const float KstarLimits[1][kNTwoBodyTriggers]{ {1.2f, 1.2f}}; static const float Downsample[2][nTriggerAllNames]{ - {-1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1}, - {1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.}}; + {-1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1, -1., -1.}, + {1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.}}; } // namespace CFTrigger @@ -466,6 +467,25 @@ struct CFFilter { {CFTrigger::pidcutsV0DaughterTable[0], CFTrigger::kNV0Daughters, CFTrigger::nPidCutsDaughers, CFTrigger::SpeciesV0DaughterName, CFTrigger::TPCCutName}, "PID selections for Lambda daughters"}; + // config for ppPhi + struct : ConfigurableGroup { + std::string prefix = "PPPhi"; + Configurable ConfResoInvMassLowLimit{"ConfResoInvMassLowLimit", 1.011461, "Lower limit of the Reso invariant mass"}; + Configurable ConfResoInvMassUpLimit{"ConfResoInvMassUpLimit", 1.027461, "Upper limit of the Reso invariant mass"}; + + Configurable ConfTrkEtaKa{"ConfTrkEtaKa", 0.85, "Eta kaon daughters"}; // 0.8 + Configurable ConfTrkDCAxyKa{"ConfTrkDCAxyKa", 0.15, "DCAxy kaon daughters"}; // 0.1 + Configurable ConfTrkDCAzKa{"ConfTrkDCAzKa", 0.3, "DCAz kaon daughters"}; // 0.2 + Configurable ConfNClusKa{"ConfNClusKa", 70, "NClusters kaon daughters"}; // 0.2 + Configurable ConfNCrossedKa{"ConfNCrossedKa", 65, "NCrossedRows kaon daughters"}; // 0.2 + Configurable ConfTrkTPCfClsKa{"ConfTrkTPCfClsKa", 0.80, "Minimum fraction of crossed rows over findable clusters kaon daughters"}; // 0.2 + + Configurable ConfTrkPtKaUp{"ConfTrkPtKaUp", 6.0, "Pt_up kaon daughters"}; // 2.0 + Configurable ConfTrkPtKaDown{"ConfTrkPtKaDown", 0.05, "Pt_down kaon daughters"}; // 0.15 + Configurable ConfTrkPTPCKaThr{"ConfTrkPTPCKaThr", 0.40, "p_TPC,Thr kaon daughters"}; // 0.4 + Configurable ConfTrkKaSigmaPID{"ConfTrkKaSigmaPID", 3.50, "n_sigma kaon daughters"}; // 3.0 + } PPPhi; + // Trigger selections Configurable> ConfTriggerSwitches{ "ConfTriggerSwitches", @@ -515,8 +535,8 @@ struct CFFilter { } // global histograms - registry.add("fProcessedEvents", "CF - event filtered;;Events", HistType::kTH1F, {{8, -0.5, 7.5}}); - std::vector eventTitles = {"all", "rejected", "ppp", "ppL", "pLL", "LLL", "pD", "LD"}; + registry.add("fProcessedEvents", "CF - event filtered;;Events", HistType::kTH1F, {{9, -0.5, 8.5}}); + std::vector eventTitles = {"all", "rejected", "ppp", "ppL", "pLL", "LLL", "ppPhi", "pD", "LD"}; for (size_t iBin = 0; iBin < eventTitles.size(); iBin++) { registry.get(HIST("fProcessedEvents"))->GetXaxis()->SetBinLabel(iBin + 1, eventTitles[iBin].data()); } @@ -742,6 +762,61 @@ struct CFFilter { registry.add("TrackCuts/AntiLambda/NegDaughter/fNsigmaTPCvsPAntiProtonAntiV0Daugh", "NSigmaTPC AntiProton antiV0Daught;p_{TPC} (GeV/c);n#sigma_{TPC}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); registry.add("TrackCuts/AntiLambda/PosDaughter/fNsigmaTPCvsPPionPlusAntiV0Daugh", "NSigmaTPC Pion antiV0Daught;p_{TPC} (GeV/c);n#sigma_{TPC}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); + // Phi + + registry.add("TrackCuts/Phi/Before/fInvMass", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + registry.add("TrackCuts/Phi/Before/fPt", "Transverse momentum V0s;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/fEta", "Pseudorapidity of V0;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + registry.add("TrackCuts/Phi/Before/fPhi", "Azimuthal angle of V0;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + + registry.add("TrackCuts/Phi/Before/PosDaughter/fP", "Momentum of Kaons at PV;p (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fPTPC", "Momentum of Kaons at TPC inner wall;p_{TPC} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fPt", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fMomCorDif", "Momentum correlation;p_{reco} (GeV/c); (p_{TPC} - p_{reco}) (GeV/c)", {HistType::kTH2F, {{500, 0, 10}, {600, -3, 3}}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fMomCorRatio", "Momentum correlation;p_{reco} (GeV/c); p_{TPC} - p_{reco} / p_{reco}", {HistType::kTH2F, {{500, 0, 10}, {200, -1, 1}}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fEta", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fPhi", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fNsigmaTPCvsP", "NSigmaTPC Kaon;p_{TPC} (GeV/c);n#sigma_{TPC}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fNsigmaTOFvsP", "NSigmaTOF Kaon;p_{TPC} (GeV/c);n#sigma_{TOF}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fNsigmaTPCTOFvsP", "NSigmaTPCTOF Kaon;p_{TPC} (GeV/c);n#sigma_{comb}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, 0.f, 10.f}}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fDCAxy", "fDCAxy Kaon;DCA_{XY};Entries", HistType::kTH1F, {{500, -0.5f, 0.5f}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fDCAz", "fDCAz Kaon;DCA_{Z};Entries", HistType::kTH1F, {{500, -0.5f, 0.5f}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fTPCsCls", "fTPCsCls Kaon;TPC Shared Clusters;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fTPCcRows", "fTPCcRows Kaon;TPC Crossed Rows;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fTrkTPCfCls", "fTrkTPCfCls Kaon;TPC Findable/CrossedRows;Entries", HistType::kTH1F, {{500, 0.0f, 3.0f}}); + registry.add("TrackCuts/Phi/Before/PosDaughter/fTPCncls", "fTPCncls Kaon;TPC Clusters;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + + registry.add("TrackCuts/Phi/Before/NegDaughter/fP", "Momentum of Kaons at PV;p (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fPTPC", "Momentum of Kaons at TPC inner wall;p_{TPC} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fPt", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fMomCorDif", "Momentum correlation;p_{reco} (GeV/c); (p_{TPC} - p_{reco}) (GeV/c)", {HistType::kTH2F, {{500, 0, 10}, {600, -3, 3}}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fMomCorRatio", "Momentum correlation;p_{reco} (GeV/c); p_{TPC} - p_{reco} / p_{reco}", {HistType::kTH2F, {{500, 0, 10}, {200, -1, 1}}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fEta", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fPhi", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fNsigmaTPCvsP", "NSigmaTPC Kaon;p_{TPC} (GeV/c);n#sigma_{TPC}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fNsigmaTOFvsP", "NSigmaTOF Kaon;p_{TPC} (GeV/c);n#sigma_{TOF}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fNsigmaTPCTOFvsP", "NSigmaTPCTOF Kaon;p_{TPC} (GeV/c);n#sigma_{comb}", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, 0.f, 10.f}}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fDCAxy", "fDCAxy Kaon;DCA_{XY};Entries", HistType::kTH1F, {{500, -0.5f, 0.5f}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fDCAz", "fDCAz Kaon;DCA_{Z};Entries", HistType::kTH1F, {{500, -0.5f, 0.5f}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fTPCsCls", "fTPCsCls Kaon;TPC Shared Clusters;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fTPCcRows", "fTPCcRows Kaon;TPC Crossed Rows;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fTrkTPCfCls", "fTrkTPCfCls Kaon;TPC Findable/CrossedRows;Entries", HistType::kTH1F, {{500, 0.0f, 3.0f}}); + registry.add("TrackCuts/Phi/Before/NegDaughter/fTPCncls", "fTPCncls Kaon;TPC Clusters;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + + registry.add("TrackCuts/Phi/After/fInvMass", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + registry.add("TrackCuts/Phi/After/fPt", "Transverse momentum V0s;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/After/fEta", "Pseudorapidity of V0;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + registry.add("TrackCuts/Phi/After/fPhi", "Azimuthal angle of V0;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + + // phi daughter + registry.add("TrackCuts/Phi/After/PosDaughter/fPt", "Transverse momentum Pos Daugh tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/After/PosDaughter/fEta", "Phi Pos Daugh Eta;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + registry.add("TrackCuts/Phi/After/PosDaughter/fPhi", "Azimuthal angle of Pos Daugh tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + + registry.add("TrackCuts/Phi/After/NegDaughter/fPt", "Transverse momentum Neg Daugh tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + registry.add("TrackCuts/Phi/After/NegDaughter/fEta", "Phi Neg Daugh Eta;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + registry.add("TrackCuts/Phi/After/NegDaughter/fPhi", "Azimuthal angle of Neg Daugh tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + // for ppp registry.add("ppp/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("ppp/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); @@ -786,6 +861,18 @@ struct CFFilter { registry.add("lll/fLambdaPtVsQ3", "Q3 vs pT (lambda)", {HistType::kTH2F, {{150, 0, 1.5}, {500, 0, 10}}}); registry.add("lll/fAntiLambdaPtVsQ3", "Q3 vs pT (antilambda)", {HistType::kTH2F, {{150, 0, 1.5}, {500, 0, 10}}}); + // for ppPhi + registry.add("ppphi/fMultiplicity", "Multiplicity of all triggered events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); + registry.add("ppphi/fZvtx", "Zvtx of all triggered events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); + registry.add("ppphi/fSE_particle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fSE_particle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fSE_antiparticle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fSE_antiparticle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fProtonPtVsQ3", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fPhiPtVsQ3", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fAntiProtonPtVsQ3", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppphi/fAntiPhiPtVsQ3", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + // for pd registry.add("pd/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("pd/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); @@ -816,6 +903,10 @@ struct CFFilter { float mMassProton = o2::constants::physics::MassProton; float mMassLambda = o2::constants::physics::MassLambda; float mMassDeuteron = o2::constants::physics::MassDeuteron; + float mMassPhi = o2::constants::physics::MassPhi; + float mMassKaonPlus = o2::constants::physics::MassKPlus; + float mMassKaonMinus = o2::constants::physics::MassKMinus; + int currentRunNumber = -999; int lastRunNumber = -999; @@ -1179,6 +1270,21 @@ struct CFFilter { return true; } + template + bool isSelectedTrackKaon(T const& track) + { + bool isSelected = false; + if (track.pt() <= PPPhi.ConfTrkPtKaUp.value && track.pt() >= PPPhi.ConfTrkPtKaDown.value && std::abs(track.eta()) <= PPPhi.ConfTrkEtaKa.value && std::abs(track.dcaXY()) <= PPPhi.ConfTrkDCAxyKa.value && std::abs(track.dcaZ()) <= PPPhi.ConfTrkDCAzKa.value && track.tpcNClsCrossedRows() >= PPPhi.ConfNCrossedKa.value && track.tpcNClsFound() >= PPPhi.ConfNClusKa.value && track.tpcCrossedRowsOverFindableCls() >= PPPhi.ConfTrkTPCfClsKa.value) { + if (track.tpcInnerParam() < PPPhi.ConfTrkPTPCKaThr.value && std::abs(track.tpcNSigmaKa()) <= PPPhi.ConfTrkKaSigmaPID.value) { + isSelected = true; + } + if (track.tpcInnerParam() >= PPPhi.ConfTrkPTPCKaThr.value && std::abs(std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa())) <= PPPhi.ConfTrkKaSigmaPID.value) { + isSelected = true; + } + } + return isSelected; + } + float getkstar(const ROOT::Math::PtEtaPhiMVector part1, const ROOT::Math::PtEtaPhiMVector part2) { @@ -1335,7 +1441,7 @@ struct CFFilter { std::vector AntiProtonIndex = {}; // Prepare vectors for different species - std::vector protons, antiprotons, deuterons, antideuterons, lambdas, antilambdas; + std::vector protons, antiprotons, deuterons, antideuterons, lambdas, antilambdas, kaons, antikaons, phi; // create deuteron and proton vectors (and corresponding antiparticles) for pair and triplet creation for (auto& track : tracks) { @@ -1516,6 +1622,54 @@ struct CFFilter { registry.fill(HIST("TrackCuts/AntiDeuteron/fTPCnclsAntiDeuteron"), track.tpcNClsFound()); } } + // get Kaons (Phi Daughters) + if (ConfTriggerSwitches->get("Switch", "ppPhi") > 0.) { + if (isSelectedTrackKaon(track)) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), mMassKaonPlus); + if (track.sign() > 0) { + temp.SetM(mMassKaonPlus); + kaons.push_back(temp); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fP"), track.p()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fPTPC"), track.tpcInnerParam()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fPt"), track.pt()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fMomCorDif"), track.p(), track.tpcInnerParam() - track.p()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fMomCorRatio"), track.p(), (track.tpcInnerParam() - track.p()) / track.p()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fEta"), track.eta()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fPhi"), track.phi()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fNsigmaTPCvsP"), track.tpcInnerParam(), track.tpcNSigmaKa()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fNsigmaTOFvsP"), track.tpcInnerParam(), track.tofNSigmaKa()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fNsigmaTPCTOFvsP"), track.tpcInnerParam(), std::abs(std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa()))); + + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fDCAxy"), track.dcaXY()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fDCAz"), track.dcaZ()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fTPCsCls"), track.tpcNClsShared()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fTPCcRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fTrkTPCfCls"), track.tpcCrossedRowsOverFindableCls()); + registry.fill(HIST("TrackCuts/Phi/Before/PosDaughter/fTPCncls"), track.tpcNClsFound()); + } + if (track.sign() < 0) { + temp.SetM(mMassKaonMinus); + antikaons.push_back(temp); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fP"), track.p()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fPTPC"), track.tpcInnerParam()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fPt"), track.pt()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fMomCorDif"), track.p(), track.tpcInnerParam() - track.p()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fMomCorRatio"), track.p(), (track.tpcInnerParam() - track.p()) / track.p()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fEta"), track.eta()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fPhi"), track.phi()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fNsigmaTPCvsP"), track.tpcInnerParam(), track.tpcNSigmaKa()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fNsigmaTOFvsP"), track.tpcInnerParam(), track.tofNSigmaKa()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fNsigmaTPCTOFvsP"), track.tpcInnerParam(), std::abs(std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa()))); + + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fDCAxy"), track.dcaXY()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fDCAz"), track.dcaZ()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fTPCsCls"), track.tpcNClsShared()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fTPCcRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fTrkTPCfCls"), track.tpcCrossedRowsOverFindableCls()); + registry.fill(HIST("TrackCuts/Phi/Before/NegDaughter/fTPCncls"), track.tpcNClsFound()); + } + } + } } // keep track of daugher indices to avoid selfcorrelations @@ -1627,6 +1781,38 @@ struct CFFilter { } } + if (ConfTriggerSwitches->get("Switch", "ppPhi") > 0.) { + for (const auto& postrack : kaons) { + for (const auto& negtrack : antikaons) { + + ROOT::Math::PtEtaPhiMVector temp = postrack + negtrack; + + registry.fill(HIST("TrackCuts/Phi/Before/fInvMass"), temp.M()); + registry.fill(HIST("TrackCuts/Phi/Before/fPt"), temp.pt()); + registry.fill(HIST("TrackCuts/Phi/Before/fEta"), temp.eta()); + registry.fill(HIST("TrackCuts/Phi/Before/fPhi"), temp.phi()); + + if ((temp.M() >= PPPhi.ConfResoInvMassLowLimit.value) && (temp.M() <= PPPhi.ConfResoInvMassUpLimit.value)) { + + phi.push_back(temp); + + registry.fill(HIST("TrackCuts/Phi/After/fInvMass"), temp.M()); + registry.fill(HIST("TrackCuts/Phi/After/fPt"), temp.pt()); + registry.fill(HIST("TrackCuts/Phi/After/fEta"), temp.eta()); + registry.fill(HIST("TrackCuts/Phi/After/fPhi"), temp.phi()); + + registry.fill(HIST("TrackCuts/Phi/After/PosDaughter/fPt"), postrack.pt()); + registry.fill(HIST("TrackCuts/Phi/After/PosDaughter/fEta"), postrack.eta()); + registry.fill(HIST("TrackCuts/Phi/After/PosDaughter/fPhi"), postrack.phi()); + + registry.fill(HIST("TrackCuts/Phi/After/NegDaughter/fPt"), negtrack.pt()); + registry.fill(HIST("TrackCuts/Phi/After/NegDaughter/fEta"), negtrack.eta()); + registry.fill(HIST("TrackCuts/Phi/After/NegDaughter/fPhi"), negtrack.phi()); + } + } + } + } + float Q3 = 999.f, kstar = 999.f; if (ConfTriggerSwitches->get("Switch", "ppp") > 0.) { // ppp trigger @@ -1892,6 +2078,54 @@ struct CFFilter { } } } + if (ConfTriggerSwitches->get("Switch", "ppPhi") > 0.) { + // ppphi trigger + for (auto iProton1 = protons.begin(); iProton1 != protons.end(); ++iProton1) { + auto iProton2 = iProton1 + 1; + for (; iProton2 != protons.end(); ++iProton2) { + for (auto iPhi1 = phi.begin(); iPhi1 != phi.end(); ++iPhi1) { + Q3 = getQ3(*iProton1, *iProton2, *iPhi1); + registry.fill(HIST("ppphi/fSE_particle"), Q3); + registry.fill(HIST("ppphi/fProtonPtVsQ3"), Q3, (*iProton1).Pt()); + registry.fill(HIST("ppphi/fProtonPtVsQ3"), Q3, (*iProton2).Pt()); + registry.fill(HIST("ppphi/fPhiPtVsQ3"), Q3, (*iPhi1).Pt()); + if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPPPhi)) { + if (ConfDownsample->get("Switch", "PPPhi") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "PPPhi")) { + registry.fill(HIST("ppphi/fSE_particle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPPPhi] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPPPhi] += 1; + } + } + } + } + } + // apapphi trigger + for (auto iAntiProton1 = antiprotons.begin(); iAntiProton1 != antiprotons.end(); ++iAntiProton1) { + auto iAntiProton2 = iAntiProton1 + 1; + for (; iAntiProton2 != antiprotons.end(); ++iAntiProton2) { + for (auto iPhi1 = phi.begin(); iPhi1 != phi.end(); ++iPhi1) { + Q3 = getQ3(*iAntiProton1, *iAntiProton2, *iPhi1); + registry.fill(HIST("ppphi/fSE_antiparticle"), Q3); + registry.fill(HIST("ppphi/fAntiProtonPtVsQ3"), Q3, (*iAntiProton1).Pt()); + registry.fill(HIST("ppphi/fAntiProtonPtVsQ3"), Q3, (*iAntiProton2).Pt()); + registry.fill(HIST("ppphi/fAntiPhiPtVsQ3"), Q3, (*iPhi1).Pt()); + if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPPPhi)) { + if (ConfDownsample->get("Switch", "aPaPPhi") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aPaPPhi")) { + registry.fill(HIST("ppphi/fSE_antiparticle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPPPhi] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPPPhi] += 1; + } + } + } + } + } + } if (ConfTriggerSwitches->get("Switch", "pd") > 0.) { // pd trigger for (auto iProton = protons.begin(); iProton != protons.end(); ++iProton) { @@ -1998,17 +2232,23 @@ struct CFFilter { registry.fill(HIST("lll/fMultiplicity"), col.multNTracksPV()); registry.fill(HIST("lll/fZvtx"), col.posZ()); } + if (lowQ3Triplets[CFTrigger::kPPPhi] > 0) { + keepEvent3N[CFTrigger::kPPPhi] = true; + registry.fill(HIST("fProcessedEvents"), 6); + registry.fill(HIST("ppphi/fMultiplicity"), col.multNTracksPV()); + registry.fill(HIST("ppphi/fZvtx"), col.posZ()); + } // create tags for two body triggers if (lowKstarPairs[CFTrigger::kPD] > 0) { keepEvent2N[CFTrigger::kPD] = true; - registry.fill(HIST("fProcessedEvents"), 6); + registry.fill(HIST("fProcessedEvents"), 7); registry.fill(HIST("pd/fMultiplicity"), col.multNTracksPV()); registry.fill(HIST("pd/fZvtx"), col.posZ()); } if (lowKstarPairs[CFTrigger::kLD] > 0) { keepEvent2N[CFTrigger::kLD] = true; - registry.fill(HIST("fProcessedEvents"), 7); + registry.fill(HIST("fProcessedEvents"), 8); registry.fill(HIST("ld/fMultiplicity"), col.multNTracksPV()); registry.fill(HIST("ld/fZvtx"), col.posZ()); } @@ -2017,10 +2257,11 @@ struct CFFilter { keepEvent3N[CFTrigger::kPPL], keepEvent3N[CFTrigger::kPLL], keepEvent3N[CFTrigger::kLLL], + keepEvent3N[CFTrigger::kPPPhi], keepEvent2N[CFTrigger::kPD], keepEvent2N[CFTrigger::kLD]); - if (!keepEvent3N[CFTrigger::kPPP] && !keepEvent3N[CFTrigger::kPPL] && !keepEvent3N[CFTrigger::kPLL] && !keepEvent3N[CFTrigger::kLLL] && + if (!keepEvent3N[CFTrigger::kPPP] && !keepEvent3N[CFTrigger::kPPL] && !keepEvent3N[CFTrigger::kPLL] && !keepEvent3N[CFTrigger::kLLL] && !keepEvent3N[CFTrigger::kPPPhi] && !keepEvent2N[CFTrigger::kPD] && !keepEvent2N[CFTrigger::kLD]) { registry.fill(HIST("fProcessedEvents"), 1); } diff --git a/EventFiltering/PWGCF/CFFilterPPPhi.cxx b/EventFiltering/PWGCF/CFFilterPPPhi.cxx index 71487754b29..623b5cb9086 100644 --- a/EventFiltering/PWGCF/CFFilterPPPhi.cxx +++ b/EventFiltering/PWGCF/CFFilterPPPhi.cxx @@ -72,23 +72,32 @@ struct CFFillterPPPhi { false, "Evt sel: check for offline selection"}; - Configurable InvMassCutWidth{"InvMassCutWidth", 0.024, "Phi Inv Mass Cut Width (GeV)"}; + Configurable ConfResoInvMassLowLimit{"ConfResoInvMassLowLimit", 1.011461, "Lower limit of the Reso invariant mass"}; + Configurable ConfResoInvMassUpLimit{"ConfResoInvMassUpLimit", 1.027461, "Upper limit of the Reso invariant mass"}; Configurable Q3Max{"Q3Max", 1.f, "Max Q3"}; /*track selection*/ - Configurable ConfTrkEta{"ConfTrkEta", 0.85, "Eta"}; // 0.8 - Configurable ConfTrkDCAxy{"ConfTrkDCAxy", 0.15, "DCAxy"}; // 0.1 - Configurable ConfTrkDCAz{"ConfTrkDCAz", 0.3, "DCAz"}; // 0.2 - Configurable ConfNClus{"ConfNClus", 70, "NClusters"}; // 0.2 - Configurable ConfNCrossed{"ConfNCrossed", 65, "NCrossedRows"}; // 0.2 + Configurable ConfTrkEtaPr{"ConfTrkEtaPr", 0.85, "Et protona"}; // 0.8 + Configurable ConfTrkDCAxyPr{"ConfTrkDCAxyPr", 0.15, "DCAxy proton"}; // 0.1 + Configurable ConfTrkDCAzPr{"ConfTrkDCAzPr", 0.3, "DCAz proton"}; // 0.2 + Configurable ConfNClusPr{"ConfNClusPr", 70, "NClusters proton"}; // 0.2 + Configurable ConfNCrossedPr{"ConfNCrossedPr", 65, "NCrossedRows proton"}; // 0.2 + Configurable ConfTrkTPCfClsPr{"ConfTrkTPCfClsPr", 0.83, "Minimum fraction of crossed rows over findable clusters proton"}; // 0.2 Configurable ConfTrkPtPrUp{"ConfTrkPtPrUp", 6.0, "Pt_up proton"}; // 2.0 Configurable ConfTrkPtPrDown{"ConfTrkPtPrDown", 0.35, "Pt_down proton"}; // 0.5 Configurable ConfTrkPTPCPrThr{"ConfTrkPTPCPrThr", 0.8, "p_TPC,Thr proton"}; // 0.75 Configurable ConfTrkPrSigmaPID{"ConfTrkPrSigmaPID", 3.50, "n_sigma proton"}; // 3.0 + Configurable ConfTrkEtaKa{"ConfTrkEtaKa", 0.85, "Eta kaon"}; // 0.8 + Configurable ConfTrkDCAxyKa{"ConfTrkDCAxyKa", 0.15, "DCAxy kaon"}; // 0.1 + Configurable ConfTrkDCAzKa{"ConfTrkDCAzKa", 0.3, "DCAz kaon"}; // 0.2 + Configurable ConfNClusKa{"ConfNClusKa", 70, "NClusters kaon"}; // 0.2 + Configurable ConfNCrossedKa{"ConfNCrossedKa", 65, "NCrossedRows kaon"}; // 0.2 + Configurable ConfTrkTPCfClsKa{"ConfTrkTPCfClsKa", 0.80, "Minimum fraction of crossed rows over findable clusters kaon"}; // 0.2 + Configurable ConfTrkPtKaUp{"ConfTrkPtKaUp", 6.0, "Pt_up kaon"}; // 2.0 Configurable ConfTrkPtKaDown{"ConfTrkPtKaDown", 0.05, "Pt_down kaon"}; // 0.15 Configurable ConfTrkPTPCKaThr{"ConfTrkPTPCKaThr", 0.40, "p_TPC,Thr kaon"}; // 0.4 @@ -193,6 +202,7 @@ struct CFFillterPPPhi { // phi cuts registry.add("TrackCuts/Phi/fPtPhiBefore", "Transverse momentum V0s;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); registry.add("TrackCuts/Phi/fInvMassPhiBefore", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + registry.add("TrackCuts/Phi/fEtaPhiBefore", "Pseudorapidity of V0;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); registry.add("TrackCuts/Phi/fPhiPhiBefore", "Azimuthal angle of V0;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); @@ -202,12 +212,13 @@ struct CFFillterPPPhi { registry.add("TrackCuts/Phi/fPhiPhi", "Azimuthal angle of V0;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); // phi daughter + registry.add("TrackCuts/Phi/PosDaughter/Pt", "Transverse momentum Pos Daugh tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); registry.add("TrackCuts/Phi/PosDaughter/Eta", "Phi Pos Daugh Eta;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); - registry.add("TrackCuts/Phi/PosDaughter/DCAXY", "Phi Pos Daugh DCAXY;DCA_{XY};Entries", HistType::kTH1F, {{1000, -2.5f, 2.5f}}); - registry.add("TrackCuts/Phi/PosDaughter/fTPCncls", "Phi Pos Daugh TPCncls;TPC Clusters;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + registry.add("TrackCuts/Phi/PosDaughter/Phi", "Azimuthal angle of Pos Daugh tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + + registry.add("TrackCuts/Phi/NegDaughter/Pt", "Transverse momentum Neg Daugh tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); registry.add("TrackCuts/Phi/NegDaughter/Eta", "Phi Neg Daugh Eta;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); - registry.add("TrackCuts/Phi/NegDaughter/DCAXY", "Phi Neg Daugh DCAXY;DCA_{XY};Entries", HistType::kTH1F, {{1000, -2.5f, 2.5f}}); - registry.add("TrackCuts/Phi/NegDaughter/fTPCncls", "Phi Neg Daugh TPCncls;TPC Clusters;Entries", HistType::kTH1F, {{163, -1.0f, 162.0f}}); + registry.add("TrackCuts/Phi/NegDaughter/Phi", "Azimuthal angle of Neg Daugh tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); // triggers registry.add("ppphi/fMultiplicity", "Multiplicity of all triggered events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); @@ -236,11 +247,11 @@ struct CFFillterPPPhi { bool isSelectedTrackProton(T const& track) { bool isSelected = false; - if (track.pt() < ConfTrkPtPrUp.value && track.pt() > ConfTrkPtPrDown.value && std::abs(track.eta()) < ConfTrkEta.value && std::abs(track.dcaXY()) < ConfTrkDCAxy.value && std::abs(track.dcaZ()) < ConfTrkDCAz.value && track.tpcNClsCrossedRows() >= ConfNCrossed.value && track.tpcNClsFound() >= ConfNClus.value) { - if (track.tpcInnerParam() < ConfTrkPTPCPrThr.value && std::abs(track.tpcNSigmaPr()) < ConfTrkPrSigmaPID.value) { + if (track.pt() <= ConfTrkPtPrUp.value && track.pt() >= ConfTrkPtPrDown.value && std::abs(track.eta()) <= ConfTrkEtaPr.value && std::abs(track.dcaXY()) <= ConfTrkDCAxyPr.value && std::abs(track.dcaZ()) <= ConfTrkDCAzPr.value && track.tpcNClsCrossedRows() >= ConfNCrossedPr.value && track.tpcNClsFound() >= ConfNClusPr.value && track.tpcCrossedRowsOverFindableCls() >= ConfTrkTPCfClsPr.value) { + if (track.tpcInnerParam() < ConfTrkPTPCPrThr.value && std::abs(track.tpcNSigmaPr()) <= ConfTrkPrSigmaPID.value) { isSelected = true; } - if (track.tpcInnerParam() >= ConfTrkPTPCPrThr.value && std::abs(std::sqrt(track.tpcNSigmaPr() * track.tpcNSigmaPr() + track.tofNSigmaPr() * track.tofNSigmaPr())) < ConfTrkPrSigmaPID.value) { + if (track.tpcInnerParam() >= ConfTrkPTPCPrThr.value && std::abs(std::sqrt(track.tpcNSigmaPr() * track.tpcNSigmaPr() + track.tofNSigmaPr() * track.tofNSigmaPr())) <= ConfTrkPrSigmaPID.value) { isSelected = true; } } @@ -251,11 +262,11 @@ struct CFFillterPPPhi { bool isSelectedTrackKaon(T const& track) { bool isSelected = false; - if (track.pt() < ConfTrkPtKaUp.value && track.pt() > ConfTrkPtKaDown.value && std::abs(track.eta()) < ConfTrkEta.value && std::abs(track.dcaXY()) < ConfTrkDCAxy.value && std::abs(track.dcaZ()) < ConfTrkDCAz.value && track.tpcNClsCrossedRows() >= ConfNCrossed.value && track.tpcNClsFound() >= ConfNClus.value) { - if (track.tpcInnerParam() < ConfTrkPTPCKaThr.value && std::abs(track.tpcNSigmaKa()) < ConfTrkKaSigmaPID.value) { + if (track.pt() <= ConfTrkPtKaUp.value && track.pt() >= ConfTrkPtKaDown.value && std::abs(track.eta()) <= ConfTrkEtaKa.value && std::abs(track.dcaXY()) <= ConfTrkDCAxyKa.value && std::abs(track.dcaZ()) <= ConfTrkDCAzKa.value && track.tpcNClsCrossedRows() >= ConfNCrossedKa.value && track.tpcNClsFound() >= ConfNClusKa.value && track.tpcCrossedRowsOverFindableCls() >= ConfTrkTPCfClsKa.value) { + if (track.tpcInnerParam() < ConfTrkPTPCKaThr.value && std::abs(track.tpcNSigmaKa()) <= ConfTrkKaSigmaPID.value) { isSelected = true; } - if (track.tpcInnerParam() >= ConfTrkPTPCKaThr.value && std::abs(std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa())) < ConfTrkKaSigmaPID.value) { + if (track.tpcInnerParam() >= ConfTrkPTPCKaThr.value && std::abs(std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa())) <= ConfTrkKaSigmaPID.value) { isSelected = true; } } @@ -263,38 +274,10 @@ struct CFFillterPPPhi { } float mMassProton = o2::constants::physics::MassProton; - float mMassKaon = o2::constants::physics::MassKPlus; - float mMassPhi = o2::constants::physics::MassPhi; - - // float getInvMass(const ROOT::Math::PtEtaPhiMVector part1, - // const ROOT::Math::PtEtaPhiMVector part2) - // { - // const ROOT::Math::PtEtaPhiMVector trackSum = part1 + part2; - // return trackSum.M(); - // } - - float CalculateInvMass(const ROOT::Math::PtEtaPhiMVector part1, - const ROOT::Math::PtEtaPhiMVector part2) - { - Double_t invMass = 0; - - float massDP = mMassKaon; - float massDN = mMassKaon; + float mMassKaonPlus = o2::constants::physics::MassKPlus; + float mMassKaonMinus = o2::constants::physics::MassKMinus; - float EDaugP = TMath::Sqrt( - massDP * massDP + part1.Px() * part1.Px() + part1.Py() * part1.Py() + part1.Pz() * part1.Pz()); - float EDaugN = TMath::Sqrt( - massDN * massDN + part2.Px() * part2.Px() + part2.Py() * part2.Py() + part2.Pz() * part2.Pz()); - - float energysum = EDaugP + EDaugN; - float pSum2 = (part2.Px() + part1.Px()) * (part2.Px() + part1.Px()) + - - (part2.Py() + part1.Py()) * (part2.Py() + part1.Py()) + - - (part2.Pz() + part1.Pz()) * (part2.Pz() + part1.Pz()); - invMass = TMath::Sqrt(energysum * energysum - pSum2); - return invMass; - } + float mMassPhi = o2::constants::physics::MassPhi; float getkstar(const ROOT::Math::PtEtaPhiMVector part1, const ROOT::Math::PtEtaPhiMVector part2) @@ -412,8 +395,9 @@ struct CFFillterPPPhi { } if (isSelectedTrackKaon(track)) { - ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), mMassKaon); + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), mMassKaonPlus); if (track.sign() > 0) { + temp.SetM(mMassKaonPlus); kaons.push_back(temp); registry.fill(HIST("TrackCuts/Kaon/fPKaon"), track.p()); registry.fill(HIST("TrackCuts/Kaon/fPTPCKaon"), track.tpcInnerParam()); @@ -436,6 +420,8 @@ struct CFFillterPPPhi { // KaonIndex.push_back(track.globalIndex()); } if (track.sign() < 0) { + temp.SetM(mMassKaonMinus); + antikaons.push_back(temp); registry.fill(HIST("TrackCuts/AntiKaon/fPAntiKaon"), track.p()); registry.fill(HIST("TrackCuts/AntiKaon/fPTPCAntiKaon"), track.tpcInnerParam()); @@ -463,29 +449,31 @@ struct CFFillterPPPhi { for (const auto& postrack : kaons) { for (const auto& negtrack : antikaons) { + ROOT::Math::PtEtaPhiMVector temp = postrack + negtrack; - temp.SetM(mMassPhi); + // temp.SetM(mMassPhi); + registry.fill(HIST("TrackCuts/Phi/fInvMassPhiBefore"), temp.M()); - registry.fill(HIST("TrackCuts/Phi/fInvMassPhiBefore"), CalculateInvMass(postrack, negtrack)); registry.fill(HIST("TrackCuts/Phi/fPtPhiBefore"), temp.pt()); registry.fill(HIST("TrackCuts/Phi/fEtaPhiBefore"), temp.eta()); registry.fill(HIST("TrackCuts/Phi/fPhiPhiBefore"), temp.phi()); - if ((CalculateInvMass(postrack, negtrack) > mMassPhi - InvMassCutWidth.value) && CalculateInvMass(postrack, negtrack) < (mMassPhi + InvMassCutWidth.value)) { + if ((temp.M() >= ConfResoInvMassLowLimit.value) && (temp.M() <= ConfResoInvMassUpLimit.value)) { // ROOT::Math::PtEtaPhiMVector temp = postrack + negtrack; phi.push_back(temp); registry.fill(HIST("TrackCuts/Phi/fPtPhi"), temp.pt()); registry.fill(HIST("TrackCuts/Phi/fEtaPhi"), temp.eta()); registry.fill(HIST("TrackCuts/Phi/fPhiPhi"), temp.phi()); - registry.fill(HIST("TrackCuts/Phi/fInvMassPhi"), CalculateInvMass(postrack, negtrack)); + registry.fill(HIST("TrackCuts/Phi/fInvMassPhi"), temp.M()); + registry.fill(HIST("TrackCuts/Phi/PosDaughter/Pt"), postrack.pt()); registry.fill(HIST("TrackCuts/Phi/PosDaughter/Eta"), postrack.eta()); - // registry.fill(HIST("TrackCuts/Phi/PosDaughter/DCAXY"), postrack.dcaXY()); - // registry.fill(HIST("TrackCuts/Phi/PosDaughter/fTPCncls"), postrack.tpcNClsFound()); + registry.fill(HIST("TrackCuts/Phi/PosDaughter/Phi"), postrack.phi()); + + registry.fill(HIST("TrackCuts/Phi/NegDaughter/Pt"), negtrack.pt()); registry.fill(HIST("TrackCuts/Phi/NegDaughter/Eta"), negtrack.eta()); - // registry.fill(HIST("TrackCuts/Phi/NegDaughter/DCAXY"), negtrack.dcaXY()); - // registry.fill(HIST("TrackCuts/Phi/NegDaughter/fTPCncls"), negtrack.tpcNClsFound()); + registry.fill(HIST("TrackCuts/Phi/NegDaughter/Phi"), negtrack.phi()); } } } diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 82293e0138c..070851ce4eb 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -19,6 +19,8 @@ /// \author Biao Zhang , CCNU /// \author Federica Zanone , Heidelberg University +#include "TRandom3.h" + #include "CommonConstants/PhysicsConstants.h" #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" @@ -126,6 +128,10 @@ struct HfFilter { // Main struct for HF triggers // parameter for Optimisation Tree Configurable applyOptimisation{"applyOptimisation", false, "Flag to enable or disable optimisation"}; + // manual downscale factors + Configurable applyDownscale{"applyDownscale", false, "Flag to enable or disable the application of downscale factors"}; + Configurable> downscaleFactors{"downscaleFactors", {defDownscaleFactors[0], kNtriggersHF, 1, hfTriggerNames, labelsDownscaleFactor}, "Downscale factors for each trigger (from 0 to 1)"}; + // array of BDT thresholds std::array, kNCharmParticles> thresholdBDTScores; @@ -289,8 +295,7 @@ struct HfFilter { // Main struct for HF triggers bool keepEvent[kNtriggersHF]{false}; if (applyEventSelection && (!collision.sel8() || std::fabs(collision.posZ()) > 11.f || (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && applyTimeFrameBorderCut))) { // safety margin for Zvtx - - tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P], keepEvent[kCharmBarToXiBach], keepEvent[kSigmaCPPK], keepEvent[kSigmaC0K0], keepEvent[kPhotonCharm2P], keepEvent[kPhotonCharm3P]); + tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P], keepEvent[kCharmBarToXiBach], keepEvent[kSigmaCPPK], keepEvent[kSigmaC0K0], keepEvent[kPhotonCharm2P], keepEvent[kPhotonCharm3P], keepEvent[kSingleCharm2P], keepEvent[kSingleCharm3P], keepEvent[kSingleNonPromptCharm2P], keepEvent[kSingleNonPromptCharm3P]); continue; } @@ -376,6 +381,11 @@ struct HfFilter { // Main struct for HF triggers continue; } + keepEvent[kSingleCharm2P] = true; + if (isBeautyTagged) { + keepEvent[kSingleNonPromptCharm2P] = true; + } + auto pVec2Prong = RecoDecay::pVec(pVecPos, pVecNeg); auto pt2Prong = RecoDecay::pt(pVec2Prong); @@ -768,6 +778,11 @@ struct HfFilter { // Main struct for HF triggers continue; } + keepEvent[kSingleCharm3P] = true; + if (std::accumulate(isBeautyTagged.begin(), isBeautyTagged.end(), 0)) { + keepEvent[kSingleNonPromptCharm3P] = true; + } + if ((!keepOnlyDplusForDouble3Prongs && std::accumulate(isCharmTagged.begin(), isCharmTagged.end(), 0)) || (keepOnlyDplusForDouble3Prongs && isCharmTagged[kDplus - 1])) { indicesDau3Prong.push_back(std::vector{trackFirst.globalIndex(), trackSecond.globalIndex(), trackThird.globalIndex()}); } // end multiple 3-prong selection @@ -1282,7 +1297,17 @@ struct HfFilter { // Main struct for HF triggers keepEvent[kDoubleCharmMix] = true; } - tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P], keepEvent[kCharmBarToXiBach], keepEvent[kSigmaCPPK], keepEvent[kSigmaC0K0], keepEvent[kPhotonCharm2P], keepEvent[kPhotonCharm3P]); + // apply downscale factors, if required + if (applyDownscale) { + auto rndValue = gRandom->Rndm(); + for (int iTrigger{0}; iTrigger < kNtriggersHF; ++iTrigger) { + if (rndValue > downscaleFactors->get(iTrigger, 0u)) { + keepEvent[iTrigger] = false; + } + } + } + + tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P], keepEvent[kCharmBarToXiBach], keepEvent[kSigmaCPPK], keepEvent[kSigmaC0K0], keepEvent[kPhotonCharm2P], keepEvent[kPhotonCharm3P], keepEvent[kSingleCharm2P], keepEvent[kSingleCharm3P], keepEvent[kSingleNonPromptCharm2P], keepEvent[kSingleNonPromptCharm3P]); if (!std::accumulate(keepEvent, keepEvent + kNtriggersHF, 0)) { hProcessedEvents->Fill(1); diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index e0dd03f3b75..4ab3a884952 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -75,6 +75,10 @@ enum HfTriggers { kSigmaC0K0, kPhotonCharm2P, kPhotonCharm3P, + kSingleCharm2P, + kSingleCharm3P, + kSingleNonPromptCharm2P, + kSingleNonPromptCharm3P, kNtriggersHF }; @@ -129,7 +133,7 @@ static const std::array charmParticleNames{"D0", static const std::array beautyParticleNames{"Bplus", "B0toDStar", "B0", "Bs", "Lb", "Xib"}; static const std::array pdgCodesCharm{421, 411, 431, 4122, 4232}; static const std::array eventTitles = {"all", "rejected"}; -static const std::array hfTriggerNames{filtering::HfHighPt2P::columnLabel(), filtering::HfHighPt3P::columnLabel(), filtering::HfBeauty3P::columnLabel(), filtering::HfBeauty4P::columnLabel(), filtering::HfFemto2P::columnLabel(), filtering::HfFemto3P::columnLabel(), filtering::HfDoubleCharm2P::columnLabel(), filtering::HfDoubleCharm3P::columnLabel(), filtering::HfDoubleCharmMix::columnLabel(), filtering::HfV0Charm2P::columnLabel(), filtering::HfV0Charm3P::columnLabel(), filtering::HfCharmBarToXiBach::columnLabel(), filtering::HfSigmaCPPK::columnLabel(), filtering::HfSigmaC0K0::columnLabel(), filtering::HfPhotonCharm2P::columnLabel(), filtering::HfPhotonCharm3P::columnLabel()}; +static const std::vector hfTriggerNames{filtering::HfHighPt2P::columnLabel(), filtering::HfHighPt3P::columnLabel(), filtering::HfBeauty3P::columnLabel(), filtering::HfBeauty4P::columnLabel(), filtering::HfFemto2P::columnLabel(), filtering::HfFemto3P::columnLabel(), filtering::HfDoubleCharm2P::columnLabel(), filtering::HfDoubleCharm3P::columnLabel(), filtering::HfDoubleCharmMix::columnLabel(), filtering::HfV0Charm2P::columnLabel(), filtering::HfV0Charm3P::columnLabel(), filtering::HfCharmBarToXiBach::columnLabel(), filtering::HfSigmaCPPK::columnLabel(), filtering::HfSigmaC0K0::columnLabel(), filtering::HfPhotonCharm2P::columnLabel(), filtering::HfPhotonCharm3P::columnLabel(), filtering::HfSingleCharm2P::columnLabel(), filtering::HfSingleCharm3P::columnLabel(), filtering::HfSingleNonPromptCharm2P::columnLabel(), filtering::HfSingleNonPromptCharm3P::columnLabel()}; static const std::array v0Labels{"#gamma", "K_{S}^{0}", "#Lambda", "#bar{#Lambda}"}; static const std::array v0Names{"Photon", "K0S", "Lambda", "AntiLambda"}; @@ -226,6 +230,10 @@ static const std::vector labelsEmpty{}; static constexpr double cutsTrackDummy[o2::analysis::hf_cuts_single_track::nBinsPtTrack][o2::analysis::hf_cuts_single_track::nCutVarsTrack] = {{0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}}; o2::framework::LabeledArray cutsSingleTrackDummy{cutsTrackDummy[0], o2::analysis::hf_cuts_single_track::nBinsPtTrack, o2::analysis::hf_cuts_single_track::nCutVarsTrack, o2::analysis::hf_cuts_single_track::labelsPtTrack, o2::analysis::hf_cuts_single_track::labelsCutVarTrack}; +// manual downscale factors for tests +constexpr double defDownscaleFactors[kNtriggersHF][1] = {{1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}}; // one for each trigger +static const std::vector labelsDownscaleFactor = {"Downscale factor"}; + // Main helper class class HfFilterHelper diff --git a/EventFiltering/PWGLF/nucleiFilter.cxx b/EventFiltering/PWGLF/nucleiFilter.cxx index ee3ec9a1683..914f5d9ca9c 100644 --- a/EventFiltering/PWGLF/nucleiFilter.cxx +++ b/EventFiltering/PWGLF/nucleiFilter.cxx @@ -36,6 +36,7 @@ namespace static constexpr int nNuclei{3}; static constexpr int nHyperNuclei{1}; +static constexpr int nITStriggers{2}; static constexpr int nCutsPID{5}; static constexpr std::array masses{ constants::physics::MassDeuteron, constants::physics::MassTriton, @@ -44,7 +45,7 @@ static constexpr std::array charges{1, 1, 2}; static const std::vector matterOrNot{"Matter", "Antimatter"}; static const std::vector nucleiNames{"H2", "H3", "Helium"}; static const std::vector hypernucleiNames{"H3L"}; // 3-body decay case -static const std::vector columnsNames{"fH2", "fH3", o2::aod::filtering::He::columnLabel(), o2::aod::filtering::H3L3Body::columnLabel()}; +static const std::vector columnsNames{o2::aod::filtering::H2::columnLabel(), "fH3", o2::aod::filtering::He::columnLabel(), o2::aod::filtering::H3L3Body::columnLabel(), o2::aod::filtering::ITSmildIonisation::columnLabel(), o2::aod::filtering::ITSextremeIonisation::columnLabel()}; static const std::vector cutsNames{ "TPCnSigmaMin", "TPCnSigmaMax", "TOFnSigmaMin", "TOFnSigmaMax", "TOFpidStartPt"}; constexpr double betheBlochDefault[nNuclei][6]{ @@ -52,16 +53,16 @@ constexpr double betheBlochDefault[nNuclei][6]{ {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; static constexpr float cutsPID[nNuclei][nCutsPID]{ - {-3.f, +3.f, -4.f, +4.f, 1.0f}, /*H2*/ - {-3.f, +3.f, -4.f, +4.f, 1.6f}, /*H3*/ - {-5.f, +5.f, -4.f, +4.f, 14000.f}, /*He3*/ + {-3.f, +400.f, -4.f, +400.f, 1.0f}, /*H2*/ + {-3.f, +3.f, -4.f, +4.f, 1.6f}, /*H3*/ + {-5.f, +400.f, -4.f, +4.f, 14000.f}, /*He3*/ }; constexpr double bbMomScalingDefault[nNuclei][2]{ {1., 1.}, {1., 1.}, {1., 1.}}; constexpr double minTPCmom[nNuclei][2]{ - {0., 0.}, + {0.8, 0.}, {0., 0.}, {0.8, 0.}}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; @@ -80,6 +81,10 @@ struct nucleiFilter { Configurable cfgCutEta{"cfgCutEta", 1.f, "Eta range for tracks"}; Configurable cfgCutNclusITS{"cfgCutNclusITS", 2, "Minimum number of ITS clusters"}; + Configurable cfgCutNclusExtremeIonisationITS{"cfgCutNclusExtremeIonisationITS", 5, "Minimum number of ITS clusters for the extreme ionisation trigger"}; + Configurable cfgMomentumCutExtremeIonisation{"cfgMomentumCutExtremeIonisation", 1.2, "Minimum momentum for the extreme ionisation trigger"}; + Configurable cfgCutClsSizeExtremeIonisation{"cfgCutClsSizeExtremeIonisation", 8, "Minimum average size of ITS clusters for the extreme ionisation trigger"}; + Configurable cfgCutClsSizeMildIonisation{"cfgCutClsSizeMildIonisation", 5, "Minimum average size of ITS clusters for the mild ionisation trigger"}; Configurable cfgCutNclusTPC{"cfgCutNclusTPC", 80, "Minimum number of TPC clusters"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 3, "Max DCAxy"}; Configurable cfgCutDCAz{"cfgCutDCAz", 10, "Max DCAz"}; @@ -113,7 +118,7 @@ struct nucleiFilter { Configurable fixTPCinnerParam{"fixTPCinnerParam", false, "Fix TPC inner param"}; HistogramRegistry qaHists{"qaHists", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - OutputObj hProcessedEvents{TH1D("hProcessedEvents", ";;Number of filtered events", nNuclei + nHyperNuclei + 1, -0.5, nNuclei + nHyperNuclei + 0.5)}; + OutputObj hProcessedEvents{TH1D("hProcessedEvents", ";;Number of filtered events", nNuclei + nHyperNuclei + nITStriggers + 1, -0.5, nNuclei + nHyperNuclei + nITStriggers + 0.5)}; void init(o2::framework::InitContext&) { @@ -125,7 +130,9 @@ struct nucleiFilter { qaHists.add("fTPCsignalAll", "Specific energy loss (before filter)", HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); qaHists.add("fTPCsignal", "Specific energy loss", HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); qaHists.add("fDeuTOFNsigma", "Deuteron TOF Nsigma distribution", HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {2000, -100, 100, "TOF n#sigma"}}); + qaHists.add("fBachDeuTOFNsigma", "Bachelor Deuteron TOF Nsigma distribution", HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {2000, -100, 100, "TOF n#sigma"}}); qaHists.add("fH3LMassVsPt", "Hypertrion mass Vs pT", HistType::kTH2F, {{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}, {80, 2.96, 3.04, "Inv. Mass (GeV/c^{2})"}}); + qaHists.add("fExtremeIonisationITS", "ITS clusters for extreme ionisation trigger", HistType::kTH3F, {{4, 3.5, 7.5, "Number of ITS clusters"}, {150, 0, 15, "Average cluster size in ITS x cos#lambda"}, {100, 0.1, 10, "#it{p} (GeV/#it{c})"}}); for (int iN{0}; iN < nNuclei; ++iN) { h2TPCsignal[iN] = qaHists.add(Form("fTPCsignal_%s", nucleiNames[iN].data()), "Specific energy loss", HistType::kTH2F, {{1200, -6, 6., "#it{p}/Z (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); @@ -138,19 +145,17 @@ struct nucleiFilter { } } - // Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta); - // using TrackCandidates = soa::Filtered>; using TrackCandidates = soa::Join; void process(soa::Join::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, TrackCandidates const& tracks) { // collision process loop - bool keepEvent[nNuclei + nHyperNuclei]{false}; + bool keepEvent[nNuclei + nHyperNuclei + nITStriggers]{false}; // qaHists.fill(HIST("fCollZpos"), collision.posZ()); hProcessedEvents->Fill(0); // if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - tags(keepEvent[2], keepEvent[3]); + tags(keepEvent[0], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5]); return; } // @@ -160,6 +165,17 @@ struct nucleiFilter { {charges[2] * cfgMomentumScalingBetheBloch->get(2u, 0u) / masses[2], charges[2] * cfgMomentumScalingBetheBloch->get(2u, 1u) / masses[2]}}; for (auto& track : tracks) { // start loop over tracks + if (track.itsNCls() >= cfgCutNclusExtremeIonisationITS) { + double avgClsSize{0.}; + double cosL{std::sqrt(1. / (1. + track.tgl() * track.tgl()))}; + for (int iC{0}; iC < 7; ++iC) { + avgClsSize += track.itsClsSizeInLayer(iC); + } + avgClsSize = avgClsSize * cosL / track.itsNCls(); + qaHists.fill(HIST("fExtremeIonisationITS"), track.itsNCls(), avgClsSize, track.p()); + keepEvent[4] = track.p() > cfgMomentumCutExtremeIonisation && avgClsSize > cfgCutClsSizeMildIonisation; + keepEvent[5] = track.p() > cfgMomentumCutExtremeIonisation && avgClsSize > cfgCutClsSizeExtremeIonisation; + } if (track.itsNCls() < cfgCutNclusITS || track.tpcNClsFound() < cfgCutNclusTPC) { continue; @@ -223,6 +239,8 @@ struct nucleiFilter { auto track1 = vtx.track1_as(); auto track2 = vtx.track2_as(); + qaHists.fill(HIST("fBachDeuTOFNsigma"), track2.p() * track2.sign(), vtx.tofNSigmaBachDe()); + if (vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()) < minCosPA3body) { continue; } @@ -233,7 +251,7 @@ struct nucleiFilter { if (vtx.dcaVtxdaughters() > dcavtxdau) { continue; } - if ((track2.tofNSigmaDe() < TofPidNsigmaMin || track2.tofNSigmaDe() > TofPidNsigmaMax) && track2.p() > minDeuteronPUseTOF) { + if ((vtx.tofNSigmaBachDe() < TofPidNsigmaMin || vtx.tofNSigmaBachDe() > TofPidNsigmaMax) && track2.p() > minDeuteronPUseTOF) { continue; } if (std::abs(track0.tpcNSigmaPr()) < TpcPidNsigmaCut && std::abs(track1.tpcNSigmaPi()) < TpcPidNsigmaCut && std::abs(track2.tpcNSigmaDe()) < TpcPidNsigmaCut && vtx.mHypertriton() > h3LMassLowerlimit && vtx.mHypertriton() < h3LMassUpperlimit) { @@ -254,12 +272,12 @@ struct nucleiFilter { } } // end loop over hypertriton 3body decay candidates - for (int iDecision{0}; iDecision < nNuclei + nHyperNuclei; ++iDecision) { + for (int iDecision{0}; iDecision < nNuclei + nHyperNuclei + nITStriggers; ++iDecision) { if (keepEvent[iDecision]) { hProcessedEvents->Fill(iDecision + 1); } } - tags(keepEvent[2], keepEvent[3]); + tags(keepEvent[0], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5]); } }; diff --git a/EventFiltering/PWGLF/strangenessFilter.cxx b/EventFiltering/PWGLF/strangenessFilter.cxx index 106e0f90bb7..1f615a54706 100644 --- a/EventFiltering/PWGLF/strangenessFilter.cxx +++ b/EventFiltering/PWGLF/strangenessFilter.cxx @@ -68,7 +68,7 @@ struct strangenessFilter { HistogramRegistry QAHistosTriggerParticles{"QAHistosTriggerParticles", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry QAHistosStrangenessTracking{"QAHistosStrangenessTracking", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry EventsvsMultiplicity{"EventsvsMultiplicity", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - OutputObj hProcessedEvents{TH1D("hProcessedEvents", "Strangeness - event filtered;; Number of events", 14, -1., 13.)}; + OutputObj hProcessedEvents{TH1D("hProcessedEvents", "Strangeness - event filtered;; Number of events", 16, -1., 15.)}; OutputObj hCandidate{TH1F("hCandidate", "; Candidate pass selection; Number of events", 30, 0., 30.)}; OutputObj hEvtvshMinPt{TH1F("hEvtvshMinPt", " Number of h-Omega events with pT_h higher than thrd; min p_{T, trigg} (GeV/c); Number of events", 11, 0., 11.)}; OutputObj hhXiPairsvsPt{TH1F("hhXiPairsvsPt", "pt distributions of Xi in events with a trigger particle; #it{p}_{T} (GeV/c); Number of Xi", 100, 0., 10.)}; @@ -195,6 +195,8 @@ struct strangenessFilter { hProcessedEvents->GetXaxis()->SetBinLabel(12, aod::filtering::TrackedXi::columnLabel()); hProcessedEvents->GetXaxis()->SetBinLabel(13, aod::filtering::TrackedOmega::columnLabel()); hProcessedEvents->GetXaxis()->SetBinLabel(14, aod::filtering::OmegaHighMult::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(15, aod::filtering::DoubleOmega::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(16, aod::filtering::OmegaXi::columnLabel()); hCandidate->GetXaxis()->SetBinLabel(1, "All"); hCandidate->GetXaxis()->SetBinLabel(2, "Has_V0"); @@ -403,270 +405,17 @@ struct strangenessFilter { void fillTriggerTable(bool keepEvent[]) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9]); + strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9], keepEvent[10], keepEvent[11]); } - void processRun2(CollisionCandidates const& collision, TrackCandidates const& tracks, Cascades const& fullCasc, DaughterTracks& /*dtracks*/) - { - // Is event good? [0] = Omega, [1] = high-pT hadron + Xi, [2] = 2Xi, [3] = 3Xi, [4] = 4Xi, [5] single-Xi, [6] Omega with high radius - // [7] tracked Xi, [8] tracked Omega, [9] tracked V0, [10] tracked 3Body - bool keepEvent[9]{}; // explicitly zero-initialised - - if (kint7 && !collision.alias_bit(kINT7)) { - fillTriggerTable(keepEvent); - return; - } - if (sel7 && !collision.sel7()) { - fillTriggerTable(keepEvent); - return; - } - if (sel8 && !collision.sel8()) { - fillTriggerTable(keepEvent); - return; - } - if (TMath::Abs(collision.posZ()) > cutzvertex) { - fillTriggerTable(keepEvent); - return; - } - - if (doextraQA) { - EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicity"), collision.centRun2V0M()); - QAHistos.fill(HIST("hCentrality"), collision.centRun2V0M()); - } - hProcessedEvents->Fill(0.5); - - // constants - const float ctauxi = 4.91; // from PDG - const float ctauomega = 2.461; // from PDG - - // variables - float xipos = -1.; - float xiproperlifetime = -1.; - float omegaproperlifetime = -1.; - float xiptotmom = -1.; - int xicounter = 0; - int xicounterYN = 0; - int omegacounter = 0; - int omegalargeRcounter = 0; - int triggcounterForEstimates = 0; - // int triggcounter = 0; - - for (auto& casc : fullCasc) { // loop over cascades - triggcounterForEstimates = 0; - auto bachelor = casc.bachelor_as(); - auto posdau = casc.posTrack_as(); - auto negdau = casc.negTrack_as(); - - bool isXi = false; - bool isXiYN = false; - bool isOmega = false; - bool isOmegalargeR = false; - - // Position - xipos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); - // Total momentum - xiptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - // Proper lifetime - xiproperlifetime = o2::constants::physics::MassXiMinus * xipos / (xiptotmom + 1e-13); - omegaproperlifetime = o2::constants::physics::MassOmegaMinus * xipos / (xiptotmom + 1e-13); - - if (casc.sign() == 1) { - if (TMath::Abs(casc.dcapostopv()) < dcamesontopv) { - continue; - } - if (TMath::Abs(casc.dcanegtopv()) < dcabaryontopv) { - continue; - } - if (TMath::Abs(posdau.tpcNSigmaPi()) > nsigmatpcpi) { - continue; - } - if (TMath::Abs(negdau.tpcNSigmaPr()) > nsigmatpcpr) { - continue; - } - } else { - if (TMath::Abs(casc.dcanegtopv()) < dcamesontopv) { - continue; - } - if (TMath::Abs(casc.dcapostopv()) < dcabaryontopv) { - continue; - } - if (TMath::Abs(posdau.tpcNSigmaPr()) > nsigmatpcpr) { - continue; - } - if (TMath::Abs(negdau.tpcNSigmaPi()) > nsigmatpcpi) { - continue; - } - } - // these selection differ for Xi and Omegas: - if (TMath::Abs(posdau.eta()) > etadau) { - continue; - } - if (TMath::Abs(negdau.eta()) > etadau) { - continue; - } - if (TMath::Abs(bachelor.eta()) > etadau) { - continue; - } - if (TMath::Abs(casc.dcabachtopv()) < dcabachtopv) { - continue; - } - if (casc.v0radius() < v0radius) { - continue; - } - if (casc.cascradius() < cascradius) { - continue; - } - if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospa) { - continue; - } - if (casc.dcaV0daughters() > dcav0dau) { - continue; - } - if (casc.dcacascdaughters() > dcacascdau) { - continue; - } - if (TMath::Abs(casc.mLambda() - constants::physics::MassLambda) > masslambdalimit) { - continue; - } - if (TMath::Abs(casc.eta()) > eta) { - continue; - } - - isXi = (TMath::Abs(bachelor.tpcNSigmaPi()) < nsigmatpcpi) && - (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaxi) && - (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && - (TMath::Abs(casc.mXi() - o2::constants::physics::MassXiMinus) < ximasswindow) && - (TMath::Abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > omegarej) && - (xiproperlifetime < properlifetimefactor * ctauxi) && - (TMath::Abs(casc.yXi()) < rapidity); // add PID on bachelor - isXiYN = (TMath::Abs(bachelor.tpcNSigmaPi()) < nsigmatpcpi) && - (casc.cascradius() > lowerradiusXiYN) && - (TMath::Abs(casc.mXi() - o2::constants::physics::MassXiMinus) < ximasswindow) && - (TMath::Abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > omegarej) && - (xiproperlifetime < properlifetimefactor * ctauxi) && - (TMath::Abs(casc.yXi()) < rapidity); // add PID on bachelor - isOmega = (TMath::Abs(bachelor.tpcNSigmaKa()) < nsigmatpcka) && - (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaomega) && - (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && - (casc.cascradius() < upperradiusOmega) && - (TMath::Abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < omegamasswindow) && - (TMath::Abs(casc.mXi() - o2::constants::physics::MassXiMinus) > xirej) && - (omegaproperlifetime < properlifetimefactor * ctauomega) && - (TMath::Abs(casc.yOmega()) < rapidity); // add PID on bachelor - isOmegalargeR = (TMath::Abs(bachelor.tpcNSigmaKa()) < nsigmatpcka) && - (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaomega) && - (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && - (casc.cascradius() > lowerradiusOmega) && - (TMath::Abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < omegamasswindow) && - (TMath::Abs(casc.mXi() - o2::constants::physics::MassXiMinus) > xirej) && - (omegaproperlifetime < properlifetimefactor * ctauomega) && - (TMath::Abs(casc.yOmega()) < rapidity); // add PID on bachelor - - if (isXi) { - // Count number of Xi candidates - xicounter++; - - // Plot for estimates - if (tracks.size() > 0) - triggcounterForEstimates = 1; - if (triggcounterForEstimates && (TMath::Abs(casc.mXi() - o2::constants::physics::MassXiMinus) < 0.01)) - hhXiPairsvsPt->Fill(casc.pt()); // Fill the histogram with all the Xis produced in events with a trigger particle - // End plot for estimates - } - if (isXiYN) { - // Xis for YN interactions - xicounterYN++; - } - if (isOmega) { - // Count number of Omega candidates - omegacounter++; - } - if (isOmegalargeR) { - // Count number of Omega candidates with high radius - omegalargeRcounter++; - } - } // end loop over cascades - - // Omega trigger definition - if (omegacounter > 0) { - keepEvent[0] = true; - } - - // High-pT hadron + Xi trigger definition - if (xicounter > 0) { - for (auto track : tracks) { // start loop over tracks - if (isTrackFilter && !mTrackSelector.IsSelected(track)) { - continue; - } - // triggcounter++; - keepEvent[1] = true; - } // end loop over tracks - } - - // 2Xi trigger definition - if (xicounter > 1) { - keepEvent[2] = true; - } - - // 3Xi trigger definition - if (xicounter > 2) { - keepEvent[3] = true; - } - - // 4Xi trigger definition - if (xicounter > 3) { - keepEvent[4] = true; - } - - // Single-Xi (YN) trigger definition - if (xicounterYN > 0) { - keepEvent[5] = true; - } - - // Omega with high radius trigger definition - if (omegalargeRcounter > 0) { - keepEvent[6] = true; - } - - // Fill centrality dependent histos - if (keepEvent[0]) { - hProcessedEvents->Fill(2.5); - } - if (keepEvent[1]) { - hProcessedEvents->Fill(3.5); - } - if (keepEvent[2]) { - hProcessedEvents->Fill(4.5); - } - if (keepEvent[3]) { - hProcessedEvents->Fill(5.5); - } - if (keepEvent[4]) { - hProcessedEvents->Fill(6.5); - } - if (keepEvent[5]) { - hProcessedEvents->Fill(7.5); - } - if (keepEvent[6]) { - hProcessedEvents->Fill(8.5); - } - - // Filling the table - fillTriggerTable(keepEvent); - } - // - PROCESS_SWITCH(strangenessFilter, processRun2, "Process data Run2", true); - - ////////////////////////////////////////////////////// - ////////// Strangeness Filter - Run 3 MC ///////////// - ////////////////////////////////////////////////////// - - void processRun3(CollisionCandidatesRun3 const& collision, TrackCandidates const& tracks, Cascades const& fullCasc, DaughterTracks& /*dtracks*/, - aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& /*cascades*/, aod::AssignedTrackedV0s const& /*trackedV0s*/, aod::AssignedTracked3Bodys const& /*tracked3Bodys*/, aod::V0s const&, aod::BCsWithTimestamps const&) + void process(CollisionCandidatesRun3 const& collision, TrackCandidates const& tracks, Cascades const& fullCasc, DaughterTracks& /*dtracks*/, + aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& /*cascades*/, aod::AssignedTrackedV0s const& /*trackedV0s*/, aod::AssignedTracked3Bodys const& /*tracked3Bodys*/, aod::V0s const&, aod::BCsWithTimestamps const&) { // Is event good? [0] = Omega, [1] = high-pT hadron + Omega, [2] = 2Xi, [3] = 3Xi, [4] = 4Xi, [5] single-Xi, [6] Omega with high radius // [7] tracked Xi, [8] tracked Omega, [9] Omega + high mult event - bool keepEvent[10]{}; // explicitly zero-initialised + bool keepEvent[12]{}; // explicitly zero-initialised + std::vector> v0sFromOmegaID; + std::vector> v0sFromXiID; if (sel8 && !collision.sel8()) { fillTriggerTable(keepEvent); @@ -910,6 +659,7 @@ struct strangenessFilter { // Count number of Xi candidates xicounter++; + v0sFromXiID.push_back({casc.posTrackId(), casc.negTrackId()}); // Plot for estimates for (auto track : tracks) { // start loop over tracks @@ -968,6 +718,7 @@ struct strangenessFilter { // Count number of Omega candidates omegacounter++; + v0sFromOmegaID.push_back({casc.posTrackId(), casc.negTrackId()}); } if (isOmegalargeR) { omegalargeRcounter++; @@ -1044,19 +795,43 @@ struct strangenessFilter { hEvtvshMinPt->Fill(i + 0.5); } - // 2Xi trigger definition - if (xicounter > 1) { - keepEvent[2] = true; + // Double/triple/quad Xi trigger definition + if (v0sFromXiID.size() > 0) { + std::set> uniqueXis = {v0sFromXiID.begin(), v0sFromXiID.end()}; + if (uniqueXis.size() > 1) { + keepEvent[2] = true; + } + if (uniqueXis.size() > 2) { + keepEvent[3] = true; + } + if (uniqueXis.size() > 3) { + keepEvent[4] = true; + } } - // 3Xi trigger definition - if (xicounter > 2) { - keepEvent[3] = true; + // Double Omega trigger definition + if (v0sFromOmegaID.size() > 0) { + std::set> uniqueOmegas = {v0sFromOmegaID.begin(), v0sFromOmegaID.end()}; + if (uniqueOmegas.size() > 1) { + keepEvent[10] = true; + } } - // 4Xi trigger definition - if (xicounter > 3) { - keepEvent[4] = true; + // Omega + Xi trigger definition + if (v0sFromOmegaID.size() > 0 && v0sFromXiID.size() > 0) { + std::set> uniqueOmegas = {v0sFromOmegaID.begin(), v0sFromOmegaID.end()}; + std::set> uniqueXis = {v0sFromXiID.begin(), v0sFromXiID.end()}; + if (uniqueOmegas.size() > 1 || uniqueXis.size() > 1) { + keepEvent[11] = true; + } else { + // keep only if there is at least one non-overlapping v0 + for (auto v0Omega : uniqueOmegas) { + if (uniqueXis.find(v0Omega) == uniqueXis.end()) { + keepEvent[11] = true; + break; + } + } + } } // Single-Xi (YN) trigger definition @@ -1292,12 +1067,16 @@ struct strangenessFilter { if (keepEvent[9]) { hProcessedEvents->Fill(12.5); } + if (keepEvent[10]) { + hProcessedEvents->Fill(13.5); + } + if (keepEvent[11]) { + hProcessedEvents->Fill(14.5); + } // Filling the table fillTriggerTable(keepEvent); } - // - PROCESS_SWITCH(strangenessFilter, processRun3, "Process Run3", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/EventFiltering/PWGUD/diffractionFilter.cxx b/EventFiltering/PWGUD/diffractionFilter.cxx index 4ea29ab18a0..c5adfcf90c5 100644 --- a/EventFiltering/PWGUD/diffractionFilter.cxx +++ b/EventFiltering/PWGUD/diffractionFilter.cxx @@ -132,11 +132,16 @@ struct DGFilterRun3 { // using MFs = aod::MFTTracks; using FWs = aod::FwdTracks; + // filter for global tracks + Filter globalTrackFilter = requireGlobalTrackInFilter(); + using globalTracks = soa::Filtered; + void process(CC const& collision, BCs const& bcs, TCs& tracks, // MFs& mfttracks, FWs& fwdtracks, + globalTracks& goodTracks, aod::Zdcs& /*zdcs*/, aod::FT0s& /*ft0s*/, aod::FV0As& /*fv0as*/, @@ -162,6 +167,7 @@ struct DGFilterRun3 { // apply DG selection auto isDGEvent = dgSelector.IsSelected(diffCuts, collision, bcRange, tracks, fwdtracks); + LOGF(debug, "isDGEvent %d", isDGEvent); // update after cut histogram registry.fill(HIST("stat/aftercuts"), isDGEvent + 2); @@ -226,8 +232,9 @@ struct DGFilterRun3 { // collisions registry.fill(HIST("collisions/tracksAll"), tracks.size()); registry.fill(HIST("collisions/PVTracksAll"), collision.numContrib()); - Partition goodTracks = requireGlobalTrackInFilter(); - goodTracks.bindTable(tracks); + // Partition goodTracks = requireGlobalTrackInFilter(); + // goodTracks.bindTable(tracks); + // LOGF(info, "# good tracks %d", goodTracks.size()); registry.get(HIST("collisions/globalTracksAll"))->Fill(goodTracks.size()); auto netCharge = udhelpers::netCharge(tracks); registry.fill(HIST("collisions/netChargeAll"), collision.numContrib(), netCharge); diff --git a/EventFiltering/Zorro.cxx b/EventFiltering/Zorro.cxx index bd5f10423b6..027861009d3 100644 --- a/EventFiltering/Zorro.cxx +++ b/EventFiltering/Zorro.cxx @@ -12,15 +12,86 @@ #include "Zorro.h" +#include #include -#include "TH1D.h" +#include #include "CCDB/BasicCCDBManager.h" #include "CommonDataFormat/InteractionRecord.h" using o2::InteractionRecord; +namespace +{ +int findBin(TH1* hist, const std::string& label) +{ // Find bin by label, avoiding the axis extention from the native ROOT implementation + for (int iBin{1}; iBin <= hist->GetNbinsX(); ++iBin) { + if (label == hist->GetXaxis()->GetBinLabel(iBin)) { + return iBin; + } + } + return -1; +} +} // namespace + +void Zorro::populateHistRegistry(o2::framework::HistogramRegistry& histRegistry, int runNumber, std::string folderName) +{ + int runId{-1}; + for (size_t i{0}; i < mRunNumberHistos.size(); ++i) { + if (mRunNumberHistos[i] == runNumber) { + runId = i; + break; + } + } + if (runId > -1) { + /// Support jobs running on non-continuous run numbers + mAnalysedTriggers = mAnalysedTriggersList[runId]; + mAnalysedTriggersOfInterest = mAnalysedTriggersOfInterestList[runId]; + return; + } + if (mSelections) { + mAnalysedTriggers = histRegistry.add((folderName + "/" + std::to_string(runNumber) + "/" + "AnalysedTriggers").data(), "", o2::framework::HistType::kTH1D, {{mSelections->GetNbinsX() - 2, -0.5, mSelections->GetNbinsX() - 2.5}}).get(); + for (int iBin{2}; iBin < mSelections->GetNbinsX(); ++iBin) { // Exclude first and last bins as they are total number of analysed and selected events, respectively + mAnalysedTriggers->GetXaxis()->SetBinLabel(iBin - 1, mSelections->GetXaxis()->GetBinLabel(iBin)); + } + std::shared_ptr selections = histRegistry.add((folderName + "/" + std::to_string(runNumber) + "/" + "Selections").data(), "", o2::framework::HistType::kTH1D, {{mSelections->GetNbinsX(), -0.5, static_cast(mSelections->GetNbinsX() - 0.5)}}); + selections->SetBit(TH1::kIsAverage); + for (int iBin{1}; iBin <= mSelections->GetNbinsX(); ++iBin) { + selections->GetXaxis()->SetBinLabel(iBin, mSelections->GetXaxis()->GetBinLabel(iBin)); + selections->SetBinContent(iBin, mSelections->GetBinContent(iBin)); + selections->SetBinError(iBin, mSelections->GetBinError(iBin)); + } + } + if (mScalers) { + std::shared_ptr scalers = histRegistry.add((folderName + "/" + std::to_string(runNumber) + "/" + "Scalers").data(), "", o2::framework::HistType::kTH1D, {{mScalers->GetNbinsX(), -0.5, static_cast(mScalers->GetNbinsX() - 0.5)}}); + scalers->SetBit(TH1::kIsAverage); + for (int iBin{1}; iBin <= mScalers->GetNbinsX(); ++iBin) { + scalers->GetXaxis()->SetBinLabel(iBin, mScalers->GetXaxis()->GetBinLabel(iBin)); + scalers->SetBinContent(iBin, mScalers->GetBinContent(iBin)); + scalers->SetBinError(iBin, mScalers->GetBinError(iBin)); + } + } + if (mInspectedTVX) { + std::shared_ptr inspectedTVX = histRegistry.add((folderName + "/" + std::to_string(runNumber) + "/" + "InspectedTVX").data(), "", o2::framework::HistType::kTH1D, {{mInspectedTVX->GetNbinsX(), -0.5, static_cast(mInspectedTVX->GetNbinsX() - 0.5)}}); + inspectedTVX->SetBit(TH1::kIsAverage); + for (int iBin{1}; iBin <= mInspectedTVX->GetNbinsX(); ++iBin) { + inspectedTVX->GetXaxis()->SetBinLabel(iBin, mInspectedTVX->GetXaxis()->GetBinLabel(iBin)); + inspectedTVX->SetBinContent(iBin, mInspectedTVX->GetBinContent(iBin)); + inspectedTVX->SetBinError(iBin, mInspectedTVX->GetBinError(iBin)); + } + } + if (mTOIs.size()) { + mAnalysedTriggersOfInterest = histRegistry.add((folderName + "/" + std::to_string(runNumber) + "/" + "AnalysedTriggersOfInterest").data(), "", o2::framework::HistType::kTH1D, {{static_cast(mTOIs.size()), -0.5, static_cast(mTOIs.size() - 0.5)}}).get(); + for (size_t i{0}; i < mTOIs.size(); ++i) { + mAnalysedTriggersOfInterest->GetXaxis()->SetBinLabel(i + 1, mTOIs[i].data()); + } + } + mAnalysedTriggersList.push_back(mAnalysedTriggers); + mAnalysedTriggersOfInterestList.push_back(mAnalysedTriggersOfInterest); + mRunNumberHistos.push_back(runNumber); +} + std::vector Zorro::initCCDB(o2::ccdb::BasicCCDBManager* ccdb, int runNumber, uint64_t timestamp, std::string tois, int bcRange) { if (mRunNumber == runNumber) { @@ -34,67 +105,119 @@ std::vector Zorro::initCCDB(o2::ccdb::BasicCCDBManager* ccdb, int runNumber mScalers = mCCDB->getSpecific(mBaseCCDBPath + "FilterCounters", timestamp, metadata); mSelections = mCCDB->getSpecific(mBaseCCDBPath + "SelectionCounters", timestamp, metadata); mInspectedTVX = mCCDB->getSpecific(mBaseCCDBPath + "InspectedTVX", timestamp, metadata); - auto selectedBCs = mCCDB->getSpecific>>(mBaseCCDBPath + "SelectedBCs", timestamp, metadata); + mZorroHelpers = mCCDB->getSpecific>(mBaseCCDBPath + "ZorroHelpers", timestamp, metadata); + std::sort(mZorroHelpers->begin(), mZorroHelpers->end(), [](const auto& a, const auto& b) { return std::min(a.bcAOD, a.bcEvSel) < std::min(b.bcAOD, b.bcEvSel); }); mBCranges.clear(); - for (auto bc : *selectedBCs) { - mBCranges.emplace_back(InteractionRecord::long2IR(std::min(bc[0], bc[1])), InteractionRecord::long2IR(std::max(bc[0], bc[1]))); + mAccountedBCranges.clear(); + for (auto helper : *mZorroHelpers) { + mBCranges.emplace_back(InteractionRecord::long2IR(std::min(helper.bcAOD, helper.bcEvSel)), InteractionRecord::long2IR(std::max(helper.bcAOD, helper.bcEvSel))); } - std::sort(mBCranges.begin(), mBCranges.end(), [](const auto& a, const auto& b) { return a.getMin() < b.getMin(); }); - - mSelectionBitMask = mCCDB->getSpecific>>(mBaseCCDBPath + "SelectionBitMask", timestamp, metadata); - mFilterBitMask = mCCDB->getSpecific>>(mBaseCCDBPath + "FilterBitMask", timestamp, metadata); + mAccountedBCranges.resize(mBCranges.size(), false); mLastBCglobalId = 0; mLastSelectedIdx = 0; mTOIs.clear(); mTOIidx.clear(); - size_t pos = 0; - while ((pos = tois.find(",")) != std::string::npos) { + while (!tois.empty()) { + size_t pos = tois.find(","); + pos = (pos == std::string::npos) ? tois.size() : pos; std::string token = tois.substr(0, pos); // Trim leading and trailing whitespaces from the token token.erase(0, token.find_first_not_of(" ")); token.erase(token.find_last_not_of(" ") + 1); - int bin = mScalers->GetXaxis()->FindBin(token.c_str()) - 2; + int bin = findBin(mSelections, token) - 2; mTOIs.push_back(token); mTOIidx.push_back(bin); - tois.erase(0, pos + 1); + tois = tois.erase(0, pos + 1); } mTOIcounts.resize(mTOIs.size(), 0); + LOGF(info, "Zorro initialized for run %d, triggers of interest:", runNumber); + for (size_t i{0}; i < mTOIs.size(); ++i) { + LOGF(info, ">>> %s : %i", mTOIs[i].data(), mTOIidx[i]); + } + mZorroSummary.setupTOIs(mTOIs.size(), tois); + std::vector toiCounters(mTOIs.size(), 0.); + for (size_t i{0}; i < mTOIs.size(); ++i) { + toiCounters[i] = mSelections->GetBinContent(mTOIidx[i] + 2); + } + mZorroSummary.setupRun(runNumber, mInspectedTVX->GetBinContent(1), toiCounters); + return mTOIidx; } std::bitset<128> Zorro::fetch(uint64_t bcGlobalId, uint64_t tolerance) { - std::bitset<128> result; + mLastResult.reset(); o2::dataformats::IRFrame bcFrame{InteractionRecord::long2IR(bcGlobalId) - tolerance, InteractionRecord::long2IR(bcGlobalId) + tolerance}; - if (bcGlobalId < mLastBCglobalId) { + if (bcGlobalId < mLastBCglobalId) { /// Handle the possible discontinuity in the BC processed by the analyses mLastSelectedIdx = 0; } + uint64_t lastSelectedIdx = mLastSelectedIdx; + mLastBCglobalId = bcGlobalId; for (size_t i = mLastSelectedIdx; i < mBCranges.size(); i++) { - if (!bcFrame.getOverlap(mBCranges[i]).isZeroLength()) { + if (!mBCranges[i].isOutside(bcFrame)) { for (int iMask{0}; iMask < 2; ++iMask) { for (int iTOI{0}; iTOI < 64; ++iTOI) { - result.set(iMask * 64 + iTOI, mFilterBitMask->at(i)[iMask] & (1ull << iTOI)); + if (mZorroHelpers->at(i).selMask[iMask] & (1ull << iTOI)) { + mLastResult.set(iMask * 64 + iTOI, 1); + if (mAnalysedTriggers && !mAccountedBCranges[i]) { + mAnalysedTriggers->Fill(iMask * 64 + iTOI); + } + } } } + mAccountedBCranges[i] = true; + mLastSelectedIdx = mLastSelectedIdx == lastSelectedIdx-- ? i : mLastSelectedIdx; /// Decrease lastSelectedIdx to make sure this check is valid only in its first instance + } else if (mBCranges[i].getMax() < bcFrame.getMin()) { mLastSelectedIdx = i; - return result; + } else if (mBCranges[i].getMin() > bcFrame.getMax()) { + break; } } - return result; + return mLastResult; } bool Zorro::isSelected(uint64_t bcGlobalId, uint64_t tolerance) { - int lastSelectedIdx = mLastSelectedIdx; - std::bitset<128> result = fetch(bcGlobalId, tolerance); + uint64_t lastSelectedIdx = mLastSelectedIdx; + fetch(bcGlobalId, tolerance); + bool retVal{false}; for (size_t i{0}; i < mTOIidx.size(); ++i) { if (mTOIidx[i] < 0) { continue; - } else if (result.test(mTOIidx[i])) { + } else if (mLastResult.test(mTOIidx[i])) { mTOIcounts[i] += (lastSelectedIdx != mLastSelectedIdx); /// Avoid double counting - return true; + if (mAnalysedTriggersOfInterest && lastSelectedIdx != mLastSelectedIdx) { + mAnalysedTriggersOfInterest->Fill(i); + mZorroSummary.increaseTOIcounter(mRunNumber, i); + } + retVal = true; + } + } + return retVal; +} + +std::vector Zorro::getTriggerOfInterestResults(uint64_t bcGlobalId, uint64_t tolerance) +{ + fetch(bcGlobalId, tolerance); + return getTriggerOfInterestResults(); +} + +std::vector Zorro::getTriggerOfInterestResults() const +{ + std::vector results(mTOIidx.size(), false); + for (size_t i{0}; i < mTOIidx.size(); ++i) { + if (mTOIidx[i] < 0) { + continue; + } else if (mLastResult.test(mTOIidx[i])) { + results[i] = true; } } - return false; -} \ No newline at end of file + return results; +} + +bool Zorro::isNotSelectedByAny(uint64_t bcGlobalId, uint64_t tolerance) +{ + fetch(bcGlobalId, tolerance); + return mLastResult.none(); +} diff --git a/EventFiltering/Zorro.h b/EventFiltering/Zorro.h index 6cde3d44aa3..5043eec232c 100644 --- a/EventFiltering/Zorro.h +++ b/EventFiltering/Zorro.h @@ -15,12 +15,16 @@ #define EVENTFILTERING_ZORRO_H_ #include +#include #include #include +#include "TH1D.h" #include "CommonDataFormat/IRFrame.h" +#include "Framework/HistogramRegistry.h" +#include "ZorroHelper.h" +#include "ZorroSummary.h" -class TH1D; namespace o2 { namespace ccdb @@ -36,29 +40,50 @@ class Zorro std::vector initCCDB(o2::ccdb::BasicCCDBManager* ccdb, int runNumber, uint64_t timestamp, std::string tois, int bcTolerance = 500); std::bitset<128> fetch(uint64_t bcGlobalId, uint64_t tolerance = 100); bool isSelected(uint64_t bcGlobalId, uint64_t tolerance = 100); + bool isNotSelectedByAny(uint64_t bcGlobalId, uint64_t tolerance = 100); + void populateHistRegistry(o2::framework::HistogramRegistry& histRegistry, int runNumber, std::string folderName = "Zorro"); + + TH1D* getScalers() const { return mScalers; } + TH1D* getSelections() const { return mSelections; } + TH1D* getInspectedTVX() const { return mInspectedTVX; } + std::bitset<128> getLastResult() const { return mLastResult; } std::vector getTOIcounters() const { return mTOIcounts; } + std::vector getTriggerOfInterestResults(uint64_t bcGlobalId, uint64_t tolerance = 100); + std::vector getTriggerOfInterestResults() const; void setCCDBpath(std::string path) { mBaseCCDBPath = path; } void setBaseCCDBPath(std::string path) { mBaseCCDBPath = path; } void setBCtolerance(int tolerance) { mBCtolerance = tolerance; } + ZorroSummary* getZorroSummary() { return &mZorroSummary; } + private: + ZorroSummary mZorroSummary{"ZorroSummary", "ZorroSummary"}; + std::string mBaseCCDBPath = "Users/m/mpuccio/EventFiltering/OTS/"; int mRunNumber = 0; + TH1* mAnalysedTriggers; /// Accounting for all triggers in the current run + TH1* mAnalysedTriggersOfInterest; /// Accounting for triggers of interest in the current run + + std::vector mRunNumberHistos; + std::vector mAnalysedTriggersList; /// Per run histograms + std::vector mAnalysedTriggersOfInterestList; /// Per run histograms + int mBCtolerance = 100; uint64_t mLastBCglobalId = 0; uint64_t mLastSelectedIdx = 0; TH1D* mScalers = nullptr; TH1D* mSelections = nullptr; TH1D* mInspectedTVX = nullptr; + std::bitset<128> mLastResult; + std::vector mAccountedBCranges; /// Avoid double accounting of inspected BC ranges std::vector mBCranges; - std::vector>* mFilterBitMask = nullptr; - std::vector>* mSelectionBitMask = nullptr; + std::vector* mZorroHelpers = nullptr; std::vector mTOIs; std::vector mTOIidx; std::vector mTOIcounts; o2::ccdb::BasicCCDBManager* mCCDB = nullptr; }; -#endif // EVENTFILTERING_ZORRO_H_ \ No newline at end of file +#endif // EVENTFILTERING_ZORRO_H_ diff --git a/EventFiltering/ZorroHelper.h b/EventFiltering/ZorroHelper.h new file mode 100644 index 00000000000..8bcc6240bc0 --- /dev/null +++ b/EventFiltering/ZorroHelper.h @@ -0,0 +1,23 @@ +// Copyright 2019-2020 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. +// + +#ifndef EVENTFILTERING_ZORROHELPER_H_ +#define EVENTFILTERING_ZORROHELPER_H_ + +#include "Rtypes.h" + +struct ZorroHelper { + ULong64_t bcAOD, bcEvSel, trigMask[2], selMask[2]; + ClassDefNV(ZorroHelper, 1); +}; + +#endif // EVENTFILTERING_ZORROHELPER_H_ diff --git a/EventFiltering/ZorroSummary.cxx b/EventFiltering/ZorroSummary.cxx new file mode 100644 index 00000000000..ee241f49108 --- /dev/null +++ b/EventFiltering/ZorroSummary.cxx @@ -0,0 +1,69 @@ +// Copyright 2019-2020 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. + +#include "ZorroSummary.h" + +#include "TCollection.h" + +void ZorroSummary::Copy(TObject& c) const +{ + static_cast(c) = *this; +} + +Long64_t ZorroSummary::Merge(TCollection* list) +{ + if (!list) { + return 0; + } + int n = 1; + if (list->IsEmpty()) { + return n; + } + + for (auto* obj : *list) { + auto* entry = dynamic_cast(obj); + if (!entry || entry->getTOInames() != mTOInames) { + continue; + } + n++; + auto& analysedToiCounters = entry->getAnalysedTOIcounters(); + for (const auto& [runNumber, currentAnalysedToiCounters] : analysedToiCounters) { + if (mAnalysedTOIcounters.find(runNumber) == mAnalysedTOIcounters.end()) { + mAnalysedTOIcounters[runNumber] = currentAnalysedToiCounters; + mTVXcounters[runNumber] = entry->getTVXcounters().at(runNumber); + mTOIcounters[runNumber] = entry->getTOIcounters().at(runNumber); + } else { + auto& thisCounters = mAnalysedTOIcounters[runNumber]; + for (size_t i = 0; i < thisCounters.size(); ++i) { + thisCounters[i] += currentAnalysedToiCounters[i]; + } + } + } + } + return n; +} + +double ZorroSummary::getNormalisationFactor(int toiId) const +{ + double totalTOI{0.}, totalTVX{0.}; + ULong64_t totalAnalysedTOI{0}; + for (const auto& [runNumber, toiCounters] : mTOIcounters) { + totalTOI += toiCounters.at(toiId); + } + for (const auto& [runNumber, tvxCounters] : mTVXcounters) { + totalTVX += tvxCounters; + } + for (const auto& [runNumber, analysedTOIcounters] : mAnalysedTOIcounters) { + totalAnalysedTOI += analysedTOIcounters.at(toiId); + } + + return totalTVX * totalAnalysedTOI / totalTOI; +} \ No newline at end of file diff --git a/EventFiltering/ZorroSummary.h b/EventFiltering/ZorroSummary.h new file mode 100644 index 00000000000..b4d401adba4 --- /dev/null +++ b/EventFiltering/ZorroSummary.h @@ -0,0 +1,76 @@ +// Copyright 2019-2020 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. +// + +#ifndef EVENTFILTERING_ZORROSUMMARY_H_ +#define EVENTFILTERING_ZORROSUMMARY_H_ + +#include + +#include +#include +#include + +class ZorroSummary : public TNamed +{ + public: + ZorroSummary() = default; + ZorroSummary(const char* name, const char* objTitle) : TNamed(name, objTitle) {} + virtual ~ZorroSummary() = default; // NOLINT: Making this override breaks compilation for unknown reason + virtual void Copy(TObject& c) const; // NOLINT: Making this override breaks compilation for unknown reason + virtual Long64_t Merge(TCollection* list); + + void setupTOIs(int ntois, const std::string& toinames) + { + mNtois = ntois; + mTOInames = toinames; + } + void setupRun(int runNumber, double tvxCountes, const std::vector& toiCounters) + { + if (mRunNumber == runNumber) { + return; + } + mRunNumber = runNumber; + mTVXcounters[runNumber] = tvxCountes; + mTOIcounters[runNumber] = toiCounters; + if (mAnalysedTOIcounters.find(runNumber) == mAnalysedTOIcounters.end()) { + mAnalysedTOIcounters[runNumber] = std::vector(mNtois, 0ull); + } + mCurrentAnalysedTOIcounters = &mAnalysedTOIcounters[runNumber]; + } + double getNormalisationFactor(int toiId) const; + void increaseTOIcounter(int runNumber, int toiId) + { + if (runNumber != mRunNumber) { + return; + } + mCurrentAnalysedTOIcounters->at(toiId)++; + } + + std::string getTOInames() const { return mTOInames; } + const auto& getTOIcounters() const { return mTOIcounters; } + const auto& getTVXcounters() const { return mTVXcounters; } + const auto& getAnalysedTOIcounters() const { return mAnalysedTOIcounters; } + + private: + int mRunNumber = 0; //! Run currently being analysed + std::vector* mCurrentAnalysedTOIcounters = nullptr; //! Analysed TOI counters for the current run + + int mNtois = 0; + std::string mTOInames; + std::unordered_map> mAnalysedTOIcounters; + std::unordered_map> mTOIcounters; + std::unordered_map mTVXcounters; + + ClassDef(ZorroSummary, 1); +}; + +#endif // EVENTFILTERING_ZORROSUMMARY_H_ \ No newline at end of file diff --git a/EventFiltering/cefpTask.cxx b/EventFiltering/cefpTask.cxx index 833634740a4..92d0ed8f6bc 100644 --- a/EventFiltering/cefpTask.cxx +++ b/EventFiltering/cefpTask.cxx @@ -213,6 +213,8 @@ struct centralEventFilterTask { HistogramRegistry scalers{"scalers", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Produces tags; + Configurable cfgDisableDownscalings{"cfgDisableDownscalings", false, "Disable downscalings"}; + FILTER_CONFIGURABLE(F1ProtonFilters); FILTER_CONFIGURABLE(NucleiFilters); FILTER_CONFIGURABLE(DiffractionFilters); @@ -261,6 +263,9 @@ struct centralEventFilterTask { col.second = filterOpt.get(col.first.data(), 0u); } } + if (cfgDisableDownscalings.value) { + LOG(info) << "Downscalings are disabled for all channels."; + } } void run(ProcessingContext& pc) @@ -327,7 +332,7 @@ struct centralEventFilterTask { uint64_t decisionBin{(bin - 2) / 64}; uint64_t triggerBit{BIT((bin - 2) % 64)}; auto column{tablePtr->GetColumnByName(colName.first)}; - double downscaling{colName.second}; + double downscaling{cfgDisableDownscalings.value ? 1. : colName.second}; if (column) { int entry = 0; for (int64_t iC{0}; iC < column->num_chunks(); ++iC) { @@ -358,7 +363,7 @@ struct centralEventFilterTask { if (!(outTrigger[iE][iD] & BIT(iB))) { continue; } - for (int jD{0}; jD < outTrigger[0].size(); ++jD) { + for (uint64_t jD{0}; jD < outTrigger[0].size(); ++jD) { for (int iC{iB}; iC < 64; ++iC) { if (outTrigger[iE][iD] & BIT(iC)) { mCovariance->Fill(iD * 64 + iB, jD * 64 + iC); diff --git a/EventFiltering/filterTables.h b/EventFiltering/filterTables.h index bfdf9b1dd3d..6020a9521b5 100644 --- a/EventFiltering/filterTables.h +++ b/EventFiltering/filterTables.h @@ -21,8 +21,11 @@ namespace o2::aod { namespace filtering { -DECLARE_SOA_COLUMN(He, hasHe, bool); //! +DECLARE_SOA_COLUMN(H2, hasH2, bool); //! deuteron trigger for the helium normalisation (to be downscaled) +DECLARE_SOA_COLUMN(He, hasHe, bool); //! helium DECLARE_SOA_COLUMN(H3L3Body, hasH3L3Body, bool); //! hypertriton 3body +DECLARE_SOA_COLUMN(ITSextremeIonisation, hasITSextremeIonisation, bool); //! ITS extreme ionisation +DECLARE_SOA_COLUMN(ITSmildIonisation, hasITSmildIonisation, bool); //! ITS mild ionisation (normalisation of the extreme ionisation), to be downscaled // diffraction DECLARE_SOA_COLUMN(UDdiffSmall, hasDiffSmall, bool); //! Double Gap events, <= 3 prongs @@ -57,16 +60,21 @@ DECLARE_SOA_COLUMN(HfSigmaCPPK, hasHfSigmaCPPK, bool); //! SigmaC( DECLARE_SOA_COLUMN(HfSigmaC0K0, hasHfSigmaC0K0, bool); //! SigmaC(2455)0KS0 and SigmaC(2520)0KS0 DECLARE_SOA_COLUMN(HfPhotonCharm2P, hasHfPhotonCharm2P, bool); //! photon with 2-prong charm hadron DECLARE_SOA_COLUMN(HfPhotonCharm3P, hasHfPhotonCharm3P, bool); //! photon with 3-prong charm hadron +DECLARE_SOA_COLUMN(HfSingleCharm2P, hasHfSingleCharm2P, bool); //! 2-prong charm hadron (for efficiency studies) +DECLARE_SOA_COLUMN(HfSingleCharm3P, hasHfSingleCharm3P, bool); //! 3-prong charm hadron (for efficiency studies) +DECLARE_SOA_COLUMN(HfSingleNonPromptCharm2P, hasHfSingleNonPromptCharm2P, bool); //! 2-prong charm hadron (for efficiency studies) +DECLARE_SOA_COLUMN(HfSingleNonPromptCharm3P, hasHfSingleNonPromptCharm3P, bool); //! 3-prong charm hadron (for efficiency studies) // CF two body triggers DECLARE_SOA_COLUMN(PD, hasPD, bool); //! has d-p pair DECLARE_SOA_COLUMN(LD, hasLD, bool); //! has l-d pair // CF three body triggers -DECLARE_SOA_COLUMN(PPP, hasPPP, bool); //! has p-p-p triplet -DECLARE_SOA_COLUMN(PPL, hasPPL, bool); //! has p-p-L triplet -DECLARE_SOA_COLUMN(PLL, hasPLL, bool); //! has p-L-L triplet -DECLARE_SOA_COLUMN(LLL, hasLLL, bool); //! has L-L-L tripletD +DECLARE_SOA_COLUMN(PPP, hasPPP, bool); //! has p-p-p triplet +DECLARE_SOA_COLUMN(PPL, hasPPL, bool); //! has p-p-L triplet +DECLARE_SOA_COLUMN(PLL, hasPLL, bool); //! has p-L-L triplet +DECLARE_SOA_COLUMN(LLL, hasLLL, bool); //! has L-L-L tripletD +DECLARE_SOA_COLUMN(PPPHI, hasPPPHI, bool); //! has P-P-PHI triplet // jets DECLARE_SOA_COLUMN(JetChLowPt, hasJetChLowPt, bool); //! low-pT charged jet @@ -101,6 +109,8 @@ DECLARE_SOA_COLUMN(hadronOmega, hashadronOmega, bool); //! at least 1 DECLARE_SOA_COLUMN(DoubleXi, hasDoubleXi, bool); //! at least 2 Xi DECLARE_SOA_COLUMN(TripleXi, hasTripleXi, bool); //! at least 3 Xi DECLARE_SOA_COLUMN(QuadrupleXi, hasQuadrupleXi, bool); //! at least 4 Xi +DECLARE_SOA_COLUMN(DoubleOmega, hasDoubleOmega, bool); //! at least 2 Omega +DECLARE_SOA_COLUMN(OmegaXi, hasOmegaXi, bool); //! at least 1 Omega + 1 Xi DECLARE_SOA_COLUMN(SingleXiYN, hasSingleXiYN, bool); //! at least 1 Xi with high radius (YN interactions) DECLARE_SOA_COLUMN(OmegaLargeRadius, hasOmegaLargeRadius, bool); //! at least 1 Omega with high radius DECLARE_SOA_COLUMN(TrackedCascade, hasTrackedCascade, bool); //! at least 1 tracked cascade @@ -157,7 +167,8 @@ DECLARE_SOA_COLUMN(BCend, hasBCend, uint64_t); //! CEFP bcrange // nuclei DECLARE_SOA_TABLE(NucleiFilters, "AOD", "NucleiFilters", //! - filtering::He, filtering::H3L3Body); + filtering::H2, filtering::He, filtering::H3L3Body, filtering::ITSmildIonisation, + filtering::ITSextremeIonisation); using NucleiFilter = NucleiFilters::iterator; // diffraction @@ -176,12 +187,31 @@ using DqFilter = DqFilters::iterator; // heavy flavours DECLARE_SOA_TABLE(HfFilters, "AOD", "HfFilters", //! - filtering::HfHighPt2P, filtering::HfHighPt3P, filtering::HfBeauty3P, filtering::HfBeauty4P, filtering::HfFemto2P, filtering::HfFemto3P, filtering::HfDoubleCharm2P, filtering::HfDoubleCharm3P, filtering::HfDoubleCharmMix, filtering::HfV0Charm2P, filtering::HfV0Charm3P, filtering::HfCharmBarToXiBach, filtering::HfSigmaCPPK, filtering::HfSigmaC0K0, filtering::HfPhotonCharm2P, filtering::HfPhotonCharm3P); + filtering::HfHighPt2P, + filtering::HfHighPt3P, + filtering::HfBeauty3P, + filtering::HfBeauty4P, + filtering::HfFemto2P, + filtering::HfFemto3P, + filtering::HfDoubleCharm2P, + filtering::HfDoubleCharm3P, + filtering::HfDoubleCharmMix, + filtering::HfV0Charm2P, + filtering::HfV0Charm3P, + filtering::HfCharmBarToXiBach, + filtering::HfSigmaCPPK, + filtering::HfSigmaC0K0, + filtering::HfPhotonCharm2P, + filtering::HfPhotonCharm3P, + filtering::HfSingleCharm2P, + filtering::HfSingleCharm3P, + filtering::HfSingleNonPromptCharm2P, + filtering::HfSingleNonPromptCharm3P); using HfFilter = HfFilters::iterator; DECLARE_SOA_TABLE(CFFilters, "AOD", "CFFilters", //! - filtering::PPP, filtering::PPL, filtering::PLL, filtering::LLL, filtering::PD, filtering::LD); + filtering::PPP, filtering::PPL, filtering::PLL, filtering::LLL, filtering::PPPHI, filtering::PD, filtering::LD); using CfFilter = CFFilters::iterator; // jets @@ -208,7 +238,7 @@ using FullJetFilter = FullJetFilters::iterator; // strangeness (lf) DECLARE_SOA_TABLE(StrangenessFilters, "AOD", "LFStrgFilters", //! - filtering::Omega, filtering::hadronOmega, filtering::DoubleXi, filtering::TripleXi, filtering::QuadrupleXi, filtering::SingleXiYN, filtering::OmegaLargeRadius, filtering::TrackedXi, filtering::TrackedOmega, filtering::OmegaHighMult); + filtering::Omega, filtering::hadronOmega, filtering::DoubleXi, filtering::TripleXi, filtering::QuadrupleXi, filtering::SingleXiYN, filtering::OmegaLargeRadius, filtering::TrackedXi, filtering::TrackedOmega, filtering::OmegaHighMult, filtering::DoubleOmega, filtering::OmegaXi); using StrangenessFilter = StrangenessFilters::iterator; diff --git a/EventFiltering/macros/checkBCrangesSkimming.C b/EventFiltering/macros/checkBCrangesSkimming.C index 78de68cde62..3dea4c56318 100644 --- a/EventFiltering/macros/checkBCrangesSkimming.C +++ b/EventFiltering/macros/checkBCrangesSkimming.C @@ -15,18 +15,58 @@ #include #include #include +#include +#include #include "CommonDataFormat/InteractionRecord.h" #include "CommonDataFormat/IRFrame.h" using o2::InteractionRecord; using o2::dataformats::IRFrame; +// Set the bit of trigger which need to be checked +const ULong64_t Trigger0BIT = BIT(61); +const ULong64_t Trigger1BIT = 0; +const ULong64_t bcDiffTolerance = 100; +const char outputFileName[15] = "output.root"; + +struct bcTuple { + bcTuple(ULong64_t bcAO2D, ULong64_t bcEvSel) : bcAO2D(bcAO2D), bcEvSel(bcEvSel) {} + ULong64_t bcAO2D{0ull}; + ULong64_t bcEvSel{0ull}; + bool operator==(const bcTuple& t) const + { + return (this->bcAO2D == t.bcAO2D && this->bcEvSel == t.bcEvSel); + } +}; + struct selectedFrames : public IRFrame { - selectedFrames(ULong64_t triMask[2], ULong64_t selMask[2], const IRFrame& frame) : IRFrame(frame), triMask{triMask[0], triMask[1]}, selMask{selMask[0], selMask[1]} {} - ULong64_t triMask[2]{0ull}, selMask[2]{0ull}; + selectedFrames(ULong64_t bcAO2D, ULong64_t bcEvSel, ULong64_t triMask[2], ULong64_t selMask[2], const IRFrame& frame) : IRFrame(frame), bcAO2D(bcAO2D), bcEvSel(bcEvSel), triMask{triMask[0], triMask[1]}, selMask{selMask[0], selMask[1]} {} + ULong64_t triMask[2]{0ull}, selMask[2]{0ull}, bcAO2D, bcEvSel; + int numSameTriggerInNearbyBCs = 0; // related to bcDiffTolerance + bool isSingle() { return numSameTriggerInNearbyBCs == 0; } + void SetNum(int n) { numSameTriggerInNearbyBCs = n; } + int GetNum() { return numSameTriggerInNearbyBCs; } }; -std::vector getSelectedFrames(TFile& file) +int DoBCSubraction(ULong64_t bc1, ULong64_t bc2) +{ + if (bc1 > bc2) { + return bc1 - bc2; + } else { + ULong64_t bcsub = bc2 - bc1; + return -static_cast(bcsub); + } +} + +bool isClose(selectedFrames a, selectedFrames b, ULong64_t bcDiffTolerance) +{ + if (a.getMin() > b.getMax() + bcDiffTolerance || a.getMax() < b.getMin() - bcDiffTolerance) + return false; + else + return true; +} + +std::vector getSelectedFrames(TFile& file, ULong64_t trigger0Bit, ULong64_t trigger1Bit) { std::vector selectedFrames; ULong64_t bcAO2D{0ull}, bcEvSel{0ull}, triMask[2]{0ull}, selMask[2]{0ull}; @@ -56,42 +96,467 @@ std::vector getSelectedFrames(TFile& file) if (!selMask[0] && !selMask[1]) { continue; } - InteractionRecord irstart, irend; - irstart.setFromLong(std::min(bcAO2D, bcEvSel)); - irend.setFromLong(std::max(bcAO2D, bcEvSel)); - IRFrame frame(irstart, irend); - selectedFrames.push_back({triMask, selMask, frame}); + if (selMask[0] & trigger0Bit || selMask[1] & trigger1Bit) { + InteractionRecord irstart, irend; + irstart.setFromLong(std::min(bcAO2D, bcEvSel)); + irend.setFromLong(std::max(bcAO2D, bcEvSel)); + IRFrame frame(irstart, irend); + selectedFrames.push_back({bcAO2D, bcEvSel, triMask, selMask, frame}); + } } } return selectedFrames; } -void checkBCrangesSkimming(std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root") +void checkNearbyBCs(std::vector& frames, ULong64_t bcDiffTolerance) +{ + std::sort(frames.begin(), frames.end(), [](const selectedFrames& a, const selectedFrames& b) { + return a.getMin() < b.getMin(); + }); + int firstID = 0; + for (auto& currentFrame : frames) { + int num = 0; + bool isFirst = true; + for (int i = firstID; i < frames.size(); i++) { + auto& frame = frames[i]; + if (frame.getMin() > currentFrame.getMax() + bcDiffTolerance) { + break; + } + if (isClose(currentFrame, frame, bcDiffTolerance)) { + isFirst = false; + bool found = currentFrame.selMask[0] & frame.selMask[0] || currentFrame.selMask[1] & frame.selMask[1]; + if (found) { + num++; + } + } else { + if (isFirst) { + firstID = i; + } + } + } + currentFrame.SetNum(num); + } +} + +// Calulate the ratio of duplicate triggers +void checkDuplicateTriggerAndBCs(std::string AnaFileName = "AnalysisResults.root", std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root") { + + // Get RunNumber + std::string runNumber = ""; + std::regex re("/5[0-9]*"); + std::smatch match; + if (std::regex_search(originalFileName, match, re)) { + // Remove the leading '/' + runNumber = match.str().substr(1); + } + + // Checks for BC difference between original and skimming data, and the ratio of triggers which have BCdiff==0 + TH1D hPairedNumCounterTotal("hPairedNumCounterTotal", "hPairedNumCounterTotal", 10, -0.5, 9.5); + TH1D hBCDiffAO2DTotal("hBCDiffAO2DTotal", "hBCDiffAO2DTotal", 201, -100.5, 100.5); + TH1D hBCDiffEvSelTotal("hBCDiffEvSelTotal", "hBCDiffEvSelTotal", 201, -100.5, 100.5); + + // Readin labels + TFile AnaFile(AnaFileName.c_str(), "READ"); + TH1* hist0 = dynamic_cast(AnaFile.Get("central-event-filter-task/scalers/mFiltered;1")); + std::vector labels; + std::vector binNum; + for (int i = 1; i <= hist0->GetNbinsX(); i++) { + std::string label = hist0->GetXaxis()->GetBinLabel(i); + if (label != "Total number of events" && label != "Filtered events") { + labels.push_back(label); + binNum.push_back(i); + } + } + AnaFile.Close(); + TFile originalFile(originalFileName.c_str(), "READ"); TFile skimmedFile(skimmedFileName.c_str(), "READ"); + std::vector sel_labels; + std::vector numOriginal, numSkimmed, numOriginalSingle, numSkimmedSingle, numOriginalDouble, numSkimmedDouble, numOriginalMultiple, numSkimmedMultiple; + std::vector numpair, numpairedBCAO2D, numpairedBCEvSel, maxDeltaBCAO2D, maxDeltaBCEvSel; + for (int i = 0; i < labels.size(); i++) { + // std::cout << "i:" << i << std::endl; + ULong64_t trigger0Bit = 0, trigger1Bit = 0; + int triggerBit = binNum[i] - 2; + if (triggerBit < 64) { + trigger0Bit = BIT(triggerBit); + } else { + trigger1Bit = BIT(triggerBit - 64); + } + // Caculate singles, doubles, and multiples + // For Original dataset + std::vector bcSet; + std::vector bcFullSet; + int noriginal{0}, nskimmed{0}, noriginalsingle{0}, nskimmedsingle{0}, noriginaldouble{0}, nskimmeddouble{0}, noriginalmultiple{0}, nskimmedmultiple{0}, maxdiffBCAO2D{0}, maxdiffBCEvSel{0}; + auto originalFrames = getSelectedFrames(originalFile, trigger0Bit, trigger1Bit); + checkNearbyBCs(originalFrames, bcDiffTolerance); + noriginal = originalFrames.size(); + for (auto originalFrame : originalFrames) { + if (originalFrame.GetNum() == 0) { + std::cerr << "Unexpected trigger!!! " << std::endl; + } else if (originalFrame.GetNum() == 1) { + noriginalsingle++; + } else if (originalFrame.GetNum() == 2) { + noriginaldouble++; + } else { + noriginalmultiple++; + } + } + // For skimmed dataset + auto skimmedFrames = getSelectedFrames(skimmedFile, trigger0Bit, trigger1Bit); + checkNearbyBCs(skimmedFrames, bcDiffTolerance); + nskimmed = skimmedFrames.size(); + for (auto& skimmedFrame : skimmedFrames) { + if (skimmedFrame.GetNum() == 0) { + std::cerr << "Unexpected trigger!!! " << std::endl; + } else if (skimmedFrame.GetNum() == 1) { + nskimmedsingle++; + } else if (skimmedFrame.GetNum() == 2) { + nskimmeddouble++; + } else { + nskimmedmultiple++; + } + } - auto originalFrames = getSelectedFrames(originalFile); - auto skimmedFrames = getSelectedFrames(skimmedFile); + sel_labels.push_back(labels[i]); + numOriginal.push_back(noriginal); + numOriginalSingle.push_back(noriginalsingle); + numOriginalDouble.push_back(noriginaldouble); + numOriginalMultiple.push_back(noriginalmultiple); + numSkimmed.push_back(nskimmed); + numSkimmedSingle.push_back(nskimmedsingle); + numSkimmedDouble.push_back(nskimmeddouble); + numSkimmedMultiple.push_back(nskimmedmultiple); - std::sort(originalFrames.begin(), originalFrames.end(), [](const selectedFrames& a, const selectedFrames& b) { - return a.getMin() < b.getMin(); - }); - std::sort(skimmedFrames.begin(), skimmedFrames.end(), [](const selectedFrames& a, const selectedFrames& b) { - return a.getMin() < b.getMin(); - }); + // Check BC differences + int npair{0}, npairedBCAO2D{0}, npairedBCEvSel{0}, maxdeltaBCAO2D{0}, maxdeltaBCEvSel{0}; + int firstID = 0; + for (auto frame : originalFrames) { + if (frame.selMask[0] & trigger0Bit || frame.selMask[1] & trigger1Bit) { + // std::cout << "------------------------------------------------" << std::endl; + if (frame.GetNum() != 1) { + continue; // Only check singles + } + std::vector skimmedbcs; + int n = 0; + bool isFirst = true; + for (int i = firstID; i < skimmedFrames.size(); i++) { + auto& skimmedFrame = skimmedFrames[i]; + if (skimmedFrame.getMin() > frame.getMax()) { + break; + } + if (skimmedFrame.GetNum() != 1) { + continue; // Only check singles + } + if (isClose(frame, skimmedFrame, bcDiffTolerance)) { + isFirst = false; + bool found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; + // found = found && (frame.bcAO2D == skimmedFrame.bcAO2D || frame.bcEvSel == skimmedFrame.bcEvSel); + if (found) { + skimmedbcs.push_back({skimmedFrame.bcAO2D, skimmedFrame.bcEvSel}); + n++; + } + } else { + if (isFirst) { + firstID = i; + } + } + } + if (n == 1) { + npair++; + int bcdiffAO2D = DoBCSubraction(frame.bcAO2D, skimmedbcs[0].bcAO2D); + int bcdiffEvSel = DoBCSubraction(frame.bcEvSel, skimmedbcs[0].bcEvSel); + hBCDiffAO2DTotal.Fill(bcdiffAO2D); + hBCDiffEvSelTotal.Fill(bcdiffEvSel); + maxdiffBCAO2D = std::max(std::abs(maxdiffBCAO2D), bcdiffAO2D); + maxdiffBCEvSel = std::max(std::abs(maxdiffBCEvSel), bcdiffEvSel); + if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { + npairedBCAO2D++; + } + if (frame.bcEvSel == skimmedbcs[0].bcEvSel) { + npairedBCEvSel++; + } + } + hPairedNumCounterTotal.Fill(n); + } + } + numpair.push_back(npair); + numpairedBCAO2D.push_back(npairedBCAO2D); + numpairedBCEvSel.push_back(npairedBCEvSel); + maxDeltaBCAO2D.push_back(maxdiffBCAO2D); + maxDeltaBCEvSel.push_back(maxdiffBCEvSel); + } + originalFile.Close(); + skimmedFile.Close(); + + TH1D hOriginalTotal("hOriginalTotal", (runNumber + " AO2D Original;;Number of events").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalSingles("hOriginalSingles", (runNumber + " Original;;Number of Singles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalSinglesRatio("hOriginalSinglesRatio", (runNumber + " Original;;Singles / Total").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalDoubles("hOriginalDoubles", (runNumber + " Original;;Number of Doubles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalDoublesRatio("hOriginalDoublesRatio", (runNumber + " Original;;Doubles / Total").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalMultiples("hOriginalMultiples", (runNumber + " Original;;Number of Multiples").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalMultiplesRatio("hOriginalMultiplesRatio", (runNumber + " Original;;Multiples / Total").data(), sel_labels.size(), 0, sel_labels.size()); + + TH1D hSkimmedTotal("hSkimmedTotal", (runNumber + " AO2D Skimmed;;Number of events").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedSingles("hSkimmedSingles", (runNumber + " Skimmed;;Number of Singles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedSinglesRatio("hSkimmedSinglesRatio", (runNumber + " Skimmed;;Singles / Total").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedDoubles("hSkimmedDoubles", (runNumber + " Skimmed;;Number of Doubles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedDoublesRatio("hSkimmedDoublesRatio", (runNumber + " Skimmed;;Doubles / Total").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedMultiples("hSkimmedMultiples", (runNumber + " Skimmed;;Number of Multiples").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedMultiplesRatio("hSkimmedMultiplesRatio", (runNumber + " Skimmed;;Multiples / Total").data(), sel_labels.size(), 0, sel_labels.size()); + + TH1D hPairedBCAO2DRatio("hPairedBCAO2DRatio", (runNumber + " One-to-One Pairs;; Pairs with same BCAO2D / Total").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hPairedBCEvSelRatio("hPairedBCEvSelRatio", (runNumber + " One-to-One Pairs;; Pairs with same BCEvSel / Total").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hMaxDiffBCAO2D("hMaxDiffBCAO2D", (runNumber + " One-to-One Pairs;;|#DeltaBCAO2D|_{max}").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hMaxDiffBCEvSel("hMaxDiffBCEvSel", (runNumber + " One-to-One Pairs;;|#DeltaBCEvSel|_{max}").data(), sel_labels.size(), 0, sel_labels.size()); + + for (int i = 0; i < sel_labels.size(); i++) { + hOriginalTotal.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalSingles.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalMultiples.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalSinglesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalDoublesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalMultiplesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalTotal.SetBinContent(i + 1, numOriginal[i]); + hOriginalSingles.SetBinContent(i + 1, numOriginalSingle[i]); + hOriginalDoubles.SetBinContent(i + 1, numOriginalDouble[i]); + hOriginalMultiples.SetBinContent(i + 1, numOriginalMultiple[i]); + if (numOriginal[i] > 0) { + hOriginalSinglesRatio.SetBinContent(i + 1, static_cast(numOriginalSingle[i]) / numOriginal[i]); + hOriginalDoublesRatio.SetBinContent(i + 1, static_cast(numOriginalSingle[i]) / numOriginal[i]); + hOriginalMultiplesRatio.SetBinContent(i + 1, static_cast(numOriginalMultiple[i]) / numOriginal[i]); + } else { + hOriginalSinglesRatio.SetBinContent(i + 1, 0); + hOriginalDoublesRatio.SetBinContent(i + 1, 0); + hOriginalMultiplesRatio.SetBinContent(i + 1, 0); + } + + hSkimmedTotal.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hSkimmedSingles.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hSkimmedMultiples.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hSkimmedSinglesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hSkimmedDoublesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hSkimmedMultiplesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + + hSkimmedTotal.SetBinContent(i + 1, numSkimmed[i]); + hSkimmedSingles.SetBinContent(i + 1, numSkimmedSingle[i]); + hSkimmedDoubles.SetBinContent(i + 1, numSkimmedDouble[i]); + hSkimmedMultiples.SetBinContent(i + 1, numSkimmedMultiple[i]); + if (numSkimmed[i] > 0) { + hSkimmedSinglesRatio.SetBinContent(i + 1, static_cast(numSkimmedSingle[i]) / numSkimmed[i]); + hSkimmedDoublesRatio.SetBinContent(i + 1, static_cast(numSkimmedDouble[i]) / numSkimmed[i]); + hSkimmedMultiplesRatio.SetBinContent(i + 1, static_cast(numSkimmedMultiple[i]) / numSkimmed[i]); + } else { + hSkimmedSinglesRatio.SetBinContent(i + 1, 0); + hSkimmedDoublesRatio.SetBinContent(i + 1, 0); + hSkimmedMultiplesRatio.SetBinContent(i + 1, 0); + } + + hPairedBCAO2DRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hPairedBCEvSelRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + if (numpair[i] > 0) { + hPairedBCAO2DRatio.SetBinContent(i + 1, static_cast(numpairedBCAO2D[i]) / numpair[i]); + hPairedBCEvSelRatio.SetBinContent(i + 1, static_cast(numpairedBCEvSel[i]) / numpair[i]); + } + + hMaxDiffBCAO2D.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hMaxDiffBCEvSel.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hMaxDiffBCAO2D.SetBinContent(i + 1, maxDeltaBCAO2D[i]); + hMaxDiffBCEvSel.SetBinContent(i + 1, maxDeltaBCEvSel[i]); + } + + TFile fout(outputFileName, "UPDATE"); + fout.cd(); + hOriginalTotal.Write(); + hOriginalSingles.Write(); + hOriginalDoubles.Write(); + hOriginalMultiples.Write(); + hOriginalSinglesRatio.Write(); + hOriginalDoublesRatio.Write(); + hOriginalMultiplesRatio.Write(); + hSkimmedTotal.Write(); + hSkimmedSingles.Write(); + hSkimmedDoubles.Write(); + hSkimmedMultiples.Write(); + hSkimmedSinglesRatio.Write(); + hSkimmedDoublesRatio.Write(); + hSkimmedMultiplesRatio.Write(); + hPairedNumCounterTotal.Write(); + hBCDiffAO2DTotal.Write(); + hBCDiffEvSelTotal.Write(); + hPairedBCAO2DRatio.Write(); + hPairedBCEvSelRatio.Write(); + hMaxDiffBCAO2D.Write(); + hMaxDiffBCEvSel.Write(); + fout.Close(); +} + +// Detailed checks for specific trigger +void checkBCrangesSkimming(std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root") +{ + //---------------------------------For specific trigger---------------------------------- + TH1D hTriggerCounter("hTriggerCounter", "hTriggerCounter", 3, 0.5, 3.5); + hTriggerCounter.GetXaxis()->SetBinLabel(1, "Original"); + hTriggerCounter.GetXaxis()->SetBinLabel(2, "Skimmed"); + TH1D hNumCounter("hNumCounter", "hNumCounter", 10, -0.5, 9.5); + TH1D hSinglePairCheck("hSinglePairCheck", "hSinglePairCheck", 4, 0.5, 4.5); + hSinglePairCheck.GetXaxis()->SetBinLabel(1, "Total"); + hSinglePairCheck.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); + hSinglePairCheck.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); + hSinglePairCheck.GetXaxis()->SetBinLabel(4, "Same Both BC"); + TH1D hMultiPairCheck("hMultiPairCheck", "hMultiPairCheck", 5, 0.5, 5.5); + hMultiPairCheck.GetXaxis()->SetBinLabel(1, "Total"); + hMultiPairCheck.GetXaxis()->SetBinLabel(2, "Total Pair"); + hMultiPairCheck.GetXaxis()->SetBinLabel(3, "Same AO2D BC"); + hMultiPairCheck.GetXaxis()->SetBinLabel(4, "Same EvSel BC"); + hMultiPairCheck.GetXaxis()->SetBinLabel(5, "Same Both BC"); + TH1D hBCDiffAO2D("hBCDiffAO2D", "hBCDiffAO2D", 2001, -1000.5, 1000.5); + TH1D hBCDiffEvSel("hBCDiffEvSel", "hBCDiffEvSel", 2001, -1000.5, 1000.5); + + TH1D hBCOriginal("hBCOriginal", "hBCOriginal", 4, 0.5, 4.5); + hBCOriginal.GetXaxis()->SetBinLabel(1, "Total"); + hBCOriginal.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); + hBCOriginal.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); + hBCOriginal.GetXaxis()->SetBinLabel(4, "Same Both BC"); + TH1D hBCSkimmed("hBCSkimmed", "hBCSkimmed", 4, 0.5, 4.5); + hBCSkimmed.GetXaxis()->SetBinLabel(1, "Total"); + hBCSkimmed.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); + hBCSkimmed.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); + hBCSkimmed.GetXaxis()->SetBinLabel(4, "Same Both BC"); + + auto t1 = std::chrono::steady_clock::now(); + TFile originalFile(originalFileName.c_str(), "READ"); + TFile skimmedFile(skimmedFileName.c_str(), "READ"); + auto originalFrames = getSelectedFrames(originalFile, Trigger0BIT, Trigger1BIT); + auto skimmedFrames = getSelectedFrames(skimmedFile, Trigger0BIT, Trigger1BIT); + originalFile.Close(); + skimmedFile.Close(); + auto t2 = std::chrono::steady_clock::now(); + int d1 = std::chrono::duration_cast(t2 - t1).count(); + std::cout << "Readin Time: " << d1 << std::endl; + + auto t3 = std::chrono::steady_clock::now(); + checkNearbyBCs(originalFrames, bcDiffTolerance); + checkNearbyBCs(skimmedFrames, bcDiffTolerance); + auto t4 = std::chrono::steady_clock::now(); + int d2 = std::chrono::duration_cast(t4 - t3).count(); + std::cout << "Sort Time: " << d2 << std::endl; + + auto t5 = std::chrono::steady_clock::now(); + std::vector bcSet; for (auto frame : originalFrames) { - bool found = false; - frame.getMin() -= 1000; - frame.getMax() += 1000; - for (auto& skimmedFrame : skimmedFrames) { - if (skimmedFrame.getMin() > frame.getMax()) { - break; + if (frame.selMask[0] & Trigger0BIT || frame.selMask[1] & Trigger1BIT) { + hTriggerCounter.Fill(1); + hBCOriginal.Fill(1); + auto p1 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcAO2D == frame.bcAO2D; }); + if (p1 != bcSet.end()) { + hBCOriginal.Fill(2); + } + auto p2 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcEvSel == frame.bcEvSel; }); + if (p2 != bcSet.end()) { + hBCOriginal.Fill(3); + } + bcTuple currentBC(frame.bcAO2D, frame.bcEvSel); + auto p3 = std::find(bcSet.begin(), bcSet.end(), currentBC); + if (p3 == bcSet.end()) { + bcSet.push_back(currentBC); + } else { + hBCOriginal.Fill(4); } - if (!frame.isOutside(skimmedFrame)) { - found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; + // std::cout << "------------------------------------------------" << std::endl; + if (frame.GetNum() != 1) { + continue; // Only check singles + } + std::vector skimmedbcs; + int n = 0; + for (auto& skimmedFrame : skimmedFrames) { + if (skimmedFrame.getMin() > frame.getMax()) { + break; + } + if (skimmedFrame.GetNum() != 1) { + continue; // Only check singles + } + if (isClose(frame, skimmedFrame, bcDiffTolerance)) { + bool found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; + // found = found && (frame.bcAO2D == skimmedFrame.bcAO2D || frame.bcEvSel == skimmedFrame.bcEvSel); + if (found) { + skimmedbcs.push_back({skimmedFrame.bcAO2D, skimmedFrame.bcEvSel}); + n++; + } + } + } + if (n == 0) { + // std::cout << "Trigger not found!!!" << std::endl; + } else if (n == 1) { + hSinglePairCheck.Fill(1); + hBCDiffAO2D.Fill(DoBCSubraction(frame.bcAO2D, skimmedbcs[0].bcAO2D)); + hBCDiffEvSel.Fill(DoBCSubraction(frame.bcEvSel, skimmedbcs[0].bcEvSel)); + if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { + hSinglePairCheck.Fill(2); + } + if (frame.bcEvSel == skimmedbcs[0].bcEvSel) { + hSinglePairCheck.Fill(3); + if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { + hSinglePairCheck.Fill(4); + } + } + } else { + // std::cout << "Unexpected trigger!!! n=" << n << std::endl; + hMultiPairCheck.Fill(1); + for (auto skimmedbc : skimmedbcs) { + hMultiPairCheck.Fill(2); + if (frame.bcAO2D == skimmedbc.bcAO2D) { + hMultiPairCheck.Fill(3); + } + if (frame.bcEvSel == skimmedbc.bcEvSel) { + hMultiPairCheck.Fill(4); + if (frame.bcAO2D == skimmedbc.bcAO2D) { + hMultiPairCheck.Fill(5); + } + } + } + } + hNumCounter.Fill(n); + } + } + auto t6 = std::chrono::steady_clock::now(); + int d3 = std::chrono::duration_cast(t6 - t5).count(); + std::cout << "Search Time: " << d3 << std::endl; + + bcSet.clear(); + for (auto& skimmedFrame : skimmedFrames) { + if (skimmedFrame.selMask[0] & Trigger0BIT || skimmedFrame.selMask[1] & Trigger1BIT) { + hTriggerCounter.Fill(2); + hBCSkimmed.Fill(1); + auto p1 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcAO2D == skimmedFrame.bcAO2D; }); + if (p1 != bcSet.end()) { + hBCSkimmed.Fill(2); + } + auto p2 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcEvSel == skimmedFrame.bcEvSel; }); + if (p2 != bcSet.end()) { + hBCSkimmed.Fill(3); + } + bcTuple currentBC(skimmedFrame.bcAO2D, skimmedFrame.bcEvSel); + auto p3 = std::find(bcSet.begin(), bcSet.end(), currentBC); + if (p3 == bcSet.end()) { + bcSet.push_back(currentBC); + } else { + hBCSkimmed.Fill(4); } } } -} \ No newline at end of file + + TFile fout(outputFileName, "RECREATE"); + fout.cd(); + hTriggerCounter.Write(); + hBCOriginal.Write(); + hBCSkimmed.Write(); + hNumCounter.Write(); + hSinglePairCheck.Write(); + hBCDiffAO2D.Write(); + hBCDiffEvSel.Write(); + hMultiPairCheck.Write(); + fout.Close(); +} diff --git a/EventFiltering/macros/selectivityPlot.C b/EventFiltering/macros/selectivityPlot.C new file mode 100644 index 00000000000..56215bcd3e6 --- /dev/null +++ b/EventFiltering/macros/selectivityPlot.C @@ -0,0 +1,90 @@ +// Copyright 2019-2020 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. + +void selectivityPlot(int runNumber = 550781, TString inputfile = "AnalysisResults_550781.root", TString outputfolder = "") +{ + TCanvas* Canvas_1 = new TCanvas("Canvas_1", "Canvas_1", 928, 592); + gStyle->SetOptFit(0); + gStyle->SetOptStat(0); + Canvas_1->Range(-6.079755, -8.734506, 67.09509, -2.808365); + Canvas_1->SetFillColor(0); + Canvas_1->SetBorderMode(0); + Canvas_1->SetBorderSize(2); + Canvas_1->SetLogy(); + Canvas_1->SetGridx(); + Canvas_1->SetGridy(); + Canvas_1->SetTickx(1); + Canvas_1->SetTicky(1); + Canvas_1->SetLeftMargin(0.08991826); + Canvas_1->SetRightMargin(0.02179836); + Canvas_1->SetTopMargin(0.05); + Canvas_1->SetBottomMargin(0.2711864); + Canvas_1->SetFrameBorderMode(0); + Canvas_1->SetFrameBorderMode(0); + + TFile* file = new TFile(inputfile.Data()); + TH1D* mFiltered = (TH1D*)file->Get("central-event-filter-task/scalers/mFiltered"); + double nEvents = mFiltered->GetBinContent(1); + mFiltered->Scale(1. / nEvents); + mFiltered->SetLineColor(2); + mFiltered->SetLineWidth(2); + mFiltered->SetMarkerColor(2); + mFiltered->SetMarkerStyle(4); + mFiltered->SetMarkerSize(0.6); + mFiltered->GetXaxis()->SetRange(2, mFiltered->GetXaxis()->GetNbins()); + for (int i = 1; i <= mFiltered->GetNbinsX(); i++) { + std::string label = mFiltered->GetXaxis()->GetBinLabel(i); + if (label[0] == 'f') { + mFiltered->GetXaxis()->SetBinLabel(i, label.substr(1).c_str()); + } + mFiltered->SetBinContent(i, mFiltered->GetBinContent(i) / mFiltered->GetBinContent(1)); + mFiltered->SetBinError(i, mFiltered->GetBinError(i) / mFiltered->GetBinContent(1)); + } + mFiltered->GetXaxis()->SetBinLabel(mFiltered->GetNbinsX(), "Total"); + mFiltered->GetXaxis()->SetLabelFont(42); + mFiltered->GetXaxis()->SetTitleOffset(1); + mFiltered->GetXaxis()->SetTitleFont(42); + mFiltered->GetYaxis()->SetTitle("Async. trigger selectivity"); + mFiltered->GetYaxis()->SetLabelFont(42); + mFiltered->GetYaxis()->SetTitleFont(42); + mFiltered->GetZaxis()->SetLabelFont(42); + mFiltered->GetZaxis()->SetTitleOffset(1); + mFiltered->GetZaxis()->SetTitleFont(42); + mFiltered->DrawClone(""); + TLine* line = new TLine(mFiltered->GetXaxis()->GetBinLowEdge(2), 5.e-05, mFiltered->GetXaxis()->GetBinLowEdge(mFiltered->GetNbinsX()), 5.e-05); + line->SetLineStyle(2); + line->Draw(); + TArrow* arrow = new TArrow(mFiltered->GetXaxis()->GetXmax(), 0.0005, mFiltered->GetXaxis()->GetXmax() + 1, 0.0005, 0.01, "<|"); + + Int_t ci; // for color index setting + TColor* color; // for color definition with alpha + ci = TColor::GetColor("#0000ff"); + arrow->SetFillColor(ci); + arrow->SetFillStyle(1001); + TLatex* tex = new TLatex(); + tex->SetTextSize(0.035); + tex->SetTextFont(42); + tex->DrawLatexNDC(0.09, 0.96, Form("ALICE Internal, pp #sqrt{s} = 13.6 TeV, Run %d, #it{L}_{int} #approx %.1f nb^{-1}", runNumber, nEvents / 78.e6)); + ci = TColor::GetColor("#0000ff"); + arrow->SetLineColor(ci); + arrow->Draw(); + Canvas_1->Modified(); + Canvas_1->SetSelected(Canvas_1); + + if (outputfolder.IsNull()) { + return; + } + gROOT->SetBatch(true); + TCanvas Canvas_2("Canvas_2", "Canvas_2", Canvas_1->GetWw() * 2, Canvas_1->GetWh() * 2); + Canvas_1->DrawClonePad(); + Canvas_2.SaveAs(Form("%s/asyncTriggerSelectivity_%d.png", outputfolder.Data(), runNumber)); + gROOT->SetBatch(false); +} diff --git a/EventFiltering/macros/uploadOTSobjects.C b/EventFiltering/macros/uploadOTSobjects.C index 5f3f076c90c..132f1b618da 100644 --- a/EventFiltering/macros/uploadOTSobjects.C +++ b/EventFiltering/macros/uploadOTSobjects.C @@ -17,23 +17,23 @@ #include #include -#include #include "TFile.h" -#include "TKey.h" +#include "TGrid.h" #include "TH1.h" +#include "TKey.h" +#include "TSystem.h" +#include "TTree.h" #include "CCDB/BasicCCDBManager.h" +#include "EventFiltering/ZorroHelper.h" -const std::string kBaseCCDBPath = "Users/r/rlietava/EventFiltering/OTS/"; - -#pragma link C++ class std::vector < std::array < uint64_t, 2>> + ; -struct bcInfo { - bcInfo() = default; - ULong64_t bcAOD, bcEvSel, trigMask, selMask; - void print() const; -}; -void uploadOTSobjects(std::string inputList) +void uploadOTSobjects(std::string inputList, std::string passName, bool useAlien) { + const std::string kBaseCCDBPath = "Users/m/mpuccio/EventFiltering/OTS/"; + std::string baseCCDBpath = passName.empty() ? kBaseCCDBPath : kBaseCCDBPath + passName + "/"; + if (useAlien) { + TGrid::Connect("alien://"); + } o2::ccdb::CcdbApi api; api.init("http://alice-ccdb.cern.ch"); @@ -49,42 +49,49 @@ void uploadOTSobjects(std::string inputList) std::pair duration = o2::ccdb::BasicCCDBManager::getRunDuration(api, runNumber); duration.first -= 10000; // subtract 3 minutes from the run start duration.second += 180000; // add 3 minutes to the run duration - TFile scalersFile((path + "/AnalysisResults_fullrun.root").data(), "READ"); - TH1* scalers = (TH1*)scalersFile.Get("central-event-filter-task/scalers/mScalers"); - TH1* filters = (TH1*)scalersFile.Get("central-event-filter-task/scalers/mFiltered"); - api.storeAsTFile(scalers, kBaseCCDBPath + "FilterCounters", metadata, duration.first, duration.second); - api.storeAsTFile(filters, kBaseCCDBPath + "SelectionCounters", metadata, duration.first, duration.second); - TH1* hCounterTVX = (TH1*)scalersFile.Get("bc-selection-task/hCounterTVX"); - api.storeAsTFile(hCounterTVX, kBaseCCDBPath + "InspectedTVX", metadata, duration.first, duration.second); + std::cout << ">>> Begin - end timestamps for the upload: " << duration.first << " - " << duration.second << std::endl; + path = useAlien ? "alien://" + path : path; + std::unique_ptr scalersFile{TFile::Open((path + "/AnalysisResults_fullrun.root").data(), "READ")}; + TH1* scalers = static_cast(scalersFile->Get("central-event-filter-task/scalers/mScalers")); + TH1* filters = static_cast(scalersFile->Get("central-event-filter-task/scalers/mFiltered")); + api.storeAsTFile(scalers, baseCCDBpath + "FilterCounters", metadata, duration.first, duration.second); + api.storeAsTFile(filters, baseCCDBpath + "SelectionCounters", metadata, duration.first, duration.second); + TH1* hCounterTVX = static_cast(scalersFile->Get("bc-selection-task/hCounterTVX")); + api.storeAsTFile(hCounterTVX, baseCCDBpath + "InspectedTVX", metadata, duration.first, duration.second); - std::vector> bcRanges, filterBitMask, selectionBitMask; - TFile bcRangesFile((path + "/bcRanges_fullrun.root").data(), "READ"); + std::vector zorroHelpers; + std::unique_ptr bcRangesFile{TFile::Open((path + "/bcRanges_fullrun.root").data(), "READ")}; int Nmax = 0; - for (auto key : *(bcRangesFile.GetListOfKeys())) { - TTree* cefpTree = (TTree*)bcRangesFile.Get(Form("%s/selectedBC", key->GetName())); + for (auto key : *(bcRangesFile->GetListOfKeys())) { + TTree* cefpTree = static_cast(bcRangesFile->Get(Form("%s/selectedBC", key->GetName()))); if (!cefpTree) continue; - bcInfo bci; + ZorroHelper bci; cefpTree->SetBranchAddress("bcAO2D", &bci.bcAOD); cefpTree->SetBranchAddress("bcEvSel", &bci.bcEvSel); - cefpTree->SetBranchAddress("selMask", &bci.selMask); - cefpTree->SetBranchAddress("triMask", &bci.trigMask); + if (cefpTree->GetBranch("selMask") && cefpTree->GetBranch("triMask")) { + cefpTree->SetBranchAddress("selMask", &bci.selMask[0]); + cefpTree->SetBranchAddress("triMask", &bci.trigMask[0]); + } else { + cefpTree->SetBranchAddress("selMask0", &bci.selMask[0]); + cefpTree->SetBranchAddress("triMask0", &bci.trigMask[0]); + cefpTree->SetBranchAddress("selMask1", &bci.selMask[1]); + cefpTree->SetBranchAddress("triMask1", &bci.trigMask[1]); + } for (int i = 0; i < cefpTree->GetEntries(); i++) { if ((i < Nmax) || (Nmax == 0)) { cefpTree->GetEntry(i); - // Check consistency - if (~bci.trigMask & bci.selMask) { - std::cout << "ERROR selMask is not subset of trigMask:"; - // bcAO2D.print(); - } - bcRanges.push_back({bci.bcAOD, bci.bcEvSel}); - filterBitMask.push_back({bci.trigMask, 0ull}); - selectionBitMask.push_back({bci.selMask, 0ull}); + zorroHelpers.push_back(bci); } } } - api.storeAsTFileAny(&bcRanges, kBaseCCDBPath + "SelectedBCs", metadata, duration.first, duration.second); - api.storeAsTFileAny(&filterBitMask, kBaseCCDBPath + "FilterBitMasks", metadata, duration.first, duration.second); - api.storeAsTFileAny(&selectionBitMask, kBaseCCDBPath + "SelectionBitMasks", metadata, duration.first, duration.second); + api.storeAsTFileAny(&zorroHelpers, baseCCDBpath + "ZorroHelpers", metadata, duration.first, duration.second); } } + +void uploadOTSobjects(std::string periodName) +{ + int year = 2000 + std::stoi(periodName.substr(3, 2)); + gSystem->Exec(Form("alien_find /alice/data/%i/%s/ ctf_skim_full/AnalysisResults_fullrun.root | sed 's:/AnalysisResults_fullrun\\.root::' > list_%s.txt", year, periodName.data(), periodName.data())); + uploadOTSobjects(Form("list_%s.txt", periodName.data()), "", true); +} diff --git a/PWGCF/Core/AnalysisConfigurableCuts.h b/PWGCF/Core/AnalysisConfigurableCuts.h index f40f0e7cd5b..c35d24430c6 100644 --- a/PWGCF/Core/AnalysisConfigurableCuts.h +++ b/PWGCF/Core/AnalysisConfigurableCuts.h @@ -124,8 +124,10 @@ class TrackSelectionPIDCfg std::vector mMaxNSigmasTOF = {0.0f, 0.0f, 3.0f, 3.0f, 3.0f}; ///< nsigmas TOF upper limit for e, mu, pi, Ka, and p bool m2Dcut = true; ///< use an elliptic cut using TPC and TOF nsigmas bool mExclude = false; ///< should the identified track be excluded for analysis? + float mPtMin = 0.2; ///< increase the lower pT limit for this species + float mPtMax = 2.0; ///< decrease the upper pT limit for this species private: - ClassDefNV(TrackSelectionPIDCfg, 1); + ClassDefNV(TrackSelectionPIDCfg, 2); }; class SimpleInclusiveCut : public TNamed diff --git a/PWGCF/DataModel/FemtoDerived.h b/PWGCF/DataModel/FemtoDerived.h index 082527cb5ef..fb8fdaba809 100644 --- a/PWGCF/DataModel/FemtoDerived.h +++ b/PWGCF/DataModel/FemtoDerived.h @@ -206,7 +206,7 @@ DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); //! Selectio DECLARE_SOA_COLUMN(BDTBkg, bdtBkg, float); //! Background score using Boosted Decision Tree for charm hadron DECLARE_SOA_COLUMN(BDTPrompt, bdtPrompt, float); //! Prompt signal score using Boosted Decision Tree for charm hadron DECLARE_SOA_COLUMN(BDTFD, bdtFD, float); //! Feed-down score using Boosted Decision Tree for charm hadron -DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); //! To select MC particle among charm hadrons, { DplusToPiKPi = 0, LcToPKPi = 2, DsToKKPi = 4, XicToPKP = 8, N3ProngD = 2ecays }; +DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); //! To select MC particle among charm hadrons, { DplusToPiKPi = 1, LcToPKPi = 2, DsToKKPi = 4, XicToPKP = 8, N3ProngD = 2ecays }; DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! flag for reconstruction level matching (1 for prompt, 2 for non-prompt) DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! flag for generator level matching (1 for prompt, 2 for non-prompt) DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); //! swapping of the prongs order (0 for Lc -> pkpi, 1 for Lc -> pikp) @@ -218,7 +218,7 @@ DECLARE_SOA_COLUMN(CharmM, charmM, float); //! Charm ha DECLARE_SOA_COLUMN(CharmPt, charmPt, float); //! Transverse momentum of charm hadron for result task DECLARE_SOA_COLUMN(Mult, mult, int); //! Charge particle multiplicity DECLARE_SOA_COLUMN(MultPercentile, multPercentile, float); //! Multiplicity precentile -DECLARE_SOA_COLUMN(PartPairSign, partPairSign, int8_t); //! Selection between ++ (1), and -- pair (2) +DECLARE_SOA_COLUMN(PairSign, pairSign, int8_t); //! Selection between like sign (1) and unlike sign pair (2) DECLARE_SOA_COLUMN(ProcessType, processType, int64_t); //! Selection between same-event (1), and mixed-event (2) DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! [](float pt0, float phi0, float eta0, float pt1, float phi1, float eta1, float pt2, float phi2, float eta2, const std::array& m) -> float { return RecoDecay::m(std::array{ @@ -294,8 +294,11 @@ DECLARE_SOA_TABLE(FDResultsHF, "AOD", "FDRESULTSHF", //! table to store results fdhf::MT, fdhf::Mult, fdhf::MultPercentile, - fdhf::PartPairSign, - fdhf::ProcessType); + fdhf::Charge, + fdhf::PairSign, + fdhf::ProcessType, + fdhf::FlagMc, + fdhf::OriginMcRec); DECLARE_SOA_TABLE(FDHfCandMC, "AOD", "FDHFCANDMC", //! Table for reconstructed MC charm hadron candidates o2::soa::Index<>, diff --git a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx index e531af223af..f235859360a 100644 --- a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx @@ -28,14 +28,11 @@ #include "ReconstructionDataFormats/GlobalTrackID.h" #include "ReconstructionDataFormats/Track.h" #include "Framework/ASoAHelpers.h" - using std::array; using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; - struct FactorialMoments { - Configurable confEta{"centralEta", 0.8, "eta limit for tracks"}; Configurable confNumPt{"numPt", 1, "number of pT bins"}; Configurable confPtMin{"ptMin", 0.2f, "lower pT cut"}; @@ -45,7 +42,16 @@ struct FactorialMoments { Configurable> confCentCut{"centLimits", {0, 5}, "centrality min and max"}; Configurable> confVertex{"vertexXYZ", {0.3f, 0.4f, 10.0f}, "vertex cuts"}; Configurable> confPtBins{"ptCuts", {0.2f, 2.0f}, "pT cuts"}; - + Configurable IsApplySameBunchPileup{"IsApplySameBunchPileup", true, "Enable SameBunchPileup cut"}; + Configurable IsApplyGoodZvtxFT0vsPV{"IsApplyGoodZvtxFT0vsPV", true, "Enable GoodZvtxFT0vsPV cut"}; + Configurable IsApplyVertexITSTPC{"IsApplyVertexITSTPC", true, "Enable VertexITSTPC cut"}; + Configurable IsApplyVertexTOFmatched{"IsApplyVertexTOFmatched", true, "Enable VertexTOFmatched cut"}; + Configurable IsApplyVertexTRDmatched{"IsApplyVertexTRDmatched", true, "Enable VertexTRDmatched cut"}; + Configurable IsApplyExtraCorrCut{"IsApplyExtraCorrCut", false, "Enable extra NPVtracks vs FTOC correlation cut"}; + Configurable IsApplyExtraPhiCut{"IsApplyExtraPhiCut", false, "Enable extra phi cut"}; + Configurable includeGlobalTracks{"includeGlobalTracks", false, "Enable Global Tracks"}; + Configurable includeTPCTracks{"includeTPCTracks", false, "TPC Tracks"}; + Configurable includeITSTracks{"includeITSTracks", false, "ITS Tracks"}; Filter filterTracks = (nabs(aod::track::eta) < confEta) && (aod::track::pt >= confPtMin) && (nabs(aod::track::dcaXY) < confDCAxy) && (nabs(aod::track::dcaZ) < confDCAz); Filter filterCollisions = (nabs(aod::collision::posZ) < confVertex.value[2]) && (nabs(aod::collision::posX) < confVertex.value[0]) && (nabs(aod::collision::posY) < confVertex.value[1]); @@ -95,7 +101,6 @@ struct FactorialMoments { std::vector> mBinConFinal; // max number of bins restricted to 5 static constexpr array mbinNames{"bin1/", "bin2/", "bin3/", "bin4/", "bin5/"}; - void init(o2::framework::InitContext&) { // NOTE: check to make number of pt and the vector consistent @@ -127,7 +132,6 @@ struct FactorialMoments { } } } - template void checkpT(const T& track) { @@ -143,7 +147,6 @@ struct FactorialMoments { } } } - void calculateMoments(std::vector> hist) { Double_t binContent = 0; @@ -163,7 +166,7 @@ struct FactorialMoments { if (binconVal >= iOrder + 2) { fqBin = TMath::Factorial(binconVal) / (TMath::Factorial(binconVal - (iOrder + 2))); } - if (isnan(fqBin)) { + if (std::isnan(fqBin)) { break; } sumfqBin[iOrder] += fqBin; @@ -181,7 +184,6 @@ struct FactorialMoments { } // end of loop over M bins } // end of loop over pT bins } - using TracksFMs = soa::Filtered>; void processRun3(soa::Filtered>::iterator const& coll, TracksFMs const& tracks) { @@ -189,6 +191,15 @@ struct FactorialMoments { if (!coll.sel8()) { return; } + if (IsApplySameBunchPileup && !coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return; + } + if (IsApplyGoodZvtxFT0vsPV && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + if (IsApplyVertexITSTPC && !coll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return; + } if (coll.centFT0C() < confCentCut.value[0] || coll.centFT0C() > confCentCut.value[1]) { return; } @@ -199,16 +210,23 @@ struct FactorialMoments { histos.fill(HIST("mCentFV0A"), coll.centFV0A()); histos.fill(HIST("mCentFT0A"), coll.centFT0A()); histos.fill(HIST("mCentFT0C"), coll.centFT0C()); - for (auto const& h : mHistArrReset) { h->Reset(); } countTracks = {0, 0, 0, 0, 0}; - fqEvent = {{{0, 0, 0, 0, 0, 0}}}; - binConEvent = {{0, 0, 0, 0, 0}}; - + fqEvent = {{{{{0, 0, 0, 0, 0, 0}}}}}; + binConEvent = {{{0, 0, 0, 0, 0}}}; for (auto const& track : tracks) { - if ((track.pt() < confPtMin) || (!track.isGlobalTrack()) || (track.tpcNClsFindable() < confMinTPCCls)) { + if (includeGlobalTracks && (!track.isGlobalTrack())) { + continue; + } + if (includeTPCTracks && (!track.hasTPC())) { + continue; + } + if (includeITSTracks && (!track.hasITS())) { + continue; + } + if ((track.pt() < confPtMin) || (track.tpcNClsFindable() < confMinTPCCls)) { continue; } histos.fill(HIST("mCollID"), track.collisionId()); @@ -241,7 +259,7 @@ struct FactorialMoments { // Calculate the normalized factorial moments calculateMoments(mHistArrReset); } - PROCESS_SWITCH(FactorialMoments, processRun3, "main process function", false); + PROCESS_SWITCH(FactorialMoments, processRun3, "main process function", true); void processRun2(soa::Filtered>::iterator const& coll, TracksFMs const& tracks) { @@ -255,13 +273,14 @@ struct FactorialMoments { histos.fill(HIST("mVertexY"), coll.posY()); histos.fill(HIST("mVertexZ"), coll.posZ()); histos.fill(HIST("mCentFT0M"), coll.centRun2V0M()); + for (auto const& h : mHistArrReset) { h->Reset(); } countTracks = {0, 0, 0, 0, 0}; - fqEvent = {{{0, 0, 0, 0, 0, 0}}}; - binConEvent = {{0, 0, 0, 0, 0}}; + fqEvent = {{{{{0, 0, 0, 0, 0, 0}}}}}; + binConEvent = {{{0, 0, 0, 0, 0}}}; for (auto const& track : tracks) { if ((track.pt() < confPtMin) || (!track.isGlobalTrack()) || (track.tpcNClsFindable() < confMinTPCCls)) { @@ -290,8 +309,10 @@ struct FactorialMoments { checkpT(track); } for (auto iPt = 0; iPt < confNumPt; ++iPt) { - if (countTracks[iPt] > 0) { + if (countTracks[iPt] > 500) { mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); + } else { + return; } } // Calculate the normalized factorial moments diff --git a/PWGCF/Femto3D/Core/femto3dPairTask.h b/PWGCF/Femto3D/Core/femto3dPairTask.h index 8480cbcbadd..a3b74c36cd0 100755 --- a/PWGCF/Femto3D/Core/femto3dPairTask.h +++ b/PWGCF/Femto3D/Core/femto3dPairTask.h @@ -109,14 +109,14 @@ float GetKstarFrom4vectors(TLorentzVector& first4momentum, TLorentzVector& secon { if (isIdentical) { TLorentzVector fourmomentadiff = first4momentum - second4momentum; - return 0.5 * abs(fourmomentadiff.Mag()); + return 0.5 * std::fabs(fourmomentadiff.Mag()); } else { TLorentzVector fourmomentasum = first4momentum + second4momentum; TLorentzVector fourmomentadif = first4momentum - second4momentum; fourmomentadif.Boost((-1) * fourmomentasum.BoostVector()); - return 0.5 * abs(fourmomentadif.Vect().Mag()); + return 0.5 * std::fabs(fourmomentadif.Vect().Mag()); } } @@ -215,7 +215,8 @@ class FemtoPair float GetKstar() const; TVector3 GetQLCMS() const; float GetKt() const; - float GetMt() const; // test + float GetMt() const; // test + float GetGammaOut() const; // test private: TrackType _first = NULL; @@ -252,9 +253,9 @@ bool FemtoPair::IsClosePair(const float& deta, const float& dphi, con return true; if (_magfield1 * _magfield2 == 0) return true; - if (std::pow(abs(GetEtaDiff()) / deta, 2) + std::pow(abs(GetPhiStarDiff(radius)) / dphi, 2) < 1.0f) + if (std::pow(std::fabs(GetEtaDiff()) / deta, 2) + std::pow(std::fabs(GetPhiStarDiff(radius)) / dphi, 2) < 1.0f) return true; - // if (abs(GetEtaDiff()) < deta && abs(GetPhiStarDiff(radius)) < dphi) + // if (std::fabs(GetEtaDiff()) < deta && std::fabs(GetPhiStarDiff(radius)) < dphi) // return true; return false; @@ -346,6 +347,34 @@ float FemtoPair::GetMt() const return 0.5 * fourmomentasum.Mt(); } + +template +float FemtoPair::GetGammaOut() const +{ + if (_first == NULL || _second == NULL) + return -1000; + if (_magfield1 * _magfield2 == 0) + return -1000; + if (_PDG1 * _PDG2 == 0) + return -1000; + + // double Qinv = 2.0 * GetKstar(); + // TVector3 QLCMS = GetQLCMS(); + // double Qout_PRF = sqrt(Qinv * Qinv - QLCMS.Y() * QLCMS.Y() - QLCMS.Z() * QLCMS.Z()); + // return std::fabs(QLCMS.X() / Qout_PRF); + + TLorentzVector first4momentum; + first4momentum.SetPtEtaPhiM(_first->pt(), _first->eta(), _first->phi(), particle_mass(_PDG1)); + TLorentzVector second4momentum; + second4momentum.SetPtEtaPhiM(_second->pt(), _second->eta(), _second->phi(), particle_mass(_PDG2)); + + TLorentzVector fourmomentasum = first4momentum + second4momentum; + + fourmomentasum.Boost(0.0, 0.0, (-1) * fourmomentasum.BoostVector().Z()); // boost to LCMS + fourmomentasum.RotateZ((-1) * fourmomentasum.Phi()); // rotate so the X axis is along pair's kT + + return fourmomentasum.Gamma(); +} } // namespace o2::aod::singletrackselector #endif // PWGCF_FEMTO3D_CORE_FEMTO3DPAIRTASK_H_ diff --git a/PWGCF/Femto3D/DataModel/singletrackselector.h b/PWGCF/Femto3D/DataModel/singletrackselector.h index e2c739fdc08..700a27283ad 100644 --- a/PWGCF/Femto3D/DataModel/singletrackselector.h +++ b/PWGCF/Femto3D/DataModel/singletrackselector.h @@ -55,6 +55,32 @@ inline o2::framework::expressions::Node unPack(const T& b) return binningType::bin_width * b + binningType::binned_center; } +template +inline typename binningType::binned_t packSymmetric(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return (binningType::underflowBin); + } else if (valueToBin >= binningType::binned_max) { + return (binningType::overflowBin); + } else if (valueToBin >= 0) { + return (static_cast((valueToBin * binningType::inv_bin_width) + 0.5f)); + } else { + return (static_cast((valueToBin * binningType::inv_bin_width) - 0.5f)); + } +} + +template +inline float unPackSymmetric(const typename binningType::binned_t& b) +{ + return binningType::bin_width * static_cast(b); +} + +template +inline o2::framework::expressions::Node unPackSymmetric(const T& b) +{ + return binningType::bin_width * static_cast(b); +} + namespace binning { @@ -70,6 +96,7 @@ struct binningParent { static constexpr float binned_max = lim.second; static constexpr float binned_center = 0.5 * (binned_min + binned_max); static constexpr float bin_width = (binned_max - binned_min) / nbins; + static constexpr float inv_bin_width = 1. / bin_width; static_assert(binned_min < binned_max, "Invalid binning range"); static void print() { @@ -78,10 +105,15 @@ struct binningParent { } }; -using nsigma = binningParent(-10.f, 10.f)>; +using nsigma_v0 = binningParent(-10.f, 10.f)>; +using nsigma_v1 = binningParent(-6.35f, 6.35f)>; // Width 0.05 symmetric around 0 +using nsigma = nsigma_v1; + using dca_v0 = binningParent(-1.f, 1.f)>; using dca_v1 = binningParent(-1.f, 1.f), int16_t>; -using dca = dca_v1; +using dca_v2 = binningParent(-3.2767f, 3.2767f), int16_t>; // Width 0.0001 symmetric around 0 +using dca = dca_v2; + using chi2 = binningParent(0.f, 10.f)>; using rowsOverFindable = binningParent(0.f, 3.f)>; @@ -101,6 +133,7 @@ DECLARE_SOA_COLUMN(Occupancy, occupancy, int); DECLARE_SOA_DYNAMIC_COLUMN(dIsNoSameBunchPileup, isNoSameBunchPileup, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kNoSameBunchPileup); }); DECLARE_SOA_DYNAMIC_COLUMN(dIsGoodZvtxFT0vsPV, isGoodZvtxFT0vsPV, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kIsGoodZvtxFT0vsPV); }); DECLARE_SOA_DYNAMIC_COLUMN(dIsVertexITSTPC, isVertexITSTPC, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kIsVertexITSTPC); }); +DECLARE_SOA_DYNAMIC_COLUMN(dIsVertexTOForTRDmatched, isVertexTOForTRDmatched, [](uint64_t selBit) -> int { return static_cast(TESTBIT(selBit, evsel::kIsVertexTOFmatched)) + static_cast(TESTBIT(selBit, evsel::kIsVertexTRDmatched)); }); DECLARE_SOA_DYNAMIC_COLUMN(dNoCollInTimeRangeStandard, noCollInTimeRangeStandard, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kNoCollInTimeRangeStandard); }); } // namespace singletrackselector @@ -126,6 +159,7 @@ DECLARE_SOA_TABLE(SingleCollExtras_v1, "AOD", "SINGLECOLLEXTR1", // Joinable col singletrackselector::dIsNoSameBunchPileup, singletrackselector::dIsGoodZvtxFT0vsPV, singletrackselector::dIsVertexITSTPC, + singletrackselector::dIsVertexTOForTRDmatched, singletrackselector::dNoCollInTimeRangeStandard); using SingleCollExtras = SingleCollExtras_v1; @@ -155,20 +189,33 @@ DECLARE_SOA_COLUMN(StoredDcaXY, storedDcaXY, binning::dca_v0::binned_t); DECLARE_SOA_COLUMN(StoredDcaZ, storedDcaZ, binning::dca_v0::binned_t); // impact parameter of the track with 8 bits (v0) DECLARE_SOA_COLUMN(StoredDcaXY_v1, storedDcaXY_v1, binning::dca_v1::binned_t); // impact parameter of the track with 16 bits (v1) DECLARE_SOA_COLUMN(StoredDcaZ_v1, storedDcaZ_v1, binning::dca_v1::binned_t); // impact parameter of the track with 16 bits (v1) +DECLARE_SOA_COLUMN(StoredDcaXY_v2, storedDcaXY_v2, binning::dca_v2::binned_t); // impact parameter of the track with 16 bits (v2, larger range) +DECLARE_SOA_COLUMN(StoredDcaZ_v2, storedDcaZ_v2, binning::dca_v2::binned_t); // impact parameter of the track with 16 bits (v2, larger range) DECLARE_SOA_COLUMN(StoredTPCChi2NCl, storedTpcChi2NCl, binning::chi2::binned_t); // TPC chi2 DECLARE_SOA_COLUMN(StoredITSChi2NCl, storedItsChi2NCl, binning::chi2::binned_t); // ITS chi2 DECLARE_SOA_COLUMN(StoredTPCCrossedRowsOverFindableCls, storedTpcCrossedRowsOverFindableCls, binning::rowsOverFindable::binned_t); // Ratio of found over findable clusters -DECLARE_SOA_COLUMN(StoredTOFNSigmaPi, storedTofNSigmaPi, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTPCNSigmaPi, storedTpcNSigmaPi, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTOFNSigmaKa, storedTofNSigmaKa, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTPCNSigmaKa, storedTpcNSigmaKa, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTOFNSigmaPr, storedTofNSigmaPr, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTPCNSigmaPr, storedTpcNSigmaPr, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTOFNSigmaDe, storedTofNSigmaDe, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTPCNSigmaDe, storedTpcNSigmaDe, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTOFNSigmaHe, storedTofNSigmaHe, binning::nsigma::binned_t); -DECLARE_SOA_COLUMN(StoredTPCNSigmaHe, storedTpcNSigmaHe, binning::nsigma::binned_t); +DECLARE_SOA_COLUMN(StoredTOFNSigmaPi, storedTofNSigmaPi, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTPCNSigmaPi, storedTpcNSigmaPi, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTOFNSigmaKa, storedTofNSigmaKa, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTPCNSigmaKa, storedTpcNSigmaKa, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTOFNSigmaPr, storedTofNSigmaPr, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTPCNSigmaPr, storedTpcNSigmaPr, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTOFNSigmaDe, storedTofNSigmaDe, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTPCNSigmaDe, storedTpcNSigmaDe, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTOFNSigmaHe, storedTofNSigmaHe, binning::nsigma::binned_t); // (v0) +DECLARE_SOA_COLUMN(StoredTPCNSigmaHe, storedTpcNSigmaHe, binning::nsigma::binned_t); // (v0) + +DECLARE_SOA_COLUMN(StoredTOFNSigmaPi_v1, storedTofNSigmaPi_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTPCNSigmaPi_v1, storedTpcNSigmaPi_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTOFNSigmaKa_v1, storedTofNSigmaKa_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTPCNSigmaKa_v1, storedTpcNSigmaKa_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTOFNSigmaPr_v1, storedTofNSigmaPr_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTPCNSigmaPr_v1, storedTpcNSigmaPr_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTOFNSigmaDe_v1, storedTofNSigmaDe_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTPCNSigmaDe_v1, storedTpcNSigmaDe_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTOFNSigmaHe_v1, storedTofNSigmaHe_v1, binning::nsigma::binned_t); // (v1) +DECLARE_SOA_COLUMN(StoredTPCNSigmaHe_v1, storedTpcNSigmaHe_v1, binning::nsigma::binned_t); // (v1) DECLARE_SOA_DYNAMIC_COLUMN(Energy, energy, [](float p, float mass) -> float { return sqrt(p * p + mass * mass); }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float p, float eta) -> float { return p / std::cosh(eta); }); @@ -192,6 +239,12 @@ DECLARE_SOA_DYNAMIC_COLUMN(DcaXY_v1, dcaXY, [](binning::dca_v1::binned_t dca_binned) -> float { return singletrackselector::unPack(dca_binned); }); DECLARE_SOA_DYNAMIC_COLUMN(DcaZ_v1, dcaZ, [](binning::dca_v1::binned_t dca_binned) -> float { return singletrackselector::unPack(dca_binned); }); + +DECLARE_SOA_DYNAMIC_COLUMN(DcaXY_v2, dcaXY, + [](binning::dca_v2::binned_t dca_binned) -> float { return singletrackselector::unPackSymmetric(dca_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(DcaZ_v2, dcaZ, + [](binning::dca_v2::binned_t dca_binned) -> float { return singletrackselector::unPackSymmetric(dca_binned); }); + DECLARE_SOA_DYNAMIC_COLUMN(TPCChi2NCl, tpcChi2NCl, [](binning::chi2::binned_t chi2_binned) -> float { return singletrackselector::unPack(chi2_binned); }); DECLARE_SOA_DYNAMIC_COLUMN(ITSChi2NCl, itsChi2NCl, @@ -203,27 +256,47 @@ DECLARE_SOA_DYNAMIC_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFind DECLARE_SOA_DYNAMIC_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, //! Fraction of shared TPC clusters [](uint8_t tpcNClsShared, int16_t tpcNClsFound) -> float { return (float)tpcNClsShared / (float)tpcNClsFound; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPi, tofNSigmaPi, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPi, tpcNSigmaPi, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaKa, tofNSigmaKa, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaKa, tpcNSigmaKa, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); - -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr, tofNSigmaPr, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr, tpcNSigmaPr, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaDe, tofNSigmaDe, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaDe, tpcNSigmaDe, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaHe, tofNSigmaHe, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaHe, tpcNSigmaHe, - [](binning::nsigma::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPi_v0, tofNSigmaPi, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPi_v0, tpcNSigmaPi, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaKa_v0, tofNSigmaKa, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaKa_v0, tpcNSigmaKa, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr_v0, tofNSigmaPr, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr_v0, tpcNSigmaPr, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaDe_v0, tofNSigmaDe, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaDe_v0, tpcNSigmaDe, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaHe_v0, tofNSigmaHe, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaHe_v0, tpcNSigmaHe, + [](binning::nsigma_v0::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); + +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPi_v1, tofNSigmaPi, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPi_v1, tpcNSigmaPi, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaKa_v1, tofNSigmaKa, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaKa_v1, tpcNSigmaKa, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr_v1, tofNSigmaPr, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr_v1, tpcNSigmaPr, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaDe_v1, tofNSigmaDe, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaDe_v1, tpcNSigmaDe, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaHe_v1, tofNSigmaHe, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaHe_v1, tpcNSigmaHe, + [](binning::nsigma_v1::binned_t nsigma_binned) -> float { return singletrackselector::unPackSymmetric(nsigma_binned); }); DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); // Momentum at inner wall of the TPC DECLARE_SOA_COLUMN(TPCSignal, tpcSignal, float); // dE/dx TPC @@ -270,14 +343,14 @@ DECLARE_SOA_TABLE_FULL(SingleTrackSels_v0, "SelTracks", "AOD", "SINGLETRACKSEL", singletrackselector::TPCCrossedRowsOverFindableCls, singletrackselector::TPCFractionSharedCls, - singletrackselector::TOFNSigmaPi, - singletrackselector::TPCNSigmaPi, - singletrackselector::TOFNSigmaKa, - singletrackselector::TPCNSigmaKa, - singletrackselector::TOFNSigmaPr, - singletrackselector::TPCNSigmaPr, - singletrackselector::TOFNSigmaDe, - singletrackselector::TPCNSigmaDe, + singletrackselector::TOFNSigmaPi_v0, + singletrackselector::TPCNSigmaPi_v0, + singletrackselector::TOFNSigmaKa_v0, + singletrackselector::TPCNSigmaKa_v0, + singletrackselector::TOFNSigmaPr_v0, + singletrackselector::TPCNSigmaPr_v0, + singletrackselector::TOFNSigmaDe_v0, + singletrackselector::TPCNSigmaDe_v0, singletrackselector::Rapidity, singletrackselector::Energy, @@ -324,16 +397,72 @@ DECLARE_SOA_TABLE_FULL(SingleTrackSels_v1, "SelTracks", "AOD", "SINGLETRACKSEL1" singletrackselector::TPCCrossedRowsOverFindableCls, singletrackselector::TPCFractionSharedCls, - singletrackselector::TOFNSigmaPi, - singletrackselector::TPCNSigmaPi, - singletrackselector::TOFNSigmaKa, - singletrackselector::TPCNSigmaKa, - singletrackselector::TOFNSigmaPr, - singletrackselector::TPCNSigmaPr, - singletrackselector::TOFNSigmaDe, - singletrackselector::TPCNSigmaDe, - singletrackselector::TOFNSigmaHe, - singletrackselector::TPCNSigmaHe, + singletrackselector::TOFNSigmaPi_v0, + singletrackselector::TPCNSigmaPi_v0, + singletrackselector::TOFNSigmaKa_v0, + singletrackselector::TPCNSigmaKa_v0, + singletrackselector::TOFNSigmaPr_v0, + singletrackselector::TPCNSigmaPr_v0, + singletrackselector::TOFNSigmaDe_v0, + singletrackselector::TPCNSigmaDe_v0, + singletrackselector::TOFNSigmaHe_v0, + singletrackselector::TPCNSigmaHe_v0, + + singletrackselector::Rapidity, + singletrackselector::Energy, + singletrackselector::Pt, + singletrackselector::Px, + singletrackselector::Py, + singletrackselector::Pz, + singletrackselector::PhiStar); + +DECLARE_SOA_TABLE_FULL(SingleTrackSels_v2, "SelTracks", "AOD", "SINGLETRACKSEL2", // Table of the variables for single track selection. + o2::soa::Index<>, + singletrackselector::SingleCollSelId, + singletrackselector::P, + singletrackselector::Eta, + singletrackselector::Phi, + singletrackselector::Sign, + singletrackselector::TPCNClsFound, + singletrackselector::TPCNClsShared, + singletrackselector::ITSclsMap, + singletrackselector::ITSclusterSizes, + singletrackselector::StoredDcaXY_v2, + singletrackselector::StoredDcaZ_v2, + singletrackselector::StoredTPCChi2NCl, + singletrackselector::StoredITSChi2NCl, + singletrackselector::StoredTPCCrossedRowsOverFindableCls, + + singletrackselector::StoredTOFNSigmaPi_v1, + singletrackselector::StoredTPCNSigmaPi_v1, + singletrackselector::StoredTOFNSigmaKa_v1, + singletrackselector::StoredTPCNSigmaKa_v1, + singletrackselector::StoredTOFNSigmaPr_v1, + singletrackselector::StoredTPCNSigmaPr_v1, + singletrackselector::StoredTOFNSigmaDe_v1, + singletrackselector::StoredTPCNSigmaDe_v1, + singletrackselector::StoredTOFNSigmaHe_v1, + singletrackselector::StoredTPCNSigmaHe_v1, + + singletrackselector::ITSNClsDyn, + track::v001::ITSClsSizeInLayer, + singletrackselector::DcaXY_v2, + singletrackselector::DcaZ_v2, + singletrackselector::TPCChi2NCl, + singletrackselector::ITSChi2NCl, + singletrackselector::TPCCrossedRowsOverFindableCls, + singletrackselector::TPCFractionSharedCls, + + singletrackselector::TOFNSigmaPi_v1, + singletrackselector::TPCNSigmaPi_v1, + singletrackselector::TOFNSigmaKa_v1, + singletrackselector::TPCNSigmaKa_v1, + singletrackselector::TOFNSigmaPr_v1, + singletrackselector::TPCNSigmaPr_v1, + singletrackselector::TOFNSigmaDe_v1, + singletrackselector::TPCNSigmaDe_v1, + singletrackselector::TOFNSigmaHe_v1, + singletrackselector::TPCNSigmaHe_v1, singletrackselector::Rapidity, singletrackselector::Energy, @@ -343,7 +472,7 @@ DECLARE_SOA_TABLE_FULL(SingleTrackSels_v1, "SelTracks", "AOD", "SINGLETRACKSEL1" singletrackselector::Pz, singletrackselector::PhiStar); -using SingleTrackSels = SingleTrackSels_v1; +using SingleTrackSels = SingleTrackSels_v2; DECLARE_SOA_TABLE(SingleTrkExtras, "AOD", "SINGLETRKEXTRA", singletrackselector::TPCInnerParam, diff --git a/PWGCF/Femto3D/TableProducer/CMakeLists.txt b/PWGCF/Femto3D/TableProducer/CMakeLists.txt index aba3d3c728f..a0e19ed9634 100644 --- a/PWGCF/Femto3D/TableProducer/CMakeLists.txt +++ b/PWGCF/Femto3D/TableProducer/CMakeLists.txt @@ -9,16 +9,13 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +add_subdirectory(Converters) + o2physics_add_dpl_workflow(single-track-selector SOURCES singleTrackSelector.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(single-track-selector-converter - SOURCES singleTrackSelectorConverter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(single-track-selector-extra SOURCES singleTrackSelectorExtra.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGEM/PhotonMeson/TableProducer/converters/CMakeLists.txt b/PWGCF/Femto3D/TableProducer/Converters/CMakeLists.txt similarity index 55% rename from PWGEM/PhotonMeson/TableProducer/converters/CMakeLists.txt rename to PWGCF/Femto3D/TableProducer/Converters/CMakeLists.txt index 2b4e7737f59..9014f8fbe4e 100644 --- a/PWGEM/PhotonMeson/TableProducer/converters/CMakeLists.txt +++ b/PWGCF/Femto3D/TableProducer/Converters/CMakeLists.txt @@ -9,13 +9,13 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(emevents-converter - SOURCES emeventsconverter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(single-track-selector-converter + SOURCES singleTrackSelectorConverter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(ambiguous-electronid-converter - SOURCES ambElectronIdconverter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(single-track-selector-converter-v1 + SOURCES singleTrackSelectorConverterV1.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Femto3D/TableProducer/singleTrackSelectorConverter.cxx b/PWGCF/Femto3D/TableProducer/Converters/singleTrackSelectorConverter.cxx similarity index 98% rename from PWGCF/Femto3D/TableProducer/singleTrackSelectorConverter.cxx rename to PWGCF/Femto3D/TableProducer/Converters/singleTrackSelectorConverter.cxx index 2fe7126ff95..4a44e331e9b 100644 --- a/PWGCF/Femto3D/TableProducer/singleTrackSelectorConverter.cxx +++ b/PWGCF/Femto3D/TableProducer/Converters/singleTrackSelectorConverter.cxx @@ -26,7 +26,7 @@ using namespace o2::aod; //::singletrackselector; // the namespace defined in .h struct singleTrackSelectorConverter { - Produces tableRow; + Produces tableRow; void init(InitContext&) {} diff --git a/PWGCF/Femto3D/TableProducer/Converters/singleTrackSelectorConverterV1.cxx b/PWGCF/Femto3D/TableProducer/Converters/singleTrackSelectorConverterV1.cxx new file mode 100644 index 00000000000..584760ce74a --- /dev/null +++ b/PWGCF/Femto3D/TableProducer/Converters/singleTrackSelectorConverterV1.cxx @@ -0,0 +1,68 @@ +// Copyright 2019-2020 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. +// +/// \brief Converter for the different versions of the singletrackselector tables +/// \author Sofia Tomassini, Gleb Romanenko, NicolĂČ Jacazio +/// \since 03 May 2024 + +#include +#include "PWGCF/Femto3D/DataModel/singletrackselector.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::track; +using namespace o2::aod; +//::singletrackselector; // the namespace defined in .h + +struct singleTrackSelectorConverter { + Produces tableRow; + + void init(InitContext&) {} + + void process(o2::aod::SingleTrackSels_v1 const& tracks) + { + tableRow.reserve(tracks.size()); + for (auto const& track : tracks) { + tableRow(track.singleCollSelId(), + track.p(), + track.eta(), + track.phi(), + track.sign(), + track.tpcNClsFound(), + track.tpcNClsShared(), + track.itsClsMap(), + track.itsClusterSizes(), + singletrackselector::packSymmetric(track.dcaXY()), + singletrackselector::packSymmetric(track.dcaZ()), + singletrackselector::packInTable(track.tpcChi2NCl()), + singletrackselector::packInTable(track.itsChi2NCl()), + singletrackselector::packInTable(track.tpcCrossedRowsOverFindableCls()), + singletrackselector::packSymmetric(track.tofNSigmaPi()), + singletrackselector::packSymmetric(track.tpcNSigmaPi()), + singletrackselector::packSymmetric(track.tofNSigmaKa()), + singletrackselector::packSymmetric(track.tpcNSigmaKa()), + singletrackselector::packSymmetric(track.tofNSigmaPr()), + singletrackselector::packSymmetric(track.tpcNSigmaPr()), + singletrackselector::packSymmetric(track.tofNSigmaDe()), + singletrackselector::packSymmetric(track.tpcNSigmaDe()), + singletrackselector::packSymmetric(track.tofNSigmaHe()), + singletrackselector::packSymmetric(track.tpcNSigmaHe())); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx b/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx index 8172d07bbf0..c9a8a6f8a4f 100644 --- a/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx +++ b/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx @@ -204,22 +204,21 @@ struct singleTrackSelector { track.tpcNClsShared(), track.itsClusterMap(), track.itsClusterSizes(), - - singletrackselector::packInTable(track.dcaXY()), - singletrackselector::packInTable(track.dcaZ()), + singletrackselector::packSymmetric(track.dcaXY()), + singletrackselector::packSymmetric(track.dcaZ()), singletrackselector::packInTable(track.tpcChi2NCl()), singletrackselector::packInTable(track.itsChi2NCl()), singletrackselector::packInTable(track.tpcCrossedRowsOverFindableCls()), - singletrackselector::packInTable(track.tofNSigmaPi()), - singletrackselector::packInTable(track.tpcNSigmaPi()), - singletrackselector::packInTable(track.tofNSigmaKa()), - singletrackselector::packInTable(track.tpcNSigmaKa()), - singletrackselector::packInTable(track.tofNSigmaPr()), - singletrackselector::packInTable(track.tpcNSigmaPr()), - singletrackselector::packInTable(track.tofNSigmaDe()), - singletrackselector::packInTable(track.tpcNSigmaDe()), - singletrackselector::packInTable(track.tofNSigmaHe()), - singletrackselector::packInTable(track.tpcNSigmaHe())); + singletrackselector::packSymmetric(track.tofNSigmaPi()), + singletrackselector::packSymmetric(track.tpcNSigmaPi()), + singletrackselector::packSymmetric(track.tofNSigmaKa()), + singletrackselector::packSymmetric(track.tpcNSigmaKa()), + singletrackselector::packSymmetric(track.tofNSigmaPr()), + singletrackselector::packSymmetric(track.tpcNSigmaPr()), + singletrackselector::packSymmetric(track.tofNSigmaDe()), + singletrackselector::packSymmetric(track.tpcNSigmaDe()), + singletrackselector::packSymmetric(track.tofNSigmaHe()), + singletrackselector::packSymmetric(track.tpcNSigmaHe())); tableRowExtra(track.tpcInnerParam(), track.tpcSignal(), @@ -492,7 +491,7 @@ struct singleTrackSelector { return; } - if (abs(mcCollision.posZ()) > _vertexZ) { + if (std::fabs(mcCollision.posZ()) > _vertexZ) { return; } diff --git a/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx b/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx index 9fd088e0350..045dc9ad2d8 100644 --- a/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx @@ -50,6 +50,7 @@ struct FemtoCorrelations { Configurable _removeSameBunchPileup{"removeSameBunchPileup", false, ""}; Configurable _requestGoodZvtxFT0vsPV{"requestGoodZvtxFT0vsPV", false, ""}; Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; + Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; @@ -96,6 +97,7 @@ struct FemtoCorrelations { ConfigurableAxis CFkStarBinning{"CFkStarBinning", {500, 0.005, 5.005}, "k* binning of the CF (Nbins, lowlimit, uplimit)"}; Configurable _fill3dCF{"fill3dCF", false, "flag for filling 3D LCMS histos: true -- fill; false -- not"}; + Configurable _fill3dAddHistos{"fill3dAddHistos", 1, "flag for filling additional 3D histos: 0 -- nothing; 1 -- Q_LCMS vs. k*; 2 -- Q_LCMS vs. Gamma_out (currently testing)"}; Configurable _fillDetaDphi{"fillDetaDphi", -1, "flag for filling dEta(dPhi*) histos: '-1' -- don't fill; '0' -- fill before the cut; '1' -- fill after the cut; '2' -- fill before & after the cut"}; ConfigurableAxis CF3DqLCMSBinning{"CF3DqLCMSBinning", {60, -0.3, 0.3}, "q_out/side/long binning of the CF 3D in LCMS (Nbins, lowlimit, uplimit)"}; // the next configarable is responsible for skipping (pseudo)randomly chosen ($value -1) pairs of events in the mixing process @@ -146,7 +148,7 @@ struct FemtoCorrelations { std::vector>> SEhistos_3D; std::vector>> MEhistos_3D; - std::vector>> qLCMSvskStar; + std::vector>> Add3dHistos; std::vector>> DoubleTrack_SE_histos_BC; // BC -- before cutting std::vector>> DoubleTrack_ME_histos_BC; // BC -- before cutting @@ -203,19 +205,26 @@ struct FemtoCorrelations { if (_fill3dCF) { std::vector> SEperMult_3D; std::vector> MEperMult_3D; - std::vector> qLCMSvskStarperMult; + std::vector> Add3dHistosperMult; for (unsigned int j = 0; j < _kTbins.value.size() - 1; j++) { auto hSE_3D = registry.add(Form("Cent%i/SE_3D_cent%i_kT%i", i, i, j), Form("SE_3D_cent%i_kT%i", i, j), kTH3F, {{CF3DqLCMSBinning, "q_out (GeV/c)"}, {CF3DqLCMSBinning, "q_side (GeV/c)"}, {CF3DqLCMSBinning, "q_long (GeV/c)"}}); auto hME_3D = registry.add(Form("Cent%i/ME_3D_cent%i_kT%i", i, i, j), Form("ME_3D_cent%i_kT%i", i, j), kTH3F, {{CF3DqLCMSBinning, "q_out (GeV/c)"}, {CF3DqLCMSBinning, "q_side (GeV/c)"}, {CF3DqLCMSBinning, "q_long (GeV/c)"}}); - auto hqLCMSvskStar = registry.add(Form("Cent%i/qLCMSvskStar_cent%i_kT%i", i, i, j), Form("qLCMSvskStar_cent%i_kT%i", i, j), kTH3F, {{CF3DqLCMSBinning, "q_out (GeV/c)"}, {CF3DqLCMSBinning, "q_side (GeV/c)"}, {CF3DqLCMSBinning, "q_long (GeV/c)"}}); SEperMult_3D.push_back(std::move(hSE_3D)); MEperMult_3D.push_back(std::move(hME_3D)); - qLCMSvskStarperMult.push_back(std::move(hqLCMSvskStar)); + + if (_fill3dAddHistos == 1) { + auto hAdd3dHistos = registry.add(Form("Cent%i/qLCMSvskStar_cent%i_kT%i", i, i, j), Form("qLCMSvskStar_cent%i_kT%i", i, j), kTH3F, {{CF3DqLCMSBinning, "q_out (GeV/c)"}, {CF3DqLCMSBinning, "q_side (GeV/c)"}, {CF3DqLCMSBinning, "q_long (GeV/c)"}}); + Add3dHistosperMult.push_back(std::move(hAdd3dHistos)); + } else if (_fill3dAddHistos == 2) { + auto hAdd3dHistos = registry.add(Form("Cent%i/qLCMSvsGout_cent%i_kT%i", i, i, j), Form("qLCMSvsGout_cent%i_kT%i", i, j), kTH3F, {{CF3DqLCMSBinning, "q_out (GeV/c)"}, {CF3DqLCMSBinning, "q_side (GeV/c)"}, {CF3DqLCMSBinning, "q_long (GeV/c)"}}); + Add3dHistosperMult.push_back(std::move(hAdd3dHistos)); + } } SEhistos_3D.push_back(std::move(SEperMult_3D)); MEhistos_3D.push_back(std::move(MEperMult_3D)); - qLCMSvskStar.push_back(std::move(qLCMSvskStarperMult)); + if (_fill3dAddHistos != 0) + Add3dHistos.push_back(std::move(Add3dHistosperMult)); } if (_fillDetaDphi > -1) { @@ -365,7 +374,10 @@ struct FemtoCorrelations { std::mt19937 mt(std::chrono::steady_clock::now().time_since_epoch().count()); TVector3 qLCMS = std::pow(-1, (mt() % 2)) * Pair->GetQLCMS(); // introducing randomness to the pair order ([first, second]); important only for 3D because if there are any sudden order/correlation in the tables, it could couse unwanted asymmetries in the final 3d rel. momentum distributions; irrelevant in 1D case because the absolute value of the rel.momentum is taken MEhistos_3D[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z()); - qLCMSvskStar[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z(), Pair->GetKstar()); + if (_fill3dAddHistos == 1) + Add3dHistos[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z(), Pair->GetKstar()); + else if (_fill3dAddHistos == 2) + Add3dHistos[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z(), Pair->GetGammaOut()); } } Pair->ResetPair(); @@ -379,7 +391,7 @@ struct FemtoCorrelations { LOGF(fatal, "One of passed PDG is 0!!!"); for (auto track : tracks) { - if (abs(track.template singleCollSel_as>().posZ()) > _vertexZ) + if (std::fabs(track.template singleCollSel_as>().posZ()) > _vertexZ) continue; if (_removeSameBunchPileup && !track.template singleCollSel_as>().isNoSameBunchPileup()) continue; @@ -387,6 +399,8 @@ struct FemtoCorrelations { continue; if (_requestVertexITSTPC && !track.template singleCollSel_as>().isVertexITSTPC()) continue; + if (_requestVertexTOForTRDmatched > track.template singleCollSel_as>().isVertexTOForTRDmatched()) + continue; if (_requestNoCollInTimeRangeStandard && !track.template singleCollSel_as>().noCollInTimeRangeStandard()) continue; if (track.tpcFractionSharedCls() > _tpcFractionSharedCls || track.itsNCls() < _itsNCls) @@ -397,7 +411,7 @@ struct FemtoCorrelations { continue; if (track.template singleCollSel_as>().occupancy() < _OccupancyCut.value.first || track.template singleCollSel_as>().occupancy() >= _OccupancyCut.value.second) continue; - if (abs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || abs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) + if (std::fabs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || std::fabs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) continue; if (track.sign() == _sign_1 && (track.p() < _PIDtrshld_1 ? o2::aod::singletrackselector::TPCselection(track, TPCcuts_1) : o2::aod::singletrackselector::TOFselection(track, TOFcuts_1, _tpcNSigmaResidual_1.value))) { // filling the map: eventID <-> selected particles1 @@ -461,6 +475,8 @@ struct FemtoCorrelations { continue; if (_requestVertexITSTPC && !collision.isVertexITSTPC()) continue; + if (_requestVertexTOForTRDmatched > collision.isVertexTOForTRDmatched()) + continue; if (_requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) continue; diff --git a/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx b/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx index 5ef7ba395f5..4c095f134df 100644 --- a/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx @@ -46,6 +46,7 @@ struct FemtoCorrelationsMC { Configurable _removeSameBunchPileup{"removeSameBunchPileup", false, ""}; Configurable _requestGoodZvtxFT0vsPV{"requestGoodZvtxFT0vsPV", false, ""}; Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; + Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; @@ -320,7 +321,7 @@ struct FemtoCorrelationsMC { int trackPDG, trackOrigin; for (auto track : tracks) { - if (abs(track.template singleCollSel_as>().posZ()) > _vertexZ) + if (std::fabs(track.template singleCollSel_as>().posZ()) > _vertexZ) continue; if (track.tpcFractionSharedCls() > _tpcFractionSharedCls || track.itsNCls() < _itsNCls) continue; @@ -336,6 +337,8 @@ struct FemtoCorrelationsMC { continue; if (_requestVertexITSTPC && !track.template singleCollSel_as>().isVertexITSTPC()) continue; + if (_requestVertexTOForTRDmatched > track.template singleCollSel_as>().isVertexTOForTRDmatched()) + continue; if (_requestNoCollInTimeRangeStandard && !track.template singleCollSel_as>().noCollInTimeRangeStandard()) continue; @@ -348,7 +351,7 @@ struct FemtoCorrelationsMC { if (trackOrigin > -1 && trackOrigin < 3) DCA_histos_1[centBin][track.origin()]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); - if (abs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || abs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) + if (std::fabs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || std::fabs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) continue; trackPDG = abs(track.pdgCode()); @@ -369,7 +372,7 @@ struct FemtoCorrelationsMC { if (trackOrigin > -1 && trackOrigin < 3) DCA_histos_2[centBin][track.origin()]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); - if (abs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || abs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) + if (std::fabs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || std::fabs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) continue; trackPDG = abs(track.pdgCode()); @@ -396,6 +399,8 @@ struct FemtoCorrelationsMC { continue; if (_requestVertexITSTPC && !collision.isVertexITSTPC()) continue; + if (_requestVertexTOForTRDmatched > collision.isVertexTOForTRDmatched()) + continue; if (_requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) continue; diff --git a/PWGCF/Femto3D/Tasks/femto3dQA.cxx b/PWGCF/Femto3D/Tasks/femto3dQA.cxx index de48ac330dd..e544b1bdacb 100644 --- a/PWGCF/Femto3D/Tasks/femto3dQA.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dQA.cxx @@ -43,6 +43,7 @@ struct QAHistograms { Configurable _removeSameBunchPileup{"removeSameBunchPileup", false, ""}; Configurable _requestGoodZvtxFT0vsPV{"requestGoodZvtxFT0vsPV", false, ""}; Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; + Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; @@ -155,6 +156,8 @@ struct QAHistograms { continue; if (_requestVertexITSTPC && !collision.isVertexITSTPC()) continue; + if (_requestVertexTOForTRDmatched > collision.isVertexTOForTRDmatched()) + continue; if (_requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) continue; if (collision.multPerc() < _centCut.value.first || collision.multPerc() >= _centCut.value.second) @@ -178,10 +181,12 @@ struct QAHistograms { continue; if (_requestVertexITSTPC && !track.template singleCollSel_as().isVertexITSTPC()) continue; + if (_requestVertexTOForTRDmatched > track.template singleCollSel_as().isVertexTOForTRDmatched()) + continue; if (_requestNoCollInTimeRangeStandard && !track.template singleCollSel_as().noCollInTimeRangeStandard()) continue; - if (abs(track.template singleCollSel_as().posZ()) > _vertexZ) + if (std::fabs(track.template singleCollSel_as().posZ()) > _vertexZ) continue; if (track.template singleCollSel_as().multPerc() < _centCut.value.first || track.template singleCollSel_as().multPerc() >= _centCut.value.second) continue; @@ -191,7 +196,7 @@ struct QAHistograms { continue; if ((track.tpcFractionSharedCls()) > _tpcFractionSharedCls || (track.itsNCls()) < _itsNCls) continue; - if (abs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || abs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) + if (std::fabs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || std::fabs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) continue; if constexpr (FillExtra) { diff --git a/PWGCF/Femto3D/Tools/checkPacking.cxx b/PWGCF/Femto3D/Tools/checkPacking.cxx index baa4322e553..51d26443200 100644 --- a/PWGCF/Femto3D/Tools/checkPacking.cxx +++ b/PWGCF/Femto3D/Tools/checkPacking.cxx @@ -24,22 +24,45 @@ using namespace o2; template -bool process(std::string outputName, int nevents = 100000) +bool process(const TString outputName, const int nevents = 100000) { class Container { public: Container() {} - void operator()(const float toPack) { mPacked = aod::singletrackselector::packInTable(toPack); } + void operator()(const float toPack) { mPacked = aod::singletrackselector::packSymmetric(toPack); } + void test(const float toPack) + { + auto bin = aod::singletrackselector::packSymmetric(toPack); + LOG(info) << toPack << " goes to " << aod::singletrackselector::unPackSymmetric(bin) << " bin " << static_cast(bin); + } T::binned_t mPacked = 0; - float unpack() { return aod::singletrackselector::unPack(mPacked); } + float unpack() { return aod::singletrackselector::unPackSymmetric(mPacked); } } container; - const float min = T::binned_min - 2; - const float max = T::binned_max + 2; + T::print(); + const float min = T::binned_min; + const float max = T::binned_max; + container.test(0); + container.test(0 + T::bin_width); + container.test(0 - T::bin_width); + container.test(0 - T::bin_width * 0.5); + const int nbins = (max - min) / T::bin_width; + std::vector xbins; + for (int i = 0; i <= nbins; i++) { + const float x = min + i * T::bin_width; + const auto ix = aod::singletrackselector::packSymmetric(x); + const float u = aod::singletrackselector::unPackSymmetric(ix); + LOG(info) << "Bin " << i << "/" << xbins.size() << " " << x << " => " << static_cast(ix) << " " << u; + if (i > 1) { + if (ix == aod::singletrackselector::packSymmetric(xbins.back())) { + continue; + } + } + xbins.push_back(u); + } LOG(info) << "Min = " << min << " Max = " << max; - TH1F* hgaus = new TH1F("hgaus", "", (max - min) / T::bin_width, - min, max); + TH1F* hgaus = new TH1F("hgaus", "", nbins, min + T::bin_width * 0.5, max + 0.5 * T::bin_width); hgaus->Print(); LOG(info) << "Bin width = " << T::bin_width << " vs histo " << hgaus->GetXaxis()->GetBinWidth(1); hgaus->SetLineColor(2); @@ -56,31 +79,47 @@ bool process(std::string outputName, int nevents = 100000) huniformPacked->SetLineStyle(2); for (int i = 0; i < nevents; i++) { - float nsigma = gRandom->Gaus(0, 1); - hgaus->Fill(nsigma); - aod::pidutils::packInTable(nsigma, container); + float randomValue = gRandom->Gaus(0, 1); + hgaus->Fill(randomValue); + container(randomValue); hgausPacked->Fill(container.unpack()); - nsigma = gRandom->Uniform(-10, 10); - huniform->Fill(nsigma); - aod::pidutils::packInTable(nsigma, container); + randomValue = gRandom->Uniform(-10, 10); + huniform->Fill(randomValue); + container(randomValue); huniformPacked->Fill(container.unpack()); } TCanvas* can = new TCanvas("can"); hgaus->Draw(); hgausPacked->Draw("same"); - outputName = "/tmp/" + outputName + ".pdf"; - can->SaveAs(Form("%s[", outputName.c_str())); - can->SaveAs(outputName.c_str()); + TString imgoutputName = "/tmp/" + outputName + ".pdf"; + can->SaveAs("/tmp/" + outputName + "_Gaus.root"); + can->SaveAs(Form("%s[", imgoutputName.Data())); + can->SaveAs(imgoutputName.Data()); huniform->Draw(); huniformPacked->Draw("same"); - can->SaveAs(outputName.c_str()); - can->SaveAs(Form("%s]", outputName.c_str())); + can->SaveAs(imgoutputName.Data()); + can->SaveAs(Form("%s]", imgoutputName.Data())); const bool gausOk = (hgaus->GetBinContent(hgaus->FindBin(0)) == hgausPacked->GetBinContent(hgausPacked->FindBin(0))); + if (!gausOk) { + LOG(info) << "Gaus packing/unpacking failed"; + } + const bool gausMeanOk = (hgaus->GetMean() == hgausPacked->GetMean()); + if (!gausMeanOk) { + LOG(info) << "Gaus packing/unpacking mean failed"; + } + const bool uniformOk = (huniform->GetBinContent(huniform->FindBin(0)) == huniformPacked->GetBinContent(huniformPacked->FindBin(0))); - return gausOk && uniformOk; + if (!uniformOk) { + LOG(info) << "Uniform packing/unpacking failed"; + } + const bool uniformMeanOk = (huniform->GetMean() == huniformPacked->GetMean()); + if (!uniformMeanOk) { + LOG(info) << "Uniform packing/unpacking mean failed"; + } + return gausOk && uniformOk && gausMeanOk && uniformMeanOk; } int main(int /*argc*/, char* /*argv*/[]) @@ -93,4 +132,11 @@ int main(int /*argc*/, char* /*argv*/[]) LOG(fatal) << "Packing and unpacking of PID signals (nsigmas) in the Femto PID response is incorrect."; } + LOG(info) << "Checking the packing and unpacking of PID signals (dca) in the Femto DCA."; + if (process("Dca", 100000)) { + LOG(info) << "Packing and unpacking of DCA signals (dca) in the Femto is correct."; + } else { + LOG(fatal) << "Packing and unpacking of DCA signals (dca) in the Femto is incorrect."; + } + } // main diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainer.h b/PWGCF/FemtoDream/Core/femtoDreamContainer.h index dace1424255..8a9038e6198 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainer.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainer.h @@ -280,7 +280,21 @@ class FemtoDreamContainer setPair_base(femtoObs, mT, part1, part2, mult, multPercentile, use4dplots, extendedplots); if constexpr (isMC) { - if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + if constexpr (isHF) { + // calculate the femto observable and the mT with MC truth information + if constexpr (mFemtoObs == femtoDreamContainer::Observable::kstar) { + femtoObsMC = FemtoDreamMath::getkstar(part1.fdMCParticle(), mMassOne, part2, mMassTwo); + } + const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2, mMassTwo); + + if (abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2, mult, multPercentile, use4dplots, extendedplots); + setPair_MC(femtoObsMC, femtoObs, mT, mult, part1.fdMCParticle().partOriginMCTruth(), part2.flagMc(), smearingByOrigin); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); + } + + } else if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { // calculate the femto observable and the mT with MC truth information if constexpr (mFemtoObs == femtoDreamContainer::Observable::kstar) { femtoObsMC = FemtoDreamMath::getkstar(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); diff --git a/PWGCF/FemtoDream/Core/femtoDreamUtils.h b/PWGCF/FemtoDream/Core/femtoDreamUtils.h index 1d6cb84b78c..92718a9d176 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamUtils.h +++ b/PWGCF/FemtoDream/Core/femtoDreamUtils.h @@ -121,6 +121,9 @@ inline float getMass(int pdgCode) case kLambda0: // Lambda mass = o2::constants::physics::MassLambda; break; + case o2::constants::physics::Pdg::kPhi: // Phi Meson + mass = o2::constants::physics::MassPhi; + break; case o2::constants::physics::Pdg::kLambdaCPlus: // Charm Lambda mass = o2::constants::physics::MassLambdaCPlus; break; diff --git a/PWGCF/FemtoDream/TableProducer/CMakeLists.txt b/PWGCF/FemtoDream/TableProducer/CMakeLists.txt index 0f8d87d9570..569a6de54cc 100644 --- a/PWGCF/FemtoDream/TableProducer/CMakeLists.txt +++ b/PWGCF/FemtoDream/TableProducer/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(femtodream-producer SOURCES femtoDreamProducerTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(femtodream-producer-reduced diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx index 4243d24cfe9..083415af5ec 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx @@ -14,6 +14,7 @@ /// \author Laura Serksnyte, TU MĂŒnchen, laura.serksnyte@tum.de #include +#include #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -31,11 +32,12 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "Math/Vector4D.h" +#include "EventFiltering/Zorro.h" #include "PWGCF/DataModel/FemtoDerived.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" #include "TMath.h" +#include "Math/Vector4D.h" using namespace o2; using namespace o2::framework; @@ -46,6 +48,7 @@ namespace o2::aod { using FemtoFullCollision = soa::Join::iterator; +using FemtoFullCollision_noCent = soa::Join::iterator; using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullCollision_noCent_MC = soa::Join::iterator; using FemtoFullMCgenCollisions = soa::Join; @@ -57,6 +60,14 @@ using FemtoFullTracks = aod::pidTOFFullEl, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe>; } // namespace o2::aod +namespace softwareTriggers +{ +static const int nTriggers = 6; +static const std::vector triggerNames{"fPPP", "fPPL", "fPLL", "fLLL", "fPD", "fLD"}; +static const float triggerSwitches[1][nTriggers]{ + {0, 0, 0, 0, 0, 0}}; +} // namespace softwareTriggers + template int getRowDaughters(int daughID, T const& vecID) { @@ -72,6 +83,8 @@ int getRowDaughters(int daughID, T const& vecID) struct femtoDreamProducerTask { + Zorro zorro; + Produces outputCollision; Produces outputMCCollision; Produces outputCollsMCLabels; @@ -88,12 +101,21 @@ struct femtoDreamProducerTask { /// Event cuts FemtoDreamCollisionSelection colCuts; + // Event cuts - Triggers + Configurable ConfEnableTriggerSelection{"ConfEnableTriggerSelection", false, "Should the trigger selection be enabled for collisions?"}; + Configurable> ConfTriggerSwitches{ + "ConfTriggerSwitches", + {softwareTriggers::triggerSwitches[0], 1, softwareTriggers::nTriggers, std::vector{"Switch"}, softwareTriggers::triggerNames}, + "Turn on which trigger should be checked for recorded events to pass selection"}; + + // Event cuts - usual selection criteria Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", true, "Evt sel: check for trigger"}; Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", kINT7, "Evt sel: trigger"}; Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", false, "Evt sel: check for offline selection"}; Configurable ConfEvtAddOfflineCheck{"ConfEvtAddOfflineCheck", false, "Evt sel: additional checks for offline selection (not part of sel8 yet)"}; Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtodream tables"}; + Configurable ConfIsActivateReso{"ConfIsActivateReso", false, "Activate filling of sl Resonances into femtodream tables"}; Configurable ConfTrkRejectNotPropagated{"ConfTrkRejectNotPropagated", false, "True: reject not propagated tracks"}; // Configurable ConfRejectITSHitandTOFMissing{ "ConfRejectITSHitandTOFMissing", false, "True: reject if neither ITS hit nor TOF timing satisfied"}; @@ -140,6 +162,22 @@ struct femtoDreamProducerTask { Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{5.f, 4.f}, "V0 Child sel: Max. PID nSigma TPC"}; Configurable> ConfChildPIDspecies{"ConfChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; + Configurable ConfResoInvMassLowLimit{"ConfResoInvMassLowLimit", 1.011461, "Lower limit of the Reso invariant mass"}; + Configurable ConfResoInvMassUpLimit{"ConfResoInvMassUpLimit", 1.027461, "Upper limit of the Reso invariant mass"}; + Configurable> ConfDaughterCharge{"ConfDaughterCharge", std::vector{1, -1}, "Reso Daughter sel: Charge"}; + Configurable> ConfDaughterEta{"ConfDaughterEta", std::vector{0.8, 0.8}, "Reso Daughter sel: Eta"}; // 0.8 + Configurable> ConfDaughterDCAxy{"ConfDaughterDCAxy", std::vector{0.1, 0.1}, "Reso Daughter sel: DCAxy"}; // 0.1 + Configurable> ConfDaughterDCAz{"ConfDaughterDCAz", std::vector{0.2, 0.2}, "Reso Daughter sel: DCAz"}; // 0.2 + Configurable> ConfDaughterNClus{"ConfDaughterNClus", std::vector{80, 80}, "Reso Daughter sel: NClusters"}; // 0.2 + Configurable> ConfDaughterNCrossed{"ConfDaughterNCrossed", std::vector{70, 70}, "Reso Daughter sel: NCrossedRowss"}; + Configurable> ConfDaughterTPCfCls{"ConfDaughterTPCfCls", std::vector{0.8, 0.8}, "Reso Daughter sel: Minimum fraction of crossed rows over findable cluster"}; // 0.2 + Configurable> ConfDaughterPtUp{"ConfDaughterPtUp", std::vector{2.0, 2.0}, "Reso Daughter sel: Upper limit pT"}; // 2.0 + Configurable> ConfDaughterPtLow{"ConfDaughterPtLow", std::vector{0.15, 0.15}, "Reso Daughter sel: Lower limit pT"}; // 0.15 + Configurable> ConfDaughterPTPCThr{"ConfDaughterPTPCThr", std::vector{0.40, 0.40}, "Reso Daughter sel: momentum threshold TPC only PID, p_TPC,Thr"}; // 0.4 + Configurable> ConfDaughterPIDnSigmaMax{"ConfDaughterPIDnSigmaMax", std::vector{3.00, 3.00}, "Reso Daughter sel: Max. PID nSigma TPC"}; // 3.0 + Configurable> ConfDaughterPIDspecies{"ConfDaughterPIDspecies", std::vector{o2::track::PID::Kaon, o2::track::PID::Kaon}, "Reso Daughter sel: Particles species for PID"}; + Configurable> ConfDaug1Daugh2ResoMass{"ConfDaug1Daugh2ResoMass", std::vector{o2::constants::physics::MassKPlus, o2::constants::physics::MassKMinus, o2::constants::physics::MassPhi}, "Masses: Daughter1 - Daughter2 - Resonance"}; + /// \todo should we add filter on min value pT/eta of V0 and daughters? /*Filter v0Filter = (nabs(aod::v0data::x) < V0DecVtxMax.value) && (nabs(aod::v0data::y) < V0DecVtxMax.value) && @@ -150,17 +188,19 @@ struct femtoDreamProducerTask { HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry TrackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry V0Registry{"V0", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry ResoRegistry{"Reso", {}, OutputObjHandlingPolicy::AnalysisObject}; int mRunNumber; float mMagField; + std::string zorroTriggerNames = ""; Service ccdb; /// Accessing the CCDB void init(InitContext&) { - if (doprocessData == false && doprocessMC == false && doprocessMC_noCentrality == false) { + if (doprocessData == false && doprocessData_noCentrality == false && doprocessMC == false && doprocessMC_noCentrality == false) { LOGF(fatal, "Neither processData nor processMC enabled. Please choose one."); } - if ((doprocessData == true && doprocessMC == true) || (doprocessData == true && doprocessMC_noCentrality == true) || (doprocessMC == true && doprocessMC_noCentrality == true)) { + if ((doprocessData == true && doprocessMC == true) || (doprocessData == true && doprocessMC_noCentrality == true) || (doprocessMC == true && doprocessMC_noCentrality == true) || (doprocessData_noCentrality == true && doprocessData == true) || (doprocessData_noCentrality == true && doprocessMC == true) || (doprocessData_noCentrality == true && doprocessMC_noCentrality == true)) { LOGF(fatal, "Cannot enable more than one process switch at the same time. " "Please choose one."); @@ -169,6 +209,25 @@ struct femtoDreamProducerTask { int CutBits = 8 * sizeof(o2::aod::femtodreamparticle::cutContainerType); TrackRegistry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); V0Registry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + ResoRegistry.add("AnalysisQA/Reso/InvMass", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + ResoRegistry.add("AnalysisQA/Reso/InvMass_selected", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Pt", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Eta", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Phi", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Pt", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Eta", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Phi", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/PtD1_selected", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/PtD2_selected", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + + if (ConfEnableTriggerSelection) { + for (const std::string& triggerName : softwareTriggers::triggerNames) { + if (ConfTriggerSwitches->get("Switch", triggerName.c_str())) { + zorroTriggerNames += triggerName + ","; + } + } + zorroTriggerNames.pop_back(); + } colCuts.setCuts(ConfEvtZvtx.value, ConfEvtTriggerCheck.value, ConfEvtTriggerSel.value, ConfEvtOfflineCheck.value, ConfEvtAddOfflineCheck.value, ConfIsRun3.value); colCuts.init(&qaRegistry); @@ -243,7 +302,7 @@ struct femtoDreamProducerTask { } /// Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T - void getMagneticFieldTesla(aod::BCsWithTimestamps::iterator bc) + void initCCDB_Mag_Trig(aod::BCsWithTimestamps::iterator bc) { // TODO done only once (and not per run). Will be replaced by CCDBConfigurable // get magnetic field for run @@ -277,6 +336,11 @@ struct femtoDreamProducerTask { } mMagField = output; mRunNumber = bc.runNumber(); + + // Init for zorro to get trigger flags + if (ConfEnableTriggerSelection) { + zorro.initCCDB(ccdb.service, mRunNumber, timestamp, zorroTriggerNames); + } } template @@ -327,27 +391,37 @@ struct femtoDreamProducerTask { auto pdgCode = particleMC.pdgCode(); int particleOrigin = 99; int pdgCodeMother = -1; - // get list of mothers - // could be empty (for example in case of injected light nuclei) + // get list of mothers, but it could be empty (for example in case of injected light nuclei) auto motherparticlesMC = particleMC.template mothers_as(); // check pdg code + // if this fails, the particle is a fake if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { + // check first if particle is from pile up + // check if the collision associated with the particle is the same as the analyzed collision by checking their Ids if ((col.has_mcCollision() && (particleMC.mcCollisionId() != col.mcCollisionId())) || !col.has_mcCollision()) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kWrongCollision; + // check if particle is primary } else if (particleMC.isPhysicalPrimary()) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kPrimary; - } else if (particleMC.getGenStatusCode() == -1) { - particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kMaterial; - } else if (!motherparticlesMC.empty()) { - // get direct mother of the particle + // check if particle is secondary + // particle is from a decay -> getProcess() == 4 + // particle is generated during transport -> getGenStatusCode() == -1 + // list of mothers is not empty + } else if (particleMC.getProcess() == 4 && particleMC.getGenStatusCode() == -1 && !motherparticlesMC.empty()) { + // get direct mother auto motherparticleMC = motherparticlesMC.front(); pdgCodeMother = motherparticleMC.pdgCode(); - if (motherparticleMC.isPhysicalPrimary() && particleMC.getProcess() == 4) { - particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); - } + particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); + // check if particle is material + // particle is from inelastic hadronic interaction -> getProcess() == 23 + // particle is generated during transport -> getGenStatusCode() == -1 + } else if (particleMC.getProcess() == 23 && particleMC.getGenStatusCode() == -1) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kMaterial; + // cross check to see if we missed a case } else { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kElse; } + // if pdg code is wrong, particle is fake } else { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kFake; } @@ -380,6 +454,14 @@ struct femtoDreamProducerTask { template void fillCollisionsAndTracksAndV0(CollisionType const& col, TrackType const& tracks, V0Type const& fullV0s) { + // If triggering is enabled, select only events which were triggered wit our triggers + if (ConfEnableTriggerSelection) { + bool zorroSelected = zorro.isSelected(col.template bc_as().globalBC()); /// check if event was selected by triggers of interest + if (!zorroSelected) { + return; + } + } + const auto vtxZ = col.posZ(); const auto spher = colCuts.computeSphericity(col, tracks); float mult = 0; @@ -420,6 +502,7 @@ struct femtoDreamProducerTask { std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index + std::vector Daughter1, Daughter2; for (auto& track : tracks) { /// if the most open selection criteria are not fulfilled there is no @@ -448,6 +531,32 @@ struct femtoDreamProducerTask { if constexpr (isMC) { fillMCParticle(col, track, o2::aod::femtodreamparticle::ParticleType::kTrack); } + + if (ConfIsActivateReso.value) { + // Already strict cuts for Daughter of reso selection + // TO DO: change TTV0 task to apply there the strict selection and have here only loose selection + + // select daugher 1 + if (track.sign() == ConfDaughterCharge.value[0] && track.pt() <= ConfDaughterPtUp.value[0] && track.pt() >= ConfDaughterPtLow.value[0] && std::abs(track.eta()) <= ConfDaughterEta.value[0] && std::abs(track.dcaXY()) <= ConfDaughterDCAxy.value[0] && std::abs(track.dcaZ()) <= ConfDaughterDCAz.value[0] && track.tpcNClsCrossedRows() >= ConfDaughterNCrossed.value[0] && track.tpcNClsFound() >= ConfDaughterNClus.value[0] && track.tpcCrossedRowsOverFindableCls() >= ConfDaughterTPCfCls.value[0]) { + if ((track.tpcInnerParam() < ConfDaughterPTPCThr.value[0] && std::abs(o2::aod::pidutils::tpcNSigma(ConfDaughterPIDspecies.value[0], track)) <= ConfDaughterPIDnSigmaMax.value[0]) || + (track.tpcInnerParam() >= ConfDaughterPTPCThr.value[0] && std::abs(std::sqrt(o2::aod::pidutils::tpcNSigma(ConfDaughterPIDspecies.value[0], track) * o2::aod::pidutils::tpcNSigma(ConfDaughterPIDspecies.value[0], track) + o2::aod::pidutils::tofNSigma(ConfDaughterPIDspecies.value[0], track) * o2::aod::pidutils::tofNSigma(ConfDaughterPIDspecies.value[0], track))) <= ConfDaughterPIDnSigmaMax.value[0])) { + Daughter1.push_back(track); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Pt"), track.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Eta"), track.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Phi"), track.phi()); + } + } + // select daugher 2 + if (track.sign() == ConfDaughterCharge.value[1] && track.pt() <= ConfDaughterPtUp.value[1] && track.pt() >= ConfDaughterPtLow.value[1] && std::abs(track.eta()) <= ConfDaughterEta.value[1] && std::abs(track.dcaXY()) <= ConfDaughterDCAxy.value[1] && std::abs(track.dcaZ()) <= ConfDaughterDCAz.value[1] && track.tpcNClsCrossedRows() >= ConfDaughterNCrossed.value[1] && track.tpcNClsFound() >= ConfDaughterNClus.value[1] && track.tpcCrossedRowsOverFindableCls() >= ConfDaughterTPCfCls.value[1]) { + if ((track.tpcInnerParam() < ConfDaughterPTPCThr.value[1] && std::abs(o2::aod::pidutils::tpcNSigma(ConfDaughterPIDspecies.value[1], track)) <= ConfDaughterPIDnSigmaMax.value[1]) || + (track.tpcInnerParam() >= ConfDaughterPTPCThr.value[1] && std::abs(std::sqrt(o2::aod::pidutils::tpcNSigma(ConfDaughterPIDspecies.value[1], track) * o2::aod::pidutils::tpcNSigma(ConfDaughterPIDspecies.value[1], track) + o2::aod::pidutils::tofNSigma(ConfDaughterPIDspecies.value[1], track) * o2::aod::pidutils::tofNSigma(ConfDaughterPIDspecies.value[1], track))) <= ConfDaughterPIDnSigmaMax.value[1])) { + Daughter2.push_back(track); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Pt"), track.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Eta"), track.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Phi"), track.phi()); + } + } + } } if (ConfIsActivateV0.value) { @@ -526,7 +635,7 @@ struct femtoDreamProducerTask { indexChildID, v0.mLambda(), v0.mAntiLambda()); - if (ConfIsDebug) { + if (ConfIsDebug.value) { fillDebugParticle(postrack); // QA for positive daughter fillDebugParticle(negtrack); // QA for negative daughter fillDebugParticle(v0); // QA for v0 @@ -536,6 +645,70 @@ struct femtoDreamProducerTask { } } } + + if (ConfIsActivateReso.value) { + for (auto iDaug1 = 0; iDaug1 < Daughter1.size(); ++iDaug1) { + for (auto iDaug2 = 0; iDaug2 < Daughter2.size(); ++iDaug2) { + // MC stuff is still missing, also V0 QA + // ALSO: fix indices and other table entries which are now set to 0 as deflaut as not needed for p-p-phi cf ana + + ROOT::Math::PtEtaPhiMVector tempD1(Daughter1.at(iDaug1).pt(), Daughter1.at(iDaug1).eta(), Daughter1.at(iDaug1).phi(), ConfDaug1Daugh2ResoMass.value[0]); + ROOT::Math::PtEtaPhiMVector tempD2(Daughter2.at(iDaug2).pt(), Daughter2.at(iDaug2).eta(), Daughter2.at(iDaug2).phi(), ConfDaug1Daugh2ResoMass.value[1]); + + ROOT::Math::PtEtaPhiMVector tempPhi = tempD1 + tempD2; + + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMass"), tempPhi.M()); + + if ((tempPhi.M() >= ConfResoInvMassLowLimit.value) && (tempPhi.M() <= ConfResoInvMassUpLimit.value)) { + + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMass_selected"), tempPhi.M()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/PtD1_selected"), Daughter1.at(iDaug1).pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/PtD2_selected"), Daughter2.at(iDaug2).pt()); + + childIDs[0] = 0; + childIDs[1] = 0; + std::vector indexChildID = {0, 0}; + outputParts(outputCollision.lastIndex(), + static_cast(Daughter1.at(iDaug1).pt()), static_cast(Daughter1.at(iDaug1).eta()), static_cast(Daughter1.at(iDaug1).phi()), + aod::femtodreamparticle::ParticleType::kV0Child, + static_cast(0), + static_cast(0), + static_cast(Daughter1.at(iDaug1).dcaXY()), + childIDs, + 0, + 0); + outputParts(outputCollision.lastIndex(), + static_cast(Daughter2.at(iDaug2).pt()), static_cast(Daughter2.at(iDaug2).eta()), static_cast(Daughter2.at(iDaug2).phi()), + aod::femtodreamparticle::ParticleType::kV0Child, + static_cast(0), + static_cast(0), + static_cast(Daughter2.at(iDaug2).dcaXY()), + childIDs, + 0, + 0); + outputParts(outputCollision.lastIndex(), + static_cast(tempPhi.pt()), + static_cast(tempPhi.eta()), + static_cast(tempPhi.phi()), + aod::femtodreamparticle::ParticleType::kV0, + static_cast(0), + 0, + 0.f, + indexChildID, + tempPhi.M(), + tempPhi.M()); + if (ConfIsDebug.value) { + fillDebugParticle(Daughter1.at(iDaug1)); // QA for positive daughter + fillDebugParticle(Daughter2.at(iDaug2)); // QA for negative daughter + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999.); // QA for Reso + } + } + } + } + } } void @@ -545,13 +718,27 @@ struct femtoDreamProducerTask { o2::aod::V0Datas const& fullV0s) { // get magnetic field for run - getMagneticFieldTesla(col.bc_as()); + initCCDB_Mag_Trig(col.bc_as()); // fill the tables fillCollisionsAndTracksAndV0(col, tracks, fullV0s); } PROCESS_SWITCH(femtoDreamProducerTask, processData, "Provide experimental data", true); + void + processData_noCentrality(aod::FemtoFullCollision_noCent const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTask, processData_noCentrality, + "Provide experimental data without centrality information", false); + void processMC(aod::FemtoFullCollisionMC const& col, aod::BCsWithTimestamps const&, soa::Join const& tracks, @@ -560,7 +747,7 @@ struct femtoDreamProducerTask { soa::Join const& fullV0s) /// \todo with FilteredFullV0s { // get magnetic field for run - getMagneticFieldTesla(col.bc_as()); + initCCDB_Mag_Trig(col.bc_as()); // fill the tables fillCollisionsAndTracksAndV0(col, tracks, fullV0s); } @@ -574,7 +761,7 @@ struct femtoDreamProducerTask { soa::Join const& fullV0s) /// \todo with FilteredFullV0s { // get magnetic field for run - getMagneticFieldTesla(col.bc_as()); + initCCDB_Mag_Trig(col.bc_as()); // fill the tables fillCollisionsAndTracksAndV0(col, tracks, fullV0s); } diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx index 24836fda097..44c1bb69990 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx @@ -49,30 +49,32 @@ struct femtoDreamPairTaskTrackTrack { /// General options struct : ConfigurableGroup { - Configurable IsMC{"Option.IsMC", false, "Enable additional Histogramms in the case of runninger over Monte Carlo"}; - Configurable Use4D{"Option.Use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; - Configurable ExtendedPlots{"Option.ExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; - Configurable HighkstarCut{"Option.HighkstarCut", -1., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; - Configurable SameSpecies{"Option.SameSpecies", false, "Set to true if particle 1 and particle 2 are the same species"}; - Configurable MixEventWithPairs{"Option.MixEventWithPairs", false, "Only use events that contain particle 1 and partile 2 for the event mixing"}; - Configurable RandomizePair{"Option.RandomizePair", true, "Randomly mix particle 1 and particle 2 in case both are identical"}; - Configurable CPROn{"Option.CPROn", true, "Close Pair Rejection"}; - Configurable CPROld{"Option.CPROld", false, "Set to FALSE to use fixed version of CPR (for testing now, will be default soon)"}; - Configurable CPRSepMeSe{"Option.CPRSepMESE", true, "Use seperated plots for same and mixed event for CPR plots"}; - Configurable CPRPlotPerRadii{"Option.CPRPlotPerRadii", false, "Plot CPR per radii"}; - Configurable CPRdeltaPhiMax{"Option.CPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; - Configurable CPRdeltaEtaMax{"Option.CPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; - Configurable DCACutPtDep{"Option.DCACutPtDep", false, "Use pt dependent dca cut"}; - ConfigurableAxis Dummy{"Option.Dummy", {1, 0, 1}, "Dummy axis"}; - Configurable SmearingByOrigin{"Option.SmearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption"}; + std::string prefix = std::string("Option"); + Configurable IsMC{"IsMC", false, "Enable additional Histogramms in the case of runninger over Monte Carlo"}; + Configurable Use4D{"Use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; + Configurable ExtendedPlots{"ExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; + Configurable HighkstarCut{"HighkstarCut", -1., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; + Configurable SameSpecies{"SameSpecies", false, "Set to true if particle 1 and particle 2 are the same species"}; + Configurable MixEventWithPairs{"MixEventWithPairs", false, "Only use events that contain particle 1 and partile 2 for the event mixing"}; + Configurable RandomizePair{"RandomizePair", true, "Randomly mix particle 1 and particle 2 in case both are identical"}; + Configurable CPROn{"CPROn", true, "Close Pair Rejection"}; + Configurable CPROld{"CPROld", false, "Set to FALSE to use fixed version of CPR (for testing now, will be default soon)"}; + Configurable CPRSepMeSe{"CPRSepMESE", true, "Use seperated plots for same and mixed event for CPR plots"}; + Configurable CPRPlotPerRadii{"CPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable CPRdeltaPhiMax{"CPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable CPRdeltaEtaMax{"CPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable DCACutPtDep{"DCACutPtDep", false, "Use pt dependent dca cut"}; + Configurable SmearingByOrigin{"SmearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption"}; + ConfigurableAxis Dummy{"Dummy", {1, 0, 1}, "Dummy axis"}; } Option; /// Event selection struct : ConfigurableGroup { - Configurable MultMin{"EventSel.MultMin", 0, "Minimum Multiplicity (MultNtr)"}; - Configurable MultMax{"EventSel.MultMax", 99999, "Maximum Multiplicity (MultNtr)"}; - Configurable MultPercentileMin{"EventSel.MultPercentileMin", 0, "Maximum Multiplicity Percentile"}; - Configurable MultPercentileMax{"EventSel.MultPercentileMax", 100, "Minimum Multiplicity Percentile"}; + std::string prefix = std::string("EventSel"); + Configurable MultMin{"MultMin", 0, "Minimum Multiplicity (MultNtr)"}; + Configurable MultMax{"MultMax", 99999, "Maximum Multiplicity (MultNtr)"}; + Configurable MultPercentileMin{"MultPercentileMin", 0, "Maximum Multiplicity Percentile"}; + Configurable MultPercentileMax{"MultPercentileMax", 100, "Minimum Multiplicity Percentile"}; } EventSel; Filter EventMultiplicity = aod::femtodreamcollision::multNtr >= EventSel.MultMin && aod::femtodreamcollision::multNtr <= EventSel.MultMax; @@ -92,18 +94,19 @@ struct femtoDreamPairTaskTrackTrack { /// Track 1 struct : ConfigurableGroup { - Configurable PDGCode{"Track1.PDGCode", 2212, "PDG code of particle 1 (Track)"}; - Configurable CutBit{"Track1.CutBit", 3191978, "Selection bit from cutCulator for particle 1 (Track)"}; - Configurable TPCBit{"Track1.TPCBit", 4, "PID TPC bit from cutCulator for particle 1 (Track)"}; - Configurable TPCBit_Reject{"Track1.TPCBit_Reject", 0, "PID TPC bit from cutCulator to reject a particle hypothesis for particle 1 (set to 0 to ignore)"}; - Configurable TPCTOFBit{"Track1.TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 1 (Track)"}; - Configurable PIDThres{"Track1.PIDThres", 0.75, "Momentum threshold for PID selection for particle 1 (Track)"}; - Configurable PtMin{"Track1.PtMin", 0., "Minimum pT of partricle 1 (Track)"}; - Configurable PtMax{"Track1.PtMax", 999., "Maximum pT of partricle 1 (Track)"}; - Configurable EtaMin{"Track1.EtaMin", -10., "Minimum eta of partricle 1 (Track)"}; - Configurable EtaMax{"Track1.EtaMax", 10., "Maximum eta of partricle 1 (Track)"}; - Configurable TempFitVarMin{"Track1.TempFitVarMin", -10., "Minimum DCAxy of partricle 1 (Track)"}; - Configurable TempFitVarMax{"Track1.TempFitVarMax", 10., "Maximum DCAxy of partricle 1 (Track)"}; + std::string prefix = std::string("Track1"); + Configurable PDGCode{"PDGCode", 2212, "PDG code of particle 1 (Track)"}; + Configurable CutBit{"CutBit", 3191978, "Selection bit from cutCulator for particle 1 (Track)"}; + Configurable TPCBit{"TPCBit", 4, "PID TPC bit from cutCulator for particle 1 (Track)"}; + Configurable TPCBit_Reject{"TPCBit_Reject", 0, "PID TPC bit from cutCulator to reject a particle hypothesis for particle 1 (set to 0 to ignore)"}; + Configurable TPCTOFBit{"TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 1 (Track)"}; + Configurable PIDThres{"PIDThres", 0.75, "Momentum threshold for PID selection for particle 1 (Track)"}; + Configurable PtMin{"PtMin", 0., "Minimum pT of partricle 1 (Track)"}; + Configurable PtMax{"PtMax", 999., "Maximum pT of partricle 1 (Track)"}; + Configurable EtaMin{"EtaMin", -10., "Minimum eta of partricle 1 (Track)"}; + Configurable EtaMax{"EtaMax", 10., "Maximum eta of partricle 1 (Track)"}; + Configurable TempFitVarMin{"TempFitVarMin", -10., "Minimum DCAxy of partricle 1 (Track)"}; + Configurable TempFitVarMax{"TempFitVarMax", 10., "Maximum DCAxy of partricle 1 (Track)"}; } Track1; /// Partition for particle 1 @@ -136,18 +139,19 @@ struct femtoDreamPairTaskTrackTrack { /// Track 2 struct : ConfigurableGroup { - Configurable PDGCode{"Track2.PDGCode", 2212, "PDG code of particle 2 (Track)"}; - Configurable CutBit{"Track2.CutBit", 3191978, "Selection bit from cutCulator for particle 2 (Track)"}; - Configurable TPCBit{"Track2.TPCBit", 4, "PID TPC bit from cutCulator for particle 2 (Track)"}; - Configurable TPCBit_Reject{"Track2.TPCBit_Reject", 0, "PID TPC bit from cutCulator to reject a particle hypothesis for particle 2 (set to 0 to ignore)"}; - Configurable TPCTOFBit{"Track2.TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 2 (Track)"}; - Configurable PIDThres{"Track2.PIDThres", 0.75, "Momentum threshold for PID selection for particle 2 (Track)"}; - Configurable PtMin{"Track2.PtMin", 0., "Minimum pT of particle 2 (Track)"}; - Configurable PtMax{"Track2.PtMax", 999., "Maximum pT of particle 2 (Track)"}; - Configurable EtaMin{"Track2.EtaMin", -10., "Minimum eta of particle 2 (Track)"}; - Configurable EtaMax{"Track2.EtaMax", 10., "Maximum eta of particle 2 (Track)"}; - Configurable TempFitVarMin{"Track2.TempFitVarMin", -10., "Minimum DCAxy of partricle 1 (Track)"}; - Configurable TempFitVarMax{"Track2.TempFitVarMax", 10., "Maximum DCAxy of partricle 1 (Track)"}; + std::string prefix = std::string("Track2"); + Configurable PDGCode{"PDGCode", 2212, "PDG code of particle 2 (Track)"}; + Configurable CutBit{"CutBit", 3191978, "Selection bit from cutCulator for particle 2 (Track)"}; + Configurable TPCBit{"TPCBit", 4, "PID TPC bit from cutCulator for particle 2 (Track)"}; + Configurable TPCBit_Reject{"TPCBit_Reject", 0, "PID TPC bit from cutCulator to reject a particle hypothesis for particle 2 (set to 0 to ignore)"}; + Configurable TPCTOFBit{"TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 2 (Track)"}; + Configurable PIDThres{"PIDThres", 0.75, "Momentum threshold for PID selection for particle 2 (Track)"}; + Configurable PtMin{"PtMin", 0., "Minimum pT of particle 2 (Track)"}; + Configurable PtMax{"PtMax", 999., "Maximum pT of particle 2 (Track)"}; + Configurable EtaMin{"EtaMin", -10., "Minimum eta of particle 2 (Track)"}; + Configurable EtaMax{"EtaMax", 10., "Maximum eta of particle 2 (Track)"}; + Configurable TempFitVarMin{"TempFitVarMin", -10., "Minimum DCAxy of partricle 1 (Track)"}; + Configurable TempFitVarMax{"TempFitVarMax", 10., "Maximum DCAxy of partricle 1 (Track)"}; } Track2; /// Partition for track 2 @@ -221,8 +225,7 @@ struct femtoDreamPairTaskTrackTrack { FemtoDreamDetaDphiStar pairCloseRejectionSE; FemtoDreamDetaDphiStar pairCloseRejectionME; /// Histogram output - HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry Registry{"Output", {}, OutputObjHandlingPolicy::AnalysisObject}; TRandom3* random; @@ -231,19 +234,19 @@ struct femtoDreamPairTaskTrackTrack { if (Option.RandomizePair.value) { random = new TRandom3(0); } - eventHisto.init(&qaRegistry, Option.IsMC); - trackHistoPartOne.init(&qaRegistry, Binning.multTempFit, Option.Dummy, Binning.TrackpT, Option.Dummy, Option.Dummy, Binning.TempFitVar, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, Track1.PDGCode); + eventHisto.init(&Registry, Option.IsMC); + trackHistoPartOne.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.TrackpT, Option.Dummy, Option.Dummy, Binning.TempFitVar, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, Track1.PDGCode); if (!Option.SameSpecies) { - trackHistoPartTwo.init(&qaRegistry, Binning.multTempFit, Option.Dummy, Binning.TrackpT, Option.Dummy, Option.Dummy, Binning.TempFitVar, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, Track2.PDGCode); + trackHistoPartTwo.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.TrackpT, Option.Dummy, Option.Dummy, Binning.TempFitVar, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, Track2.PDGCode); } - sameEventCont.init(&resultRegistry, + sameEventCont.init(&Registry, Binning.kstar, Binning.pT, Binning.kT, Binning.mT, Mixing.MultMixBins, Mixing.MultPercentileMixBins, Binning4D.kstar, Binning4D.mT, Binning4D.mult, Binning4D.multPercentile, Option.IsMC, Option.Use4D, Option.ExtendedPlots, Option.HighkstarCut, Option.SmearingByOrigin); - mixedEventCont.init(&resultRegistry, + mixedEventCont.init(&Registry, Binning.kstar, Binning.pT, Binning.kT, Binning.mT, Mixing.MultMixBins, Mixing.MultPercentileMixBins, Binning4D.kstar, Binning4D.mT, Binning4D.mult, Binning4D.multPercentile, Option.IsMC, Option.Use4D, Option.ExtendedPlots, @@ -251,10 +254,10 @@ struct femtoDreamPairTaskTrackTrack { Option.SmearingByOrigin); sameEventCont.setPDGCodes(Track1.PDGCode, Track2.PDGCode); mixedEventCont.setPDGCodes(Track1.PDGCode, Track2.PDGCode); - pairCleaner.init(&qaRegistry); + pairCleaner.init(&Registry); if (Option.CPROn.value) { - pairCloseRejectionSE.init(&resultRegistry, &qaRegistry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 1, Option.CPROld.value); - pairCloseRejectionME.init(&resultRegistry, &qaRegistry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 2, Option.CPROld.value); + pairCloseRejectionSE.init(&Registry, &Registry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 1, Option.CPROld.value); + pairCloseRejectionME.init(&Registry, &Registry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 2, Option.CPROld.value); } // get bit for the collision mask diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackV0.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackV0.cxx index 3c58faddfb4..7b6fe7ec1ab 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackV0.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackV0.cxx @@ -22,7 +22,6 @@ #include "Framework/ASoAHelpers.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/Expressions.h" -#include "Framework/StepTHn.h" #include "PWGCF/DataModel/FemtoDerived.h" #include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" @@ -45,152 +44,172 @@ struct femtoDreamPairTaskTrackV0 { /// General options struct : ConfigurableGroup { - Configurable IsMC{"Option.IsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; - Configurable Use4D{"Option.Use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; - Configurable ExtendedPlots{"Option.ExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; - Configurable HighkstarCut{"Option.HighkstarCut", -1., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; - Configurable CPROn{"Option.CPROn", true, "Close Pair Rejection"}; - Configurable CPROld{"Option.CPROld", false, "Set to FALSE to use fixed version of CPR (for testing now, will be default soon)"}; - Configurable CPRPlotPerRadii{"Option.CPRPlotPerRadii", false, "Plot CPR per radii"}; - Configurable CPRdeltaPhiMax{"Option.CPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; - Configurable CPRdeltaEtaMax{"Option.CPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; - Configurable DCACutPtDep{"Option.DCACutPtDep", false, "Use pt dependent dca cut"}; - Configurable MixEventWithPairs{"Option.MixEventWithPairs", false, "Only use events that contain particle 1 and partile 2 for the event mixing"}; - Configurable smearingByOrigin{"Option.smearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption. Use with care!"}; - ConfigurableAxis Dummy{"Option.Dummy", {1, 0, 1}, "Dummy axis"}; + std::string prefix = std::string("Option"); + Configurable IsMC{"IsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable Use4D{"Use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; + Configurable ExtendedPlots{"ExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; + Configurable HighkstarCut{"HighkstarCut", -1., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; + Configurable CPROn{"CPROn", true, "Close Pair Rejection"}; + Configurable CPROld{"CPROld", false, "Set to FALSE to use fixed version of CPR (for testing now, will be default soon)"}; + Configurable CPRPlotPerRadii{"CPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable CPRdeltaPhiMax{"CPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable CPRdeltaEtaMax{"CPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable DCACutPtDep{"DCACutPtDep", false, "Use pt dependent dca cut"}; + Configurable MixEventWithPairs{"MixEventWithPairs", false, "Only use events that contain particle 1 and partile 2 for the event mixing"}; + Configurable smearingByOrigin{"smearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption. Use with care!"}; + ConfigurableAxis Dummy{"Dummy", {1, 0, 1}, "Dummy axis"}; } Option; /// Event selection struct : ConfigurableGroup { - Configurable MultMin{"EventSel.MultMin", 0, "Minimum Multiplicity (MultNtr)"}; - Configurable MultMax{"EventSel.MultMax", 99999, "Maximum Multiplicity (MultNtr)"}; - Configurable MultPercentileMin{"EventSel.MultPercentileMin", 0, "Minimum Multiplicity Percentile"}; - Configurable MultPercentileMax{"EventSel.MultPercentileMax", 100, "Maximum Multiplicity Percentile"}; + std::string prefix = std::string("EventSel"); + Configurable MultMin{"MultMin", 0, "Minimum Multiplicity (MultNtr)"}; + Configurable MultMax{"MultMax", 99999, "Maximum Multiplicity (MultNtr)"}; + Configurable MultPercentileMin{"MultPercentileMin", 0, "Minimum Multiplicity Percentile"}; + Configurable MultPercentileMax{"MultPercentileMax", 100, "Maximum Multiplicity Percentile"}; } EventSel; Filter EventMultiplicity = aod::femtodreamcollision::multNtr >= EventSel.MultMin && aod::femtodreamcollision::multNtr <= EventSel.MultMax; Filter EventMultiplicityPercentile = aod::femtodreamcollision::multV0M >= EventSel.MultPercentileMin && aod::femtodreamcollision::multV0M <= EventSel.MultPercentileMax; + /// Histogramming for Event + FemtoDreamEventHisto eventHisto; + using FilteredMaskedCollisions = soa::Filtered>; using FilteredMaskedCollision = FilteredMaskedCollisions::iterator; using FilteredMaskedMCCollisions = soa::Filtered>; using FilteredMaskedMCCollision = FilteredMaskedMCCollisions::iterator; + using FDMCParts = soa::Join; + using FDMCPart = FDMCParts::iterator; + femtodreamcollision::BitMaskType BitMask = 1; /// Particle 1 (track) struct : ConfigurableGroup { - Configurable PDGCode{"Track1.PDGCode", 2212, "PDG code of Particle 1 (Track)"}; - Configurable CutBit{"Track1.CutBit", 5542474, "Particle 1 (Track) - Selection bit from cutCulator"}; - Configurable TPCBit{"Track1.TPCBit", 4, "PID TPC bit from cutCulator for particle 1 (Track)"}; - Configurable TPCBit_Reject{"Track1.TPCBit_Reject", 0, "Reject PID TPC bit from cutCulator for particle 1 (Track). Set to 0 to turn off"}; - Configurable TPCTOFBit{"Track1.TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 1 (Track)"}; - Configurable PIDThres{"Track1.PIDThres", 0.75, "Momentum threshold for PID selection for particle 1 (Track)"}; - Configurable PtMin{"Track1.PtMin", 0., "Minimum pT of partricle 1 (Track)"}; - Configurable PtMax{"Track1.PtMax", 999., "Maximum pT of partricle 1 (Track)"}; - Configurable EtaMin{"Track1.EtaMin", -10., "Minimum eta of partricle 1 (Track)"}; - Configurable EtaMax{"Track1.EtaMax", 10., "Maximum eta of partricle 1 (Track)"}; - Configurable TempFitVarMin{"Track1.TempFitVarMin", -10., "Minimum DCAxy of partricle 1 (Track)"}; - Configurable TempFitVarMax{"Track1.TempFitVarMax", 10., "Maximum DCAxy of partricle 1 (Track)"}; + std::string prefix = std::string("Track1"); + Configurable PDGCode{"PDGCode", 2212, "PDG code of Particle 1 (Track)"}; + Configurable CutBit{"CutBit", 5542474, "Particle 1 (Track) - Selection bit from cutCulator"}; + Configurable TPCBit{"TPCBit", 4, "PID TPC bit from cutCulator for particle 1 (Track)"}; + Configurable TPCBit_Reject{"TPCBit_Reject", 0, "Reject PID TPC bit from cutCulator for particle 1 (Track). Set to 0 to turn off"}; + Configurable TPCTOFBit{"TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 1 (Track)"}; + Configurable PIDThres{"PIDThres", 0.75, "Momentum threshold for PID selection for particle 1 (Track)"}; + Configurable PtMin{"PtMin", 0., "Minimum pT of partricle 1 (Track)"}; + Configurable PtMax{"PtMax", 999., "Maximum pT of partricle 1 (Track)"}; + Configurable EtaMin{"EtaMin", -10., "Minimum eta of partricle 1 (Track)"}; + Configurable EtaMax{"EtaMax", 10., "Maximum eta of partricle 1 (Track)"}; + Configurable TempFitVarMin{"TempFitVarMin", -10., "Minimum DCAxy of partricle 1 (Track)"}; + Configurable TempFitVarMax{"TempFitVarMax", 10., "Maximum DCAxy of partricle 1 (Track)"}; } Track1; - Filter trackPtFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt > Track1.PtMin, true); - Filter trackPtFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt < Track1.PtMax, true); - Filter trackEtaFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta > Track1.EtaMin, true); - Filter trackEtaFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta < Track1.EtaMax, true); - Filter trackTempFitVarFilterUp = !Option.DCACutPtDep && ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::tempFitVar > Track1.TempFitVarMin, true); - Filter trackTempFitVarFilterLow = !Option.DCACutPtDep && ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::tempFitVar < Track1.TempFitVarMax, true); - Filter trackTempFitVarFilterPtDep = Option.DCACutPtDep && ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), nabs(aod::femtodreamparticle::tempFitVar) <= 0.0105f + (0.035f / npow(aod::femtodreamparticle::pt, 1.1f)), true); + /// Partition for particle 1 + Partition PartitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + (ncheckbit(aod::femtodreamparticle::cut, Track1.CutBit)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= Track1.PIDThres, ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCBit) && ((aod::femtodreamparticle::pidcut & Track1.TPCBit_Reject) == 0u), ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCTOFBit)) && + (aod::femtodreamparticle::pt > Track1.PtMin) && + (aod::femtodreamparticle::pt < Track1.PtMax) && + (aod::femtodreamparticle::eta > Track1.EtaMin) && + (aod::femtodreamparticle::eta < Track1.EtaMax) && + ifnode(Option.DCACutPtDep, (nabs(aod::femtodreamparticle::tempFitVar) <= 0.0105f + (0.035f / npow(aod::femtodreamparticle::pt, 1.1f))), + ((aod::femtodreamparticle::tempFitVar >= Track1.TempFitVarMin) && + (aod::femtodreamparticle::tempFitVar <= Track1.TempFitVarMax))); + + Partition PartitionMCTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + (ncheckbit(aod::femtodreamparticle::cut, Track1.CutBit)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= Track1.PIDThres, ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCBit) && ((aod::femtodreamparticle::pidcut & Track1.TPCBit_Reject) == 0u), ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCTOFBit)) && + (aod::femtodreamparticle::pt > Track1.PtMin) && + (aod::femtodreamparticle::pt < Track1.PtMax) && + (aod::femtodreamparticle::eta > Track1.EtaMin) && + (aod::femtodreamparticle::eta < Track1.EtaMax) && + ifnode(Option.DCACutPtDep, (nabs(aod::femtodreamparticle::tempFitVar) <= 0.0105f + (0.035f / npow(aod::femtodreamparticle::pt, 1.1f))), + ((aod::femtodreamparticle::tempFitVar >= Track1.TempFitVarMin) && + (aod::femtodreamparticle::tempFitVar <= Track1.TempFitVarMax))); /// Histogramming for particle 1 FemtoDreamParticleHisto trackHistoPartOne; /// Particle 2 (V0) struct : ConfigurableGroup { - Configurable PDGCode{"V02.PDGCode", 3122, "PDG code of particle 2 (V0)"}; - Configurable CutBit{"V02.CutBit", 338, "Selection bit for particle 2 (V0)"}; - Configurable ChildPos_CutBit{"V02.ChildPos_CutBit", 149, "Selection bit for positive child of V0"}; - Configurable ChildPos_TPCBit{"V02.ChildPos_TPCBit", 2, "PID TPC bit for positive child of V0"}; - Configurable ChildNeg_CutBit{"V02.ChildNeg_CutBit", 149, "Selection bit for negative child of V0"}; - Configurable ChildNeg_TPCBit{"V02.ChildNeg_TPCBit", 2, "PID TPC bit for negative child of V0"}; - - Configurable InvMassMin{"V02.InvMassMin", 1.08, "Minimum invariant mass of Partricle 2 (particle) (V0)"}; - Configurable InvMassMax{"V02.InvMassMax", 1.15, "Maximum invariant mass of Partricle 2 (particle) (V0)"}; - Configurable InvMassAntiMin{"V02.InvMassAntiMin", 0., "Minimum invariant mass of Partricle 2 (antiparticle) (V0)"}; - Configurable InvMassAntiMax{"V02.InvMassAntiMax", 999., "Maximum invariant mass of Partricle 2 (antiparticle) (V0)"}; - - Configurable PtMin{"V02.PtMin", 0., "Minimum pT of Partricle 2 (V0)"}; - Configurable PtMax{"V02.PtMax", 999., "Maximum pT of Partricle 2 (V0)"}; - Configurable EtaMin{"V02.EtaMin", -10., "Minimum eta of Partricle 2 (V0)"}; - Configurable EtaMax{"V02.EtaMax", 10., "Maximum eta of Partricle 2 (V0)"}; + std::string prefix = std::string("V02"); + Configurable PDGCode{"PDGCode", 3122, "PDG code of particle 2 (V0)"}; + Configurable CutBit{"CutBit", 338, "Selection bit for particle 2 (V0)"}; + Configurable ChildPos_CutBit{"ChildPos_CutBit", 149, "Selection bit for positive child of V0"}; + Configurable ChildPos_TPCBit{"ChildPos_TPCBit", 2, "PID TPC bit for positive child of V0"}; + Configurable ChildNeg_CutBit{"ChildNeg_CutBit", 149, "Selection bit for negative child of V0"}; + Configurable ChildNeg_TPCBit{"ChildNeg_TPCBit", 2, "PID TPC bit for negative child of V0"}; + + Configurable InvMassMin{"InvMassMin", 1.08, "Minimum invariant mass of Partricle 2 (particle) (V0)"}; + Configurable InvMassMax{"InvMassMax", 1.15, "Maximum invariant mass of Partricle 2 (particle) (V0)"}; + Configurable InvMassAntiMin{"InvMassAntiMin", 0., "Minimum invariant mass of Partricle 2 (antiparticle) (V0)"}; + Configurable InvMassAntiMax{"InvMassAntiMax", 999., "Maximum invariant mass of Partricle 2 (antiparticle) (V0)"}; + + Configurable PtMin{"PtMin", 0., "Minimum pT of Partricle 2 (V0)"}; + Configurable PtMax{"PtMax", 999., "Maximum pT of Partricle 2 (V0)"}; + Configurable EtaMin{"EtaMin", -10., "Minimum eta of Partricle 2 (V0)"}; + Configurable EtaMax{"EtaMax", 10., "Maximum eta of Partricle 2 (V0)"}; } V02; - Filter v0MassFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::mLambda > V02.InvMassMin, true); - Filter v0MassFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::mLambda < V02.InvMassMax, true); - Filter antiv0MassFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::mAntiLambda > V02.InvMassAntiMin, true); - Filter antiv0MassFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::mAntiLambda < V02.InvMassAntiMax, true); - - Filter v0PtFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::pt > V02.PtMin, true); - Filter v0PtFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::pt < V02.PtMax, true); - Filter v0EtaFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::eta > V02.EtaMin, true); - Filter v0EtaFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0), aod::femtodreamparticle::eta < V02.EtaMax, true); + /// Partition for particle 2 + Partition PartitionV02 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && + ((aod::femtodreamparticle::cut & V02.CutBit) == V02.CutBit) && + (aod::femtodreamparticle::pt > V02.PtMin) && + (aod::femtodreamparticle::pt < V02.PtMax) && + (aod::femtodreamparticle::eta > V02.EtaMin) && + (aod::femtodreamparticle::eta < V02.EtaMax) && + (aod::femtodreamparticle::mLambda > V02.InvMassMin) && + (aod::femtodreamparticle::mLambda < V02.InvMassMax) && + (aod::femtodreamparticle::mAntiLambda > V02.InvMassAntiMin) && + (aod::femtodreamparticle::mAntiLambda < V02.InvMassAntiMax); + + Partition PartitionMCV02 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && + ((aod::femtodreamparticle::cut & V02.CutBit) == V02.CutBit) && + (aod::femtodreamparticle::pt > V02.PtMin) && + (aod::femtodreamparticle::pt < V02.PtMax) && + (aod::femtodreamparticle::eta > V02.EtaMax) && + (aod::femtodreamparticle::eta < V02.EtaMin) && + (aod::femtodreamparticle::mLambda > V02.InvMassMin) && + (aod::femtodreamparticle::mLambda < V02.InvMassMax) && + (aod::femtodreamparticle::mAntiLambda > V02.InvMassAntiMin) && + (aod::femtodreamparticle::mAntiLambda < V02.InvMassAntiMax); /// Histogramming for particle 2 FemtoDreamParticleHisto trackHistoPartTwo; FemtoDreamParticleHisto posChildHistos; FemtoDreamParticleHisto negChildHistos; - using FilteredFDParticles = soa::Filtered; - using FilteredFDParticle = FilteredFDParticles::iterator; - - using FilteredFDMCParts = soa::Filtered>; - using FilteredFDMCPart = FilteredFDMCParts::iterator; - - /// Partition for particle 1 - Partition PartitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && - (ncheckbit(aod::femtodreamparticle::cut, Track1.CutBit)) && - ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= Track1.PIDThres, ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCBit) && ((aod::femtodreamparticle::pidcut & Track1.TPCBit_Reject) == 0u), ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCTOFBit)); - Partition PartitionMCTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && - (ncheckbit(aod::femtodreamparticle::cut, Track1.CutBit)) && - ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= Track1.PIDThres, ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCBit) && ((aod::femtodreamparticle::pidcut & Track1.TPCBit_Reject) == 0u), ncheckbit(aod::femtodreamparticle::pidcut, Track1.TPCTOFBit)); - - /// Partition for particle 2 - Partition PartitionV02 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && ((aod::femtodreamparticle::cut & V02.CutBit) == V02.CutBit); - Partition PartitionMCV02 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && ((aod::femtodreamparticle::cut & V02.CutBit) == V02.CutBit); - - /// Histogramming for Event - FemtoDreamEventHisto eventHisto; - /// Binning configurables struct : ConfigurableGroup { - ConfigurableAxis TempFitVarTrack{"Binning.TempFitVarTrack", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Track)"}; - ConfigurableAxis TempFitVarV0{"Binning.TempFitVarV0", {300, 0.9, 1}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis TempFitVarV0Child{"Binning.TempFitVarV0Child", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0 child)"}; - ConfigurableAxis InvMass{"Binning.InvMass", {200, 1, 1.2}, "InvMass binning"}; - ConfigurableAxis pTTrack{"Binning.pTTrack", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; - ConfigurableAxis pTV0{"Binning.pTV0", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis pTV0Child{"Binning.pTV0Child", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis pT{"Binning.pT", {20, 0.5, 4.05}, "pT binning"}; - ConfigurableAxis kstar{"Binning.kstar", {1500, 0., 6.}, "binning kstar"}; - ConfigurableAxis kT{"Binning.kT", {150, 0., 9.}, "binning kT"}; - ConfigurableAxis mT{"Binning.mT", {225, 0., 7.5}, "binning mT"}; - ConfigurableAxis multTempFit{"Binning.multTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; + std::string prefix = std::string("Binning"); + ConfigurableAxis TempFitVarTrack{"TempFitVarTrack", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis TempFitVarV0{"TempFitVarV0", {300, 0.9, 1}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0)"}; + ConfigurableAxis TempFitVarV0Child{"TempFitVarV0Child", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0 child)"}; + ConfigurableAxis InvMass{"InvMass", {200, 1, 1.2}, "InvMass binning"}; + ConfigurableAxis pTTrack{"pTTrack", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis pTV0{"pTV0", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; + ConfigurableAxis pTV0Child{"pTV0Child", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; + ConfigurableAxis pT{"pT", {20, 0.5, 4.05}, "pT binning"}; + ConfigurableAxis kstar{"kstar", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis kT{"kT", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis mT{"mT", {225, 0., 7.5}, "binning mT"}; + ConfigurableAxis multTempFit{"multTempFit", {1, 0, 1}, "multiplicity for the TempFitVar plot"}; } Binning; struct : ConfigurableGroup { - ConfigurableAxis kstar{"Binning4D.kstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis mT{"Binning4D.mT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis Mult{"Binning4D.mult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis multPercentile{"Binning4D.multPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + std::string prefix = std::string("Binning4D"); + ConfigurableAxis kstar{"kstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis mT{"mT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis Mult{"mult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis multPercentile{"multPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; } Binning4D; // Mixing configurables struct : ConfigurableGroup { - ConfigurableAxis BinMult{"Mixing.BinMult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "Mixing bins - multiplicity"}; - ConfigurableAxis BinMultPercentile{"Mixing.BinMultPercentile", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f}, "Mixing bins - multiplicity percentile"}; - ConfigurableAxis BinVztx{"Mixing.BinVztx", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - Configurable Depth{"Mixing.Depth", 5, "Number of events for mixing"}; - Configurable Policy{"Mixing.BinPolicy", 0, "Binning policy for mixing - 0: multiplicity, 1: multipliciy percentile, 2: both"}; + std::string prefix = std::string("Mixing"); + ConfigurableAxis BinMult{"BinMult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "bins - multiplicity"}; + ConfigurableAxis BinMultPercentile{"BinMultPercentile", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f}, "bins - multiplicity percentile"}; + ConfigurableAxis BinVztx{"BinVztx", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "bins - z-vertex"}; + Configurable Depth{"Depth", 5, "Number of events for mixing"}; + Configurable Policy{"BinPolicy", 0, "Binning policy for mixing - 0: multiplicity, 1: multipliciy percentile, 2: both"}; } Mixing; ColumnBinningPolicy colBinningMult{{Mixing.BinVztx, Mixing.BinMult}, true}; @@ -204,21 +223,17 @@ struct femtoDreamPairTaskTrackV0 { FemtoDreamDetaDphiStar pairCloseRejectionME; /// Histogram output - HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry Registry{"Output", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext& context) { - eventHisto.init(&qaRegistry, Option.IsMC); - // void init(HistogramRegistry* registry, - // T& MomentumBins, T& tempFitVarBins, T& NsigmaTPCBins, T& NsigmaTOFBins, T& NsigmaTPCTOFBins, T& InvMassBins, - // bool isMC, int pdgCode, bool isDebug = false) - trackHistoPartOne.init(&qaRegistry, Binning.multTempFit, Option.Dummy, Binning.pTTrack, Option.Dummy, Option.Dummy, Binning.TempFitVarTrack, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, Track1.PDGCode); - trackHistoPartTwo.init(&qaRegistry, Binning.multTempFit, Option.Dummy, Binning.pTV0, Option.Dummy, Option.Dummy, Binning.TempFitVarV0, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Binning.InvMass, Option.IsMC, V02.PDGCode); - posChildHistos.init(&qaRegistry, Binning.multTempFit, Option.Dummy, Binning.pTV0Child, Option.Dummy, Option.Dummy, Binning.TempFitVarV0Child, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); - negChildHistos.init(&qaRegistry, Binning.multTempFit, Option.Dummy, Binning.pTV0Child, Option.Dummy, Option.Dummy, Binning.TempFitVarV0Child, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); - - sameEventCont.init(&resultRegistry, + eventHisto.init(&Registry, Option.IsMC); + trackHistoPartOne.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTTrack, Option.Dummy, Option.Dummy, Binning.TempFitVarTrack, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, Track1.PDGCode); + trackHistoPartTwo.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTV0, Option.Dummy, Option.Dummy, Binning.TempFitVarV0, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Binning.InvMass, Option.IsMC, V02.PDGCode); + posChildHistos.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTV0Child, Option.Dummy, Option.Dummy, Binning.TempFitVarV0Child, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); + negChildHistos.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTV0Child, Option.Dummy, Option.Dummy, Binning.TempFitVarV0Child, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); + + sameEventCont.init(&Registry, Binning.kstar, Binning.pT, Binning.kT, Binning.mT, Mixing.BinMult, Mixing.BinMultPercentile, Binning4D.kstar, Binning4D.mT, Binning4D.Mult, Binning4D.multPercentile, Option.IsMC, Option.Use4D, Option.ExtendedPlots, @@ -226,7 +241,7 @@ struct femtoDreamPairTaskTrackV0 { Option.smearingByOrigin); sameEventCont.setPDGCodes(Track1.PDGCode, V02.PDGCode); - mixedEventCont.init(&resultRegistry, + mixedEventCont.init(&Registry, Binning.kstar, Binning.pT, Binning.kT, Binning.mT, Mixing.BinMult, Mixing.BinMultPercentile, Binning4D.kstar, Binning4D.mT, Binning4D.Mult, Binning4D.multPercentile, Option.IsMC, Option.Use4D, Option.ExtendedPlots, @@ -234,10 +249,10 @@ struct femtoDreamPairTaskTrackV0 { Option.smearingByOrigin); mixedEventCont.setPDGCodes(Track1.PDGCode, V02.PDGCode); - pairCleaner.init(&qaRegistry); + pairCleaner.init(&Registry); if (Option.CPROn.value) { - pairCloseRejectionSE.init(&resultRegistry, &qaRegistry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 1, Option.CPROld.value); - pairCloseRejectionME.init(&resultRegistry, &qaRegistry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 2, Option.CPROld.value, 8, true); + pairCloseRejectionSE.init(&Registry, &Registry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 1, Option.CPROld.value); + pairCloseRejectionME.init(&Registry, &Registry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 2, Option.CPROld.value, 99, true); } // get bit for the collision mask @@ -331,7 +346,7 @@ struct femtoDreamPairTaskTrackV0 { } } - void processSameEventMasked(FilteredMaskedCollision const& col, FilteredFDParticles const& parts) + void processSameEventMasked(FilteredMaskedCollision const& col, FDParticles const& parts) { if ((col.bitmaskTrackOne() & BitMask) != BitMask || (col.bitmaskTrackTwo() & BitMask) != BitMask) { return; @@ -343,7 +358,7 @@ struct femtoDreamPairTaskTrackV0 { } PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processSameEventMasked, "Enable processing same event with masks", true); - void processSameEventMCMasked(FilteredMaskedMCCollision const& col, o2::aod::FDMCCollisions&, FilteredFDMCParts const& parts, o2::aod::FDMCParticles const&) + void processSameEventMCMasked(FilteredMaskedMCCollision const& col, o2::aod::FDMCCollisions&, FDMCParts const& parts, o2::aod::FDMCParticles const&) { if ((col.bitmaskTrackOne() & BitMask) != BitMask && (col.bitmaskTrackTwo() & BitMask) != BitMask) { return; @@ -433,7 +448,7 @@ struct femtoDreamPairTaskTrackV0 { } } - void processMixedEventMasked(FilteredMaskedCollisions const& cols, FilteredFDParticles const& parts) + void processMixedEventMasked(FilteredMaskedCollisions const& cols, FDParticles const& parts) { switch (Mixing.Policy.value) { case femtodreamcollision::kMult: @@ -451,7 +466,7 @@ struct femtoDreamPairTaskTrackV0 { } PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processMixedEventMasked, "Enable processing mixed events with masks", true); - void processMixedEventMCMasked(FilteredMaskedMCCollisions const& cols, o2::aod::FDMCCollisions&, FilteredFDMCParts const& parts, o2::aod::FDMCParticles const&) + void processMixedEventMCMasked(FilteredMaskedMCCollisions const& cols, o2::aod::FDMCCollisions&, FDMCParts const& parts, o2::aod::FDMCParticles const&) { switch (Mixing.Policy.value) { case femtodreamcollision::kMult: diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h index 6d48650c2ba..c08c131ab99 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h @@ -74,7 +74,6 @@ class FemtoUniverse3DContainer /// \param mTAxis axis object for the mT axis /// \param use3dplots Flag to fill 3D plots /// \param isiden Identical or non-identical particle pair - /// \param islcms LCMS or PRF template void init_base(std::string folderName, std::string femtoObs1D, std::string femtoObsKout, std::string femtoObsKside, std::string femtoObsKlong, T femtoObsAxis1D, T femtoObsAxisOut, T femtoObsAxisSide, T femtoObsAxisLong, T multAxis, T kTAxis, T mTAxis, T multAxis3D, T mTAxis3D, bool use3dplots, bool isiden) { @@ -214,13 +213,13 @@ class FemtoUniverse3DContainer /// \param isiden Choosing identical or non-identical pairs /// \param islcm Choosing LCMS or PRF template - void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, bool isiden, bool islcms) + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, bool isiden) { std::vector f3d; const float kT = FemtoUniverseMath::getkT(part1, mMassOne, part2, mMassTwo); const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); - f3d = FemtoUniverseMath::getpairmom3d(part1, mMassOne, part2, mMassTwo, isiden, islcms); + f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, isiden); const float femtoObs1D = f3d[0]; const float femtoObsKout = f3d[1]; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h index e0429bd73e8..2f29f3df474 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h @@ -153,7 +153,7 @@ class FemtoUniverseAngularContainer /// \param part2 Particle two /// \param mult Multiplicity of the event template - void setPair_base(const float /*femtoObs*/, const float /*mT*/, T const& part1, T const& part2, const int /*mult*/, bool use3dplots) + void setPair_base(const float /*femtoObs*/, const float /*mT*/, T const& part1, T const& part2, const int /*mult*/, bool use3dplots, float weight = 1.0f) { delta_eta = part1.eta() - part2.eta(); delta_phi = part1.phi() - part2.phi(); @@ -165,7 +165,7 @@ class FemtoUniverseAngularContainer delta_phi -= o2::constants::math::TwoPI; } - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), delta_phi, delta_eta); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), delta_phi, delta_eta, weight); if (use3dplots) { // use 3d plots } @@ -194,7 +194,7 @@ class FemtoUniverseAngularContainer /// \param part2 Particle two /// \param mult Multiplicity of the event template - void setPair(T const& part1, T const& part2, const int mult, bool use3dplots) + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, float weight = 1.0f) { float femtoObs, femtoObsMC; // Calculate femto observable and the mT with reconstructed information @@ -215,7 +215,7 @@ class FemtoUniverseAngularContainer const float mTMC = FemtoUniverseMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); if (abs(part1.fdMCParticle().pdgMCTruth()) == abs(mPDGOne) && abs(part2.fdMCParticle().pdgMCTruth()) == abs(mPDGTwo)) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates - setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots); + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots, weight); setPair_MC(femtoObsMC, femtoObs, mT, mult); } else { } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h new file mode 100644 index 00000000000..64e9c339b55 --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h @@ -0,0 +1,586 @@ +// Copyright 2019-2022 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. + +/// \file femtoUniverseCascadeSelection.h +/// \brief Definition of the femtoUniverseCascadeSelection +/// \author Valentina Mantovani Sarti, TU MĂŒnchen valentina.mantovani-sarti@tum.de +/// \author Andi Mathis, TU MĂŒnchen, andreas.mathis@ph.tum.de +/// \author Luca Barioglio, TU MĂŒnchen, luca.barioglio@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch +/// \author Barbara Chytla, WUT Warsaw, barbara.chytla@cern.ch + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECASCADESELECTION_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECASCADESELECTION_H_ + +#include +#include +#include + +#include // FIXME + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +#include "Common/Core/RecoDecay.h" +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoUniverse +{ +namespace femtoUniverseCascadeSelection +{ +/// The different selections this task is capable of doing +enum CascadeSel { + kCascadeSign, ///< +1 particle, -1 antiparticle + kCascadepTMin, + kCascadepTMax, + kCascadeetaMax, + kCascadeV0DCADaughMax, + kCascadeV0CPAMin, + kCascadeV0TranRadMin, + kCascadeV0TranRadMax, + kCascadeV0DecVtxMax, + kCascadeDCADaughMax, + kCascadeCPAMin, + kCascadeTranRadMin, + kCascadeTranRadMax, + kCascadeDecVtxMax, + kCascadeDCAPosToPV, + kCascadeDCANegToPV, + kCascadeDCABachToPV, + kCascadeDCAV0ToPV, + kCascadeV0MassMin, + kCascadeV0MassMax +}; + +enum ChildTrackType { kPosTrack, + kNegTrack, + kBachTrack }; + +/*enum CascadeContainerPosition { + kCascade, + kPosCuts, + kPosPID, + kNegCuts, + kNegPID, +}; /// Position in the full VO cut container (for cutculator) +*/ +} // namespace femtoUniverseCascadeSelection + +/// \class FemtoUniverseCascadeSelection +/// \brief Cut class to contain and execute all cuts applied to Cascades +class FemtoUniverseCascadeSelection + : public FemtoUniverseObjectSelection +{ + // do cutculatora + + public: + FemtoUniverseCascadeSelection() + : nPtCascadeMinSel(0), nPtCascadeMaxSel(0), nEtaCascadeMaxSel(0), nDCAV0DaughMax(0), nCPAV0Min(0), nTranRadV0Min(0), nTranRadV0Max(0), nV0DecVtxMax(0), nDCACascadeDaughMax(0), nCPACascadeMin(0), nTranRadCascadeMin(0), nTranRadCascadeMax(0), nDecVtxMax(0), nDCAPosToPV(0), nDCANegToPV(0), nDCABachToPV(0), nDCAV0ToPV(0), pTCascadeMin(9999999.), pTCascadeMax(-9999999.), etaCascadeMax(-9999999.), DCAV0DaughMax(-9999999.), CPAV0Min(9999999.), TranRadV0Min(9999999.), TranRadV0Max(-9999999.), V0DecVtxMax(-9999999.), DCACascadeDaughMax(-9999999.), CPACascadeMin(9999999.), TranRadCascadeMin(9999999.), TranRadCascadeMax(-9999999.), DecVtxMax(-9999999.), DCAPosToPV(9999999.), DCANegToPV(9999999.), DCABachToPV(9999999.), DCAV0ToPV(9999999.), fV0InvMassLowLimit(1.05), fV0InvMassUpLimit(1.3), fInvMassLowLimit(1.25), fInvMassUpLimit(1.4), fRejectOmega(false), fInvMassOmegaLowLimit(1.5), fInvMassOmegaUpLimit(2.0) /*, nSigmaPIDOffsetTPC(0.)*/ + { + } + + /// Initializes histograms for the task + template + void init(HistogramRegistry* registry); + + template + bool isSelectedMinimal(Col const& col, Casc const& cascade, Track const& posTrack, Track const& negTrack, Track const& bachTrack); + + template + void fillCascadeQA(Col const& col, Casc const& cascade, Track const& posTrack, Track const& negTrack); + + template + void fillQA(Col const& col, Casc const& cascade, Track const& posTrack, Track const& negTrack, Track const& bachTrack); + + template + void setChildCuts(femtoUniverseCascadeSelection::ChildTrackType child, T1 selVal, + T2 selVar, femtoUniverseSelection::SelectionType selType) + { + if (child == femtoUniverseCascadeSelection::kPosTrack) { + PosDaughTrack.setSelection(selVal, selVar, selType); + } else if (child == femtoUniverseCascadeSelection::kNegTrack) { + NegDaughTrack.setSelection(selVal, selVar, selType); + } else if (child == femtoUniverseCascadeSelection::kBachTrack) { + BachTrack.setSelection(selVal, selVar, selType); + } + } + + template + void setChildPIDSpecies(femtoUniverseCascadeSelection::ChildTrackType child, + T& pids) + { + if (child == femtoUniverseCascadeSelection::kPosTrack) { + PosDaughTrack.setPIDSpecies(pids); + } else if (child == femtoUniverseCascadeSelection::kNegTrack) { + NegDaughTrack.setPIDSpecies(pids); + } else if (child == femtoUniverseCascadeSelection::kBachTrack) { + BachTrack.setPIDSpecies(pids); + } + } + + /// Helper function to obtain the name of a given selection criterion for consistent naming of the configurables + /// \param iSel Track selection variable to be examined + /// \param prefix Additional prefix for the name of the configurable + /// \param suffix Additional suffix for the name of the configurable + static std::string getSelectionName(femtoUniverseCascadeSelection::CascadeSel iSel, + std::string_view prefix = "", + std::string_view suffix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionNames[iSel]); + outString += suffix; + return outString; + } + + /// Helper function to obtain the helper string of a given selection criterion + /// for consistent description of the configurables + /// \param iSel Track selection variable to be examined + /// \param prefix Additional prefix for the output of the configurable + static std::string getSelectionHelper(femtoUniverseCascadeSelection::CascadeSel iSel, + std::string_view prefix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionHelper[iSel]); + return outString; + } + + /// Set limit for the selection on the invariant mass + /// \param lowLimit Lower limit for the invariant mass distribution + /// \param upLimit Upper limit for the invariant mass distribution + void setInvMassLimits(float lowLimit, float upLimit) + { + fInvMassLowLimit = lowLimit; + fInvMassUpLimit = upLimit; + } + + /// Set limit for the omega rejection on the invariant mass + /// \param lowLimit Lower limit for the invariant mass distribution + /// \param upLimit Upper limit for the invariant mass distribution + void setOmegaInvMassLimits(float lowLimit, float upLimit) + { + fRejectOmega = true; + fInvMassOmegaLowLimit = lowLimit; + fInvMassOmegaUpLimit = upLimit; + } + + private: + int nPtCascadeMinSel; + int nPtCascadeMaxSel; + int nEtaCascadeMaxSel; + int nDCAV0DaughMax; + int nCPAV0Min; + int nTranRadV0Min; + int nTranRadV0Max; + int nV0DecVtxMax; + int nDCACascadeDaughMax; + int nCPACascadeMin; + int nTranRadCascadeMin; + int nTranRadCascadeMax; + int nDecVtxMax; + int nDCAPosToPV; + int nDCANegToPV; + int nDCABachToPV; + int nDCAV0ToPV; + float pTCascadeMin; + float pTCascadeMax; + float etaCascadeMax; + float DCAV0DaughMax; + float CPAV0Min; + float TranRadV0Min; + float TranRadV0Max; + float V0DecVtxMax; + float DCACascadeDaughMax; + float CPACascadeMin; + float TranRadCascadeMin; + float TranRadCascadeMax; + float DecVtxMax; + float DCAPosToPV; + float DCANegToPV; + float DCABachToPV; + float DCAV0ToPV; + + float fV0InvMassLowLimit; + float fV0InvMassUpLimit; + + float fInvMassLowLimit; + float fInvMassUpLimit; + + float fRejectOmega; + float fInvMassOmegaLowLimit; + float fInvMassOmegaUpLimit; + + // float nSigmaPIDOffsetTPC; + + FemtoUniverseTrackSelection PosDaughTrack; + FemtoUniverseTrackSelection NegDaughTrack; + FemtoUniverseTrackSelection BachTrack; + + static constexpr int kNcascadeSelection = 20; // can I do less ? + + static constexpr std::string_view mSelectionNames[kNcascadeSelection] = { + "Sign", "PtMin", "PtMax", "EtaMax", "DCAv0daughMax", "v0CPAMin", + "v0TranRadMin", "v0TranRadMax", "v0DecVecMax", "DCAcascDaugh", + "CPAMin", "TranRadMin", "TranRadMax", "DecVtxMax", + "DCAPosToPV", "DCANegToPV", "DCABachToPV", "DCAV0ToPV", + "kV0MassMin", "V0MassMax"}; ///< Name of the different + ///< selections + + static constexpr femtoUniverseSelection::SelectionType + mSelectionTypes[kNcascadeSelection]{ + femtoUniverseSelection::kEqual, // sign + femtoUniverseSelection::kLowerLimit, // pt min + femtoUniverseSelection::kUpperLimit, // pt max + femtoUniverseSelection::kUpperLimit, // eta max + femtoUniverseSelection::kUpperLimit, // DCA v0 daughters max + femtoUniverseSelection::kLowerLimit, // v0 cos PA min + femtoUniverseSelection::kLowerLimit, // v0 tran rad min + femtoUniverseSelection::kUpperLimit, // v0 tran rad max + femtoUniverseSelection::kUpperLimit, // v0 maximum distance of decay vertex to PV + femtoUniverseSelection::kUpperLimit, // DCA cascade daughters max + femtoUniverseSelection::kLowerLimit, // cascade cos PA min + femtoUniverseSelection::kLowerLimit, // cascade tran rad min + femtoUniverseSelection::kUpperLimit, // cascade tran rad max + femtoUniverseSelection::kUpperLimit, // cascade maximum distance of decay vertex to PV + femtoUniverseSelection::kLowerLimit, // DCA pos to PV max + femtoUniverseSelection::kLowerLimit, // DCA neg to PV max + femtoUniverseSelection::kLowerLimit, // DCA bach to PV max + femtoUniverseSelection::kLowerLimit, // DCA v0 to PV max + femtoUniverseSelection::kLowerLimit, // v0 mass min + femtoUniverseSelection::kUpperLimit, // v0 mass max + }; ///< Map to match a variable with + ///< its type + + static constexpr std::string_view mSelectionHelper[kNcascadeSelection] = { + "Cascade particle sign (+1 or -1)", + "Minimum pT (GeV/c)", + "Maximum pT (GeV/c)", + "Maximum |Eta|", + "Maximum DCA between v0 daughters (cm)", + "Minimum Cosine of Pointing Angle for v0", + "Minimum v0 transverse radius (cm)", + "Maximum v0 transverse radius (cm)", + "Maximum distance of v0 from primary vertex", + "Maximum DCA between cascade daughters (cm)", + "Minimum Cosine of Pointing Angle for cascade", + "Minimum cascade transverse radius (cm)", + "Maximum cascade transverse radius (cm)", + "Maximum distance of cascade from primary vertex", + "Maximum DCA of positive track form primary vertex", + "Maximum DCA of negative track form primary vertex", + "Maximum DCA of bachelor track form primary vertex", + "Maximum DCA of v0 form primary vertex", + "Minimum V0 mass", + "Maximum V0 mass"}; ///< Helper information for the + ///< different selections + +}; // namespace femtoUniverse + +template +void FemtoUniverseCascadeSelection::init(HistogramRegistry* registry) +{ + + if (registry) { + mHistogramRegistry = registry; + fillSelectionHistogram(); // cascade + fillSelectionHistogram(); // pos, neg + fillSelectionHistogram(); // bach + + AxisSpec massAxisCascade = {600, 1.25f, 1.4f, "m_{#Cascade} (GeV/#it{c}^{2})"}; + AxisSpec massAxisV0 = {600, 0.0f, 3.0f, "m_{#V0} (GeV/#it{c}^{2})"}; + AxisSpec DCADaughAxis = {1000, 0.0f, 2.0f, "DCA (cm)"}; + AxisSpec DCAToPVAxis = {1000, -10.0f, 10.0f, "DCA to PV (cm)"}; + AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec etaAxis = {100, -2.0f, 2.0f, "#it{#eta}"}; + AxisSpec phiAxis = {100, 0.0f, 6.0f, "#it{#phi}"}; + AxisSpec CPAAxis = {1000, 0.95f, 1.0f, "#it{cos #theta_{p}}"}; + AxisSpec tranRadAxis = {1000, 0.0f, 100.0f, "#it{r}_{xy} (cm)"}; + + /// \todo this should be an automatic check in the parent class, and the + /// return type should be templated + size_t nSelections = getNSelections(); + if (nSelections > 17 * sizeof(cutContainerType)) { + LOG(fatal) << "FemtoUniverseCascadeCuts: Number of selections to large for your " + "container - quitting!"; + } + + PosDaughTrack.init( + mHistogramRegistry); + NegDaughTrack.init( + mHistogramRegistry); + BachTrack.init( + mHistogramRegistry); + + // V0 (Lambda) + // mHistogramRegistry->add("CascadeQA/hInvMassV0NoCuts", "No cuts", kTH1F, {massAxisV0}); + mHistogramRegistry->add("CascadeQA/hInvMassV0Cut", "Invariant mass cut", kTH1F, {massAxisV0}); + mHistogramRegistry->add("CascadeQA/hDCAV0Daugh", "V0-daughters DCA", kTH1F, {DCADaughAxis}); + mHistogramRegistry->add("CascadeQA/hV0CPA", "V0 cos PA", kTH1F, {CPAAxis}); + mHistogramRegistry->add("CascadeQA/hV0TranRad", "V0 transverse radius", kTH1F, {tranRadAxis}); + // mHistogramRegistry->add("CascadeQA/hV0DecVtxMax", "V0 maximum distance on decay vertex", kTH1F, {massAxisV0}); + + // Cascade (Xi, Omega) + // mHistogramRegistry->add("CascadeQA/hInvMassCascadeNoCuts", "No cuts", kTH1F, {massAxisCascade}); + mHistogramRegistry->add("CascadeQA/hInvMassCascadeCut", "Invariant mass with cut", kTH1F, {massAxisCascade}); + mHistogramRegistry->add("CascadeQA/hCascadePt", "pT distribution", kTH1F, {ptAxis}); + mHistogramRegistry->add("CascadeQA/hCascadeEta", "Eta distribution", kTH1F, {etaAxis}); + mHistogramRegistry->add("CascadeQA/hCascadePhi", "Phi distribution", kTH1F, {phiAxis}); + mHistogramRegistry->add("CascadeQA/hDCACascadeDaugh", "Cascade-daughters DCA", kTH1F, {DCADaughAxis}); + mHistogramRegistry->add("CascadeQA/hCascadeCPA", "Cos PA", kTH1F, {CPAAxis}); + mHistogramRegistry->add("CascadeQA/hCascadeTranRad", "Transverse radius", kTH1F, {tranRadAxis}); + mHistogramRegistry->add("CascadeQA/hDCAPosToPV", "Pos V0 daughter DCA to primary vertex", kTH1F, {DCAToPVAxis}); + mHistogramRegistry->add("CascadeQA/hDCANegToPV", "Neg V0 daughter DCA to primary vertex", kTH1F, {DCAToPVAxis}); + mHistogramRegistry->add("CascadeQA/hDCABachToPV", "Bachelor DCA to primary vertex", kTH1F, {DCAToPVAxis}); + mHistogramRegistry->add("CascadeQA/hDCAV0ToPV", "V0 DCA to primary vertex", kTH1F, {DCAToPVAxis}); + } + + /// check whether the most open cuts are fulfilled - most of this should have + /// already be done by the filters + nPtCascadeMinSel = getNSelections(femtoUniverseCascadeSelection::kCascadepTMin); + nPtCascadeMaxSel = getNSelections(femtoUniverseCascadeSelection::kCascadepTMax); + nEtaCascadeMaxSel = getNSelections(femtoUniverseCascadeSelection::kCascadeetaMax); + nDCAV0DaughMax = getNSelections(femtoUniverseCascadeSelection::kCascadeV0DCADaughMax); + nCPAV0Min = getNSelections(femtoUniverseCascadeSelection::kCascadeV0CPAMin); + nTranRadV0Min = getNSelections(femtoUniverseCascadeSelection::kCascadeV0TranRadMin); + nTranRadV0Max = getNSelections(femtoUniverseCascadeSelection::kCascadeV0TranRadMax); + nV0DecVtxMax = getNSelections(femtoUniverseCascadeSelection::kCascadeV0DecVtxMax); + nDCACascadeDaughMax = getNSelections(femtoUniverseCascadeSelection::kCascadeDCADaughMax); + nCPACascadeMin = getNSelections(femtoUniverseCascadeSelection::kCascadeCPAMin); + nTranRadCascadeMin = getNSelections(femtoUniverseCascadeSelection::kCascadeTranRadMin); + nTranRadCascadeMax = getNSelections(femtoUniverseCascadeSelection::kCascadeTranRadMax); + nDecVtxMax = getNSelections(femtoUniverseCascadeSelection::kCascadeDecVtxMax); + nDCAPosToPV = getNSelections(femtoUniverseCascadeSelection::kCascadeDCAPosToPV); + nDCANegToPV = getNSelections(femtoUniverseCascadeSelection::kCascadeDCANegToPV); + nDCABachToPV = getNSelections(femtoUniverseCascadeSelection::kCascadeDCABachToPV); + nDCAV0ToPV = getNSelections(femtoUniverseCascadeSelection::kCascadeDCAV0ToPV); + // dodac V0 mass min i max + + pTCascadeMin = getMinimalSelection(femtoUniverseCascadeSelection::kCascadepTMin, + femtoUniverseSelection::kLowerLimit); + pTCascadeMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadepTMax, + femtoUniverseSelection::kUpperLimit); + etaCascadeMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeetaMax, + femtoUniverseSelection::kAbsUpperLimit); + DCAV0DaughMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0DCADaughMax, + femtoUniverseSelection::kUpperLimit); + CPAV0Min = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0CPAMin, + femtoUniverseSelection::kLowerLimit); + TranRadV0Min = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0TranRadMin, + femtoUniverseSelection::kLowerLimit); + TranRadV0Max = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0TranRadMax, + femtoUniverseSelection::kUpperLimit); + V0DecVtxMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0DecVtxMax, + femtoUniverseSelection::kAbsUpperLimit); + DCACascadeDaughMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeDCADaughMax, + femtoUniverseSelection::kUpperLimit); + CPACascadeMin = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeCPAMin, + femtoUniverseSelection::kLowerLimit); + TranRadCascadeMin = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeTranRadMin, + femtoUniverseSelection::kLowerLimit); + TranRadCascadeMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeTranRadMax, + femtoUniverseSelection::kUpperLimit); + DecVtxMax = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeDecVtxMax, + femtoUniverseSelection::kAbsUpperLimit); + DCAPosToPV = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeDCAPosToPV, + femtoUniverseSelection::kLowerLimit); + DCANegToPV = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeDCANegToPV, + femtoUniverseSelection::kLowerLimit); + DCABachToPV = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeDCABachToPV, + femtoUniverseSelection::kLowerLimit); + DCAV0ToPV = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeDCAV0ToPV, + femtoUniverseSelection::kLowerLimit); + fV0InvMassLowLimit = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0MassMin, + femtoUniverseSelection::kLowerLimit); + fV0InvMassUpLimit = getMinimalSelection(femtoUniverseCascadeSelection::kCascadeV0MassMax, + femtoUniverseSelection::kUpperLimit); +} + +template +bool FemtoUniverseCascadeSelection::isSelectedMinimal(Col const& col, Casc const& cascade, Track const& posTrack, Track const& negTrack, Track const& bachTrack) +{ + const auto signPos = posTrack.sign(); + const auto signNeg = negTrack.sign(); + + if (signPos < 0 || signNeg > 0) { + LOG(warn) << "Something wrong in isSelectedMinimal"; + LOG(warn) << "ERROR - Wrong sign for V0 daughters"; + } + + const std::vector decVtx = {cascade.x(), cascade.y(), cascade.z()}; + + const float cpav0 = cascade.v0cosPA(col.posX(), col.posY(), col.posZ()); + const float cpaCasc = cascade.casccosPA(col.posX(), col.posY(), col.posZ()); + const float dcav0topv = cascade.dcav0topv(col.posX(), col.posY(), col.posZ()); + const float invMassLambda = cascade.mLambda(); + const float invMassXi = cascade.mXi(); + + if (invMassLambda < fV0InvMassLowLimit || invMassLambda > fV0InvMassUpLimit) { + return false; + } + if (invMassXi < fInvMassLowLimit || invMassXi > fInvMassUpLimit) { + return false; + } + if (fRejectOmega) { + const float invMassOmega = cascade.mOmega(); + if (invMassOmega > fInvMassOmegaLowLimit && + invMassOmega < fInvMassOmegaUpLimit) { + return false; + } + } + if (nPtCascadeMinSel > 0 && cascade.pt() < pTCascadeMin) { + return false; + } + if (nPtCascadeMaxSel > 0 && cascade.pt() > pTCascadeMax) { + return false; + } + if (nEtaCascadeMaxSel > 0 && std::abs(cascade.eta()) > etaCascadeMax) { + return false; + } + if (nDCAV0DaughMax > 0 && cascade.dcaV0daughters() > DCAV0DaughMax) { + return false; + } + if (nCPAV0Min > 0 && cpav0 < CPAV0Min) { + return false; + } + if (nTranRadV0Min > 0 && cascade.v0radius() < TranRadV0Min) { + return false; + } + if (nTranRadV0Max > 0 && cascade.v0radius() > TranRadV0Max) { + return false; + } + if (nDCACascadeDaughMax > 0 && cascade.dcacascdaughters() > DCACascadeDaughMax) { + return false; + } + if (nCPACascadeMin > 0 && cpaCasc < CPACascadeMin) { + return false; + } + if (nTranRadCascadeMin > 0 && cascade.cascradius() < TranRadCascadeMin) { + return false; + } + if (nTranRadCascadeMax > 0 && cascade.cascradius() > TranRadCascadeMax) { + return false; + } + for (size_t i = 0; i < decVtx.size(); i++) { + if (nDecVtxMax > 0 && decVtx.at(i) > DecVtxMax) { + return false; + } + } + if (nDCAPosToPV > 0 && abs(cascade.dcapostopv()) < DCAPosToPV) { + return false; + } + if (nDCANegToPV > 0 && abs(cascade.dcanegtopv()) < DCANegToPV) { + return false; + } + if (nDCABachToPV > 0 && abs(cascade.dcabachtopv()) < DCABachToPV) { + return false; + } + if (nDCAV0ToPV > 0 && abs(dcav0topv) < DCAV0ToPV) { + return false; + } + + if (!PosDaughTrack.isSelectedMinimal(posTrack)) { + return false; + } + if (!NegDaughTrack.isSelectedMinimal(negTrack)) { + return false; + } + if (!BachTrack.isSelectedMinimal(bachTrack)) { + return false; + } + /* + // check that track combinations for V0 or antiV0 would be fulfilling PID + float nSigmaPIDMax = PosDaughTrack.getSigmaPIDMax(); + // antiV0 + auto nSigmaPrNeg = negTrack.tpcNSigmaPr(); + auto nSigmaPiPos = posTrack.tpcNSigmaPi(); + // v0 + auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); + auto nSigmaPrPos = posTrack.tpcNSigmaPr(); + if (!(abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) && + !(abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax)) { + return false; + } + */ + return true; +} + +template +void FemtoUniverseCascadeSelection::fillCascadeQA(Col const& col, Casc const& cascade, Track const& posTrack, Track const& negTrack) +{ + const auto signPos = posTrack.sign(); + const auto signNeg = negTrack.sign(); + if (signPos < 0 || signNeg > 0) { + LOG(warn) << "Something wrong in isSelectedMinimal"; + LOG(warn) << "ERROR - Wrong sign for V0 daughters"; + } + + // const std::vector decVtx = {cascade.x(), cascade.y(), cascade.z()}; + const float cpav0 = cascade.v0cosPA(col.posX(), col.posY(), col.posZ()); + const float cpaCasc = cascade.casccosPA(col.posX(), col.posY(), col.posZ()); + const float dcav0topv = cascade.dcav0topv(col.posX(), col.posY(), col.posZ()); + + const float invMassLambda = cascade.mLambda(); + const float invMassXi = cascade.mXi(); + + mHistogramRegistry->fill(HIST("CascadeQA/hInvMassV0Cut"), invMassLambda); + mHistogramRegistry->fill(HIST("CascadeQA/hInvMassCascadeCut"), invMassXi); + mHistogramRegistry->fill(HIST("CascadeQA/hCascadePt"), cascade.pt()); + mHistogramRegistry->fill(HIST("CascadeQA/hCascadeEta"), cascade.eta()); + mHistogramRegistry->fill(HIST("CascadeQA/hCascadePhi"), cascade.phi()); + mHistogramRegistry->fill(HIST("CascadeQA/hDCAV0Daugh"), cascade.dcaV0daughters()); + mHistogramRegistry->fill(HIST("CascadeQA/hV0CPA"), cpav0); + mHistogramRegistry->fill(HIST("CascadeQA/hV0TranRad"), cascade.v0radius()); + mHistogramRegistry->fill(HIST("CascadeQA/hCascadeCPA"), cpaCasc); + mHistogramRegistry->fill(HIST("CascadeQA/hDCACascadeDaugh"), cascade.dcacascdaughters()); + mHistogramRegistry->fill(HIST("CascadeQA/hCascadeTranRad"), cascade.cascradius()); + mHistogramRegistry->fill(HIST("CascadeQA/hDCAPosToPV"), cascade.dcapostopv()); + mHistogramRegistry->fill(HIST("CascadeQA/hDCANegToPV"), cascade.dcanegtopv()); + mHistogramRegistry->fill(HIST("CascadeQA/hDCABachToPV"), cascade.dcabachtopv()); + mHistogramRegistry->fill(HIST("CascadeQA/hDCAV0ToPV"), dcav0topv); + + // is this necessary + /* + bool write = true; + for (size_t i = 0; i < decVtx.size(); i++) { + write = write && (decVtx.at(i) < DecVtxMax); + } + if (write) { + mHistogramRegistry->fill(HIST("CAscadeQA/hInvMassCascadeDecVtxMax"), + cascade.mXi()); + } + */ +} + +template +void FemtoUniverseCascadeSelection::fillQA(Col const& /*col*/, Casc const& /*cascade*/, Track const& posTrack, Track const& negTrack, Track const& bachTrack) +{ + PosDaughTrack.fillQA(posTrack); + NegDaughTrack.fillQA(negTrack); + BachTrack.fillQA(bachTrack); +} + +} // namespace o2::analysis::femtoUniverse + +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECASCADESELECTION_H_ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h index 285dabc0b4d..e3f9c0feee6 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h @@ -168,7 +168,7 @@ class FemtoUniverseContainer /// \param part2 Particle two /// \param mult Multiplicity of the event template - void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots) + void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots, float weight = 1.0f) { const float kT = FemtoUniverseMath::getkT(part1, mMassOne, part2, mMassTwo); delta_eta = part1.eta() - part2.eta(); @@ -181,19 +181,19 @@ class FemtoUniverseContainer delta_phi -= o2::constants::math::TwoPI; } - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairDist"), femtoObs); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkT"), kT); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarkT"), femtoObs, kT); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmT"), femtoObs, mT); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarMult"), femtoObs, mult); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart1"), femtoObs, part1.pt()); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart2"), femtoObs, part2.pt()); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart1"), part1.pt(), mult); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart2"), part2.pt(), mult); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/PtPart1PtPart2"), part1.pt(), part2.pt()); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), delta_phi, delta_eta); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairDist"), femtoObs, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkT"), kT, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarkT"), femtoObs, kT, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmT"), femtoObs, mT, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarMult"), femtoObs, mult, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart1"), femtoObs, part1.pt(), weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart2"), femtoObs, part2.pt(), weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart1"), part1.pt(), mult, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart2"), part2.pt(), mult, weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/PtPart1PtPart2"), part1.pt(), part2.pt(), weight); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), delta_phi, delta_eta, weight); if (use3dplots) { - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmTMult"), femtoObs, mT, mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmTMult"), femtoObs, mT, mult, weight); } } @@ -225,7 +225,7 @@ class FemtoUniverseContainer /// \param part2 Particle two /// \param mult Multiplicity of the event template - void setPair(T const& part1, T const& part2, const int mult, bool use3dplots) + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, float weight = 1.0f) { float femtoObs, femtoObsMC; // Calculate femto observable and the mT with reconstructed information @@ -235,7 +235,7 @@ class FemtoUniverseContainer const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); if (mHistogramRegistry) { - setPair_base(femtoObs, mT, part1, part2, mult, use3dplots); + setPair_base(femtoObs, mT, part1, part2, mult, use3dplots, weight); if constexpr (isMC) { if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { @@ -246,7 +246,7 @@ class FemtoUniverseContainer const float mTMC = FemtoUniverseMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); if (abs(part1.fdMCParticle().pdgMCTruth()) == abs(mPDGOne) && abs(part2.fdMCParticle().pdgMCTruth()) == abs(mPDGTwo)) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates - setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots); + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots, weight); setPair_MC(femtoObsMC, femtoObs, mT, mult); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index ed79156cabb..d89aeef295f 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -140,45 +140,6 @@ class FemtoUniverseDetaDphiStar } } - bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) - { - if (mom < 0.3) { // 0.0-0.3 - if (TMath::Abs(nsigmaTPCK) < 3.0) { - return true; - } else { - return false; - } - } else if (mom < 0.45) { // 0.30 - 0.45 - if (TMath::Abs(nsigmaTPCK) < 2.0) { - return true; - } else { - return false; - } - } else if (mom < 0.55) { // 0.45-0.55 - if (TMath::Abs(nsigmaTPCK) < 1.0) { - return true; - } else { - return false; - } - } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) - if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { - { - return true; - } - } else { - return false; - } - } else if (mom > 1.5) { // 1.5 - - if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { - return true; - } else { - return false; - } - } else { - return false; - } - } - /// Check if pair is close or not template bool isClosePair(Part const& part1, Part const& part2, Parts const& particles, float lmagfield, uint8_t ChosenEventType) @@ -264,8 +225,6 @@ class FemtoUniverseDetaDphiStar for (int i = 0; i < 2; i++) { auto indexOfDaughterpart1 = (ChosenEventType == femtoUniverseContainer::EventType::mixed ? part1.globalIndex() : part1.index()) - 2 + i; auto indexOfDaughterpart2 = (ChosenEventType == femtoUniverseContainer::EventType::mixed ? part2.globalIndex() : part2.index()) - 2 + i; - // auto indexOfDaughterpart1 = part1.globalIndex() - 2 + i; - // auto indexOfDaughterpart2 = part2.globalIndex() - 2 + i; auto daughterpart1 = particles.begin() + indexOfDaughterpart1; auto daughterpart2 = particles.begin() + indexOfDaughterpart2; auto deta = daughterpart1.eta() - daughterpart2.eta(); @@ -278,7 +237,8 @@ class FemtoUniverseDetaDphiStar LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; } - if (pow(dphiAvg, 2) / pow(CutDeltaPhiStarMax, 2) + pow(deta, 2) / pow(CutDeltaEtaMax, 2) < 1.) { + // if (pow(dphiAvg, 2) / pow(CutDeltaPhiStarMax, 2) + pow(deta, 2) / pow(CutDeltaEtaMax, 2) < 1.) { + if ((dphiAvg > CutDeltaPhiStarMin) && (dphiAvg < CutDeltaPhiStarMax) && (deta > CutDeltaEtaMin) && (deta < CutDeltaEtaMax)) { pass = true; } else { if (ChosenEventType == femtoUniverseContainer::EventType::same) { @@ -363,21 +323,18 @@ class FemtoUniverseDetaDphiStar LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; } - // if proton is kaon reject the ring - if (IsKaonNSigma(daughter.pt(), trackCuts.getNsigmaTPC(daughter, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(daughter, o2::track::PID::Kaon))) { - // REMOVING THE "RING" -- CALCULATING THE INVARIANT MASS - TLorentzVector part1Vec; - TLorentzVector part2Vec; - float mMassOne = TDatabasePDG::Instance()->GetParticle(321)->Mass(); - float mMassTwo = TDatabasePDG::Instance()->GetParticle(321)->Mass(); - part1Vec.SetPtEtaPhiM(part1.pt(), part1.eta(), part1.phi(), mMassOne); - part2Vec.SetPtEtaPhiM(daughter.pt(), daughter.eta(), daughter.phi(), mMassTwo); - TLorentzVector sumVec(part1Vec); - sumVec += part2Vec; - float phiM = sumVec.M(); - if ((phiM > CutPhiInvMassLow) && (phiM < CutPhiInvMassHigh)) { - pass = true; // pair comes from Phi meson decay - } + // REMOVING THE "RING" -- CALCULATING THE INVARIANT MASS + TLorentzVector part1Vec; + TLorentzVector part2Vec; + float mMassOne = TDatabasePDG::Instance()->GetParticle(321)->Mass(); + float mMassTwo = TDatabasePDG::Instance()->GetParticle(321)->Mass(); + part1Vec.SetPtEtaPhiM(part1.pt(), part1.eta(), part1.phi(), mMassOne); + part2Vec.SetPtEtaPhiM(daughter.pt(), daughter.eta(), daughter.phi(), mMassTwo); + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + float phiM = sumVec.M(); + if ((phiM > CutPhiInvMassLow) && (phiM < CutPhiInvMassHigh)) { + pass = true; // pair comes from Phi meson decay } // APPLYING THE CUTS diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h index 216cecb1148..ebd95d31a00 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h @@ -38,6 +38,8 @@ class FemtoUniverseEventHisto mHistogramRegistry->add("Event/zvtxhist", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{16384, 0, 32768}}); mHistogramRegistry->add("Event/MultNTr", "; vMultNTr; Entries", kTH1F, {{200, 0, 200}}); + mHistogramRegistry->add("Event/MultNTrVSMultV0M", "; vMultNTr; MultV0M", kTH2F, {{4000, 0, 4000}, {32768, 0, 32768}}); + mHistogramRegistry->add("Event/zvtxhist_MultNTr", "; zvtxhist; MultNTr", kTH2F, {{300, -12.5, 12.5}, {200, 0, 200}}); } /// Some basic QA of the event @@ -50,6 +52,8 @@ class FemtoUniverseEventHisto mHistogramRegistry->fill(HIST("Event/zvtxhist"), col.posZ()); mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multV0M()); mHistogramRegistry->fill(HIST("Event/MultNTr"), col.multNtr()); + mHistogramRegistry->fill(HIST("Event/MultNTrVSMultV0M"), col.multNtr(), col.multV0M()); + mHistogramRegistry->fill(HIST("Event/zvtxhist_MultNTr"), col.posZ(), col.multNtr()); } } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h index cd992906c89..95c0165b26d 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h @@ -149,9 +149,8 @@ class FemtoUniverseMath /// \param part2 Particle 2 /// \param mass2 Mass of particle 2 /// \param isiden Identical or non-identical particle pair - /// \param islcms LCMS or PRF template - static std::vector getpairmom3d(const T& part1, const float mass1, const T& part2, const float mass2, bool isiden, bool islcms) + static std::vector newpairfunc(const T& part1, const float mass1, const T& part2, const float mass2, bool isiden) { const double E1 = sqrt(pow(part1.px(), 2) + pow(part1.py(), 2) + pow(part1.pz(), 2) + pow(mass1, 2)); const double E2 = sqrt(pow(part2.px(), 2) + pow(part2.py(), 2) + pow(part2.pz(), 2) + pow(mass2, 2)); @@ -165,80 +164,62 @@ class FemtoUniverseMath const double tPx = trackSum.px(); const double tPy = trackSum.py(); const double tPz = trackSum.pz(); - const double tPE = trackSum.E(); + const double tE = trackSum.E(); - const double tPt = trackSum.pt(); - const double tMt = trackSum.mt(); - const double tPinv = std::sqrt((tMt * tMt) - (tPt * tPt)); + double tPt = (tPx * tPx + tPy * tPy); + double tMt = (tE * tE - tPz * tPz); + double tM = sqrt(tMt - tPt); + tMt = sqrt(tMt); + tPt = sqrt(tPt); - float nullmass = 0.0; - const double m1 = std::max(nullmass, mass1); - const double m2 = std::max(nullmass, mass2); - - const double tQinvL = std::pow((E1 - E2), 2) - std::pow((part1.px() - part2.px()), 2) - - std::pow((part1.py() - part2.py()), 2) - std::pow((part1.pz() - part2.pz()), 2); - - double tQ = (m1 - m2) / tPinv; - tQ = ::sqrt(tQ * tQ - tQinvL); - - const double fKStarCalc = tQ / 2.0; - vect.push_back(fKStarCalc); + double fDKOutLCMS, fDKSideLCMS, fDKLongLCMS; + double fDKOut, fDKSide, fDKLong, fDE; + double px1LCMS, py1LCMS, pz1LCMS; + double px2LCMS, py2LCMS, pz2LCMS; + double kstar; // Boost to LCMS - const double beta = tPz / tPE; - const double gamma = tPE / tMt; + const double beta = tPz / tE; + const double gamma = tE / tMt; - const double px1L = (part1.px() * tPx + part1.py() * tPy) / tPt; - const double py1L = (-part1.px() * tPy + part1.py() * tPx) / tPt; - const double pz1L = gamma * (part1.pz() - beta * E1); - const double pE1L = gamma * (E1 - beta * part1.pz()); + fDKOut = (part1.px() * tPx + part1.py() * tPy) / tPt; + fDKSide = (-part1.px() * tPy + part1.py() * tPx) / tPt; + fDKLong = gamma * (part1.pz() - beta * E1); + fDE = gamma * (E1 - beta * part1.pz()); - const double px2L = (part2.px() * tPx + part2.py() * tPy) / tPt; - const double py2L = (-part2.px() * tPy + part2.py() * tPx) / tPt; - const double pz2L = gamma * (part2.pz() - beta * E2); - const double pE2L = gamma * (E2 - beta * part2.pz()); + px1LCMS = fDKOut; + py1LCMS = fDKSide; + pz1LCMS = fDKLong; + // pE1LCMS = fDE; - double fDKOutLCMS; - double fDKSideLCMS; - double fDKLongLCMS; + px2LCMS = (part2.px() * tPx + part2.py() * tPy) / tPt; + py2LCMS = (part2.py() * tPx - part2.px() * tPy) / tPt; + pz2LCMS = gamma * (part2.pz() - beta * E2); + // pE2LCMS = gamma * (E2 - beta * part2.pz()); - double fDKOutPRF; - double fDKSidePRF; - double fDKLongPRF; - - if (!isiden) { - fDKOutLCMS = px1L; - fDKSideLCMS = py1L; - fDKLongLCMS = pz1L; - } else { - fDKOutLCMS = px1L - px2L; - fDKSideLCMS = py1L - py2L; - fDKLongLCMS = pz1L - pz2L; - } + fDKOutLCMS = px1LCMS - px2LCMS; + fDKSideLCMS = py1LCMS - py2LCMS; + fDKLongLCMS = pz1LCMS - pz2LCMS; // Boost to PRF + const double betaOut = tPt / tMt; - const double gammaOut = tMt / tPinv; + const double gammaOut = tMt / tM; - if (!isiden) { - fDKOutPRF = gammaOut * (fDKOutLCMS - betaOut * pE1L); - fDKSidePRF = fDKSideLCMS; - fDKLongPRF = fDKLongLCMS; - } else { - fDKOutPRF = gammaOut * (fDKOutLCMS - betaOut * (pE1L - pE2L)); - fDKSidePRF = fDKSideLCMS; - fDKLongPRF = fDKLongLCMS; - } + fDKOut = gammaOut * (fDKOut - betaOut * fDE); + kstar = sqrt(fDKOut * fDKOut + fDKSide * fDKSide + fDKLong * fDKLong); - if (islcms) { + if (isiden) { + vect.push_back(2.0 * (kstar)); vect.push_back(fDKOutLCMS); vect.push_back(fDKSideLCMS); vect.push_back(fDKLongLCMS); } else { - vect.push_back(fDKOutPRF); - vect.push_back(fDKSidePRF); - vect.push_back(fDKLongPRF); + vect.push_back(kstar); + vect.push_back(fDKOut); + vect.push_back(fDKSide); + vect.push_back(fDKLong); } return vect; } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h index 2c7e4db7bd9..1be3d76085e 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h @@ -49,7 +49,7 @@ class PairSHCentMultKt /// \param maxl Maximum valie of L component of the spherical harmonics template void init(HistogramRegistry* registry, t1& kstarbins, t1& centmultbins, - t1& ktbins, int maxl) + t1& ktbins, int /*maxl*/) { PairSHCentMultKtRegistry = registry; AxisSpec kstarAxis = {kstarbins, "#it{k*} (GeV/#it{c})"}; @@ -184,24 +184,24 @@ class PairSHCentMultKt /// \param ktval kT value template void fill_mult_NumDen(T const& part1, T const& part2, uint8_t ChosenEventType, - int maxl, int multval, float ktval) + int maxl, int multval, float ktval, bool isiden) { int multbinval; int absmultval = multval; - if ((absmultval > CentMultBins[0]) && (absmultval <= CentMultBins[1])) { + if ((absmultval >= CentMultBins[0]) && (absmultval < CentMultBins[1])) { multbinval = 0; - } else if (absmultval <= CentMultBins[2]) { + } else if (absmultval < CentMultBins[2]) { multbinval = 1; - } else if (absmultval <= CentMultBins[3]) { + } else if (absmultval < CentMultBins[3]) { multbinval = 2; - } else if (ktval <= CentMultBins[4]) { + } else if (ktval < CentMultBins[4]) { multbinval = 3; } else { return; } // std::cout<<"multbinval "< void fill_kT_NumDen(T const& part1, T const& part2, uint8_t ChosenEventType, - int maxl, int multval, float ktval) + int maxl, int multval, float ktval, bool isiden) { int ktbinval = -1; - if ((ktval > KtBins[0]) && (ktval <= KtBins[1])) { + if ((ktval >= KtBins[0]) && (ktval < KtBins[1])) { ktbinval = 0; - } else if (ktval <= KtBins[2]) { + } else if (ktval < KtBins[2]) { ktbinval = 1; - } else if (ktval <= KtBins[3]) { + } else if (ktval < KtBins[3]) { ktbinval = 2; - } else if (ktval <= KtBins[4]) { + } else if (ktval < KtBins[4]) { ktbinval = 3; } else { return; } - AddEventPair(part1, part2, ChosenEventType, maxl, multval, ktbinval); + AddEventPair(part1, part2, ChosenEventType, maxl, multval, ktbinval, isiden); } /// Set the PDG codes of the two particles involved @@ -262,14 +262,14 @@ class PairSHCentMultKt /// \param ktval kT value template void AddEventPair(T const& part1, T const& part2, uint8_t ChosenEventType, - int maxl, int multval, int ktval) + int /*maxl*/, int multval, int ktval, bool isiden) { int fMultBin = multval; int fKtBin = ktval; std::vector> fYlmBuffer(fMaxJM); std::vector f3d; - f3d = FemtoUniverseMath::getpairmom3d(part1, mMassOne, part2, mMassTwo, - true, true); + f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, + isiden); const float qout = f3d[1]; const float qside = f3d[2]; @@ -329,7 +329,7 @@ class PairSHCentMultKt /// \param MaxJM Maximum value of J /// \param multval Multiplicity value /// \param ktval kT value - void PackCov(uint8_t ChosenEventType, int MaxJM, int multval, int ktval) + void PackCov(uint8_t ChosenEventType, int /*MaxJM*/, int multval, int ktval) { int fMultBin = multval; int fKtBin = ktval; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h index 9a5070a22e6..50827d8b243 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h @@ -70,7 +70,7 @@ class FemtoUniverseParticleHisto void init_debug(std::string folderName) { std::string folderSuffix = static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[mc]).c_str(); - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { mHistogramRegistry->add((folderName + folderSuffix + "/hCharge").c_str(), "; Charge; Entries", kTH1F, {{5, -2.5, 2.5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfindable").c_str(), "; TPC findable clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfound").c_str(), "; TPC found clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); @@ -83,16 +83,16 @@ class FemtoUniverseParticleHisto mHistogramRegistry->add((folderName + folderSuffix + "/hDCAz").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hDCA").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", kTH2F, {{100, 0, 10}, {301, 0., 1.5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTPCdEdX").c_str(), "; #it{p} (GeV/#it{c}); TPC Signal", kTH2F, {{100, 0, 10}, {1000, 0, 1000}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); @@ -125,7 +125,7 @@ class FemtoUniverseParticleHisto mHistogramRegistry->add((folderName + folderSuffix + "/hPt_ReconNoFake").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { /// Track histograms mHistogramRegistry->add((folderName + folderSuffix + "/hPDG").c_str(), "; PDG; Entries", kTH1I, {{6001, -3000, 3000}}); mHistogramRegistry->add((folderName + folderSuffix + "/hOrigin_MC").c_str(), "; Origin; Entries", kTH1I, {{7, 0, 7}}); @@ -168,7 +168,7 @@ class FemtoUniverseParticleHisto mHistogramRegistry = registry; /// The folder names are defined by the type of the object and the suffix (if applicable) std::string tempFitVarAxisTitle; - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child) { + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor) { /// Track histograms tempFitVarAxisTitle = "DCA_{xy} (cm)"; } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { @@ -231,7 +231,7 @@ class FemtoUniverseParticleHisto void fillQA_debug(T const& part, H const& histFolder) { // Histograms holding further debug information - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hCharge"), part.sign()); mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCfindable"), part.tpcNClsFindable()); mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCfound"), part.tpcNClsFound()); @@ -289,7 +289,7 @@ class FemtoUniverseParticleHisto mHistogramRegistry->fill(histFolder + HIST("_MC/hPt_ReconNoFake"), part.pt()); } - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { /// Track histograms switch (mctruthorigin) { case (o2::aod::femtouniverseMCparticle::kPrimary): @@ -348,7 +348,6 @@ class FemtoUniverseParticleHisto template void fillQABase(T const& part, H const& histFolder) { - fillQA_base(part, histFolder); std::string tempFitVarName; if (mHistogramRegistry) { fillQA_base(part, histFolder); diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h index 090bfef1443..4bc96996408 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h @@ -67,7 +67,7 @@ class FemtoUniverseSHContainer /// \param registry Histogram registry to be passed /// \param kstarbins k* binning for the histograms template - void init(HistogramRegistry* registry, T& kstarbins, int maxl) + void init(HistogramRegistry* registry, T& kstarbins, int /*maxl*/) { KStarBins = kstarbins; std::string femtoObs1D; @@ -159,20 +159,17 @@ class FemtoUniverseSHContainer /// \param ChosenEventType same or mixed event /// \param maxl Maximum valie of L component of the spherical harmonics template - void AddEventPair(T const& part1, T const& part2, uint8_t ChosenEventType, int maxl) + void AddEventPair(T const& part1, T const& part2, uint8_t ChosenEventType, int /*maxl*/, bool isiden) { - // int fMaxL = 2; - // int fMaxJM = (2+1)*(2+1); std::vector> fYlmBuffer(fMaxJM); std::vector f3d; - f3d = FemtoUniverseMath::getpairmom3d(part1, mMassOne, part2, mMassTwo, true, true); + f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, isiden); - // const float qstar = f3d[0]; + const float kv = f3d[0]; const float qout = f3d[1]; const float qside = f3d[2]; const float qlong = f3d[3]; - double kv = sqrt(qout * qout + qside * qside + qlong * qlong); int nqbin = fbinctn->GetXaxis()->FindFixBin(kv) - 1; FemtoUniverseSpherHarMath Ylm; @@ -216,7 +213,7 @@ class FemtoUniverseSHContainer /// Function to fill covariance matrix in 3D histograms /// \param ChosenEventType same or mixed event /// \param MaxJM Maximum value of J - void PackCov(uint8_t ChosenEventType, int MaxJM) + void PackCov(uint8_t ChosenEventType, int /*MaxJM*/) { if (ChosenEventType == femtoUniverseSHContainer::EventType::same) { for (int ibin = 1; ibin <= fcovnum->GetNbinsX(); ibin++) { diff --git a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h index b7fd3e34524..0d7871008f1 100644 --- a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h +++ b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h @@ -70,10 +70,11 @@ enum TrackType { kNoChild, //! Not a V0 child kPosChild, //! Positive V0 child kNegChild, //! Negative V0 child + kBachelor, //! Cascade bachelor kNTrackTypes //! Number of child types }; -static constexpr std::string_view TrackTypeName[kNTrackTypes] = {"Trk", "Pos", "Neg"}; //! Naming of the different particle types +static constexpr std::string_view TrackTypeName[kNTrackTypes] = {"Trk", "Pos", "Neg", "Bach"}; //! Naming of the different particle types DECLARE_SOA_INDEX_COLUMN(FDCollision, fdCollision); DECLARE_SOA_COLUMN(Pt, pt, float); //! p_T (GeV/c) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index 5a5f9d32d8c..0bd9b95b771 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -29,6 +29,7 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -45,6 +46,7 @@ #include "ReconstructionDataFormats/Track.h" #include "TMath.h" #include "TLorentzVector.h" +#include "Framework/O2DatabasePDGPlugin.h" using namespace o2; using namespace o2::analysis::femtoUniverse; @@ -57,9 +59,9 @@ namespace o2::aod using FemtoFullCollision = soa::Join::iterator; using FemtoFullCollisionCentRun2 = - soa::Join::iterator; + soa::Join::iterator; using FemtoFullCollisionCentRun3 = - soa::Join::iterator; + soa::Join::iterator; using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullTracks = @@ -105,7 +107,7 @@ struct femtoUniverseProducerTask { // Choose if filtering or skimming version is run Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; // Choose if running on converted data or Run3 / Pilot - Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; + Configurable ConfIsRun3{"ConfIsRun3", true, "Running on Run3 or pilot"}; Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; Configurable ConfIsForceGRP{"ConfIsForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; @@ -119,13 +121,17 @@ struct femtoUniverseProducerTask { Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", true, "Evt sel: check for trigger"}; Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", kINT7, "Evt sel: trigger"}; Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", false, "Evt sel: check for offline selection"}; - Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtouniverse tables"}; + Configurable ConfIsActivateV0{"ConfIsActivateV0", false, "Activate filling of V0 into femtouniverse tables"}; + Configurable ConfActivateSecondaries{"ConfActivateSecondaries", false, "Fill secondary MC gen particles that were reconstructed"}; + Configurable ConfIsActivateCascade{"ConfIsActivateCascade", true, "Activate filling of Cascade into femtouniverse tables"}; Configurable ConfIsActivatePhi{"ConfIsActivatePhi", false, "Activate filling of Phi into femtouniverse tables"}; Configurable ConfMCTruthAnalysisWithPID{"ConfMCTruthAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles (for MC Truth)"}; Configurable> ConfMCTruthPDGCodes{"ConfMCTruthPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; Configurable ConfCentFT0Min{"ConfCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"}; Configurable ConfCentFT0Max{"ConfCentFT0Max", 200.f, "Max CentFT0 value for centrality selection"}; - + Configurable ConfEvIsGoodZvtxFT0vsPV{"ConfEvIsGoodZvtxFT0vsPV", true, "Require kIsGoodZvtxFT0vsPV selection on Events."}; + Configurable ConfEvNoSameBunchPileup{"ConfEvNoSameBunchPileup", true, "Require kNoSameBunchPileup selection on Events."}; + Configurable ConfEvIsVertexITSTPC{"ConfEvIsVertexITSTPC", true, "Require kIsVertexITSTPC selection on Events"}; Filter CustomCollCentFilter = (aod::cent::centFT0C > ConfCentFT0Min) && (aod::cent::centFT0C < ConfCentFT0Max); @@ -136,17 +142,7 @@ struct femtoUniverseProducerTask { // "ConfRejectITSHitandTOFMissing", false, // "True: reject if neither ITS hit nor TOF timing satisfied"}; - Configurable ConfTrkPDGCode{"ConfTrkPDGCode", 2212, "PDG code of the selected track for Monte Carlo truth"}; // only for checking the particle origin (particles for which PDG does not match are marked as "Fake") FemtoUniverseTrackSelection trackCuts; - - struct : o2::framework::ConfigurableGroup { - Configurable ConfPtLowFilterCut{"ConfPtLowFilterCut", 0.14, "Lower limit for Pt for the global track"}; // pT low - Configurable ConfPtHighFilterCut{"ConfPtHighFilterCut", 5.0, "Higher limit for Pt for the global track"}; // pT high - Configurable ConfEtaFilterCut{"ConfEtaFilterCut", 0.8, "Eta cut for the global track"}; // eta - Configurable ConfDcaXYFilterCut{"ConfDcaXYFilterCut", 2.4, "Value for DCA_XY for the global track"}; // max dca to vertex XY - Configurable ConfDcaZFilterCut{"ConfDcaZFilterCut", 3.2, "Value for DCA_Z for the global track"}; // max dca to vertex Z - } ConfFilterCuts; - Configurable> ConfTrkCharge{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kSign, "ConfTrk"), std::vector{-1, 1}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kSign, "Track selection: ")}; Configurable> ConfTrkPtmin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMin, "ConfTrk"), std::vector{0.5f, 0.4f, 0.6f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMin, "Track selection: ")}; Configurable> ConfTrkPtmax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMax, "ConfTrk"), std::vector{5.4f, 5.6f, 5.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMax, "Track selection: ")}; @@ -171,76 +167,107 @@ struct femtoUniverseProducerTask { // V0 FemtoUniverseV0Selection v0Cuts; - Configurable> ConfV0Sign{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0Sign, "V0 selection: ")}; - Configurable> ConfV0PtMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMin, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMin, "V0 selection: ")}; - Configurable> ConfV0PtMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMax, "ConfV0"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMax, "V0 selection: ")}; - Configurable> ConfV0EtaMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0etaMax, "ConfV0"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0etaMax, "V0 selection: ")}; - Configurable> ConfV0DCADaughMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0DCADaughMax, "ConfV0"), std::vector{1.2f, 1.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0DCADaughMax, "V0 selection: ")}; - Configurable> ConfV0CPAMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0CPAMin, "ConfV0"), std::vector{0.99f, 0.995f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0CPAMin, "V0 selection: ")}; - Configurable> ConfV0TranRadMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0TranRadMin, "ConfV0"), std::vector{0.2f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0TranRadMin, "V0 selection: ")}; - Configurable> ConfV0TranRadMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0TranRadMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0TranRadMax, "V0 selection: ")}; - Configurable> ConfV0DecVtxMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0DecVtxMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0DecVtxMax, "V0 selection: ")}; - - Configurable> ConfChildCharge{"ConfChildSign", std::vector{-1, 1}, "V0 Child sel: Charge"}; - Configurable> ConfChildEtaMax{"ConfChildEtaMax", std::vector{0.8f}, "V0 Child sel: max eta"}; - Configurable> ConfChildTPCnClsMin{"ConfChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "V0 Child sel: Min. nCls TPC"}; - Configurable> ConfChildDCAMin{"ConfChildDCAMin", std::vector{0.05f, 0.06f}, "V0 Child sel: Max. DCA Daugh to PV (cm)"}; - Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{5.f, 4.f}, "V0 Child sel: Max. PID nSigma TPC"}; - Configurable> ConfChildPIDspecies{"ConfChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; - - Configurable ConfV0InvMassLowLimit{"ConfV0InvV0MassLowLimit", 1.05, "Lower limit of the V0 invariant mass"}; - Configurable ConfV0InvMassUpLimit{"ConfV0InvV0MassUpLimit", 1.30, "Upper limit of the V0 invariant mass"}; - - Configurable ConfV0RejectKaons{"ConfV0RejectKaons", false, "Switch to reject kaons"}; - Configurable ConfV0InvKaonMassLowLimit{"ConfV0InvKaonMassLowLimit", 0.48, "Lower limit of the V0 invariant mass for Kaon rejection"}; - Configurable ConfV0InvKaonMassUpLimit{"ConfV0InvKaonMassUpLimit", 0.515, "Upper limit of the V0 invariant mass for Kaon rejection"}; + struct : o2::framework::ConfigurableGroup { + Configurable> ConfV0Sign{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0Sign, "V0 selection: ")}; + Configurable> ConfV0PtMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMin, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMin, "V0 selection: ")}; + Configurable> ConfV0PtMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMax, "ConfV0"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMax, "V0 selection: ")}; + Configurable> ConfV0EtaMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0etaMax, "ConfV0"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0etaMax, "V0 selection: ")}; + Configurable> ConfV0DCADaughMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0DCADaughMax, "ConfV0"), std::vector{1.2f, 1.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0DCADaughMax, "V0 selection: ")}; + Configurable> ConfV0CPAMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0CPAMin, "ConfV0"), std::vector{0.99f, 0.995f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0CPAMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0TranRadMin, "ConfV0"), std::vector{0.2f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0TranRadMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0TranRadMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0TranRadMax, "V0 selection: ")}; + Configurable> ConfV0DecVtxMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0DecVtxMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0DecVtxMax, "V0 selection: ")}; + + Configurable> ConfChildCharge{"ConfChildSign", std::vector{-1, 1}, "V0 Child sel: Charge"}; + Configurable> ConfChildEtaMax{"ConfChildEtaMax", std::vector{0.8f}, "V0 Child sel: max eta"}; + Configurable> ConfChildTPCnClsMin{"ConfChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "V0 Child sel: Min. nCls TPC"}; + Configurable> ConfChildDCAMin{"ConfChildDCAMin", std::vector{0.05f, 0.06f}, "V0 Child sel: Max. DCA Daugh to PV (cm)"}; + Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{5.f, 4.f}, "V0 Child sel: Max. PID nSigma TPC"}; + Configurable> ConfChildPIDspecies{"ConfChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; + + Configurable ConfV0InvMassLowLimit{"ConfV0InvV0MassLowLimit", 1.05, "Lower limit of the V0 invariant mass"}; + Configurable ConfV0InvMassUpLimit{"ConfV0InvV0MassUpLimit", 1.30, "Upper limit of the V0 invariant mass"}; + + Configurable ConfV0RejectKaons{"ConfV0RejectKaons", false, "Switch to reject kaons"}; + Configurable ConfV0InvKaonMassLowLimit{"ConfV0InvKaonMassLowLimit", 0.48, "Lower limit of the V0 invariant mass for Kaon rejection"}; + Configurable ConfV0InvKaonMassUpLimit{"ConfV0InvKaonMassUpLimit", 0.515, "Upper limit of the V0 invariant mass for Kaon rejection"}; + } ConfV0Selection; - Filter GlobalCutFilter = requireGlobalTrackInFilter(); + struct : o2::framework::ConfigurableGroup { + Configurable ConfPtLowFilterCut{"ConfPtLowFilterCut", 0.14, "Lower limit for Pt for the global track"}; // pT low + Configurable ConfPtHighFilterCut{"ConfPtHighFilterCut", 5.0, "Higher limit for Pt for the global track"}; // pT high + Configurable ConfEtaFilterCut{"ConfEtaFilterCut", 0.8, "Eta cut for the global track"}; // eta + Configurable ConfDxaXYCustom0Cut{"ConfDxaXYCustom0Cut", false, "Enable Custom Dcaxy < [0] cut."}; + Configurable ConfDcaXYFilterCut{"ConfDcaXYFilterCut", 2.4, "Value for DCA_XY for the global track"}; // max dca to vertex XY + Configurable ConfDcaZFilterCut{"ConfDcaZFilterCut", 3.2, "Value for DCA_Z for the global track"}; // max dca to vertex Z + Configurable ConfDcaXYCustom1Cut{"ConfDcaXYCustom1Cut", true, "Enable Custom |DCAxy| < [1] + [2]/pt cut."}; + Configurable ConfDcaXYCustom11FilterCut{"ConfDcaXY1FilterCut", 0.004, "Value for [1] custom DCAxy cut -> |DCAxy| < [1] + [2]/pT"}; + Configurable ConfDcaXYCustom12FilterCut{"ConfDcaXY2FilterCut", 0.013, "Value for [2] custom DCAxy cut -> |DCAxy| < [1] + [2]/pT"}; + } ConfFilterCuts; + Filter GlobalCutFilter = requireGlobalTrackInFilter(); Filter CustomTrackFilter = (aod::track::pt > ConfFilterCuts.ConfPtLowFilterCut) && (aod::track::pt < ConfFilterCuts.ConfPtHighFilterCut) && (nabs(aod::track::eta) < ConfFilterCuts.ConfEtaFilterCut) && - (aod::track::dcaXY < ConfFilterCuts.ConfDcaXYFilterCut) && - (aod::track::dcaZ < ConfFilterCuts.ConfDcaZFilterCut); - - // PHI - FemtoUniversePhiSelection phiCuts; - struct : o2::framework::ConfigurableGroup { - Configurable> ConfPhiSign{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiSign, "ConfPhi"), std::vector{-1, 1}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiSign, "Phi selection: ")}; - Configurable> ConfPhiPtMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhipTMin, "ConfPhi"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhipTMin, "Phi selection: ")}; - Configurable> ConfPhiPtMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhipTMax, "ConfPhi"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhipTMax, "Phi selection: ")}; - Configurable> ConfPhiEtaMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhietaMax, "ConfPhi"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhietaMax, "Phi selection: ")}; - Configurable> ConfPhiDCADaughMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiDCADaughMax, "ConfPhi"), std::vector{1.2f, 1.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiDCADaughMax, "Phi selection: ")}; - Configurable> ConfPhiCPAMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiCPAMin, "ConfPhi"), std::vector{0.99f, 0.995f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiCPAMin, "Phi selection: ")}; - Configurable> ConfPhiTranRadMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiTranRadMin, "ConfPhi"), std::vector{0.2f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiTranRadMin, "Phi selection: ")}; - Configurable> ConfPhiTranRadMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiTranRadMax, "ConfPhi"), std::vector{100.f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiTranRadMax, "Phi selection: ")}; - Configurable> ConfPhiDecVtxMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiDecVtxMax, "ConfPhi"), std::vector{100.f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiDecVtxMax, "Phi selection: ")}; - } ConfPhiSelection; + (!ConfFilterCuts.ConfDxaXYCustom0Cut || (aod::track::dcaXY < ConfFilterCuts.ConfDcaXYFilterCut)) && // true if configurable set to false or if configurable is true and it passes the selection + (aod::track::dcaZ < ConfFilterCuts.ConfDcaZFilterCut) && + (!ConfFilterCuts.ConfDcaXYCustom1Cut || (nabs(aod::track::dcaXY) < ConfFilterCuts.ConfDcaXYCustom11FilterCut + ConfFilterCuts.ConfDcaXYCustom12FilterCut / aod::track::pt)); // same logic here + // CASCADE + FemtoUniverseCascadeSelection cascadeCuts; struct : o2::framework::ConfigurableGroup { - Configurable> ConfPhiChildCharge{"ConfPhiChildSign", std::vector{-1, 1}, "Phi Child sel: Charge"}; - Configurable> ConfPhiChildEtaMax{"ConfPhiChildEtaMax", std::vector{0.8f}, "Phi Child sel: max eta"}; - Configurable> ConfPhiChildTPCnClsMin{"ConfPhiChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "Phi Child sel: Min. nCls TPC"}; - Configurable> ConfPhiChildDCAMin{"ConfPhiChildDCAMin", std::vector{0.05f, 0.06f}, "Phi Child sel: Max. DCA Daugh to PV (cm)"}; - Configurable> ConfPhiChildPIDnSigmaMax{"ConfPhiChildPIDnSigmaMax", std::vector{5.f, 4.f}, "Phi Child sel: Max. PID nSigma TPC"}; - Configurable> ConfPhiChildPIDspecies{"ConfPhiChildPIDspecies", std::vector{o2::track::PID::Kaon, o2::track::PID::Kaon}, "Phi Child sel: Particles species for PID"}; - } ConfPhiChildSelection; + Configurable> ConfCascSign{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeSign, "ConfCasc"), std::vector{-1, 1}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeSign, "Cascade selection: ")}; + Configurable> ConfCascPtMin{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadepTMin, "ConfCasc"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadepTMin, "Cascade selection: ")}; + Configurable> ConfCascPtMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadepTMax, "ConfCasc"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadepTMax, "Cascade selection: ")}; + Configurable> ConfCascEtaMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeetaMax, "ConfCasc"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeetaMax, "Cascade selection: ")}; + Configurable> ConfCascV0DCADaughMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0DCADaughMax, "ConfCasc"), std::vector{1.f, 1.2f, 1.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0DCADaughMax, "Cascade selection: ")}; + Configurable> ConfCascV0CPAMin{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0CPAMin, "ConfCasc"), std::vector{0.99f, 0.95f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0CPAMin, "Cascade selection: ")}; + Configurable> ConfCascV0TranRadMin{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0TranRadMin, "ConfCasc"), std::vector{0.2f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0TranRadMin, "Cascade selection: ")}; + Configurable> ConfCascV0TranRadMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0TranRadMax, "ConfCasc"), std::vector{100.f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0TranRadMax, "Cascade selection: ")}; + Configurable> ConfCascV0DecVtxMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0DecVtxMax, "ConfCasc"), std::vector{100.f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0DecVtxMax, "Cascade selection: ")}; + Configurable> ConfCascDCADaughMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeDCADaughMax, "ConfCasc"), std::vector{1.f, 1.2f, 1.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeDCADaughMax, "Cascade selection: ")}; + Configurable> ConfCascCPAMin{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeCPAMin, "ConfCasc"), std::vector{0.99f, 0.95f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeCPAMin, "Cascade selection: ")}; + Configurable> ConfCascTranRadMin{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeTranRadMin, "ConfCasc"), std::vector{0.2f, 0.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeTranRadMin, "Cascade selection: ")}; + Configurable> ConfCascTranRadMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeTranRadMax, "ConfCasc"), std::vector{100.f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeTranRadMax, "Cascade selection: ")}; + Configurable> ConfCascDecVtxMax{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeDecVtxMax, "ConfCasc"), std::vector{100.f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeDecVtxMax, "Cascade selection: ")}; + + Configurable> ConfCascDCAPosToPV{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeDCAPosToPV, "ConfCasc"), std::vector{0.1f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeDCAPosToPV, "Cascade selection: ")}; + Configurable> ConfCascDCANegToPV{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeDCANegToPV, "ConfCasc"), std::vector{0.1f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeDCANegToPV, "Cascade selection: ")}; + Configurable> ConfCascDCABachToPV{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeDCABachToPV, "ConfCasc"), std::vector{0.1f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeDCABachToPV, "Cascade selection: ")}; + Configurable> ConfCascDCAV0ToPV{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeDCAV0ToPV, "ConfCasc"), std::vector{0.01f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeDCAV0ToPV, "Cascade selection: ")}; + Configurable> ConfCascV0MassLowLimit{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0MassMin, "ConfCasc"), std::vector{1.05f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0MassMin, "Cascade selection: ")}; + Configurable> ConfCascV0MassUpLimit{FemtoUniverseCascadeSelection::getSelectionName(femtoUniverseCascadeSelection::kCascadeV0MassMax, "ConfCasc"), std::vector{1.30f}, FemtoUniverseCascadeSelection::getSelectionHelper(femtoUniverseCascadeSelection::kCascadeV0MassMax, "Cascade selection: ")}; + + Configurable> ConfCascChildCharge{"ConfCascChildSign", std::vector{-1, 1}, "Cascade Child sel: Charge"}; + Configurable> ConfCascChildEtaMax{"ConfCascChildEtaMax", std::vector{0.8f}, "Cascade Child sel: max eta"}; + Configurable> ConfCascChildTPCnClsMin{"ConfCascChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "Cascade Child sel: Min. nCls TPC"}; + // Configurable> ConfCascChildDCAMin{"ConfCascChildDCAMin", std::vector{0.05f, 0.06f}, "Cascade Child sel: Max. DCA Daugh to PV (cm)"}; + Configurable> ConfCascChildPIDnSigmaMax{"ConfCascChildPIDnSigmaMax", std::vector{3.f, 4.f}, "Cascade Child sel: Max. PID nSigma TPC"}; + Configurable> ConfCascChildPIDspecies{"ConfCascChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; + + Configurable ConfCascInvMassLowLimit{"ConfCascInvMassLowLimit", 1.25, "Lower limit of the V0 invariant mass"}; + Configurable ConfCascInvMassUpLimit{"ConfCascInvMassUpLimit", 1.40, "Upper limit of the V0 invariant mass"}; + + Configurable ConfCascRejectOmegas{"ConfCascRejectOmegas", false, "Switch on to reject Omegas (for Xi) or Xis (for Omega)"}; + Configurable ConfCascInvOmegaMassLowLimit{"ConfCascInvOmegaMassLowLimit", 1.66, "Lower limit of the cascade invariant mass for Omega rejection"}; + Configurable ConfCascInvOmegaMassUpLimit{"ConfCascInvOmegaMassUpLimit", 1.68, "Upper limit of the cascade invariant mass for Omega rejection"}; + } ConfCascadeSelection; + // PHI + FemtoUniversePhiSelection phiCuts; struct : o2::framework::ConfigurableGroup { - Configurable ConfNsigmaCombinedKaon{"ConfNsigmaCombinedKaon", 3.0, "TPC and TOF Kaon Sigma (combined) for momentum > 0.4"}; - Configurable ConfNsigmaTPCKaon{"ConfNsigmaTPCKaon", 3.0, "TPC Kaon Sigma for momentum < 0.4"}; - Configurable ConfNsigmaTPCTOFKaon{"ConfNsigmaTPCTOFKaon", true, "Use TPC and TOF for PID of Kaons"}; + Configurable ConfLooseTPCNSigma{"ConfLooseTPCNSigma", false, "Use loose TPC N sigmas for Kaon PID."}; + Configurable ConfLooseTPCNSigmaValue{"ConfLooseTPCNSigmaValue", 10, "Value for the loose TPC N Sigma for Kaon PID."}; + Configurable ConfLooseTOFNSigma{"ConfLooseTOFNSigma", false, "Use loose TPC N sigmas for Kaon PID."}; + Configurable ConfLooseTOFNSigmaValue{"ConfLooseTOFNSigmaValue", 10, "Value for the loose TOF N Sigma for Kaon PID."}; Configurable ConfInvMassLowLimitPhi{"ConfInvMassLowLimitPhi", 1.011, "Lower limit of the Phi invariant mass"}; // change that to do invariant mass cut Configurable ConfInvMassUpLimitPhi{"ConfInvMassUpLimitPhi", 1.027, "Upper limit of the Phi invariant mass"}; - } ConfPhiCommon; - // PHI child one - struct : o2::framework::ConfigurableGroup { - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; - } ConfPhiChildOne; - // PHI child two - struct : o2::framework::ConfigurableGroup { - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; - } ConfPhiChildTwo; + Configurable ConfNsigmaRejectPion{"ConfNsigmaRejectPion", 3.0, "Reject if particle could be a Pion combined nsigma value."}; + Configurable ConfNsigmaRejectProton{"ConfNsigmaRejectProton", 3.0, "Reject if particle could be a Proton combined nsigma value."}; + } ConfPhiSelection; + + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; // D0/D0bar mesons struct : o2::framework::ConfigurableGroup { @@ -252,13 +279,6 @@ struct femtoUniverseProducerTask { bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) { - //|nsigma_TPC| < 5 for p < 0.4 GeV/c - //|nsigma_combined| < 5 for p > 0.4 - - // using configurables: - // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) - // ConfNsigmaTPCKaon -> TPC Kaon Sigma for momentum < 0.4 - // ConfNsigmaCombinedKaon -> TPC and TOF Kaon Sigma (combined) for momentum > 0.4 if (mom < 0.3) { // 0.0-0.3 if (TMath::Abs(nsigmaTPCK) < 3.0) { @@ -297,6 +317,105 @@ struct femtoUniverseProducerTask { } } + bool IsKaonNSigmaTPCLoose(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + + if (mom < 0.3) { // 0.0-0.3 + if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue) { + return true; + } else { + return false; + } + } else if (mom < 0.45) { // 0.30 - 0.45 + if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue) { + return true; + } else { + return false; + } + } else if (mom < 0.55) { // 0.45-0.55 + if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue) { + return true; + } else { + return false; + } + } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) + if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue)) { + return true; + } else { + return false; + } + } else if (mom > 1.5) { // 1.5 - + if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool IsKaonNSigmaTOFLoose(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + if (mom < 0.3) { // 0.0-0.3 + if (TMath::Abs(nsigmaTPCK) < 3.0) { + return true; + } else { + return false; + } + } else if (mom < 0.45) { // 0.30 - 0.45 + if (TMath::Abs(nsigmaTPCK) < 2.0) { + return true; + } else { + return false; + } + } else if (mom < 0.55) { // 0.45-0.55 + if (TMath::Abs(nsigmaTPCK) < 1.0) { + return true; + } else { + return false; + } + } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) + if ((TMath::Abs(nsigmaTOFK) < ConfPhiSelection.ConfLooseTOFNSigmaValue) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + { + return true; + } + } else { + return false; + } + } else if (mom > 1.5) { // 1.5 - + if ((TMath::Abs(nsigmaTOFK) < ConfPhiSelection.ConfLooseTOFNSigmaValue) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool IsKaonRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi) + { + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCPi) < ConfPhiSelection.ConfNsigmaRejectPion) { + return true; + } else if (TMath::Abs(nsigmaTPCPr) < ConfPhiSelection.ConfNsigmaRejectProton) { + return true; + } + } + if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfPhiSelection.ConfNsigmaRejectPion) { + return true; + } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfPhiSelection.ConfNsigmaRejectProton) { + return true; + } else { + return false; + } + } else { + return false; + } + } + /// \todo should we add filter on min value pT/eta of V0 and daughters? /*Filter v0Filter = (nabs(aod::v0data::x) < V0DecVtxMax.value) && (nabs(aod::v0data::y) < V0DecVtxMax.value) && @@ -305,6 +424,7 @@ struct femtoUniverseProducerTask { // for now do not know why HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry cascadeQaRegistry{"CascadeQAHistos", {}, OutputObjHandlingPolicy::QAObject}; int mRunNumber; float mMagField; @@ -312,10 +432,10 @@ struct femtoUniverseProducerTask { void init(InitContext&) { - if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackD0mesonData || doprocessTrackCentRun2Data || doprocessTrackCentRun3Data) == false && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth) == false) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackCentRun2Data || doprocessTrackCentRun3Data || doprocessTrackV0CentRun3) == false && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMC || doprocessFullMCCent) == false) { LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one."); } - if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackD0mesonData || doprocessTrackCentRun2Data || doprocessTrackCentRun3Data) == true && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth) == true) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackCentRun2Data || doprocessTrackCentRun3Data || doprocessTrackV0CentRun3) == true && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMC || doprocessFullMCCent) == true) { LOGF(fatal, "Cannot enable process Data and process MC at the same time. " "Please choose one."); @@ -347,29 +467,29 @@ struct femtoUniverseProducerTask { // femtoUniverseV0Selection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); if (ConfIsActivateV0) { // initializing for V0 - v0Cuts.setSelection(ConfV0Sign, femtoUniverseV0Selection::kV0Sign, femtoUniverseSelection::kEqual); - v0Cuts.setSelection(ConfV0PtMin, femtoUniverseV0Selection::kV0pTMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setSelection(ConfV0PtMax, femtoUniverseV0Selection::kV0pTMax, femtoUniverseSelection::kUpperLimit); - v0Cuts.setSelection(ConfV0EtaMax, femtoUniverseV0Selection::kV0etaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setSelection(ConfV0DCADaughMax, femtoUniverseV0Selection::kV0DCADaughMax, femtoUniverseSelection::kUpperLimit); - v0Cuts.setSelection(ConfV0CPAMin, femtoUniverseV0Selection::kV0CPAMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setSelection(ConfV0TranRadMin, femtoUniverseV0Selection::kV0TranRadMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setSelection(ConfV0TranRadMax, femtoUniverseV0Selection::kV0TranRadMax, femtoUniverseSelection::kUpperLimit); - v0Cuts.setSelection(ConfV0DecVtxMax, femtoUniverseV0Selection::kV0DecVtxMax, femtoUniverseSelection::kUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kPosTrack, ConfChildPIDspecies); - v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kNegTrack, ConfChildPIDspecies); + v0Cuts.setSelection(ConfV0Selection.ConfV0Sign, femtoUniverseV0Selection::kV0Sign, femtoUniverseSelection::kEqual); + v0Cuts.setSelection(ConfV0Selection.ConfV0PtMin, femtoUniverseV0Selection::kV0pTMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0PtMax, femtoUniverseV0Selection::kV0pTMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0EtaMax, femtoUniverseV0Selection::kV0etaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0DCADaughMax, femtoUniverseV0Selection::kV0DCADaughMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0CPAMin, femtoUniverseV0Selection::kV0CPAMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0TranRadMin, femtoUniverseV0Selection::kV0TranRadMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0TranRadMax, femtoUniverseV0Selection::kV0TranRadMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0Selection.ConfV0DecVtxMax, femtoUniverseV0Selection::kV0DecVtxMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0Selection.ConfChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0Selection.ConfChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0Selection.ConfChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0Selection.ConfChildDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0Selection.ConfChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0Selection.ConfChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0Selection.ConfChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0Selection.ConfChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0Selection.ConfChildDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0Selection.ConfChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kPosTrack, ConfV0Selection.ConfChildPIDspecies); + v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kNegTrack, ConfV0Selection.ConfChildPIDspecies); v0Cuts.init(&qaRegistry); - v0Cuts.setInvMassLimits(ConfV0InvMassLowLimit, ConfV0InvMassUpLimit); + v0Cuts.setInvMassLimits(ConfV0Selection.ConfV0InvMassLowLimit, ConfV0Selection.ConfV0InvMassUpLimit); v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kPosTrack, ConfTrkRejectNotPropagated); v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kNegTrack, ConfTrkRejectNotPropagated); @@ -378,8 +498,8 @@ struct femtoUniverseProducerTask { v0Cuts.setChildnSigmaPIDOffset(femtoUniverseV0Selection::kPosTrack, ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); v0Cuts.setChildnSigmaPIDOffset(femtoUniverseV0Selection::kNegTrack, ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); - if (ConfV0RejectKaons) { - v0Cuts.setKaonInvMassLimits(ConfV0InvKaonMassLowLimit, ConfV0InvKaonMassUpLimit); + if (ConfV0Selection.ConfV0RejectKaons) { + v0Cuts.setKaonInvMassLimits(ConfV0Selection.ConfV0InvKaonMassLowLimit, ConfV0Selection.ConfV0InvKaonMassUpLimit); } // if (ConfRejectITSHitandTOFMissing) { // o2PhysicsTrackSelection = new @@ -388,6 +508,59 @@ struct femtoUniverseProducerTask { // } } + if (ConfIsActivateCascade) { + // initializing for cascades + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascSign, femtoUniverseCascadeSelection::kCascadeSign, femtoUniverseSelection::kEqual); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascPtMin, femtoUniverseCascadeSelection::kCascadepTMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascPtMax, femtoUniverseCascadeSelection::kCascadepTMax, femtoUniverseSelection::kUpperLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascEtaMax, femtoUniverseCascadeSelection::kCascadeetaMax, femtoUniverseSelection::kAbsUpperLimit); + // v0 child cuts + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0DCADaughMax, femtoUniverseCascadeSelection::kCascadeV0DCADaughMax, femtoUniverseSelection::kUpperLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0CPAMin, femtoUniverseCascadeSelection::kCascadeV0CPAMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0TranRadMin, femtoUniverseCascadeSelection::kCascadeV0TranRadMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0TranRadMax, femtoUniverseCascadeSelection::kCascadeV0TranRadMax, femtoUniverseSelection::kUpperLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0DecVtxMax, femtoUniverseCascadeSelection::kCascadeV0DecVtxMax, femtoUniverseSelection::kUpperLimit); + // cascade cuts + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascDCADaughMax, femtoUniverseCascadeSelection::kCascadeDCADaughMax, femtoUniverseSelection::kUpperLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascCPAMin, femtoUniverseCascadeSelection::kCascadeCPAMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascTranRadMin, femtoUniverseCascadeSelection::kCascadeTranRadMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascTranRadMax, femtoUniverseCascadeSelection::kCascadeTranRadMax, femtoUniverseSelection::kUpperLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascDecVtxMax, femtoUniverseCascadeSelection::kCascadeDecVtxMax, femtoUniverseSelection::kUpperLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascDCAPosToPV, femtoUniverseCascadeSelection::kCascadeDCAPosToPV, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascDCANegToPV, femtoUniverseCascadeSelection::kCascadeDCANegToPV, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascDCABachToPV, femtoUniverseCascadeSelection::kCascadeDCABachToPV, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascDCAV0ToPV, femtoUniverseCascadeSelection::kCascadeDCAV0ToPV, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0MassLowLimit, femtoUniverseCascadeSelection::kCascadeV0MassMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setSelection(ConfCascadeSelection.ConfCascV0MassUpLimit, femtoUniverseCascadeSelection::kCascadeV0MassMax, femtoUniverseSelection::kUpperLimit); + // children cuts + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kPosTrack, ConfCascadeSelection.ConfCascChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kPosTrack, ConfCascadeSelection.ConfCascChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kPosTrack, ConfCascadeSelection.ConfCascChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kPosTrack, ConfCascadeSelection.ConfCascChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kNegTrack, ConfCascadeSelection.ConfCascChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kNegTrack, ConfCascadeSelection.ConfCascChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kNegTrack, ConfCascadeSelection.ConfCascChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kNegTrack, ConfCascadeSelection.ConfCascChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kBachTrack, ConfCascadeSelection.ConfCascChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kBachTrack, ConfCascadeSelection.ConfCascChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kBachTrack, ConfCascadeSelection.ConfCascChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + cascadeCuts.setChildCuts(femtoUniverseCascadeSelection::kBachTrack, ConfCascadeSelection.ConfCascChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + + // TODO + cascadeCuts.setChildPIDSpecies(femtoUniverseCascadeSelection::kPosTrack, ConfV0Selection.ConfChildPIDspecies); + cascadeCuts.setChildPIDSpecies(femtoUniverseCascadeSelection::kNegTrack, ConfV0Selection.ConfChildPIDspecies); + cascadeCuts.setChildPIDSpecies(femtoUniverseCascadeSelection::kBachTrack, ConfV0Selection.ConfChildPIDspecies); + + // check if works correctly for bachelor track + cascadeCuts.init(&cascadeQaRegistry); + // invmass cuts + cascadeCuts.setInvMassLimits(ConfCascadeSelection.ConfCascInvMassLowLimit, ConfCascadeSelection.ConfCascInvMassUpLimit); + + if (ConfCascadeSelection.ConfCascRejectOmegas) { + cascadeCuts.setOmegaInvMassLimits(ConfCascadeSelection.ConfCascInvOmegaMassLowLimit, ConfCascadeSelection.ConfCascInvOmegaMassUpLimit); + } + } + if (ConfIsActivatePhi) { // initializing for Phi meson phiCuts.init(&qaRegistry); @@ -441,7 +614,7 @@ struct femtoUniverseProducerTask { mRunNumber = bc.runNumber(); } - template + template void fillDebugParticle(ParticleType const& particle) { if constexpr (isTrackOrV0) { @@ -464,10 +637,17 @@ struct femtoUniverseProducerTask { -999., -999., -999., -999., -999., -999.); // QA for phi or D0/D0bar + } else if constexpr (isXi) { + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., + particle.dcacascdaughters(), particle.cascradius(), + particle.x(), particle.y(), particle.z(), + particle.mOmega()); // QA for Xi Cascades (later do the same for Omegas) } else { // LOGF(info, "isTrack0orV0: %d, isPhi: %d", isTrackOrV0, isPhiOrD0); outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., - -999., -999., -999., -999., -999., -999., -999., -999., + particle.dcav0topv(), -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., particle.dcaV0daughters(), particle.v0radius(), particle.x(), particle.y(), particle.z(), @@ -483,13 +663,15 @@ struct femtoUniverseProducerTask { auto particleMC = particle.mcParticle(); auto pdgCode = particleMC.pdgCode(); int particleOrigin = 99; - auto motherparticleMC = particleMC.template mothers_as().front(); + auto motherparticlesMC = particleMC.template mothers_as(); - if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { + if (abs(pdgCode) == abs(ConfPDGCodePartOne.value) || abs(pdgCode) == abs(ConfPDGCodePartTwo.value)) { if (particleMC.isPhysicalPrimary()) { particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kPrimary; - } else if (motherparticleMC.producedByGenerator()) { - particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); + } else if (!motherparticlesMC.empty()) { + auto motherparticleMC = motherparticlesMC.front(); + if (motherparticleMC.producedByGenerator()) + particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); } else { particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kMaterial; } @@ -503,6 +685,62 @@ struct femtoUniverseProducerTask { outputPartsMCLabels(-1); } } + + template + void fillMCParticlePhi(ParticleType const& kaon1, ParticleType const& kaon2) + { + if (kaon1.has_mcParticle() && kaon2.has_mcParticle()) { + // get corresponding MC particle and its info + auto kaon1MC = kaon1.mcParticle(); + auto kaon2MC = kaon2.mcParticle(); + auto pdgCode1 = kaon1MC.pdgCode(); + auto pdgCode2 = kaon2MC.pdgCode(); + + int phiOrigin = 99; + auto motherskaon1MC = kaon1MC.template mothers_as(); + auto motherskaon2MC = kaon2MC.template mothers_as(); + + if (abs(pdgCode1) == abs(321) || abs(pdgCode2) == abs(-321)) { + if ((kaon1MC.isPhysicalPrimary() && kaon2MC.isPhysicalPrimary()) && (!motherskaon1MC.empty() && !motherskaon2MC.empty())) { + for (auto& particleMotherOfNeg : motherskaon1MC) { + for (auto& particleMotherOfPos : motherskaon2MC) { + if (particleMotherOfNeg == particleMotherOfPos && particleMotherOfNeg.pdgCode() == 333) { + phiOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kPrimary; + } else { + phiOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kFake; + } + } + } + } else { + phiOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kFake; + } + } else { + phiOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kFake; + } + + TLorentzVector part1Vec; + TLorentzVector part2Vec; + + float mMassOne = TDatabasePDG::Instance()->GetParticle(321)->Mass(); // FIXME: Get from the PDG service of the common header + float mMassTwo = TDatabasePDG::Instance()->GetParticle(-321)->Mass(); // FIXME: Get from the PDG service of the common header + + part1Vec.SetPtEtaPhiM(kaon1MC.pt(), kaon1MC.eta(), kaon1MC.phi(), mMassOne); + part2Vec.SetPtEtaPhiM(kaon2MC.pt(), kaon2MC.eta(), kaon2MC.phi(), mMassTwo); + + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + + float phiEta = sumVec.Eta(); + float phiPt = sumVec.Pt(); + float phiPhi = sumVec.Phi(); + + outputPartsMC(phiOrigin, 333, phiPt, phiEta, phiPhi); + outputPartsMCLabels(outputPartsMC.lastIndex()); + } else { + outputPartsMCLabels(-1); + } + } + template void fillCollisions(CollisionType const& col, TrackType const& tracks) { @@ -528,7 +766,7 @@ struct femtoUniverseProducerTask { // particle candidates for such collisions if (!colCuts.isSelected(col)) { if (ConfIsTrigger) { - if (ConfDoSpher) { + if (ConfDoSpher && (!ConfEvNoSameBunchPileup || col.selection_bit(aod::evsel::kNoSameBunchPileup)) && (!ConfEvIsGoodZvtxFT0vsPV || col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && (!ConfEvIsVertexITSTPC || col.selection_bit(aod::evsel::kIsVertexITSTPC))) { outputCollision(vtxZ, mult, multNtr, colCuts.computeSphericity(col, tracks), mMagField); } else { outputCollision(vtxZ, mult, multNtr, 2, mMagField); @@ -546,16 +784,22 @@ struct femtoUniverseProducerTask { } template - void fillMCTruthCollisions(CollisionType const& col, TrackType const&) + void fillMCTruthCollisions(CollisionType const& col, TrackType const& tracks) { for (auto& c : col) { const auto vtxZ = c.posZ(); - const auto spher = 0; // colCuts.computeSphericity(col, tracks); int mult = 0; int multNtr = 0; - // colCuts.fillQA(c); //for now, TODO: create a configurable so in the FemroUniverseCollisionSelection.h there is an option to plot QA just for the posZ - outputCollision(vtxZ, mult, multNtr, spher, mMagField); + if (std::abs(vtxZ) > ConfEvtZvtx) { + continue; + } + + if (ConfDoSpher) { + outputCollision(vtxZ, mult, multNtr, colCuts.computeSphericity(col, tracks), mMagField); + } else { + outputCollision(vtxZ, mult, multNtr, 2, mMagField); + } } } @@ -567,7 +811,7 @@ struct femtoUniverseProducerTask { int multNtr = 0; if (!ConfIsRun3) { cent = col.centRun2V0M(); - multNtr = col.centRun2V0M(); + multNtr = col.multNTracksPV(); } // check whether the basic event selection criteria are fulfilled @@ -602,7 +846,7 @@ struct femtoUniverseProducerTask { int cent = 0; int multNtr = 0; if (ConfIsRun3) { - multNtr = col.centFT0C(); + multNtr = col.multNTracksPV(); cent = col.centFT0C(); } @@ -665,7 +909,7 @@ struct femtoUniverseProducerTask { track.dcaXY(), childIDs, 0, 0); tmpIDtrack.push_back(track.globalIndex()); if (ConfIsDebug) { - fillDebugParticle(track); + fillDebugParticle(track); } if constexpr (isMC) { @@ -755,9 +999,9 @@ struct femtoUniverseProducerTask { v0.mLambda(), v0.mAntiLambda()); if (ConfIsDebug) { - fillDebugParticle(postrack); // QA for positive daughter - fillDebugParticle(negtrack); // QA for negative daughter - fillDebugParticle(v0); // QA for v0 + fillDebugParticle(postrack); // QA for positive daughter + fillDebugParticle(negtrack); // QA for negative daughter + fillDebugParticle(v0); // QA for v0 } if constexpr (isMC) { fillMCParticle(v0, o2::aod::femtouniverseparticle::ParticleType::kV0); @@ -765,6 +1009,107 @@ struct femtoUniverseProducerTask { } } + template + void fillCascade(CollisionType const& col, CascadeType const& fullCascades, TrackType const&) + { + std::vector childIDs = {0, 0, 0}; // child1, child2, bachelor; these IDs are necessary to keep track of the children + std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index + + for (const auto& casc : fullCascades) { + const auto& posTrackCasc = casc.template posTrack_as(); + const auto& negTrackCasc = casc.template negTrack_as(); + const auto& bachTrackCasc = casc.template bachelor_as(); + + if (!cascadeCuts.isSelectedMinimal(col, casc, posTrackCasc, negTrackCasc, bachTrackCasc)) { + continue; + } + + cascadeCuts.fillCascadeQA(col, casc, posTrackCasc, negTrackCasc); + cascadeCuts.fillQA(col, casc, posTrackCasc, negTrackCasc, bachTrackCasc); // fill QA for daughters + + int postrackID = casc.posTrackId(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; // pos + childIDs[1] = 0; // neg + childIDs[2] = 0; // bachelor + outputParts(outputCollision.lastIndex(), + casc.positivept(), + casc.positiveeta(), + casc.positivephi(), + aod::femtouniverseparticle::ParticleType::kV0Child, + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosCuts), + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0); + const int rowOfPosTrack = outputParts.lastIndex(); + // if constexpr (isMC) { + // fillMCParticle(postrack, o2::aod::femtouniverseparticle::ParticleType::kV0Child); + // } + int negtrackID = casc.negTrackId(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; // pos + childIDs[1] = rowInPrimaryTrackTableNeg; // neg + childIDs[2] = 0; // bachelor + outputParts(outputCollision.lastIndex(), + casc.negativept(), + casc.negativeeta(), + casc.negativephi(), + aod::femtouniverseparticle::ParticleType::kV0Child, + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), + 0., + childIDs, + 0, + 0); + const int rowOfNegTrack = outputParts.lastIndex(); + // if constexpr (isMC) { + // fillMCParticle(negtrack, o2::aod::femtouniverseparticle::ParticleType::kV0Child); + // } + // bachelor + int bachtrackID = casc.bachelorId(); + int rowInPrimaryTrackTableBach = -1; + rowInPrimaryTrackTableBach = getRowDaughters(bachtrackID, tmpIDtrack); + childIDs[0] = 0; // pos + childIDs[1] = 0; // neg + childIDs[2] = rowInPrimaryTrackTableBach; // bachelor + outputParts(outputCollision.lastIndex(), + casc.bachelorpt(), + casc.bacheloreta(), + casc.bachelorphi(), + aod::femtouniverseparticle::ParticleType::kCascadeBachelor, + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), + 0., + childIDs, + 0, + 0); + const int rowOfBachTrack = outputParts.lastIndex(); + // cascade + std::vector indexCascChildID = {rowOfPosTrack, rowOfNegTrack, rowOfBachTrack}; + outputParts(outputCollision.lastIndex(), + casc.pt(), + casc.eta(), + casc.phi(), + aod::femtouniverseparticle::ParticleType::kCascade, + 0, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kV0), // zmienic + 0, + casc.casccosPA(col.posX(), col.posY(), col.posZ()), + indexCascChildID, + casc.mXi(), + casc.mXi()); + if (ConfIsDebug) { + fillDebugParticle(posTrackCasc); // QA for positive daughter + fillDebugParticle(negTrackCasc); // QA for negative daughter + fillDebugParticle(bachTrackCasc); // QA for negative daughter + fillDebugParticle(casc); // QA for cascade + } + } + } + template void fillD0mesons(CollisionType const&, TrackType const&, HfCandidate const& hfCands) { @@ -773,6 +1118,7 @@ struct femtoUniverseProducerTask { double invMassD0 = 0.0; double invMassD0bar = 0.0; bool isD0D0bar = false; + uint8_t daughFlag = 0; // flag = 0 (daugh of D0 or D0bar), 1 (daug of D0), -1 (daugh of D0bar) for (auto const& hfCand : hfCands) { @@ -801,14 +1147,17 @@ struct femtoUniverseProducerTask { invMassD0 = hfHelper.invMassD0ToPiK(hfCand); invMassD0bar = -hfHelper.invMassD0barToKPi(hfCand); isD0D0bar = true; + daughFlag = 1; } else if (hfCand.isSelD0() == 0 && hfCand.isSelD0bar() == 1) { invMassD0 = -hfHelper.invMassD0ToPiK(hfCand); invMassD0bar = hfHelper.invMassD0barToKPi(hfCand); isD0D0bar = true; + daughFlag = -1; } else if (hfCand.isSelD0() == 1 && hfCand.isSelD0bar() == 1) { invMassD0 = hfHelper.invMassD0ToPiK(hfCand); invMassD0bar = hfHelper.invMassD0barToKPi(hfCand); isD0D0bar = true; + daughFlag = 0; } else { invMassD0 = 0.0; invMassD0bar = 0.0; @@ -825,12 +1174,12 @@ struct femtoUniverseProducerTask { -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosPID), -999, childIDs, - 0, // D0 mass - 0); // D0bar mass + postrack.sign(), // D0 mass -> positive daughter of D0/D0bar + daughFlag); // D0bar mass -> sign that the daugh is from D0 or D0 decay const int rowOfPosTrack = outputParts.lastIndex(); - /*if constexpr (isMC) { - fillMCParticle(tracks, o2::aod::femtouniverseparticle::ParticleType::kDmesonChild); - }*/ + if constexpr (isMC) { + fillMCParticle(postrack, o2::aod::femtouniverseparticle::ParticleType::kD0Child); + } // int negtrackID = hfCand.prong1().globalIndex(); int negtrackID = hfCand.prong1Id(); int rowInPrimaryTrackTableNeg = -1; @@ -847,12 +1196,12 @@ struct femtoUniverseProducerTask { -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), -999, childIDs, - 0, - 0); + negtrack.sign(), // negative daughter of D0/D0bar + daughFlag); // sign that the daugh is from D0 or D0 decay const int rowOfNegTrack = outputParts.lastIndex(); - /*if constexpr (isMC) { - fillMCParticle(p2, o2::aod::femtouniverseparticle::ParticleType::kDmesonChild); - }*/ + if constexpr (isMC) { + fillMCParticle(negtrack, o2::aod::femtouniverseparticle::ParticleType::kD0Child); + } std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; outputParts(outputCollision.lastIndex(), @@ -868,9 +1217,9 @@ struct femtoUniverseProducerTask { invMassD0bar); // D0bar mass (mAntiLambda) if (ConfIsDebug) { - fillDebugParticle(postrack); // QA for positive daughter - fillDebugParticle(negtrack); // QA for negative daughter - fillDebugParticle(hfCand); // QA for D0/D0bar + fillDebugParticle(postrack); // QA for positive daughter + fillDebugParticle(negtrack); // QA for negative daughter + fillDebugParticle(hfCand); // QA for D0/D0bar } if constexpr (isMC) { fillMCParticle(hfCand, o2::aod::femtouniverseparticle::ParticleType::kD0); @@ -885,22 +1234,50 @@ struct femtoUniverseProducerTask { std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index // lorentz vectors and filling the tables - for (auto& [p1, p2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { + for (auto& [p1, p2] : combinations(soa::CombinationsFullIndexPolicy(tracks, tracks))) { + if (!trackCuts.isSelectedMinimal(p1) || !trackCuts.isSelectedMinimal(p1)) { + continue; + } // implementing PID cuts for phi children - if (!(IsKaonNSigma(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { + if (ConfPhiSelection.ConfLooseTPCNSigma) { + if (!(IsKaonNSigmaTPCLoose(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { + continue; + } + if (!(IsKaonNSigmaTPCLoose(p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon)))) { + continue; + } + } + if (ConfPhiSelection.ConfLooseTOFNSigma) { + if (!(IsKaonNSigmaTOFLoose(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { + continue; + } + if (!(IsKaonNSigmaTOFLoose(p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon)))) { + continue; + } + } else { + if (!(IsKaonNSigma(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { + continue; + } + if (!(IsKaonNSigma(p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon)))) { + continue; + } + } + if (IsKaonRejected(p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion))) { continue; } - if (!(IsKaonNSigma(p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon)))) { + if (IsKaonRejected(p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion))) { continue; - } else if ((!(p1.sign() == 1)) || (!(p2.sign() == -1))) { + } + + if ((!(p1.sign() == 1)) || (!(p2.sign() == -1))) { continue; } TLorentzVector part1Vec; TLorentzVector part2Vec; - float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPhiChildOne.ConfPDGCodePartOne)->Mass(); // FIXME: Get from the PDG service of the common header - float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPhiChildTwo.ConfPDGCodePartTwo)->Mass(); // FIXME: Get from the PDG service of the common header + float mMassOne = TDatabasePDG::Instance()->GetParticle(321)->Mass(); // FIXME: Get from the PDG service of the common header + float mMassTwo = TDatabasePDG::Instance()->GetParticle(-321)->Mass(); // FIXME: Get from the PDG service of the common header part1Vec.SetPtEtaPhiM(p1.pt(), p1.eta(), p1.phi(), mMassOne); part2Vec.SetPtEtaPhiM(p2.pt(), p2.eta(), p2.phi(), mMassTwo); @@ -926,11 +1303,11 @@ struct femtoUniverseProducerTask { } float phiM = sumVec.M(); - if (((phiM < ConfPhiCommon.ConfInvMassLowLimitPhi) || (phiM > ConfPhiCommon.ConfInvMassUpLimitPhi))) { + if (((phiM < ConfPhiSelection.ConfInvMassLowLimitPhi) || (phiM > ConfPhiSelection.ConfInvMassUpLimitPhi))) { continue; } - phiCuts.fillQA(col, p1, p1, p2, ConfPhiChildOne.ConfPDGCodePartOne, ConfPhiChildTwo.ConfPDGCodePartTwo); ///\todo fill QA also for daughters + phiCuts.fillQA(col, p1, p1, p2, 321, -321); ///\todo fill QA also for daughters int postrackID = p1.globalIndex(); int rowInPrimaryTrackTablePos = -1; // does it do anything? @@ -986,20 +1363,21 @@ struct femtoUniverseProducerTask { -999); // v0.mAntiLambda() if (ConfIsDebug) { - fillDebugParticle(p1); // QA for positive daughter - fillDebugParticle(p2); // QA for negative daughter - fillDebugParticle(p1); // QA for phi + fillDebugParticle(p1); // QA for positive daughter + fillDebugParticle(p2); // QA for negative daughter + fillDebugParticle(p1); // QA for phi + } + if constexpr (isMC) { + fillMCParticlePhi(p1, p2); } - // if constexpr (isMC) { - // fillMCParticle(v0, o2::aod::femtouniverseparticle::ParticleType::kV0); - // } } } - template - void fillParticles(TrackType const& tracks) + template + void fillParticles(TrackType const& tracks, std::optional>> recoMcIds = std::nullopt) { std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children + std::vector tmpIDtrack; for (auto& particle : tracks) { /// if the most open selection criteria are not fulfilled there is no @@ -1017,10 +1395,10 @@ struct femtoUniverseProducerTask { std::vector tmpPDGCodes = ConfMCTruthPDGCodes; // necessary due to some features of the Configurable for (uint32_t pdg : tmpPDGCodes) { if (static_cast(pdg) == static_cast(pdgCode)) { - if (pdgCode == 333) { // ATTENTION: workaround for now, because all Phi mesons are NOT primary particles for now. + if ((pdgCode == 333)) { // && (recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) { // ATTENTION: all Phi mesons are NOT primary particles pass = true; } else { - if (particle.isPhysicalPrimary()) + if (particle.isPhysicalPrimary() || (ConfActivateSecondaries && recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) pass = true; } } @@ -1041,6 +1419,10 @@ struct femtoUniverseProducerTask { // instead of the bitmask, the PDG of the particle is stored as uint32_t // now the table is filled + if constexpr (resolveDaughs) { + tmpIDtrack.push_back(particle.globalIndex()); + continue; + } outputParts(outputCollision.lastIndex(), particle.pt(), particle.eta(), @@ -1052,6 +1434,51 @@ struct femtoUniverseProducerTask { childIDs, 0, 0); + if (ConfIsDebug) { + fillDebugParticle(particle); + } + + // Workaround to keep the FDParticles and MC label tables + // aligned, so that they can be joined in the task. + if constexpr (transientLabels) { + outputPartsMCLabels(-1); + } + } + if constexpr (resolveDaughs) { + childIDs[0] = 0; + childIDs[1] = 0; + for (int i = 0; i < tmpIDtrack.size(); i++) { + const auto& particle = tracks.iteratorAt(tmpIDtrack[i] - tracks.begin().globalIndex()); + for (int daughIndex = 0, n = std::min(2ul, particle.daughtersIds().size()); daughIndex < n; daughIndex++) { + // loop to find the corresponding index of the daughters + for (int j = 0; j < tmpIDtrack.size(); j++) { + if (tmpIDtrack[j] == particle.daughtersIds()[daughIndex]) { + childIDs[daughIndex] = i - j; + break; + } + } + } + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + static_cast(particle.pdgCode()), + particle.pdgCode(), + childIDs, + 0, + 0); + if (ConfIsDebug) { + fillDebugParticle(particle); + } + + // Workaround to keep the FDParticles and MC label tables + // aligned, so that they can be joined in the task. + if constexpr (transientLabels) { + outputPartsMCLabels(-1); + } + } } } @@ -1067,6 +1494,9 @@ struct femtoUniverseProducerTask { if (ConfIsActivatePhi) { fillPhi(col, tracks); } + // if (ConfIsActivateCascade) { + // fillCascade(col, fullCascades, tracks); + // } } void processFullData(aod::FemtoFullCollision const& col, @@ -1093,6 +1523,34 @@ struct femtoUniverseProducerTask { } PROCESS_SWITCH(femtoUniverseProducerTask, processTrackV0, "Provide experimental data for track v0", false); + void processTrackCascadeData(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + soa::Filtered const& tracks, + o2::aod::CascDatas const& fullCascades) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisions(col, tracks); + fillTracks(tracks); + fillCascade(col, fullCascades, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackCascadeData, "Provide experimental data for track cascades", false); + + void processTrackV0CentRun3(aod::FemtoFullCollisionCentRun3 const& col, + aod::BCsWithTimestamps const&, + soa::Filtered const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisionsCentRun3(col, tracks); + fillTracks(tracks); + fillV0(col, fullV0s, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackV0CentRun3, "Provide experimental data for track v0", false); + void processFullMC(aod::FemtoFullCollisionMC const& col, aod::BCsWithTimestamps const&, soa::Join const& tracks, @@ -1121,6 +1579,36 @@ struct femtoUniverseProducerTask { } PROCESS_SWITCH(femtoUniverseProducerTask, processTrackMC, "Provide MC data for track analysis", false); + void processTrackPhiMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const&, + aod::McParticles const&) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisions(col, tracks); + fillTracks(tracks); + fillPhi(col, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackPhiMC, "Provide MC data for track Phi analysis", false); + + void processTrackD0MC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const&, + aod::McParticles const&) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisions(col, tracks); + fillTracks(tracks); + // fillD0mesons(col, tracks, candidates); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackD0MC, "Provide MC data for track D0 analysis", false); + void processTrackData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) @@ -1176,6 +1664,65 @@ struct femtoUniverseProducerTask { } PROCESS_SWITCH(femtoUniverseProducerTask, processTrackMCTruth, "Provide MC data for MC truth track analysis", false); + void processTrackMCGen(aod::McCollision const& col, + aod::McParticles const& mcParticles) + { + outputCollision(col.posZ(), 0, 0, 2, 0); + fillParticles(mcParticles); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackMCGen, "Provide MC Generated for model comparisons", false); + + Preslice perMCCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted> recoCollsPerMCColl = aod::mcparticle::mcCollisionId; + Preslice> perCollisionTracks = aod::track::collisionId; + Preslice> perCollisionV0s = aod::track::collisionId; + void processTruthAndFullMC( + aod::McCollisions const& mccols, + aod::McParticles const& mcParticles, + soa::Join const& collisions, + soa::Filtered> const& tracks, + soa::Join const& fullV0s, + aod::BCsWithTimestamps const&) + { + // recos + std::set recoMcIds; + for (auto& col : collisions) { + auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); + auto groupedV0s = fullV0s.sliceBy(perCollisionV0s, col.globalIndex()); + getMagneticFieldTesla(col.bc_as()); + fillCollisionsAndTracksAndV0AndPhi(col, groupedTracks, groupedV0s); + for (auto& track : groupedTracks) { + if (trackCuts.isSelectedMinimal(track)) + recoMcIds.insert(track.mcParticleId()); + } + } + + // truth + for (auto& mccol : mccols) { + auto groupedMCParticles = mcParticles.sliceBy(perMCCollision, mccol.globalIndex()); + auto groupedCollisions = collisions.sliceBy(recoCollsPerMCColl, mccol.globalIndex()); + fillMCTruthCollisions(groupedCollisions, groupedMCParticles); // fills the reco collisions for mc collision + fillParticles(groupedMCParticles, recoMcIds); // fills mc particles + } + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTruthAndFullMC, "Provide both MC truth and reco for tracks and V0s", false); + + void processFullMCCent(aod::FemtoFullCollisionCentRun3 const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisionsCentRun3(col, tracks); + fillTracks(tracks); + fillV0(col, fullV0s, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processFullMCCent, "Provide MC data with centrality bins", false); + void processTrackCentRun2Data(aod::FemtoFullCollisionCentRun2 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) diff --git a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt index c1e487e8908..7e82d3c4525 100644 --- a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt @@ -49,6 +49,11 @@ o2physics_add_dpl_workflow(femtouniverse-pair-track-v0-extended PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-pair-track-cascade-extended + SOURCES femtoUniversePairTaskTrackCascadeExtended.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtouniverse-pair-track-d0 SOURCES femtoUniversePairTaskTrackD0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -79,6 +84,11 @@ o2physics_add_dpl_workflow(femtouniverse-efficiency-task PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-efficiency-base + SOURCES femtoUniverseEfficiencyBase.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_executable(femtouniverse-cutculator SOURCES femtoUniverseCutCulator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx index 04bc95eb5c9..94a0d58a646 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx @@ -53,7 +53,7 @@ struct femtoUniverseDebugTrack { Configurable ConfIsTrackIdentified{"ConfIsTrackIdentified", true, "Enable PID for the track"}; Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable ConfTrackChoicePartOne{"ConfTrackChoicePartOne", 1, "Type of particle (track1): {0:Proton, 1:Pion, 2:Kaon}"}; - Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; + Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; } trackonefilter; struct : o2::framework::ConfigurableGroup { diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx new file mode 100644 index 00000000000..feb6495e1cd --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx @@ -0,0 +1,627 @@ +// Copyright 2019-2022 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. + +/// \file femtoUniverseEfficiencyBase.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch +/// \author Alicja PƂachta, WUT Warsaw, alicja.plachta@cern.ch + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct femtoUniverseEfficiencyBase { + SliceCache cache; + using FemtoFullParticles = soa::Join; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + Configurable ConfIsDebug{"ConfIsDebug", true, "Enable debug histograms"}; + + // Collisions + Configurable ConfZVertex{"ConfZVertex", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + + Filter collisionFilter = (nabs(aod::collision::posZ) < ConfZVertex); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + /// Particle selection part + /// Configurables for both particles + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "Binning of the pT in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarPDGBins{"ConfTempFitVarPDGBins", {6000, -2300, 2300}, "Binning of the PDG code in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarCPABins{"ConfTempFitVarCPABins", {1000, 0.9, 1}, "Binning of the pointing angle cosinus in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarDCABins{"ConfTempFitVarDCABins", {1000, -5, 5}, "Binning of the PDG code in the pT vs. TempFitVar plot"}; + + struct : o2::framework::ConfigurableGroup { + Configurable ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + Configurable ConfMomProton{"ConfMomProton", 0.75, "Momentum threshold for proton identification using TOF"}; + Configurable ConfMomPion{"ConfMomPion", 0.75, "Momentum threshold for pion identification using TOF"}; + Configurable ConfNsigmaCombinedProton{"ConfNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > ConfMomProton"}; + Configurable ConfNsigmaTPCProton{"ConfNsigmaTPCProton", 3.0, "TPC Proton Sigma for momentum < ConfMomProton"}; + Configurable ConfNsigmaCombinedPion{"ConfNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > ConfMomPion"}; + Configurable ConfNsigmaTPCPion{"ConfNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < ConfMomPion"}; + } ConfBothTracks; + + // Lambda cuts + Configurable ConfV0InvMassLowLimit{"ConfV0InvV0MassLowLimit", 1.10, "Lower limit of the V0 invariant mass"}; + Configurable ConfV0InvMassUpLimit{"ConfV0InvV0MassUpLimit", 1.13, "Upper limit of the V0 invariant mass"}; + + // Kaon configurables + Configurable IsKaonRun2{"IsKaonRun2", false, "Enable kaon selection used in Run2"}; // to check consistency with Run2 results + + /// Particle 1 + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + Configurable ConfParticleTypePartOne{"ConfParticleTypePartOne", aod::femtouniverseparticle::ParticleType::kTrack, "Particle 1 - particle type: 0 - track, 2 - V0, 6 - phi"}; + Configurable ConfNoPDGPartOne{"ConfNoPDGPartOne", false, "0: selecting part one by PDG, 1: no PID selection"}; + Configurable ConfPtLowPart1{"ConfPtLowPart1", 0.2, "Lower limit for Pt for the first particle"}; + Configurable ConfPtHighPart1{"ConfPtHighPart1", 2.5, "Higher limit for Pt for the first particle"}; + Configurable ConfChargePart1{"ConfChargePart1", 1, "Charge of the first particle"}; + + /// Partition for particle 1 + Partition partsOneMCGen = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && aod::femtouniverseparticle::pt < ConfPtHighPart1 && aod::femtouniverseparticle::pt > ConfPtLowPart1&& nabs(aod::femtouniverseparticle::eta) < ConfBothTracks.ConfEtaMax; + + Partition partsTrackOneMCReco = aod::femtouniverseparticle::pt < ConfPtHighPart1 && aod::femtouniverseparticle::pt > ConfPtLowPart1&& nabs(aod::femtouniverseparticle::eta) < ConfBothTracks.ConfEtaMax; + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOneGen; + FemtoUniverseParticleHisto trackHistoPartOneRec; + FemtoUniverseParticleHisto trackHistoV0OneRec; + FemtoUniverseParticleHisto trackHistoV0OneChildPosRec; + FemtoUniverseParticleHisto trackHistoV0OneChildNegRec; + + /// Particle 2 + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 333, "Particle 2 - PDG code"}; + Configurable ConfParticleTypePartTwo{"ConfParticleTypePartTwo", aod::femtouniverseparticle::ParticleType::kTrack, "Particle 2 - particle type: 0 - track, 2 - V0, 6 - phi"}; + Configurable ConfNoPDGPartTwo{"ConfNoPDGPartTwo", false, "0: selecting part two by PDG, 1: no PID selection"}; + Configurable ConfPtLowPart2{"ConfPtLowPart2", 0.2, "Lower limit for Pt for the second particle"}; + Configurable ConfPtHighPart2{"ConfPtHighPart2", 2.5, "Higher limit for Pt for the second particle"}; + Configurable ConfChargePart2{"ConfChargePart2", 1, "Charge of the second particle"}; + + /// Partition for particle 2 + Partition partsTwoGen = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && aod::femtouniverseparticle::pt < ConfPtHighPart2 && aod::femtouniverseparticle::pt > ConfPtLowPart2&& nabs(aod::femtouniverseparticle::eta) < ConfBothTracks.ConfEtaMax; + + Partition partsTrackTwoMCReco = aod::femtouniverseparticle::pt < ConfPtHighPart2 && aod::femtouniverseparticle::pt > ConfPtLowPart2&& nabs(aod::femtouniverseparticle::eta) < ConfBothTracks.ConfEtaMax; + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwoGen; + FemtoUniverseParticleHisto trackHistoPartTwoRec; + FemtoUniverseParticleHisto trackHistoV0TwoRec; + FemtoUniverseParticleHisto trackHistoV0TwoChildPosRec; + FemtoUniverseParticleHisto trackHistoV0TwoChildNegRec; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + FemtoUniverseTrackSelection trackCuts; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registryPDG{"PDGHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryMCOrigin{"MCOriginHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + void init(InitContext&) + { + + eventHisto.init(&qaRegistry); + trackHistoPartOneGen.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartOne, false); + trackHistoPartOneRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarDCABins, 0, ConfPDGCodePartOne, ConfIsDebug); + registryMCOrigin.add("part1/hPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); + registryPDG.add("part1/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + if (ConfParticleTypePartOne == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) { + trackHistoV0OneRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarCPABins, 0, ConfPDGCodePartOne, ConfIsDebug); + trackHistoV0OneChildPosRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarDCABins, 0, 0, ConfIsDebug, "posChildV0_1"); + trackHistoV0OneChildNegRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarDCABins, 0, 0, ConfIsDebug, "negChildV0_1"); + registryPDG.add("part1/dpositive/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + registryPDG.add("part1/dnegative/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + } + + registryPDG.add("part2/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + if (!ConfIsSame) { + trackHistoPartTwoGen.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartTwo, false); + trackHistoPartTwoRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarDCABins, 0, ConfPDGCodePartTwo, ConfIsDebug); + registryMCOrigin.add("part2/hPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); + if (ConfParticleTypePartTwo == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) { + trackHistoV0TwoRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarCPABins, 0, ConfPDGCodePartTwo, ConfIsDebug); + trackHistoV0TwoChildPosRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarDCABins, 0, 0, ConfIsDebug, "posChildV0_2"); + trackHistoV0TwoChildNegRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarDCABins, 0, 0, ConfIsDebug, "negChildV0_2"); + registryPDG.add("part2/dpositive/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + registryPDG.add("part2/dnegative/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + } + } + } + + bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + if (mom < ConfBothTracks.ConfMomProton) { + if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaTPCProton) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { + return true; + } else { + return false; + } + } + return false; + } + + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + if (IsKaonRun2 == true) { + if (mom < 0.4) { + return TMath::Abs(nsigmaTPCK) < 2; + } else if (mom > 0.4 && mom < 0.45) { + return TMath::Abs(nsigmaTPCK) < 1; + } else if (mom > 0.45 && mom < 0.8) { + return (TMath::Abs(nsigmaTPCK) < 3 && TMath::Abs(nsigmaTOFK) < 2); + } else if (mom > 0.8 && mom < 1.5) { + return (TMath::Abs(nsigmaTPCK) < 3 && TMath::Abs(nsigmaTOFK) < 1.5); + } else { + return false; + } + } else { + if (mom < 0.3) { // 0.0-0.3 + if (TMath::Abs(nsigmaTPCK) < 3.0) { + return true; + } else { + return false; + } + } else if (mom < 0.45) { // 0.30 - 0.45 + if (TMath::Abs(nsigmaTPCK) < 2.0) { + return true; + } else { + return false; + } + } else if (mom < 0.55) { // 0.45-0.55 + if (TMath::Abs(nsigmaTPCK) < 1.0) { + return true; + } else { + return false; + } + } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) + if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + { + return true; + } + } else { + return false; + } + } else if (mom > 1.5) { // 1.5 - + if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + } + + bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + { + if (mom < ConfBothTracks.ConfMomPion) { + if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaTPCPion) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { + return true; + } else { + return false; + } + } + return false; + } + + bool IsParticleNSigma(int pdgCode, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + switch (pdgCode) { + case 2212: // Proton + case -2212: // anty Proton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion + case -211: // Pion- + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + } + + bool invMLambda(float invMassLambda, float invMassAntiLambda) + { + if ((invMassLambda < ConfV0InvMassLowLimit || invMassLambda > ConfV0InvMassUpLimit) && (invMassAntiLambda < ConfV0InvMassLowLimit || invMassAntiLambda > ConfV0InvMassUpLimit)) { + return false; + } + return true; + } + + template + void fillCollision(CollisionType col) + { + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param grouppartsOneMCGen partition for the first particle passed by the process function + /// @param grouppartsTwoMCGen partition for the second particle passed by the process function + template + void doMCGen(PartitionType grouppartsOneMCGen, PartitionType grouppartsTwoMCGen) + { + /// Histogramming same event + for (auto& part : grouppartsOneMCGen) { + if (!ConfNoPDGPartOne && part.pidcut() != ConfPDGCodePartOne) { + continue; + } + trackHistoPartOneGen.fillQA(part); + } + + if (!ConfIsSame) { + for (auto& part : grouppartsTwoMCGen) { + if (!ConfNoPDGPartTwo && part.pidcut() != ConfPDGCodePartTwo) { + continue; + } + trackHistoPartTwoGen.fillQA(part); + } + } + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @tparam isDebug: enables debug histograms + /// @param grouppartsOneMCRec partition for the first particle passed by the process function + /// @param grouppartsTwoMCRec partition for the second particle passed by the process function + template + void doMCRecTrackTrack(PartitionType grouppartsOneMCRec, PartitionType grouppartsTwoMCRec) + { + /// Histogramming same event + for (auto& part : grouppartsOneMCRec) { + if (part.partType() != ConfParticleTypePartOne || part.sign() != ConfChargePart1 || !IsParticleNSigma(ConfPDGCodePartOne, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + trackHistoPartOneRec.fillQA(part); + + if (!part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + + registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryMCOrigin.fill(HIST("part1/hPt"), mcParticle.pt()); + } + + if (!ConfIsSame) { + for (auto& part : grouppartsTwoMCRec) { + if (part.partType() != ConfParticleTypePartTwo || part.sign() != ConfChargePart2 || !IsParticleNSigma(ConfPDGCodePartTwo, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + + trackHistoPartTwoRec.fillQA(part); + + if (!part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + + registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryMCOrigin.fill(HIST("part2/hPt"), mcParticle.pt()); + } + } + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @tparam isDebug: enables debug histograms + /// @param grouppartsOneMCRec partition for the first particle passed by the process function + /// @param grouppartsTwoMCRec partition for the second particle passed by the process function + template + void doMCRecTrackPhi(PartitionType grouppartsOneMCRec, PartitionType grouppartsTwoMCRec) + { // part1 is track and part2 is Phi + + for (auto& part : grouppartsOneMCRec) { + if (part.partType() != ConfParticleTypePartOne || part.sign() != ConfChargePart1 || !IsParticleNSigma(ConfPDGCodePartOne, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + trackHistoPartOneRec.fillQA(part); + + if (!part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + + registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryMCOrigin.fill(HIST("part1/hPt"), mcParticle.pt()); + } + + if (!ConfIsSame) { + for (auto& part : grouppartsTwoMCRec) { + if (part.partType() != ConfParticleTypePartTwo || part.sign() != ConfChargePart2) { + continue; + } + + trackHistoPartTwoRec.fillQA(part); + + if (!part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + + registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryMCOrigin.fill(HIST("part2/hPt"), mcParticle.pt()); + } + } + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam ParticlesType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @tparam isDebug: enables debug histograms + /// @param grouppartsOneMCRec partition for the first particle passed by the process function + /// @param grouppartsTwoMCRec partition for the second particle passed by the process function + /// @param parts all tracks + template + void doMCRecV0V0(PartitionType grouppartsOneMCRec, PartitionType grouppartsTwoMCRec, ParticlesType parts) + { + /// Histogramming same event + for (auto& part : grouppartsOneMCRec) { + + if (part.partType() != ConfParticleTypePartOne || !invMLambda(part.mLambda(), part.mAntiLambda())) { + continue; + } + + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + + if (ConfPDGCodePartOne > 0 && (!IsProtonNSigma(0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Proton)) || !IsPionNSigma(0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Pion), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Pion)))) { // give momentum as 0 to only check TPC nSigma, not combined with TOF + continue; + } + if (ConfPDGCodePartOne < 0 && (!IsProtonNSigma(0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Proton)) || !IsPionNSigma(0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Pion), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Pion)))) { // give momentum as 0 to only check TPC nSigma, not combined with TOF + continue; + } + + trackHistoV0OneRec.fillQA(part); + trackHistoV0OneChildPosRec.fillQABase(posChild, HIST("posChildV0_1")); + trackHistoV0OneChildNegRec.fillQABase(negChild, HIST("negChildV0_1")); + + if (!posChild.has_fdMCParticle() || !negChild.has_fdMCParticle() || !part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + const auto mcPosChild = posChild.fdMCParticle(); + const auto mcNegChild = negChild.fdMCParticle(); + + registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryPDG.fill(HIST("part1/dpositive/PDGvspT"), part.pt(), mcPosChild.pdgMCTruth()); + registryPDG.fill(HIST("part1/dnegative/PDGvspT"), part.pt(), mcNegChild.pdgMCTruth()); + registryMCOrigin.fill(HIST("part1/hPt"), mcParticle.pt()); + } + + if (!ConfIsSame) { + for (auto& part : grouppartsTwoMCRec) { + + if (part.partType() != ConfParticleTypePartTwo || !invMLambda(part.mLambda(), part.mAntiLambda())) { + continue; + } + + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + + if (ConfPDGCodePartTwo > 0 && (!IsProtonNSigma(0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Proton)) || !IsPionNSigma(0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Pion), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Pion)))) { // give momentum as 0 to only check TPC nSigma, not combined with TOF + continue; + } + if (ConfPDGCodePartTwo < 0 && (!IsProtonNSigma(0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Proton)) || !IsPionNSigma(0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Pion), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Pion)))) { // give momentum as 0 to only check TPC nSigma, not combined with TOF + continue; + } + + trackHistoV0TwoRec.fillQA(part); + trackHistoV0TwoChildPosRec.fillQABase(posChild, HIST("posChildV0_2")); + trackHistoV0TwoChildNegRec.fillQABase(negChild, HIST("negChildV0_2")); + + if (!posChild.has_fdMCParticle() || !negChild.has_fdMCParticle() || !part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + const auto mcPosChild = posChild.fdMCParticle(); + const auto mcNegChild = negChild.fdMCParticle(); + + registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryPDG.fill(HIST("part2/dpositive/PDGvspT"), part.pt(), mcPosChild.pdgMCTruth()); + registryPDG.fill(HIST("part2/dnegative/PDGvspT"), part.pt(), mcNegChild.pdgMCTruth()); + registryMCOrigin.fill(HIST("part2/hPt"), mcParticle.pt()); + } + } + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam ParticlesType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @tparam isDebug: enables debug histograms + /// @param grouppartsOneMCRec partition for the first particle passed by the process function + /// @param grouppartsTwoMCRec partition for the second particle passed by the process function + /// @param parts all tracks + template + void doMCRecTrackV0(PartitionType grouppartsOneMCRec, PartitionType grouppartsTwoMCRec, ParticlesType const& parts) + { // part1 is track and part2 is V0 + + /// Histogramming same event + for (auto& part : grouppartsOneMCRec) { + if (part.partType() != ConfParticleTypePartOne || part.sign() != ConfChargePart1 || !IsParticleNSigma(ConfPDGCodePartOne, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + + trackHistoPartOneRec.fillQA(part); + if (!part.has_fdMCParticle()) + continue; + + const auto mcParticle = part.fdMCParticle(); + registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryMCOrigin.fill(HIST("part1/hPt"), mcParticle.pt()); + } + + if (!ConfIsSame) { + for (auto& part : grouppartsTwoMCRec) { + + if (part.partType() != ConfParticleTypePartTwo || !invMLambda(part.mLambda(), part.mAntiLambda())) { + continue; + } + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + + if (ConfPDGCodePartTwo > 0 && (!IsProtonNSigma(0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Proton)) || !IsPionNSigma(0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Pion), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Pion)))) { // give momentum as 0 to only check TPC nSigma, not combined with TOF + continue; + } + if (ConfPDGCodePartTwo < 0 && (!IsProtonNSigma(0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Proton)) || !IsPionNSigma(0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Pion), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Pion)))) { // give momentum as 0 to only check TPC nSigma, not combined with TOF + continue; + } + + trackHistoV0TwoRec.fillQA(part); + trackHistoV0TwoChildPosRec.fillQABase(posChild, HIST("posChildV0_2")); + trackHistoV0TwoChildNegRec.fillQABase(negChild, HIST("negChildV0_2")); + + if (!posChild.has_fdMCParticle() || !negChild.has_fdMCParticle() || !part.has_fdMCParticle()) { + continue; + } + const auto mcParticle = part.fdMCParticle(); + const auto mcPosChild = posChild.fdMCParticle(); + const auto mcNegChild = negChild.fdMCParticle(); + + registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); + registryPDG.fill(HIST("part2/dpositive/PDGvspT"), part.pt(), mcPosChild.pdgMCTruth()); + registryPDG.fill(HIST("part2/dnegative/PDGvspT"), part.pt(), mcNegChild.pdgMCTruth()); + registryMCOrigin.fill(HIST("part2/hPt"), mcParticle.pt()); + } + } + } + + /// process function for to call doMCRecTrackTrack with Data + /// \param col subscribe to the collision table (Data) + void processTrackTrack(FilteredFDCollision& col, + FemtoFullParticles&, aod::FDMCParticles const&) + { + fillCollision(col); + // MCGen + auto thegrouppartsOneMCGen = partsOneMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegrouppartsTwoMCGen = partsTwoGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + // MCRec + auto thegroupPartsTrackOneRec = partsTrackOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTrackTwoRec = partsTrackTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + if (ConfIsDebug) { + doMCRecTrackTrack(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + } else { + doMCRecTrackTrack(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + } + } + PROCESS_SWITCH(femtoUniverseEfficiencyBase, processTrackTrack, "Enable processing track-track efficiency task", true); + + /// process function for to call doMCRecTrackPhi with Data + /// \param col subscribe to the collision table (Data) + void processTrackPhi(FilteredFDCollision& col, + FemtoFullParticles&, aod::FDMCParticles const&) + { + fillCollision(col); + // MCGen + auto thegrouppartsOneMCGen = partsOneMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegrouppartsTwoMCGen = partsTwoGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + // MCRec + auto thegroupPartsTrackOneRec = partsTrackOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTrackTwoRec = partsTrackTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + if (ConfIsDebug) { + doMCRecTrackPhi(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + } else { + doMCRecTrackPhi(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + } + } + PROCESS_SWITCH(femtoUniverseEfficiencyBase, processTrackPhi, "Enable processing track-phi efficiency task", false); + + /// process function for to call doMCRecV0V0 with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processV0V0(FilteredFDCollision& col, + FemtoFullParticles& parts, aod::FDMCParticles const&) + { + fillCollision(col); + // MCGen + auto thegrouppartsOneMCGen = partsOneMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegrouppartsTwoMCGen = partsTwoGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + + // MCRec + auto thegroupPartsTrackOneRec = partsTrackOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTrackTwoRec = partsTrackTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + if (ConfIsDebug) { + doMCRecV0V0(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec, parts); + } else { + doMCRecV0V0(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec, parts); + } + } + PROCESS_SWITCH(femtoUniverseEfficiencyBase, processV0V0, "Enable processing V0-V0 efficiency task", false); + + /// process function for to call doMCRecTrackV0 with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processTrackV0(FilteredFDCollision& col, + FemtoFullParticles& parts, aod::FDMCParticles const&) + { + fillCollision(col); + // MCGen + auto thegrouppartsOneMCGen = partsOneMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegrouppartsTwoMCGen = partsTwoGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + // MCRec + auto thegroupPartsTrackOneRec = partsTrackOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTrackTwoRec = partsTrackTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + if (ConfIsDebug) { + doMCRecTrackV0(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec, parts); + } else { + doMCRecTrackV0(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec, parts); + } + } + PROCESS_SWITCH(femtoUniverseEfficiencyBase, processTrackV0, "Enable processing track-V0 efficiency task", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx new file mode 100644 index 00000000000..7c87254f9ea --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -0,0 +1,163 @@ +// Copyright 2019-2022 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. + +/// \brief Task for cascade QA; in the future: for cascade correlations +/// \author Barbara Chytla, WUT Warsaw, barbara.chytla@cern.ch + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femtoUniverse; +using namespace o2::aod::pidutils; + +struct femtoUniversePairTaskTrackCascadeExtended { + + SliceCache cache; + using FemtoFullParticles = soa::Join; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + Configurable ConfZVertexCut{"ConfZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + + Filter collisionFilter = (nabs(aod::collision::posZ) < ConfZVertexCut); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + ConfigurableAxis ConfChildTempFitVarpTBins{"ConfChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfChildTempFitVarBins{"ConfChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + Configurable ConfCascInvMassLowLimit{"ConfCascInvMassLowLimit", 1.315, "Lower limit of the Casc invariant mass"}; + Configurable ConfCascInvMassUpLimit{"ConfCascInvMassUpLimit", 1.325, "Upper limit of the Casc invariant mass"}; + Configurable ConfCascTranRad{"ConfCascTranRad", 0.5, "Cascade transverse radius"}; + + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + /// Partition for cascades + Partition cascs = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)); + + FemtoUniverseParticleHisto posChildHistos; + FemtoUniverseParticleHisto negChildHistos; + FemtoUniverseParticleHisto bachHistos; + + HistogramRegistry rXiQA{"xi", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + + bool invMCascade(float invMassCascade, float invMassAntiCascade) + { + if ((invMassCascade < ConfCascInvMassLowLimit || invMassCascade > ConfCascInvMassUpLimit) && (invMassAntiCascade < ConfCascInvMassLowLimit || invMassAntiCascade > ConfCascInvMassUpLimit)) { + return false; + } + return true; + } + + void init(InitContext const&) + { + // Axes + AxisSpec XiMassAxis = {200, 1.28f, 1.36f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec etaAxis = {100, -2.0f, 2.0f, "#it{#eta}"}; + AxisSpec phiAxis = {100, 0.0f, 6.0f, "#it{#phi}"}; + + // Histograms + rXiQA.add("hMassXiMinus", "hMassXiMinus", {HistType::kTH1F, {XiMassAxis}}); + rXiQA.add("hMassXiPlus", "hMassXiPlus", {HistType::kTH1F, {XiMassAxis}}); + rXiQA.add("hMassXiMinusSelected", "hMassXiSelected", {HistType::kTH1F, {XiMassAxis}}); + rXiQA.add("hMassXiPlusSelected", "hMassXiSelected", {HistType::kTH1F, {XiMassAxis}}); + rXiQA.add("hPtXi", "hPtXi", {HistType::kTH1F, {{ptAxis}}}); + rXiQA.add("hEtaXi", "hEtaXi", {HistType::kTH1F, {{etaAxis}}}); + rXiQA.add("hPhiXi", "hPhiXi", {HistType::kTH1F, {{phiAxis}}}); + rXiQA.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.9f, 1.f}}}); + // rXiQA.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + + posChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, 0, true); + negChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, 0, true); + bachHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, 0, true, "hBachelor"); + } + + void processCascades(FilteredFDCollision& col, FemtoFullParticles& parts) + { + auto groupCascs = cascs->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + // const int multCol = col.multNtr(); + + for (auto& casc : groupCascs) { + rXiQA.fill(HIST("hMassXiMinus"), casc.mLambda()); + rXiQA.fill(HIST("hMassXiPlus"), casc.mAntiLambda()); + + // if (!invMCascade(casc.mLambda(), casc.mAntiLambda())) + // continue; + + const auto& posChild = parts.iteratorAt(casc.index() - 3); + const auto& negChild = parts.iteratorAt(casc.index() - 2); + const auto& bachelor = parts.iteratorAt(casc.index() - 1); + + // if (casc.transRadius() < ConfCascTranRad) + // continue; + // std::cout< NSigmaTPCProton) { + continue; + } + if (TMath::Abs(negChild.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } else { + if (TMath::Abs(negChild.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(posChild.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } + if (TMath::Abs(bachelor.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + + rXiQA.fill(HIST("hPtXi"), casc.pt()); + rXiQA.fill(HIST("hEtaXi"), casc.eta()); + rXiQA.fill(HIST("hPhiXi"), casc.phi()); + rXiQA.fill(HIST("hMassXiMinusSelected"), casc.mLambda()); + rXiQA.fill(HIST("hMassXiPlusSelected"), casc.mAntiLambda()); + rXiQA.fill(HIST("hCascCosPA"), casc.tempFitVar()); + // rXiQA.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); // nie ma miejsca na to w FemtoDerived + + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + bachHistos.fillQABase(bachelor, HIST("hBachelor")); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processCascades, "Enable processing cascades", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx index d9496c47212..bd59782fc0a 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx @@ -134,7 +134,7 @@ struct femtoUniversePairTaskTrackD0 { } ConfD0D0barSideBand; Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Configurable ConfUseAllD0mesons{"ConfUseAllD0mesons", false, "Include cand. which are both D0 and D0bar cand."}; + Configurable ConfChooseD0trackCorr{"ConfChooseD0trackCorr", 3, "If 0 - only D0s, 1 - only D0bars, 2 - D0/D0bar (one mass hypo.), 3 - all D0/D0bar cand."}; Configurable ConfUsePtCutForD0D0bar{"ConfUsePtCutForD0D0bar", false, "Include pT cut for D0/D0bar in same and mixed processes."}; Configurable ConfUseMassCutForD0D0bar{"ConfUseMassCutForD0D0bar", false, "Switch to save D0/D0bar within declared inv. mass range"}; @@ -143,8 +143,15 @@ struct femtoUniversePairTaskTrackD0 { Partition> partsTrackMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); /// Partitions for particle 2 + /// Partition with all D0/D0bar mesons (which pass double and one mass hypothesis) Partition partsAllDmesons = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)); + /// Partition with D0/D0bar candidates, which pass only one mass hypothesis Partition partsOnlyD0D0bar = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f || aod::femtouniverseparticle::mAntiLambda < 0.0f); + /// Partition with D0 mesons only (one mass hypothesis) + Partition partsD0s = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > 0.0f) && (aod::femtouniverseparticle::mAntiLambda < 0.0f); + /// Partition with D0bar mesons only (one mass hypothesis) + Partition partsD0bars = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f) && (aod::femtouniverseparticle::mAntiLambda > 0.0f); + /// Partition for D0/D0bar mesons from MC Partition> partsD0D0barMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)); /// Partition for D0/D0bar daughters @@ -230,13 +237,6 @@ struct femtoUniversePairTaskTrackD0 { // PID for protons bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using configurables: - // ConfNsigmaTPCProton -> TPC Kaon Sigma for momentum < 0.5 - // ConfNsigmaCombinedProton -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 - if (mom < 0.5) { if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaTPCProton) { return true; @@ -245,7 +245,6 @@ struct femtoUniversePairTaskTrackD0 { } } else if (mom > 0.4) { if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { - // if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { return true; } else { return false; @@ -282,7 +281,7 @@ struct femtoUniversePairTaskTrackD0 { } else { return false; } - } else if (mom > 1.5) { // 1.5 - + } else if (mom > 1.5) { if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { return true; } else { @@ -310,7 +309,6 @@ struct femtoUniversePairTaskTrackD0 { } } else if (mom > 0.5) { if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { - // if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { return true; } else { return false; @@ -343,6 +341,41 @@ struct femtoUniversePairTaskTrackD0 { void init(InitContext&) { eventHisto.init(&qaRegistry); + qaRegistry.add("D0_pos_daugh/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0_pos_daugh/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0_pos_daugh/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); + qaRegistry.add("D0_pos_daugh/eta", "; #it{eta}; Counts", kTH1F, {{200, -1.5, 1.5}}); + qaRegistry.add("D0_pos_daugh/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, 2. * M_PI}}); + qaRegistry.add("D0_pos_daugh/hDCAxy", "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + + qaRegistry.add("D0_neg_daugh/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0_neg_daugh/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0_neg_daugh/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); + qaRegistry.add("D0_neg_daugh/eta", "; #it{eta}; Counts", kTH1F, {{200, -1.5, 1.5}}); + qaRegistry.add("D0_neg_daugh/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, 2. * M_PI}}); + qaRegistry.add("D0_neg_daugh/hDCAxy", "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + + qaRegistry.add("D0bar_pos_daugh/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0bar_pos_daugh/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0bar_pos_daugh/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); + qaRegistry.add("D0bar_pos_daugh/eta", "; #it{eta}; Counts", kTH1F, {{200, -1.5, 1.5}}); + qaRegistry.add("D0bar_pos_daugh/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, 2. * M_PI}}); + qaRegistry.add("D0bar_pos_daugh/hDCAxy", "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + + qaRegistry.add("D0bar_neg_daugh/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0bar_neg_daugh/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("D0bar_neg_daugh/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); + qaRegistry.add("D0bar_neg_daugh/eta", "; #it{eta}; Counts", kTH1F, {{200, -1.5, 1.5}}); + qaRegistry.add("D0bar_neg_daugh/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, 2. * M_PI}}); + qaRegistry.add("D0bar_neg_daugh/hDCAxy", "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + + qaRegistry.add("Hadron/nSigmaTPCPr", "; #it{p} (GeV/#it{c}); n#sigma_{TPCPr}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFPr", "; #it{p} (GeV/#it{c}); n#sigma_{TOFPr}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTPCPi", "; #it{p} (GeV/#it{c}); n#sigma_{TPCPi}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFPi", "; #it{p} (GeV/#it{c}); n#sigma_{TOFPi}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTPCKa", "; #it{p} (GeV/#it{c}); n#sigma_{TPCKa}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFKa", "; #it{p} (GeV/#it{c}); n#sigma_{TOFKa}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + trackHistoPartD0D0bar.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarInvMassBins, ConfBothTracks.ConfIsMC, ConfDmesons.ConfPDGCodeD0); if (!ConfTrack.ConfIsSame) { trackHistoPartTrack.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfBothTracks.ConfIsMC, ConfTrack.ConfPDGCodeTrack); @@ -441,6 +474,31 @@ struct femtoUniversePairTaskTrackD0 { // loop over D mesons childen for (auto const& daughD0D0bar : groupPartsD0D0barChildren) { registry.fill(HIST("hPtDaughters"), daughD0D0bar.pt()); + registry.fill(HIST("hSignDaughters"), daughD0D0bar.mLambda()); + // filling QA plots for D0 mesons' positive daughters (K+) + if (daughD0D0bar.mLambda() == 1 && daughD0D0bar.mAntiLambda() == 1) { + qaRegistry.fill(HIST("D0_pos_daugh/pt"), daughD0D0bar.pt()); + qaRegistry.fill(HIST("D0_pos_daugh/eta"), daughD0D0bar.eta()); + qaRegistry.fill(HIST("D0_pos_daugh/phi"), daughD0D0bar.phi()); + } + // filling QA plots for D0 mesons' negative daughters (pi-) + if (daughD0D0bar.mLambda() == -1 && daughD0D0bar.mAntiLambda() == 1) { + qaRegistry.fill(HIST("D0_pos_daugh/pt"), daughD0D0bar.pt()); + qaRegistry.fill(HIST("D0_pos_daugh/eta"), daughD0D0bar.eta()); + qaRegistry.fill(HIST("D0_pos_daugh/phi"), daughD0D0bar.phi()); + } + // filling QA plots for D0bar mesons' positive daughters (pi+) + if (daughD0D0bar.mLambda() == 1 && daughD0D0bar.mAntiLambda() == -1) { + qaRegistry.fill(HIST("D0bar_pos_daugh/pt"), daughD0D0bar.pt()); + qaRegistry.fill(HIST("D0bar_pos_daugh/eta"), daughD0D0bar.eta()); + qaRegistry.fill(HIST("D0bar_pos_daugh/phi"), daughD0D0bar.phi()); + } + // filling QA plots for D0bar mesons' negative daughters (K-) + if (daughD0D0bar.mLambda() == -1 && daughD0D0bar.mAntiLambda() == -1) { + qaRegistry.fill(HIST("D0bar_neg_daugh/pt"), daughD0D0bar.pt()); + qaRegistry.fill(HIST("D0bar_neg_daugh/eta"), daughD0D0bar.eta()); + qaRegistry.fill(HIST("D0bar_neg_daugh/phi"), daughD0D0bar.phi()); + } } } PROCESS_SWITCH(femtoUniversePairTaskTrackD0, processD0mesons, "Enable processing D0 mesons", true); @@ -520,6 +578,7 @@ struct femtoUniversePairTaskTrackD0 { for (auto& d0candidate : groupPartsD0) { trackHistoPartD0D0bar.fillQA(d0candidate); } + float tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa; if (!ConfTrack.ConfIsSame) { for (auto& track : groupPartsTrack) { @@ -529,6 +588,20 @@ struct femtoUniversePairTaskTrackD0 { } } trackHistoPartTrack.fillQA(track); + + tpcNSigmaPi = trackCuts.getNsigmaTPC(track, o2::track::PID::Pion); + tofNSigmaPi = trackCuts.getNsigmaTOF(track, o2::track::PID::Pion); + tpcNSigmaKa = trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon); + tofNSigmaKa = trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon); + tpcNSigmaPr = trackCuts.getNsigmaTPC(track, o2::track::PID::Proton); + tofNSigmaPr = trackCuts.getNsigmaTOF(track, o2::track::PID::Proton); + + qaRegistry.fill(HIST("Hadron/nSigmaTPCPi"), track.p(), tpcNSigmaPi); + qaRegistry.fill(HIST("Hadron/nSigmaTOFPi"), track.p(), tofNSigmaPi); + qaRegistry.fill(HIST("Hadron/nSigmaTPCKa"), track.p(), tpcNSigmaKa); + qaRegistry.fill(HIST("Hadron/nSigmaTOFKa"), track.p(), tofNSigmaKa); + qaRegistry.fill(HIST("Hadron/nSigmaTPCPr"), track.p(), tpcNSigmaPr); + qaRegistry.fill(HIST("Hadron/nSigmaTOFPr"), track.p(), tofNSigmaPr); } } /// Now build the combinations @@ -577,11 +650,23 @@ struct femtoUniversePairTaskTrackD0 { auto thegroupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsAllD0D0bar = partsAllDmesons->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsOnlyD0D0bar = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto theGroupPartsD0s = partsD0s->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto theGroupPartsD0bars = partsD0bars->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - if (ConfUseAllD0mesons) { - doSameEvent(thegroupPartsTrack, thegroupPartsAllD0D0bar, parts, col.magField(), col.multNtr()); - } else { - doSameEvent(thegroupPartsTrack, thegroupPartsOnlyD0D0bar, parts, col.magField(), col.multNtr()); + switch (ConfChooseD0trackCorr) { + case 0: + doSameEvent(thegroupPartsTrack, theGroupPartsD0s, parts, col.magField(), col.multNtr()); + break; + case 1: + doSameEvent(thegroupPartsTrack, theGroupPartsD0bars, parts, col.magField(), col.multNtr()); + break; + case 2: + doSameEvent(thegroupPartsTrack, thegroupPartsOnlyD0D0bar, parts, col.magField(), col.multNtr()); + break; + case 3: + doSameEvent(thegroupPartsTrack, thegroupPartsAllD0D0bar, parts, col.magField(), col.multNtr()); + default: + break; } } PROCESS_SWITCH(femtoUniversePairTaskTrackD0, processSameEvent, "Enable processing same event", true); @@ -661,6 +746,8 @@ struct femtoUniversePairTaskTrackD0 { auto groupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); auto groupPartsAllD0D0bar = partsAllDmesons->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsOnlyD0D0bar = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto theGroupPartsD0s = partsD0s->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto theGroupPartsD0bars = partsD0bars->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -671,10 +758,20 @@ struct femtoUniversePairTaskTrackD0 { /// \todo before mixing we should check whether both collisions contain a pair of particles! // if (partsD0.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTrack.size() == 0 ) continue; - if (ConfUseAllD0mesons) { - doMixedEvent(groupPartsTrack, groupPartsAllD0D0bar, parts, magFieldTesla1, multiplicityCol); - } else { - doMixedEvent(groupPartsTrack, groupPartsOnlyD0D0bar, parts, magFieldTesla1, multiplicityCol); + switch (ConfChooseD0trackCorr) { + case 0: + doMixedEvent(groupPartsTrack, theGroupPartsD0s, parts, magFieldTesla1, multiplicityCol); + break; + case 1: + doMixedEvent(groupPartsTrack, theGroupPartsD0bars, parts, magFieldTesla1, multiplicityCol); + break; + case 2: + doMixedEvent(groupPartsTrack, groupPartsOnlyD0D0bar, parts, magFieldTesla1, multiplicityCol); + break; + case 3: + doMixedEvent(groupPartsTrack, groupPartsAllD0D0bar, parts, magFieldTesla1, multiplicityCol); + default: + break; } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx index b74fb942a59..66a7477aff7 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx @@ -32,11 +32,13 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" #include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include +#include +#include "CCDB/BasicCCDBManager.h" using namespace o2; using namespace o2::analysis::femtoUniverse; @@ -57,10 +59,15 @@ static const float cutsTable[nPart][nCuts]{ struct femtoUniversePairTaskTrackPhi { + Service pdgMC; + using FemtoFullParticles = soa::Join; SliceCache cache; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + using FemtoRecoParticles = soa::Join; + Preslice perColMC = aod::femtouniverseparticle::fdCollisionId; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; Configurable ConfCPRdeltaPhiCutMax{"ConfCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; @@ -75,6 +82,9 @@ struct femtoUniversePairTaskTrackPhi { struct : o2::framework::ConfigurableGroup { Configurable ConfNsigmaCombinedProton{"ConfNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; Configurable ConfNsigmaTPCProton{"ConfNsigmaTPCProton", 3.0, "TPC Proton Sigma for momentum < 0.5"}; + Configurable ConfNsigmaRejectKaon{"ConfNsigmaRejectKaon", 3.0, "Reject if particle could be a Kaon combined nsigma value."}; + Configurable ConfNsigmaRejectPion{"ConfNsigmaRejectPion", 3.0, "Reject if particle could be a Pion combined nsigma value."}; + Configurable ConfNsigmaRejectProton{"ConfNsigmaRejectProton", 3.0, "Reject if particle could be a Proton combined nsigma value."}; Configurable ConfNsigmaCombinedPion{"ConfNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > 0.5"}; Configurable ConfNsigmaTPCPion{"ConfNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < 0.5"}; @@ -94,6 +104,7 @@ struct femtoUniversePairTaskTrackPhi { Configurable ConfPIDTrack{"ConfPIDTrack", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; Configurable ConfIsTrackIdentified{"ConfIsTrackIdentified", true, "Enable PID for the track"}; + Configurable ConfIsTrackRejected{"ConfIsTrackRejected", true, "Enable PID rejection for the track other species than the identified one."}; } ConfTrack; /// Particle 2 --- PHI @@ -114,6 +125,10 @@ struct femtoUniversePairTaskTrackPhi { Partition partsPhiDaugh = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kPhiChild)); Partition> partsPhiDaughMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kPhiChild)); + // Partition for K+K- minv + Partition partsKaons = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); + Partition> partsKaonsMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); + /// Histogramming for particle 1 FemtoUniverseParticleHisto trackHistoPartTrack; @@ -144,8 +159,12 @@ struct femtoUniversePairTaskTrackPhi { ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; - FemtoUniverseFemtoContainer sameEventFemtoCont; - FemtoUniverseFemtoContainer mixedEventFemtoCont; + // Efficiency + Configurable ConfLocalEfficiencyProton{"ConfLocalEfficiencyProton", "", "Local path to proton efficiency th2d file"}; + Configurable ConfLocalEfficiencyPhi{"ConfLocalEfficiencyPhi", "", "Local path to Phi efficiency th2d file"}; + Configurable ConfEffProtonTimestamp{"ConfEffProtonTimestamp", 10, "(int) Timestamp for hadron"}; + Configurable ConfEffPhiTimestamp{"ConfEffPhiTimestamp", 10, "(int) Timestamp for phi"}; + FemtoUniverseAngularContainer sameEventAngularCont; FemtoUniverseAngularContainer mixedEventAngularCont; FemtoUniversePairCleaner pairCleaner; @@ -156,6 +175,13 @@ struct femtoUniversePairTaskTrackPhi { HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registryMCtruth{"MCtruthHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryMCreco{"MCrecoHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryPhiMinvBackground{"registryPhiMinvBackground", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + Service ccdb; + TH2D* protoneff; + TH2D* phieff; // PID for protons bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx @@ -176,6 +202,24 @@ struct femtoUniversePairTaskTrackPhi { return false; } + bool IsProtonRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + if (mom < 0.5) { + return true; + } + if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaRejectPion) { + return true; + } else if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfBothTracks.ConfNsigmaRejectKaon) { + return true; + } else { + return false; + } + } else { + return false; + } + } + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) { if (mom < 0.3) { // 0.0-0.3 @@ -215,6 +259,28 @@ struct femtoUniversePairTaskTrackPhi { } } + bool IsKaonRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi) + { + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaRejectPion) { + return true; + } else if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + return true; + } + } + if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaRejectPion) { + return true; + } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + return true; + } else { + return false; + } + } else { + return false; + } + } + bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) { if (true) { @@ -235,7 +301,29 @@ struct femtoUniversePairTaskTrackPhi { return false; } - bool IsParticleNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + bool IsPionRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCK, float nsigmaTOFK) + { + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCK) < ConfBothTracks.ConfNsigmaRejectKaon) { + return true; + } else if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + return true; + } + } + if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfBothTracks.ConfNsigmaRejectKaon) { + return true; + } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool IsParticleNSigmaAccepted(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) { switch (ConfTrack.ConfPDGCodeTrack) { case 2212: // Proton @@ -255,23 +343,71 @@ struct femtoUniversePairTaskTrackPhi { } } + bool IsParticleNSigmaRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + switch (ConfTrack.ConfPDGCodeTrack) { + case 2212: // Proton + case -2212: // anty Proton + return IsProtonRejected(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCK, nsigmaTOFK); + break; + case 211: // Pion + case -211: // Pion- + return IsPionRejected(mom, nsigmaTPCPr, nsigmaTOFPr, nsigmaTPCK, nsigmaTOFK); + break; + case 321: // Kaon+ + case -321: // Kaon- + return IsKaonRejected(mom, nsigmaTPCPr, nsigmaTOFPr, nsigmaTPCPi, nsigmaTOFPi); + break; + default: + return false; + } + } + void init(InitContext&) { eventHisto.init(&qaRegistry); - qaRegistry.add("PhiDaugh_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - qaRegistry.add("PhiDaugh_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + qaRegistry.add("PhiDaugh_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("PhiDaugh_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("PhiDaugh_pos/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); qaRegistry.add("PhiDaugh_pos/eta", "; #it{eta}; Counts", kTH1F, {{200, -1.5, 1.5}}); qaRegistry.add("PhiDaugh_pos/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, 2. * M_PI}}); qaRegistry.add("PhiDaugh_pos/hDCAxy", "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); - qaRegistry.add("PhiDaugh_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - qaRegistry.add("PhiDaugh_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + qaRegistry.add("PhiDaugh_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("PhiDaugh_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("PhiDaugh_neg/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); qaRegistry.add("PhiDaugh_neg/eta", "; #it{eta}; Counts", kTH1F, {{200, -1.5, 1.5}}); qaRegistry.add("PhiDaugh_neg/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, 2. * M_PI}}); qaRegistry.add("PhiDaugh_neg/hDCAxy", "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + registryPhiMinvBackground.add("InvariantMassKpKp", "; invariant mass K+K+; Counts", kTH1F, {{6000, 0.9, 4.0}}); + registryPhiMinvBackground.add("InvariantMassKmKm", "; invariant mass K-K-; Counts", kTH1F, {{6000, 0.9, 4.0}}); + + qaRegistry.add("Hadron/nSigmaTPCPr", "; #it{p} (GeV/#it{c}); n#sigma_{TPCPr}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFPr", "; #it{p} (GeV/#it{c}); n#sigma_{TOFPr}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTPCPi", "; #it{p} (GeV/#it{c}); n#sigma_{TPCPi}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFPi", "; #it{p} (GeV/#it{c}); n#sigma_{TOFPi}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTPCKa", "; #it{p} (GeV/#it{c}); n#sigma_{TPCKa}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFKa", "; #it{p} (GeV/#it{c}); n#sigma_{TOFKa}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + + // MC truth + registryMCtruth.add("MCtruthPhi", "MC truth Phi;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("MCtruthAllPositivePt", "MC truth all positive;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("MCtruthAllNegativePt", "MC truth all negative;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("MCtruthKp", "MC truth K+;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("MCtruthKm", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("MCtruthKpPt", "MC truth kaons positive;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("MCtruthKmPt", "MC truth kaons negative;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("MCtruthPpos", "MC truth proton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("MCtruthPneg", "MC truth antiproton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + // MC reco + registryMCreco.add("MCrecoPhi", "MC reco Phi;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("MCrecoAllPositivePt", "MC reco all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("MCrecoAllNegativePt", "MC reco all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("MCrecoPpos", "MC reco proton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("MCrecoPneg", "MC reco antiproton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + trackHistoPartPhi.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarInvMassBins, ConfBothTracks.ConfIsMC, ConfPhi.ConfPDGCodePhi); if (!ConfTrack.ConfIsSame) { trackHistoPartTrack.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfBothTracks.ConfIsMC, ConfTrack.ConfPDGCodeTrack); @@ -280,13 +416,9 @@ struct femtoUniversePairTaskTrackPhi { MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - sameEventFemtoCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); - mixedEventFemtoCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); sameEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfEtaBins, ConfBothTracks.ConfPhiBins, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); mixedEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfEtaBins, ConfBothTracks.ConfPhiBins, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); - sameEventFemtoCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); - mixedEventFemtoCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); sameEventAngularCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); mixedEventAngularCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); @@ -295,6 +427,27 @@ struct femtoUniversePairTaskTrackPhi { pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiCutMin.value, ConfCPRdeltaPhiCutMax.value, ConfCPRdeltaEtaCutMin.value, ConfCPRdeltaEtaCutMax.value, ConfCPRChosenRadii.value, ConfCPRPlotPerRadii.value, ConfCPRInvMassCutMin.value, ConfCPRInvMassCutMax.value); } + /// Initializing CCDB + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + if (!ConfLocalEfficiencyProton.value.empty()) { + protoneff = ccdb->getForTimeStamp(ConfLocalEfficiencyProton.value.c_str(), ConfEffProtonTimestamp); + if (!protoneff || protoneff->IsZombie()) { + LOGF(fatal, "Could not load efficiency protoneff histogram from %s", ConfLocalEfficiencyProton.value.c_str()); + } + } + if (!ConfLocalEfficiencyPhi.value.empty()) { + phieff = ccdb->getForTimeStamp(ConfLocalEfficiencyPhi.value.c_str(), ConfEffPhiTimestamp); + if (!phieff || phieff->IsZombie()) { + LOGF(fatal, "Could not load efficiency phieff histogram from %s", ConfLocalEfficiencyPhi.value.c_str()); + } + } + vPIDPhiCandidate = ConfPhi.ConfPIDPhi.value; vPIDTrack = ConfTrack.ConfPIDTrack.value; kNsigma = ConfBothTracks.ConfTrkPIDnSigmaMax.value; @@ -318,7 +471,7 @@ struct femtoUniversePairTaskTrackPhi { /// @param magFieldTesla magnetic field of the collision /// @param multCol multiplicity of the collision template - void doSameEvent(PartitionType groupPartsTrack, PartitionType groupPartsPhi, PartitionType groupPartsPhiDaugh, PartType parts, float magFieldTesla, int multCol) + void doSameEvent(PartitionType groupPartsTrack, PartitionType groupPartsPhi, PartitionType groupPartsPhiDaugh, PartitionType groupPartsKaons, PartType parts, float magFieldTesla, int multCol) { /// Histogramming same event @@ -351,58 +504,52 @@ struct femtoUniversePairTaskTrackPhi { qaRegistry.fill(HIST("PhiDaugh_neg/hDCAxy"), phidaugh.p(), phidaugh.tempFitVar()); } } - + float tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa; if (!ConfTrack.ConfIsSame) { for (auto& track : groupPartsTrack) { - // if (track.p() > ConfBothTracks.ConfCutTable->get("Track", "MaxP") || track.pt() > ConfBothTracks.ConfCutTable->get("Track", "MaxPt")) { - // continue; - // } - // if (!isFullPIDSelected(track.pidcut(), - // track.p(), - // ConfBothTracks.ConfCutTable->get("Track", "PIDthr"), - // vPIDTrack, - // ConfBothTracks.ConfNspecies, - // kNsigma, - // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPC"), - // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPCTOF"))) { - // continue; - // } + tpcNSigmaPi = trackCuts.getNsigmaTPC(track, o2::track::PID::Pion); + tofNSigmaPi = trackCuts.getNsigmaTOF(track, o2::track::PID::Pion); + tpcNSigmaKa = trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon); + tofNSigmaKa = trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon); + tpcNSigmaPr = trackCuts.getNsigmaTPC(track, o2::track::PID::Proton); + tofNSigmaPr = trackCuts.getNsigmaTOF(track, o2::track::PID::Proton); + if (ConfTrack.ConfIsTrackIdentified) { - if (!IsParticleNSigma(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + if (!IsParticleNSigmaAccepted(track.p(), tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa)) { continue; } } + + if (ConfTrack.ConfIsTrackRejected) { + if (IsParticleNSigmaRejected(track.p(), tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa)) { + continue; + } + } + trackHistoPartTrack.fillQA(track); + + qaRegistry.fill(HIST("Hadron/nSigmaTPCPi"), track.p(), tpcNSigmaPi); + qaRegistry.fill(HIST("Hadron/nSigmaTOFPi"), track.p(), tofNSigmaPi); + qaRegistry.fill(HIST("Hadron/nSigmaTPCKa"), track.p(), tpcNSigmaKa); + qaRegistry.fill(HIST("Hadron/nSigmaTOFKa"), track.p(), tofNSigmaKa); + qaRegistry.fill(HIST("Hadron/nSigmaTPCPr"), track.p(), tpcNSigmaPr); + qaRegistry.fill(HIST("Hadron/nSigmaTOFPr"), track.p(), tofNSigmaPr); } } /// Now build the combinations for (auto& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { - // if (track.p() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxP") || track.pt() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxPt") || phicandidate.p() > ConfBothTracks.ConfCutTable->get("Track", "MaxP") || phicandidate.pt() > ConfBothTracks.ConfCutTable->get("Track", "MaxPt")) { - // continue; - // } - // if (!isFullPIDSelected(track.pidcut(), - // track.p(), - // ConfBothTracks.ConfCutTable->get("PhiCandidate", "PIDthr"), - // vPIDPhiCandidate, - // ConfBothTracks.ConfNspecies, - // kNsigma, - // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPC"), - // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPCTOF")) || - // !isFullPIDSelected(phicandidate.pidcut(), - // phicandidate.p(), - // ConfBothTracks.ConfCutTable->get("Track", "PIDthr"), - // vPIDTrack, - // ConfBothTracks.ConfNspecies, - // kNsigma, - // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPC"), - // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPCTOF"))) { - // continue; - // } if (ConfTrack.ConfIsTrackIdentified) { - if (!IsParticleNSigma(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + if (!IsParticleNSigmaAccepted(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + continue; + } + } + + if (ConfTrack.ConfIsTrackRejected) { + if (IsParticleNSigmaRejected(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { continue; } } + // // Close Pair Rejection if (ConfIsCPR.value) { if (pairCloseRejection.isClosePair(track, phicandidate, parts, magFieldTesla, femtoUniverseContainer::EventType::same)) { @@ -414,8 +561,42 @@ struct femtoUniversePairTaskTrackPhi { if (!pairCleaner.isCleanPair(track, phicandidate, parts)) { continue; } - sameEventFemtoCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); - sameEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); + + float weight = 1.0f; + if (phieff) { + weight = protoneff->GetBinContent(protoneff->FindBin(track.pt(), track.eta())) * phieff->GetBinContent(phieff->FindBin(phicandidate.pt(), phicandidate.eta())); + sameEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D, weight); + } else { + sameEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D, weight); + } + } + + TLorentzVector part1Vec; + TLorentzVector part2Vec; + + float mMassOne = TDatabasePDG::Instance()->GetParticle(321)->Mass(); // FIXME: Get from the PDG service of the common header + float mMassTwo = TDatabasePDG::Instance()->GetParticle(-321)->Mass(); // FIXME: Get from the PDG service of the common header + + for (auto& [kaon1, kaon2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsKaons, groupPartsKaons))) { + if (!IsKaonNSigma(kaon1.p(), trackCuts.getNsigmaTPC(kaon1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(kaon1, o2::track::PID::Kaon))) { + } + if (!IsKaonNSigma(kaon2.p(), trackCuts.getNsigmaTPC(kaon2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(kaon2, o2::track::PID::Kaon))) { + } + if ((kaon1.mAntiLambda() == 1) && (kaon2.mAntiLambda() == 1)) { + part1Vec.SetPtEtaPhiM(kaon1.pt(), kaon1.eta(), kaon1.phi(), mMassOne); + part2Vec.SetPtEtaPhiM(kaon2.pt(), kaon2.eta(), kaon2.phi(), mMassOne); + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + registryPhiMinvBackground.fill(HIST("InvariantMassKpKp"), sumVec.M()); + } + if ((kaon1.mAntiLambda() == -1) && (kaon2.mAntiLambda() == -1)) { + part1Vec.SetPtEtaPhiM(kaon1.pt(), kaon1.eta(), kaon1.phi(), mMassTwo); + part2Vec.SetPtEtaPhiM(kaon2.pt(), kaon2.eta(), kaon2.phi(), mMassTwo); + + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + registryPhiMinvBackground.fill(HIST("InvariantMassKmKm"), sumVec.M()); + } } } @@ -430,8 +611,9 @@ struct femtoUniversePairTaskTrackPhi { auto thegroupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsPhi = partsPhi->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsPhiDaugh = partsPhiDaugh->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsKaons = partsKaons->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEvent(thegroupPartsTrack, thegroupPartsPhi, thegroupPartsPhiDaugh, parts, col.magField(), col.multNtr()); + doSameEvent(thegroupPartsTrack, thegroupPartsPhi, thegroupPartsPhiDaugh, thegroupPartsKaons, parts, col.magField(), col.multNtr()); } PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processSameEvent, "Enable processing same event", true); @@ -448,8 +630,9 @@ struct femtoUniversePairTaskTrackPhi { auto thegroupPartsPhi = partsPhiMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsTrack = partsTrackMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsPhiDaugh = partsPhiDaughMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsKaons = partsKaonsMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEvent(thegroupPartsTrack, thegroupPartsPhi, thegroupPartsPhiDaugh, parts, col.magField(), col.multNtr()); + doSameEvent(thegroupPartsTrack, thegroupPartsPhi, thegroupPartsPhiDaugh, thegroupPartsKaons, parts, col.magField(), col.multNtr()); } PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processSameEventMC, "Enable processing same event for Monte Carlo", false); @@ -468,40 +651,31 @@ struct femtoUniversePairTaskTrackPhi { { for (auto& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { - // if (track.p() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxP") || track.pt() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxPt") || phicandidate.p() > ConfBothTracks.ConfCutTable->get("Track", "MaxP") || phicandidate.pt() > ConfBothTracks.ConfCutTable->get("Track", "MaxPt")) { - // continue; - // } - // if (!isFullPIDSelected(track.pidcut(), - // track.p(), - // ConfBothTracks.ConfCutTable->get("PhiCandidate", "PIDthr"), - // vPIDPhiCandidate, - // ConfBothTracks.ConfNspecies, - // kNsigma, - // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPC"), - // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPCTOF")) || - // !isFullPIDSelected(phicandidate.pidcut(), - // phicandidate.p(), - // ConfBothTracks.ConfCutTable->get("Track", "PIDthr"), - // vPIDTrack, - // ConfBothTracks.ConfNspecies, - // kNsigma, - // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPC"), - // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPCTOF"))) { - // continue; - // } if (ConfTrack.ConfIsTrackIdentified) { - if (!IsParticleNSigma(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + if (!IsParticleNSigmaAccepted(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + continue; + } + } + + if (ConfTrack.ConfIsTrackRejected) { + if (IsParticleNSigmaRejected(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { continue; } } + if (ConfIsCPR.value) { if (pairCloseRejection.isClosePair(track, phicandidate, parts, magFieldTesla, femtoUniverseContainer::EventType::mixed)) { continue; } } - mixedEventFemtoCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); - mixedEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); + float weight = 1.0f; + if (protoneff) { + weight = protoneff->GetBinContent(protoneff->FindBin(track.pt(), track.eta())) * phieff->GetBinContent(phieff->FindBin(phicandidate.pt(), phicandidate.eta())); + mixedEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D, weight); + } else { + mixedEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D, weight); + } } } @@ -562,6 +736,81 @@ struct femtoUniversePairTaskTrackPhi { } } PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processMixedEventMC, "Enable processing mixed events MC", false); + + ///--------------------------------------------MC-------------------------------------------------/// + + /// This function fills MC truth particles from derived MC table + void processMCTruth(aod::FDParticles const& parts) + { + for (auto& part : parts) { + if (part.partType() != uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) + continue; + + int pdgCode = static_cast(part.pidcut()); + const auto& pdgParticle = pdgMC->GetParticle(pdgCode); + if (!pdgParticle) { + continue; + } + + if (pdgParticle->Charge() > 0.0) { + registryMCtruth.fill(HIST("MCtruthAllPositivePt"), part.pt()); + } + if (pdgCode == 321) { + registryMCtruth.fill(HIST("MCtruthKp"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("MCtruthKpPt"), part.pt()); + } + if ((pdgCode == 333)) { + registryMCtruth.fill(HIST("MCtruthPhi"), part.pt(), part.eta()); + continue; + } + if (pdgCode == 2212) { + registryMCtruth.fill(HIST("MCtruthPpos"), part.pt(), part.eta()); + } + + if (pdgParticle->Charge() < 0.0) { + registryMCtruth.fill(HIST("MCtruthAllNegativePt"), part.pt()); + } + if (pdgCode == -321) { + registryMCtruth.fill(HIST("MCtruthKm"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("MCtruthKmPt"), part.pt()); + } + if (pdgCode == -2212) { + registryMCtruth.fill(HIST("MCtruthPneg"), part.pt(), part.eta()); + } + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processMCTruth, "Process MC truth data", false); + + void processMCReco(FemtoRecoParticles const& parts, aod::FDMCParticles const& mcparts) + { + for (auto& part : parts) { + auto mcPartId = part.fdMCParticleId(); + if (mcPartId == -1) + continue; // no MC particle + const auto& mcpart = mcparts.iteratorAt(mcPartId); + if (part.partType() == aod::femtouniverseparticle::ParticleType::kPhi) { + if ((mcpart.pdgMCTruth() == 333) && (mcpart.partOriginMCTruth() == aod::femtouniverseMCparticle::ParticleOriginMCTruth::kPrimary)) { + registryMCreco.fill(HIST("MCrecoPhi"), mcpart.pt(), mcpart.eta()); // phi + } + } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { + if (part.sign() > 0) { + registryMCreco.fill(HIST("MCrecoAllPositivePt"), mcpart.pt()); + if (mcpart.pdgMCTruth() == 2212 && IsParticleNSigmaAccepted(part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + registryMCreco.fill(HIST("MCrecoPpos"), mcpart.pt(), mcpart.eta()); + } + } + + if (part.sign() < 0) { + registryMCreco.fill(HIST("MCrecoAllNegativePt"), mcpart.pt()); + if (mcpart.pdgMCTruth() == -2212 && IsParticleNSigmaAccepted(part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + registryMCreco.fill(HIST("MCrecoPneg"), mcpart.pt(), mcpart.eta()); + } + } + } // partType + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processMCReco, "Process MC reco data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx index ed5ff3c56f1..d5b7c010acc 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx @@ -476,9 +476,9 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); if (!cfgProcessMultBins) { - sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - std::vector k3d = FemtoUniverseMath::getpairmom3d(p1, mass1, p2, mass2, ConfIsIden, ConfIsLCMS); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); sameEventMultCont.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -515,16 +515,16 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - k3d = FemtoUniverseMath::getpairmom3d(p1, mass1, p2, mass2, ConfIsIden, ConfIsLCMS); + k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); sameEventMultContPP.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } else { if (!cfgProcessMultBins) { - sameEventContPP.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + sameEventContPP.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - k3d = FemtoUniverseMath::getpairmom3d(p2, mass2, p1, mass1, ConfIsIden, ConfIsLCMS); + k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); sameEventMultContPP.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -538,16 +538,16 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - k3d = FemtoUniverseMath::getpairmom3d(p1, mass1, p2, mass2, ConfIsIden, ConfIsLCMS); + k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); sameEventMultContMM.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } else { if (!cfgProcessMultBins) { - sameEventContMM.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + sameEventContMM.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - k3d = FemtoUniverseMath::getpairmom3d(p2, mass2, p1, mass1, ConfIsIden, ConfIsLCMS); + k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); sameEventMultContMM.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -650,9 +650,9 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { case 1: { float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); if (!cfgProcessMultBins) { - mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - std::vector k3d = FemtoUniverseMath::getpairmom3d(p1, mass1, p2, mass2, ConfIsIden, ConfIsLCMS); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); mixedEventMultCont.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } break; @@ -660,9 +660,9 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { case 2: { float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); if (!cfgProcessMultBins) { - mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - std::vector k3d = FemtoUniverseMath::getpairmom3d(p1, mass1, p2, mass2, ConfIsIden, ConfIsLCMS); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); mixedEventMultContPP.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } break; @@ -671,9 +671,9 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { case 3: { float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); if (!cfgProcessMultBins) { - mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden, ConfIsLCMS); + mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); } else { - std::vector k3d = FemtoUniverseMath::getpairmom3d(p1, mass1, p2, mass2, ConfIsIden, ConfIsLCMS); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); mixedEventMultContMM.fill_3D(k3d[1], k3d[2], k3d[3], multCol, kT); } break; diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx index f1d7285d070..e2e2104a9fb 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx @@ -50,13 +50,13 @@ struct femtoUniversePairTaskTrackTrackMcTruth { Configurable ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; /// Particle 1 - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 211, "Particle 1 - PDG code"}; + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; Configurable ConfNoPDGPartOne{"ConfNoPDGPartOne", false, "0: selecting part by PDG, 1: no PID selection"}; Configurable ConfPtLowPart1{"ConfPtLowPart1", 0.2, "Lower limit for Pt for the first particle"}; Configurable ConfPtHighPart1{"ConfPtHighPart1", 2.5, "Higher limit for Pt for the first particle"}; /// Partition for particle 1 - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (ConfNoPDGPartOne || aod::femtouniverseparticle::pidcut == uint32_t(ConfPDGCodePartOne)) && + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && aod::femtouniverseparticle::pt < ConfPtHighPart1 && aod::femtouniverseparticle::pt > ConfPtLowPart1&& nabs(aod::femtouniverseparticle::eta) < ConfEtaMax; /// Histogramming for particle 1 @@ -64,13 +64,13 @@ struct femtoUniversePairTaskTrackTrackMcTruth { /// Particle 2 Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 211, "Particle 2 - PDG code"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 333, "Particle 2 - PDG code"}; Configurable ConfNoPDGPartTwo{"ConfNoPDGPartTwo", false, "0: selecting part by PDG, 1: no PID selection"}; Configurable ConfPtLowPart2{"ConfPtLowPart2", 0.2, "Lower limit for Pt for the second particle"}; Configurable ConfPtHighPart2{"ConfPtHighPart2", 2.5, "Higher limit for Pt for the second particle"}; /// Partition for particle 2 - Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (ConfNoPDGPartTwo || aod::femtouniverseparticle::pidcut == uint32_t(ConfPDGCodePartTwo)) && + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && aod::femtouniverseparticle::pt < ConfPtHighPart2 && aod::femtouniverseparticle::pt > ConfPtLowPart2&& nabs(aod::femtouniverseparticle::eta) < ConfEtaMax; /// Histogramming for particle 2 @@ -161,13 +161,17 @@ struct femtoUniversePairTaskTrackTrackMcTruth { /// Histogramming same event for (auto& part : groupPartsOne) { - + if (!ConfNoPDGPartOne && part.pidcut() != ConfPDGCodePartOne) { + continue; + } trackHistoPartOne.fillQA(part); } if (!ConfIsSame) { for (auto& part : groupPartsTwo) { - + if (!ConfNoPDGPartTwo && part.pidcut() != ConfPDGCodePartTwo) { + continue; + } trackHistoPartTwo.fillQA(part); } } @@ -177,6 +181,9 @@ struct femtoUniversePairTaskTrackTrackMcTruth { if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } + if ((!ConfNoPDGPartOne && p2.pidcut() != ConfPDGCodePartOne) || (!ConfNoPDGPartTwo && p1.pidcut() != ConfPDGCodePartTwo)) { + continue; + } if (swpart) sameEventCont.setPair(p1, p2, multCol, ConfUse3D); else @@ -218,6 +225,9 @@ struct femtoUniversePairTaskTrackTrackMcTruth { fNeventsProcessed++; for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if ((!ConfNoPDGPartOne && p2.pidcut() != ConfPDGCodePartOne) || (!ConfNoPDGPartTwo && p1.pidcut() != ConfPDGCodePartTwo)) { + continue; + } if (swpart) mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); else diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx index ff1761f8fb4..c762393af6d 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx @@ -65,9 +65,10 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { /// Table for both particles struct : o2::framework::ConfigurableGroup { - Configurable ConfNsigmaCombined{"ConfNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > ConfTOFPtMin"}; - Configurable ConfNsigmaTPC{"ConfNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < ConfTOFPtMin"}; - Configurable ConfTOFPtMin{"ConfTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; + Configurable IsKaonNsigma{"IsKaonNsigma", false, "Enable a strict cut selection for K+ and K-"}; + Configurable ConfNsigmaCombined{"ConfNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > ConfTOFpMin"}; + Configurable ConfNsigmaTPC{"ConfNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < ConfTOFpMin"}; + Configurable ConfTOFpMin{"ConfTOFpMin", 0.5f, "Min. momentum for which TOF is required for PID."}; Configurable ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; @@ -75,9 +76,35 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; - } twotracksconfigs; + /// Table for separate deuteron configurables + struct : o2::framework::ConfigurableGroup { + Configurable ConfNsigmaTPCDe{"ConfNsigmaTPCDe", 2.0f, "TPC Deuteron Sigma for momentum < ConfTOFpMinDe"}; + Configurable ConfNsigmaTOFDe{"ConfNsigmaTOFDe", 2.0f, "TOF Deuteron Sigma"}; + Configurable ConfTOFpMinDe{"ConfTOFpMinDe", 0.5f, "Min. momentum for deuterons for which TOF is required for PID"}; + Configurable ConfPLowDe{"ConfPLowDe", 0.8f, "Lower limit for momentum for deuterons"}; + Configurable ConfPHighDe{"ConfPHighDe", 1.8f, "Higher limit for momentum for deuterons"}; + } deuteronconfigs; + + /// Table for linear cut for TPC Deuteron Sigma + struct : o2::framework::ConfigurableGroup { + Configurable ConfIsLine{"ConfIsLine", false, "Enable a separation line for clearer TPC Deuteron Sigma"}; + Configurable pLow{"pLow", 0.0f, "Lower limit of momentum for linear cut of TPC Deuteron Sigma"}; + Configurable pHigh{"pHigh", 1.4f, "Higher limit of momentum for linear cut of TPC Deuteron Sigma"}; + Configurable a{"a", -167.0f, "Parameter 'a' of a linear function 'y = a * x + b'"}; + Configurable b{"b", 300.0f, "Parameter 'b' of a linear function 'y = a * x + b'"}; + } lincut; + + /// Table for polynomial 3 cut for TPC Deuteron Sigma + struct : o2::framework::ConfigurableGroup { + Configurable ConfIsPol{"ConfIsPol", false, "Enable a separation polynomial 3 curve for clearer TPC Deuteron Sigma"}; + Configurable A{"A", -52.2f, "Parameter 'A' of a polynomial function 'y = A * x^3 + B * x^2 + C * x + D'"}; + Configurable B{"B", 357.7f, "Parameter 'B' of a polynomial function 'y = A * x^3 + B * x^2 + C * x + D'"}; + Configurable C{"C", -834.7f, "Parameter 'C' of a polynomial function 'y = A * x^3 + B * x^2 + C * x + D'"}; + Configurable D{"D", 705.8f, "Parameter 'D' of a polynomial function 'y = A * x^3 + B * x^2 + C * x + D'"}; + } polcut; + using FemtoFullParticles = soa::Join; // Filters for selecting particles (both p1 and p2) Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.ConfEtaMax); // example filtering on configurable @@ -89,38 +116,36 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { /// Particle 1 struct : o2::framework::ConfigurableGroup { - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 211, "Particle 1 - PDG code"}; - // Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; - Configurable ConfPIDPartOne{"ConfPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> - Configurable ConfPtLowPart1{"ConfPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 211, "Particle 1 -- PDG code"}; + // Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 -- Selection bit from cutCulator"}; + Configurable ConfPIDPartOne{"ConfPIDPartOne", 2, "Particle 1 -- Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable ConfpLowPart1{"ConfpLowPart1", 0.14, "Lower limit for Pt for the first particle"}; Configurable ConfPtHighPart1{"ConfPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; Configurable ConfChargePart1{"ConfChargePart1", 1, "Particle 1 sign"}; } trackonefilter; /// Partition for particle 1 - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfPtLowPart1; + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfpLowPart1; - Partition> partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfPtLowPart1; - // + Partition> partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfpLowPart1; /// Histogramming for particle 1 FemtoUniverseParticleHisto trackHistoPartOne; /// Particle 2 struct : o2::framework::ConfigurableGroup { - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 211, "Particle 2 - PDG code"}; - // Configurable ConfCutPartTwo{"ConfCutPartTwo", 5542474, "Particle 2 - Selection bit"}; - Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> - - Configurable ConfPtLowPart2{"ConfPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 211, "Particle 2 -- PDG code"}; + // Configurable ConfCutPartTwo{"ConfCutPartTwo", 5542474, "Particle 2 -- Selection bit"}; + Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 2, "Particle 2 -- Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + Configurable ConfpLowPart2{"ConfpLowPart2", 0.14, "Lower limit for Pt for the second particle"}; Configurable ConfPtHighPart2{"ConfPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; Configurable ConfChargePart2{"ConfChargePart2", -1, "Particle 2 sign"}; } tracktwofilter; /// Partition for particle 2 - Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfPtLowPart2; + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfpLowPart2; - Partition> partsTwoMC = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfPtLowPart2; + Partition> partsTwoMC = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfpLowPart2; /// Histogramming for particle 2 FemtoUniverseParticleHisto trackHistoPartTwo; @@ -169,12 +194,13 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { Configurable ConfCPRdeltaEtaCutMin{"ConfCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"}; Configurable ConfCPRChosenRadii{"ConfCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; - Configurable cfgProcessPM{"cfgProcessPM", false, "Process particles of the opposite charge"}; - Configurable cfgProcessPP{"cfgProcessPP", true, "Process particles of the same, positice charge"}; - Configurable cfgProcessMM{"cfgProcessMM", true, "Process particles of the same, positice charge"}; - Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; - Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; - Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and Mult bins"}; + Configurable IsPairIdentical{"IsPairIdentical", true, "'true' for identical particles, 'false' for non-identical particles"}; + Configurable cfgProcessPM{"cfgProcessPM", true, "Process differently charged particles (plus-minus)"}; + Configurable cfgProcessPP{"cfgProcessPP", true, "Process positively charged particles (plus-plus)"}; + Configurable cfgProcessMM{"cfgProcessMM", true, "Process negatively charged particles (minus-minus)"}; + Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms (in multiplicity bins)"}; + Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if 'cfgProcessMultBins' is false, it will not be processed regardless of 'cfgProcessKtBins' state)"}; + Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and MultBins"}; FemtoUniverseFemtoContainer sameEventCont; FemtoUniverseFemtoContainer mixedEventCont; @@ -220,122 +246,142 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { HistogramRegistry sphericityRegistry{"SphericityHisto", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // PID for protons - bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + /// TPC Pion/Kaon/Proton Sigma selection (general) + bool IsNSigma(float mom, float nsigmaTPC, float nsigmaTOF) { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 + // |nsigma_TPC| < 3 for p < 0.5 GeV/c + // |nsigma_combined| < 3 for p > 0.5 // using configurables: - // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed - // ConfNsigmaTPC -> TPC Sigma for momentum < 0.5 - // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 + // ConfTOFpMin -- momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPC -> TPC Sigma for momentum < ConfTOFpMin + // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > ConfTOFpMin + + if (mom < twotracksconfigs.ConfTOFpMin) { + return TMath::Abs(nsigmaTPC) < twotracksconfigs.ConfNsigmaTPC; + } else { + return TMath::Hypot(nsigmaTOF, nsigmaTPC) < twotracksconfigs.ConfNsigmaCombined; + } + } - if (mom < twotracksconfigs.ConfTOFPtMin) { - if (TMath::Abs(nsigmaTPCPr) < twotracksconfigs.ConfNsigmaTPC) { - return true; + /// TPC Kaon Sigma selection (stricter cuts for K+ and K-) -- based on Run2 results + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + if (twotracksconfigs.IsKaonNsigma == true) { + if (mom < 0.4) { + return TMath::Abs(nsigmaTPCK) < 2; + } else if (mom > 0.4 && mom < 0.45) { + return TMath::Abs(nsigmaTPCK) < 1; + } else if (mom > 0.45 && mom < 0.8) { + return (TMath::Abs(nsigmaTPCK) < 3 && TMath::Abs(nsigmaTOFK) < 2); + } else if (mom > 0.8 && mom < 1.5) { + return (TMath::Abs(nsigmaTPCK) < 3 && TMath::Abs(nsigmaTOFK) < 1.5); } else { return false; } } else { - if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.ConfNsigmaCombined) { - return true; + return IsNSigma(mom, nsigmaTPCK, nsigmaTOFK); + } + } + + /// TPC Deuteron Sigma selection + bool IsDeuteronNSigma(float mom, float nsigmaTPCDe, float nsigmaTOFDe) + { + if (mom > deuteronconfigs.ConfPLowDe && mom < deuteronconfigs.ConfPHighDe) { + if (mom < deuteronconfigs.ConfTOFpMinDe) { + return TMath::Abs(nsigmaTPCDe) < deuteronconfigs.ConfNsigmaTPCDe; } else { - return false; + return (TMath::Abs(nsigmaTOFDe) < deuteronconfigs.ConfNsigmaTOFDe && (TMath::Abs(nsigmaTPCDe) < deuteronconfigs.ConfNsigmaTPCDe)); } + } else { + return false; } - return false; } - bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + /// Linear cut for clearer TPC Deuteron Sigma + bool IsDeuteronNSigmaLinearCut(float mom, float nsigmaTPCDe, float nsigmaTOFDe, float tpcSignal) { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using configurables: - // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed - // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) - // ConfNsigmaTPC -> TPC Kaon Sigma for momentum < 0.5 - // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 - if (true) { - if (mom < twotracksconfigs.ConfTOFPtMin) { - if (TMath::Abs(nsigmaTPCK) < twotracksconfigs.ConfNsigmaTPC) { - return true; + if (lincut.ConfIsLine == true) { + if (mom > lincut.pLow && mom < lincut.pHigh) { + if (tpcSignal > lincut.a * mom + lincut.b) { + return IsDeuteronNSigma(mom, nsigmaTPCDe, nsigmaTOFDe); } else { return false; } } else { - if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < twotracksconfigs.ConfNsigmaCombined) { - return true; - } else { - return false; - } + return IsDeuteronNSigma(mom, nsigmaTPCDe, nsigmaTOFDe); } + } else { + return IsDeuteronNSigma(mom, nsigmaTPCDe, nsigmaTOFDe); } - return false; } - bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + /// Polynomial 3 cut for clearer TPC Deuteron Sigma + bool IsDeuteronNSigmaPolCut(float mom, float nsigmaTPCDe, float nsigmaTOFDe, float tpcSignal) { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using configurables: - // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed - // ConfNsigmaTPC -> TPC Sigma for momentum < 0.5 - // ConfNsigmaCombined -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 - if (true) { - if (mom < twotracksconfigs.ConfTOFPtMin) { - if (TMath::Abs(nsigmaTPCPi) < twotracksconfigs.ConfNsigmaTPC) { - return true; - } else { - return false; - } + if (polcut.ConfIsPol == true) { + if (tpcSignal > polcut.A * TMath::Power(mom, 3) + polcut.B * TMath::Power(mom, 2) + polcut.C * mom + polcut.D) { + return IsDeuteronNSigma(mom, nsigmaTPCDe, nsigmaTOFDe); } else { - if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.ConfNsigmaCombined) { - return true; - } else { - return false; - } + return false; } + } else { + return IsDeuteronNSigma(mom, nsigmaTPCDe, nsigmaTOFDe); } - return false; } - bool IsParticleNSigma(int8_t particle_number, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + bool IsParticleNSigma(int8_t particle_number, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCDe, float nsigmaTOFDe, float tpcSignal) { if (particle_number == 1) { switch (trackonefilter.ConfPDGCodePartOne) { - case 2212: // Proton - case -2212: // Antiproton - return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + case 2212: // Proton+ + case -2212: // Proton- + return IsNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); break; case 211: // Pion+ case -211: // Pion- - return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + case 111: // Pion 0 + return IsNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); break; case 321: // Kaon+ case -321: // Kaon- return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); break; + case 130: // Kaon 0 LONG + case 310: // Kaon 0 SHORT + return IsNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + case 1000010020: // Deuteron+ + case -1000010020: // Deuteron- + return IsDeuteronNSigmaPolCut(mom, nsigmaTPCDe, nsigmaTOFDe, tpcSignal); + break; default: return false; } return false; } else if (particle_number == 2) { switch (tracktwofilter.ConfPDGCodePartTwo) { - case 2212: // Proton - case -2212: // Antiproton - return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + case 2212: // Proton+ + case -2212: // Proton- + return IsNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); break; case 211: // Pion+ case -211: // Pion- - return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + case 111: // Pion 0 + return IsNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); break; case 321: // Kaon+ case -321: // Kaon- return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); break; + case 130: // Kaon 0 LONG + case 310: // Kaon 0 SHORT + return IsNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + case 1000010020: // Deuteron+ + case -1000010020: // Deuteron- + return IsDeuteronNSigmaPolCut(mom, nsigmaTPCDe, nsigmaTOFDe, tpcSignal); + break; default: return false; } @@ -417,47 +463,49 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { /// This function processes the same event and takes care of all the histogramming /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - /// @tparam PartitionType - /// @tparam PartType - /// @tparam isMC: enables Monte Carlo truth specific histograms - /// @param groupPartsOne partition for the first particle passed by the process function - /// @param groupPartsTwo partition for the second particle passed by the process function - /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) - /// @param magFieldTesla magnetic field of the collision - /// @param multCol multiplicity of the collision + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + /// \param pairType describes charge of correlation pair (plus-minus (1), plus-plus (2), minus-minus (3)) + /// \param fillQA enables filling of QA histograms template - void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int ContType, bool fillQA) + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int pairType, bool fillQA) { /// Histogramming same event - if ((ContType == 1 || ContType == 2) && fillQA) { + if ((pairType == 1 || pairType == 2) && fillQA) { for (auto& part : groupPartsOne) { - if (!IsParticleNSigma((int8_t)1, part.pt(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)1, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(part, o2::track::PID::Deuteron), part.tpcSignal())) { continue; } trackHistoPartOne.fillQA(part); } } - if ((ContType == 1 || ContType == 3) && fillQA) { + if ((pairType == 1 || pairType == 3) && fillQA) { for (auto& part : groupPartsTwo) { - if (!IsParticleNSigma((int8_t)2, part.pt(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)2, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(part, o2::track::PID::Deuteron), part.tpcSignal())) { continue; } trackHistoPartTwo.fillQA(part); } } - if (ContType == 1) { + if (pairType == 1) { /// Now build the combinations for non-identical particle pairs for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (!IsParticleNSigma((int8_t)1, p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)1, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(p1, o2::track::PID::Deuteron), p1.tpcSignal())) { continue; } - if (!IsParticleNSigma((int8_t)2, p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(p2, o2::track::PID::Deuteron), p2.tpcSignal())) { continue; } @@ -483,11 +531,11 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { /// Now build the combinations for identical particles pairs for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { - if (!IsParticleNSigma((int8_t)2, p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)2, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(p1, o2::track::PID::Deuteron), p1.tpcSignal())) { continue; } - if (!IsParticleNSigma((int8_t)2, p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(p2, o2::track::PID::Deuteron), p2.tpcSignal())) { continue; } @@ -502,24 +550,44 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { continue; } - switch (ContType) { + switch (pairType) { case 2: { - float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass1); - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); + if (IsPairIdentical == true) { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass1); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); + + sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultContPP.fill(kstar, multCol, kT); + } else { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + + sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultContPP.fill(kstar, multCol, kT); + } - sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); - if (cfgProcessMultBins) - sameEventMultContPP.fill(kstar, multCol, kT); break; } case 3: { - float kstar = FemtoUniverseMath::getkstar(p1, mass2, p2, mass2); - float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); + if (IsPairIdentical == true) { + float kstar = FemtoUniverseMath::getkstar(p1, mass2, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); + + sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultContMM.fill(kstar, multCol, kT); + } else { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + + sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultContMM.fill(kstar, multCol, kT); + } - sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); - if (cfgProcessMultBins) - sameEventMultContMM.fill(kstar, multCol, kT); break; } default: @@ -589,17 +657,18 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) /// \param magFieldTesla magnetic field of the collision /// \param multCol multiplicity of the collision + /// \param pairType describes charge of correlation pair (plus-minus (1), plus-plus (2), minus-minus (3)) template - void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int ContType) + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int pairType) { for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (!IsParticleNSigma((int8_t)2, p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)2, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(p1, o2::track::PID::Deuteron), p1.tpcSignal())) { continue; } - if (!IsParticleNSigma((int8_t)2, p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(p2, o2::track::PID::Deuteron), p2.tpcSignal())) { continue; } @@ -609,30 +678,54 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { } } - switch (ContType) { + switch (pairType) { case 1: { float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); if (cfgProcessMultBins) mixedEventMultCont.fill(kstar, multCol, kT); + break; } case 2: { - float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass1); - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); - mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); - if (cfgProcessMultBins) - mixedEventMultContPP.fill(kstar, multCol, kT); + if (IsPairIdentical == true) { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass1); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); + + mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultContPP.fill(kstar, multCol, kT); + } else { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + + mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultContPP.fill(kstar, multCol, kT); + } + break; } case 3: { - float kstar = FemtoUniverseMath::getkstar(p1, mass2, p2, mass2); - float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); - mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); - if (cfgProcessMultBins) - mixedEventMultContMM.fill(kstar, multCol, kT); + if (IsPairIdentical == true) { + float kstar = FemtoUniverseMath::getkstar(p1, mass2, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); + + mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultContMM.fill(kstar, multCol, kT); + } else { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + + mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultContMM.fill(kstar, multCol, kT); + } + break; } default: @@ -642,8 +735,8 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { } /// process function for to call doMixedEvent with Data - /// @param cols subscribe to the collisions table (Data) - /// @param parts subscribe to the femtoUniverseParticleTable + /// \param cols subscribe to the collisions table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable void processMixedEvent(soa::Filtered& cols, FilteredFemtoFullParticles& parts) { @@ -679,9 +772,9 @@ struct femtoUniversePairTaskTrackTrackMultKtExtended { PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMultKtExtended, processMixedEvent, "Enable processing mixed events", true); /// brief process function for to call doMixedEvent with Monte Carlo - /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) - /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth - /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + /// \param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table void processMixedEventMC(o2::aod::FDCollisions& cols, soa::Join& parts, o2::aod::FDMCParticles&) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 6ea6b877825..8dc39769732 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -132,8 +132,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// Event part Configurable ConfV0MLow{"ConfV0MLow", 0.0, "Lower limit for V0M multiplicity"}; Configurable ConfV0MHigh{"ConfV0MHigh", 25000.0, "Upper limit for V0M multiplicity"}; - Filter collV0Mfilter = ((o2::aod::femtouniversecollision::multV0M > ConfV0MLow) && (o2::aod::femtouniversecollision::multV0M < ConfV0MHigh)); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = soa::Filtered::iterator; // Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.ConfEtaMax); // example filtering on configurable /// Particle part @@ -149,7 +150,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; - ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; ConfigurableAxis ConfkstarBins{"ConfkstarBins", {60, 0.0, 0.3}, "binning kstar"}; ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; @@ -413,7 +414,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { template void fillCollision(CollisionType col) { - MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multV0M()})); eventHisto.fillQA(col); } @@ -474,7 +475,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { continue; } float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - sameEventMultCont.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::same, 2, multCol, kT); + sameEventMultCont.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::same, 2, multCol, kT, ConfIsIden); } } else { for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { @@ -506,9 +507,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 2: { rand = randgen->Rndm(); if (rand > 0.5) { - sameEventMultContPP.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::same, 2, multCol, kT); + sameEventMultContPP.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::same, 2, multCol, kT, ConfIsIden); } else if (rand <= 0.5) { - sameEventMultContPP.fill_mult_NumDen(p2, p1, femtoUniverseSHContainer::EventType::same, 2, multCol, kT); + sameEventMultContPP.fill_mult_NumDen(p2, p1, femtoUniverseSHContainer::EventType::same, 2, multCol, kT, ConfIsIden); } break; } @@ -516,9 +517,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 3: { rand = randgen->Rndm(); if (rand > 0.5) { - sameEventMultContMM.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::same, 2, multCol, kT); + sameEventMultContMM.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::same, 2, multCol, kT, ConfIsIden); } else if (rand <= 0.5) { - sameEventMultContMM.fill_mult_NumDen(p2, p1, femtoUniverseSHContainer::EventType::same, 2, multCol, kT); + sameEventMultContMM.fill_mult_NumDen(p2, p1, femtoUniverseSHContainer::EventType::same, 2, multCol, kT, ConfIsIden); } break; } @@ -533,7 +534,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// process function for to call doSameEvent with Data /// \param col subscribe to the collision table (Data) /// \param parts subscribe to the femtoUniverseParticleTable - void processSameEvent(soa::Filtered::iterator& col, + void processSameEvent(FilteredFDCollision& col, FilteredFemtoFullParticles& parts) { fillCollision(col); @@ -544,15 +545,15 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { bool fillQA = true; if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 1, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 1, fillQA); } if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), 2, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), 2, fillQA); } if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 3, fillQA); + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 3, fillQA); } } PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEvent, "Enable processing same event", true); @@ -562,7 +563,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table void processSameEventMC(o2::aod::FDCollision& col, - soa::Join& parts, + soa::Join& /*parts*/, o2::aod::FDMCParticles&) { fillCollision(col); @@ -605,15 +606,15 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); switch (ContType) { case 1: { - mixedEventMultCont.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::mixed, 2, multCol, kT); + mixedEventMultCont.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::mixed, 2, multCol, kT, ConfIsIden); break; } case 2: { - mixedEventMultContPP.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::mixed, 2, multCol, kT); + mixedEventMultContPP.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::mixed, 2, multCol, kT, ConfIsIden); break; } case 3: { - mixedEventMultContMM.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::mixed, 2, multCol, kT); + mixedEventMultContMM.fill_mult_NumDen(p1, p2, femtoUniverseSHContainer::EventType::mixed, 2, multCol, kT, ConfIsIden); break; } default: @@ -625,12 +626,12 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// process function for to call doMixedEvent with Data /// @param cols subscribe to the collisions table (Data) /// @param parts subscribe to the femtoUniverseParticleTable - void processMixedEvent(soa::Filtered& cols, + void processMixedEvent(FilteredFDCollisions& cols, FilteredFemtoFullParticles& parts) { - for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols)) { - const int multiplicityCol = collision1.multNtr(); + const int multiplicityCol = collision1.multV0M(); MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); const auto& magFieldTesla1 = collision1.magField(); @@ -661,8 +662,8 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// process function for to fill covariance histograms /// \param col subscribe to the collision table (Data) /// \param parts subscribe to the femtoUniverseParticleTable - void processCov(soa::Filtered::iterator& col, - FilteredFemtoFullParticles& parts) + void processCov(soa::Filtered::iterator& /*col*/, + FilteredFemtoFullParticles& /*parts*/) { int JMax = (ConfLMax + 1) * (ConfLMax + 1); if (cfgProcessMM) { @@ -685,12 +686,12 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table void processMixedEventMC(o2::aod::FDCollisions& cols, - soa::Join& parts, + soa::Join& /*parts*/, o2::aod::FDMCParticles&) { - for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols)) { - const int multiplicityCol = collision1.multNtr(); + const int multiplicityCol = collision1.multV0M(); MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); const auto& magFieldTesla1 = collision1.magField(); diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index f5ca99cba5c..b542eff0cbe 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -28,6 +28,9 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" #include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include using namespace o2; using namespace o2::soa; @@ -35,13 +38,23 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::analysis::femtoUniverse; using namespace o2::aod::pidutils; +using namespace o2::track; struct femtoUniversePairTaskTrackV0Extended { + Service pdgMC; + SliceCache cache; using FemtoFullParticles = soa::Join; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + using FemtoRecoParticles = soa::Join; + Preslice perColMC = aod::femtouniverseparticle::fdCollisionId; + + /// To apply narrow cut + Configurable ConfZVertexCut{"ConfZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + Configurable ConfEta{"ConfEta", 0.8, "Eta cut for the global track"}; + /// Particle 1 (track) Configurable ConfTrkPDGCodePartOne{"ConfTrkPDGCodePartOne", 211, "Particle 1 (Track) - PDG code"}; Configurable ConfTrackChoicePartOne{"ConfTrackChoicePartOne", 1, "0:Proton, 1:Pion, 2:Kaon"}; @@ -54,8 +67,14 @@ struct femtoUniversePairTaskTrackV0Extended { Configurable ConfNsigmaTPCParticle{"ConfNsigmaTPCParticle", 3.0, "TPC Sigma for particle momentum < Confmom"}; Configurable ConfNsigmaCombinedParticle{"ConfNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle momentum > Confmom"}; + Filter collisionFilter = (nabs(aod::collision::posZ) < ConfZVertexCut); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + /// Partition for particle 1 - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == ConfChargePart1 && aod::femtouniverseparticle::pt < ConfHPtPart1 && aod::femtouniverseparticle::pt > ConfLPtPart1; + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == ConfChargePart1) && (nabs(aod::femtouniverseparticle::eta) < ConfEta) && (aod::femtouniverseparticle::pt < ConfHPtPart1) && (aod::femtouniverseparticle::pt > ConfLPtPart1); + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (nabs(aod::femtouniverseparticle::eta) < ConfEta) && (aod::femtouniverseparticle::pt < ConfHPtPart1) && (aod::femtouniverseparticle::pt > ConfLPtPart1); + Partition partsOneMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == ConfChargePart1) && (nabs(aod::femtouniverseparticle::eta) < ConfEta) && (aod::femtouniverseparticle::pt < ConfHPtPart1) && (aod::femtouniverseparticle::pt > ConfLPtPart1); /// Histogramming for particle 1 FemtoUniverseParticleHisto trackHistoPartOnePos; @@ -75,7 +94,9 @@ struct femtoUniversePairTaskTrackV0Extended { Configurable ConfLPtPart2{"ConfLPtPart2", 0.3f, "lower limit for pt of particle 2"}; /// Partition for particle 2 - Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && aod::femtouniverseparticle::pt < ConfHPtPart2 && aod::femtouniverseparticle::pt > ConfLPtPart2; + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && (aod::femtouniverseparticle::pt < ConfHPtPart2) && (aod::femtouniverseparticle::pt > ConfLPtPart2); + Partition partsTwoMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pt < ConfHPtPart2) && (aod::femtouniverseparticle::pt > ConfLPtPart2); + Partition partsTwoMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && (aod::femtouniverseparticle::pt < ConfHPtPart2) && (aod::femtouniverseparticle::pt > ConfLPtPart2); /// Histogramming for particle 2 FemtoUniverseParticleHisto trackHistoPartTwo; @@ -94,8 +115,9 @@ struct femtoUniversePairTaskTrackV0Extended { /// Correlation part // Configurable ConfTrackChoicePartTwo{"ConfTrackChoicePartTwo", 1, "0:Proton, 1:Pion, 2:Kaon"}; //not used - Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"}; Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable ConfUseCent{"ConfUseCent", false, "Use centrality in place of multiplicity"}; ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; @@ -113,6 +135,9 @@ struct femtoUniversePairTaskTrackV0Extended { ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; ConfigurableAxis ConfmultBins3D{"ConfMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + // Efficiency + Configurable ConfLocalEfficiency{"ConfLocalEfficiency", "", "Local path to efficiency .root file"}; + static constexpr UInt_t V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; // Table to select the V0 children FemtoUniverseContainer sameEventCont; @@ -124,21 +149,19 @@ struct femtoUniversePairTaskTrackV0Extended { /// Histogram output HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registryMCtruth{"MCtruthHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryMCreco{"MCrecoHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + std::unique_ptr plocalEffFile; + std::unique_ptr plocalEffp1; + std::unique_ptr plocalEffp2; bool IsNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) { if (mom <= Confmom) { - if (TMath::Abs(nsigmaTPCParticle) < ConfNsigmaTPCParticle) { - return true; - } else { - return false; - } + return (TMath::Abs(nsigmaTPCParticle) < ConfNsigmaTPCParticle); } else { - if (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < ConfNsigmaCombinedParticle) { - return true; - } else { - return false; - } + return (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < ConfNsigmaCombinedParticle); } } @@ -180,10 +203,10 @@ struct femtoUniversePairTaskTrackV0Extended { void init(InitContext&) { eventHisto.init(&qaRegistry); - qaRegistry.add("Tracks_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - qaRegistry.add("Tracks_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - qaRegistry.add("Tracks_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - qaRegistry.add("Tracks_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + qaRegistry.add("Tracks_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Tracks_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Tracks_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Tracks_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); trackHistoPartOnePos.init(&qaRegistry, ConfTrkTempFitVarpTBins, ConfTrkTempFitVarBins, ConfIsMC, ConfTrkPDGCodePartOne); trackHistoPartOneNeg.init(&qaRegistry, ConfTrkTempFitVarpTBins, ConfTrkTempFitVarBins, ConfIsMC, ConfTrkPDGCodePartOne); trackHistoPartTwo.init(&qaRegistry, ConfV0TempFitVarpTBins, ConfV0TempFitVarBins, ConfIsMC, ConfV0PDGCodePartTwo, true); @@ -197,6 +220,46 @@ struct femtoUniversePairTaskTrackV0Extended { posChildV0Type2.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, 0, true, "posChildV0Type2"); negChildV0Type2.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, 0, true, "negChildV0Type2"); + // MC truth + registryMCtruth.add("plus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("minus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("plus/MCtruthAllPt", "MC truth all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthAllPt", "MC truth all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + + registryMCtruth.add("plus/MCtruthPi", "MC truth pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("plus/MCtruthPr", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("minus/MCtruthPi", "MC truth pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("minus/MCtruthPr", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("plus/MCtruthPiPt", "MC truth pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("plus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthPiPt", "MC truth pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + // MC reco + registryMCreco.add("plus/MCrecoLambda", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("plus/MCrecoLambdaChildPr", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("plus/MCrecoLambdaChildPi", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoLambda", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoLambdaChildPr", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoLambdaChildPi", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCreco.add("plus/MCrecoAllPt", "MC reco all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("minus/MCrecoAllPt", "MC reco all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + + registryMCreco.add("plus/MCrecoPi", "MC reco pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("plus/MCrecoPr", "MC reco protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCreco.add("minus/MCrecoPi", "MC reco pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoPr", "MC reco protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCreco.add("plus/MCrecoPiPt", "MC reco pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("plus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("minus/MCrecoPiPt", "MC reco pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("minus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, ConfIsMC, ConfUse3D); sameEventCont.setPDGCodes(ConfTrkPDGCodePartOne, ConfV0PDGCodePartTwo); mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, ConfIsMC, ConfUse3D); @@ -208,15 +271,29 @@ struct femtoUniversePairTaskTrackV0Extended { pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiCutMin.value, ConfCPRdeltaPhiCutMax.value, ConfCPRdeltaEtaCutMin.value, ConfCPRdeltaEtaCutMax.value, ConfCPRChosenRadii.value, ConfCPRPlotPerRadii.value); pairCloseRejectionV0.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiCutMin.value, ConfCPRdeltaPhiCutMax.value, ConfCPRdeltaEtaCutMin.value, ConfCPRdeltaEtaCutMax.value, ConfCPRChosenRadii.value, ConfCPRPlotPerRadii.value); } + + if (!ConfLocalEfficiency.value.empty()) { + plocalEffFile = std::unique_ptr(TFile::Open(ConfLocalEfficiency.value.c_str(), "read")); + if (!plocalEffFile || plocalEffFile.get()->IsZombie()) + LOGF(fatal, "Could not load efficiency histogram from %s", ConfLocalEfficiency.value.c_str()); + if (doprocessSameEvent || doprocessMixedEvent) { + plocalEffp1 = (ConfChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + plocalEffp2 = (ConfV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + LOGF(info, "Loaded efficiency histograms for track-V0."); + } else if (doprocessSameEventV0 || doprocessMixedEventV0) { + plocalEffp1 = (ConfV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + plocalEffp2 = (ConfV0Type2 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + LOGF(info, "Loaded efficiency histograms for V0-V0."); + } + } } /// This function processes the same event for track - V0 - void processSameEvent(o2::aod::FDCollision& col, FemtoFullParticles& parts) + template + void doSameEvent(FilteredFDCollision& col, PartType& parts, PartitionType& groupPartsOne, PartitionType& groupPartsTwo, [[maybe_unused]] MCParticles mcParts = nullptr) { const auto& magFieldTesla = col.magField(); - auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - const int multCol = col.multNtr(); + const int multCol = ConfUseCent ? col.multV0M() : col.multNtr(); eventHisto.fillQA(col); @@ -258,6 +335,9 @@ struct femtoUniversePairTaskTrackV0Extended { // Lambda invariant mass cut if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) continue; + /// PID using stored binned nsigma + if (!IsParticleCombined(p1, ConfTrackChoicePartOne)) + continue; // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; @@ -267,9 +347,6 @@ struct femtoUniversePairTaskTrackV0Extended { continue; } } - /// PID using stored binned nsigma - if (!IsParticleCombined(p1, ConfTrackChoicePartOne)) - continue; const auto& posChild = parts.iteratorAt(p2.index() - 2); const auto& negChild = parts.iteratorAt(p2.index() - 1); @@ -277,19 +354,39 @@ struct femtoUniversePairTaskTrackV0Extended { if (!IsParticleTPC(posChild, V0ChildTable[ConfV0Type1][0]) || !IsParticleTPC(negChild, V0ChildTable[ConfV0Type1][1])) continue; - sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + float weight = 1.0f; + if (plocalEffp1) + weight = plocalEffp1.get()->GetBinContent(plocalEffp1->FindBin(p1.pt(), p1.eta())) * plocalEffp2.get()->GetBinContent(plocalEffp2->FindBin(p2.pt(), p2.eta())); + if constexpr (std::is_same::value) + sameEventCont.setPair(p1, p2, multCol, ConfUse3D, weight); + else + sameEventCont.setPair(p1, p2, multCol, ConfUse3D, weight); } } + void processSameEvent(FilteredFDCollision& col, FemtoFullParticles& parts) + { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo); + } PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processSameEvent, "Enable processing same event for track - V0", false); + void processSameEventMCReco(FilteredFDCollision& col, FemtoRecoParticles& parts, aod::FDMCParticles const& mcparts) + { + auto groupPartsOne = partsOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, mcparts); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processSameEventMCReco, "Enable processing same event for track - V0 MC Reco", false); + /// This function processes the same event for V0 - V0 - void processSameEventV0(o2::aod::FDCollision& col, FemtoFullParticles& parts) + void processSameEventV0(FilteredFDCollision& col, FemtoFullParticles& parts) { const auto& magFieldTesla = col.magField(); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - const int multCol = col.multNtr(); + const int multCol = ConfUseCent ? col.multV0M() : col.multNtr(); eventHisto.fillQA(col); @@ -314,52 +411,116 @@ struct femtoUniversePairTaskTrackV0Extended { } } - /// Now build the combinations - for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { // Lambda invariant mass cut for p1 if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) - continue; + return; // Lambda invariant mass cut for p2 if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) - continue; + return; // track cleaning if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { - continue; + return; } if (ConfIsCPR.value) { if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femtoUniverseContainer::EventType::same)) { - continue; + return; } } const auto& posChild1 = parts.iteratorAt(p1.index() - 2); const auto& negChild1 = parts.iteratorAt(p1.index() - 1); /// Daughters that do not pass this condition are not selected if (!IsParticleTPC(posChild1, V0ChildTable[ConfV0Type1][0]) || !IsParticleTPC(negChild1, V0ChildTable[ConfV0Type1][1])) - continue; + return; const auto& posChild2 = parts.iteratorAt(p2.index() - 2); const auto& negChild2 = parts.iteratorAt(p2.index() - 1); /// Daughters that do not pass this condition are not selected if (!IsParticleTPC(posChild2, V0ChildTable[ConfV0Type2][0]) || !IsParticleTPC(negChild2, V0ChildTable[ConfV0Type2][1])) - continue; + return; sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + }; + if (ConfV0Type1 == ConfV0Type2) { + /// Now build the combinations for identical V0s + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } else { + /// Now build the combinations for not identical identical V0s + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } } } PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processSameEventV0, "Enable processing same event for V0 - V0", false); + void processMCSameEvent(FilteredFDCollision& col, FemtoFullParticles& parts) + { + const auto& magFieldTesla = col.magField(); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + const int multCol = ConfUseCent ? col.multV0M() : col.multNtr(); + + eventHisto.fillQA(col); + + /// Histogramming same event + for (auto& part : groupPartsTwo) { + int pdgCode = static_cast(part.pidcut()); + if ((ConfV0Type1 == 0 && pdgCode != 3122) || (ConfV0Type1 == 1 && pdgCode != -3122)) + continue; + trackHistoPartTwo.fillQA(part); + } + + for (auto& part : groupPartsOne) { + int pdgCode = static_cast(part.pidcut()); + if (pdgCode != ConfTrkPDGCodePartOne) + continue; + const auto& pdgParticle = pdgMC->GetParticle(pdgCode); + if (!pdgParticle) { + continue; + } + /// PID plot for particle 1 + if (pdgParticle->Charge() > 0.0) { + trackHistoPartOnePos.fillQA(part); + } else if (pdgParticle->Charge() < 0.0) { + trackHistoPartOneNeg.fillQA(part); + } + } + + /// Now build the combinations + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (static_cast(p1.pidcut()) != ConfTrkPDGCodePartOne) + continue; + int pdgCode2 = static_cast(p2.pidcut()); + if ((ConfV0Type1 == 0 && pdgCode2 != 3122) || (ConfV0Type1 == 1 && pdgCode2 != -3122)) + continue; + // track cleaning + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femtoUniverseContainer::EventType::same)) { + continue; + } + } + sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMCSameEvent, "Enable processing same event for MC truth track - V0", false); + /// This function processes the mixed event for track - V0 - void processMixedEvent(o2::aod::FDCollisions& cols, FemtoFullParticles& parts) + template + void doMixedEvent(FilteredFDCollisions& cols, PartType& parts, PartitionType& partitionOne, PartitionType& partitionTwo, [[maybe_unused]] MCParticles mcParts = nullptr) { ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { - const int multCol = collision1.multNtr(); + const int multCol = ConfUseCent ? collision1.multV0M() : collision1.multNtr(); - auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsOne = partitionOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partitionTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -372,39 +533,57 @@ struct femtoUniversePairTaskTrackV0Extended { // Lambda invariant mass cut if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) continue; - // track cleaning - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } - if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femtoUniverseContainer::EventType::mixed)) { - continue; - } - } /// PID using stored binned nsigma if (!IsParticleCombined(p1, ConfTrackChoicePartOne)) continue; + const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2); const auto& negChild = parts.iteratorAt(p2.globalIndex() - 1); /// Daughters that do not pass this condition are not selected if (!IsParticleTPC(posChild, V0ChildTable[ConfV0Type1][0]) || !IsParticleTPC(negChild, V0ChildTable[ConfV0Type1][1])) continue; - mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femtoUniverseContainer::EventType::mixed)) { + continue; + } + } + float weight = 1.0f; + if (plocalEffp1) + weight = plocalEffp1.get()->GetBinContent(plocalEffp1->FindBin(p1.pt(), p1.eta())) * plocalEffp2.get()->GetBinContent(plocalEffp2->FindBin(p2.pt(), p2.eta())); + + if constexpr (std::is_same::value) + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D, weight); + else + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D, weight); } } } - PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMixedEvent, "Enable processing mixed events for track - V0", false); + void processMixedEvent(FilteredFDCollisions& cols, FemtoFullParticles& parts) + { + doMixedEvent(cols, parts, partsOne, partsTwo); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMixedEvent, "Enable processing mixed event for track - V0", false); + + void processMixedEventMCReco(FilteredFDCollisions& cols, FemtoRecoParticles& parts, aod::FDMCParticles const& mcparts) + { + doMixedEvent(cols, parts, partsOneMCReco, partsTwoMCReco, mcparts); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMixedEventMCReco, "Enable processing mixed event for track - V0 for MC Reco", false); /// This function processes the mixed event for V0 - V0 - void processMixedEventV0(o2::aod::FDCollisions& cols, FemtoFullParticles& parts) + void processMixedEventV0(FilteredFDCollisions& cols, FemtoFullParticles& parts) { ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { - const int multCol = collision1.multNtr(); + const int multCol = ConfUseCent ? collision1.multV0M() : collision1.multNtr(); auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); @@ -423,15 +602,7 @@ struct femtoUniversePairTaskTrackV0Extended { // Lambda invariant mass cut for p2 if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) continue; - // track cleaning - if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { - continue; - } - if (ConfIsCPR.value) { - if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femtoUniverseContainer::EventType::mixed)) { - continue; - } - } + const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 2); const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 1); /// Daughters that do not pass this condition are not selected @@ -444,12 +615,174 @@ struct femtoUniversePairTaskTrackV0Extended { if (!IsParticleTPC(posChild2, V0ChildTable[ConfV0Type2][0]) || !IsParticleTPC(negChild2, V0ChildTable[ConfV0Type2][1])) continue; + // track cleaning + if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { + continue; + } + if (ConfIsCPR.value) { + if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femtoUniverseContainer::EventType::mixed)) { + continue; + } + } mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); } } } - PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMixedEventV0, "Enable processing mixed events for V0 - V0", false); + + void processMCMixedEvent(FilteredFDCollisions& cols, FemtoFullParticles& parts) + { + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multCol = ConfUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (static_cast(p1.pidcut()) != ConfTrkPDGCodePartOne) + continue; + int pdgCode2 = static_cast(p2.pidcut()); + if ((ConfV0Type1 == 0 && pdgCode2 != 3122) || (ConfV0Type1 == 1 && pdgCode2 != -3122)) + continue; + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femtoUniverseContainer::EventType::mixed)) { + continue; + } + } + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMCMixedEvent, "Enable processing mixed events for MC truth track - V0", false); + + ///--------------------------------------------MC-------------------------------------------------/// + + /// This function fills MC truth particles from derived MC table + void processMCTruth(aod::FDParticles const& parts) + { + for (auto& part : parts) { + if (part.partType() != uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) + continue; + + int pdgCode = static_cast(part.pidcut()); + const auto& pdgParticle = pdgMC->GetParticle(pdgCode); + if (!pdgParticle) { + continue; + } + + if (pdgCode == 3122) { + registryMCtruth.fill(HIST("plus/MCtruthLambda"), part.pt(), part.eta()); + continue; + } else if (pdgCode == -3122) { + registryMCtruth.fill(HIST("minus/MCtruthLambda"), part.pt(), part.eta()); + continue; + } + + if (pdgParticle->Charge() > 0.0) { + registryMCtruth.fill(HIST("plus/MCtruthAllPt"), part.pt()); + } + if (pdgCode == 211) { + registryMCtruth.fill(HIST("plus/MCtruthPi"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("plus/MCtruthPiPt"), part.pt()); + } + if (pdgCode == 2212) { + registryMCtruth.fill(HIST("plus/MCtruthPr"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("plus/MCtruthPrPt"), part.pt()); + } + + if (pdgParticle->Charge() < 0.0) { + registryMCtruth.fill(HIST("minus/MCtruthAllPt"), part.pt()); + } + if (pdgCode == -211) { + registryMCtruth.fill(HIST("minus/MCtruthPi"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("minus/MCtruthPiPt"), part.pt()); + } + if (pdgCode == -2212) { + registryMCtruth.fill(HIST("minus/MCtruthPr"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("minus/MCtruthPrPt"), part.pt()); + } + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMCTruth, "Process MC truth data", false); + + void processMCReco(FemtoRecoParticles const& parts, aod::FDMCParticles const& mcparts) + { + for (auto& part : parts) { + auto mcPartId = part.fdMCParticleId(); + if (mcPartId == -1) + continue; // no MC particle + const auto& mcpart = mcparts.iteratorAt(mcPartId); + // + if (part.partType() == aod::femtouniverseparticle::ParticleType::kV0) { + if (mcpart.pdgMCTruth() == 3122) { + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); + /// Daughters that do not pass this condition are not selected + if (IsParticleTPC(posChild, 0) && IsParticleTPC(negChild, 1)) { + registryMCreco.fill(HIST("plus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // lambda + if (auto mcpartIdChild = posChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("plus/MCrecoLambdaChildPr"), mcpartChild.pt(), mcpartChild.eta()); // lambda proton child + } + if (auto mcpartIdChild = negChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("plus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // lambda pion child + } + } + } else if (mcpart.pdgMCTruth() == -3122) { + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); + /// Daughters that do not pass this condition are not selected + if (IsParticleTPC(posChild, 1) && IsParticleTPC(negChild, 0)) { + registryMCreco.fill(HIST("minus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // anti-lambda + if (auto mcpartIdChild = posChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("minus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // anti-lambda pion child + } + if (auto mcpartIdChild = negChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("minus/MCrecoLambdaChildPr"), mcpartChild.pt(), mcpartChild.eta()); // anti-lambda proton child + } + } + } + } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { + if (part.sign() > 0) { + registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); + if (mcpart.pdgMCTruth() == 211 && IsNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tofNSigmaStorePi()))) { + registryMCreco.fill(HIST("plus/MCrecoPi"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("plus/MCrecoPiPt"), mcpart.pt()); + } else if (mcpart.pdgMCTruth() == 2212 && IsNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) { + registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); + } + } + + if (part.sign() < 0) { + registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); + if (mcpart.pdgMCTruth() == -211 && IsNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tofNSigmaStorePi()))) { + registryMCreco.fill(HIST("minus/MCrecoPi"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("minus/MCrecoPiPt"), mcpart.pt()); + } else if (mcpart.pdgMCTruth() == -2212 && IsNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) { + registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); + } + } + } // partType + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackV0Extended, processMCReco, "Process MC reco data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldPhiSelection.h b/PWGCF/FemtoWorld/Core/FemtoWorldPhiSelection.h index e6581daaa13..39040d70ec0 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldPhiSelection.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldPhiSelection.h @@ -388,7 +388,7 @@ void FemtoWorldPhiSelection::initPhi(HistogramRegistry* registry) } template -bool FemtoWorldPhiSelection::isSelectedMinimal(C const& col, V const& v0, T const& posTrack, T const& negTrack) +bool FemtoWorldPhiSelection::isSelectedMinimal(C const& /*col*/, V const& v0, T const& posTrack, T const& negTrack) { const auto signPos = posTrack.sign(); const auto signNeg = negTrack.sign(); @@ -460,7 +460,7 @@ bool FemtoWorldPhiSelection::isSelectedMinimal(C const& col, V const& v0, T cons } template -void FemtoWorldPhiSelection::fillPhiQA(C const& col, V const& v0, T const& posTrack, T const& negTrack) +void FemtoWorldPhiSelection::fillPhiQA(C const& /*col*/, V const& v0, T const& posTrack, T const& negTrack) { const auto signPos = posTrack.sign(); const auto signNeg = negTrack.sign(); @@ -510,7 +510,7 @@ void FemtoWorldPhiSelection::fillPhiQA(C const& col, V const& v0, T const& posTr } template -void FemtoWorldPhiSelection::fillPhiQAMass(C const& col, V const& MassPhi, T const& posTrack, T const& negTrack, P const& ConfInvMassLowLimit, P const& ConfInvMassUpLimit) +void FemtoWorldPhiSelection::fillPhiQAMass(C const& /*col*/, V const& MassPhi, T const& posTrack, T const& negTrack, P const& /*ConfInvMassLowLimit*/, P const& /*ConfInvMassUpLimit*/) { const auto signPos = posTrack.sign(); const auto signNeg = negTrack.sign(); @@ -652,7 +652,7 @@ void FemtoWorldPhiSelection::fillQA(C const& /*col*/, V const& /*v0*/, T const& } template -void FemtoWorldPhiSelection::fillQAPhi(C const& col, V const& v0, T const& posTrack, T const& negTrack) +void FemtoWorldPhiSelection::fillQAPhi(C const& /*col*/, V const& v0, T const& posTrack, T const& negTrack) { if (mHistogramRegistry) { mHistogramRegistry->fill(HIST(o2::aod::femtoworldparticle::ParticleTypeName[part]) + HIST("/hPtPhi"), v0.pt()); diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index bb658dc7398..6185363ce56 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -14,8 +14,8 @@ o2physics_add_dpl_workflow(flow-pt-efficiency PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(flow-pbpb-task - SOURCES FlowPbPbTask.cxx +o2physics_add_dpl_workflow(flow-task + SOURCES FlowTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) @@ -38,3 +38,8 @@ o2physics_add_dpl_workflow(flow-pbpb-pikp-task SOURCES FlowPbPbpikp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flow-gfw-omegaxi + SOURCES flowGFWOmegaXi.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Flow/Tasks/FlowGFWPbPb.cxx b/PWGCF/Flow/Tasks/FlowGFWPbPb.cxx index 48868e86934..ef559ff23bf 100644 --- a/PWGCF/Flow/Tasks/FlowGFWPbPb.cxx +++ b/PWGCF/Flow/Tasks/FlowGFWPbPb.cxx @@ -38,6 +38,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod::track; +using namespace o2::aod::evsel; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -51,12 +53,16 @@ struct FlowGFWPbPb { O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum TPC clusters") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, false, "Use additional track cut on phi") - O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") + O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, true, "Use Nch for flow observables") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgMagnetField, std::string, "GLO/Config/GRPMagField", "CCDB path to Magnet field object") + O2_DEFINE_CONFIGURABLE(dcaZ, float, 0.2f, "Custom DCA Z cut (ignored if negative)") + O2_DEFINE_CONFIGURABLE(GlobalplusITS, bool, false, "Global and ITS tracks") + O2_DEFINE_CONFIGURABLE(Globalonly, bool, false, "Global only tracks") + O2_DEFINE_CONFIGURABLE(ITSonly, bool, true, "ITS only tracks") ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; @@ -71,11 +77,23 @@ struct FlowGFWPbPb { ConfigurableAxis axisT0A{"axisT0A", {200, 0, 200000}, "N_{ch} (T0A)"}; ConfigurableAxis axisNchPV{"axisNchPV", {4000, 0, 4000}, "N_{ch} (PV)"}; - using Colls = soa::Join; // collisions filter - using aodTracks = soa::Filtered>; // tracks filter + using Colls = soa::Filtered>; // collisions filter + using aodTracks = soa::Filtered>; // tracks filter Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + static constexpr TrackSelectionFlags::flagtype trackSelectionITS = + TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | + TrackSelectionFlags::kITSHits; + static constexpr TrackSelectionFlags::flagtype trackSelectionTPC = + TrackSelectionFlags::kTPCNCls | + TrackSelectionFlags::kTPCCrossedRowsOverNCls | + TrackSelectionFlags::kTPCChi2NDF; + static constexpr TrackSelectionFlags::flagtype trackSelectionDCA = + TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy; + static constexpr TrackSelectionFlags::flagtype trackSelectionDCAXYonly = + TrackSelectionFlags::kDCAxy; + // Corrections TH1D* mEfficiency = nullptr; GFWWeights* mAcceptance = nullptr; @@ -149,10 +167,6 @@ struct FlowGFWPbPb { registry.add("BeforeCut_globalTracks_multV0A", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); registry.add("BeforeCut_multV0A_multT0A", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); registry.add("BeforeCut_multT0C_centT0C", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); - registry.add("multITSnoTPC_vs_MultITSTPC_Bef", " multiplicity ITS vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); - registry.add("multITSonly_vs_MultITSTPC_Bef", " multiplicity ITS vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); - registry.add("multNTracksITSonly_vs_MultNTracksITSTPC_Bef", " multiplicity ITS vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); - registry.add("multNTracksTPConly_vs_MultNtracksITSTPC_Bef", " multiplicity TPC only vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); // After cuts registry.add("globalTracks_centT0C_Aft", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); @@ -162,10 +176,11 @@ struct FlowGFWPbPb { registry.add("globalTracks_multV0A_Aft", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); registry.add("multV0A_multT0A_Aft", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); registry.add("multT0C_centT0C_Aft", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); - registry.add("multITSnoTPC_vs_MultITSTPC_Aft", " multiplicity ITS vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); - registry.add("multITSonly_vs_MultITSTPC_Aft", " multiplicity ITS vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); - registry.add("multNTracksITSonly_vs_MultNTracksITSTPC_Aft", " multiplicity ITS vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); - registry.add("multNTracksTPConly_vs_MultNtracksITSTPC_Aft", " multiplicity TPC only vs multiplicity ITS+TPC", kTH2F, {axisNch, axisNch}); + + // Track types + registry.add("GlobalplusITS", "Global plus ITS;Centrality FT0C;Nch", kTH1F, {axisCentrality}); + registry.add("Globalonly", "Global only;Centrality FT0C;Nch", kTH1F, {axisCentrality}); + registry.add("ITSonly", "ITS only;Centrality FT0C;Nch", kTH1F, {axisCentrality}); // Track QA registry.add("hPt", "p_{T} distribution before cut", {HistType::kTH1D, {axisPtHist}}); @@ -433,6 +448,13 @@ struct FlowGFWPbPb { return true; } + Filter trackSelectionProperMixed = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, trackSelectionITS) && + ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), + ncheckbit(aod::track::trackCutFlag, trackSelectionTPC), true) && + ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, trackSelectionDCAXYonly), + ncheckbit(aod::track::trackCutFlag, trackSelectionDCA)); + void process(Colls::iterator const& collision, aod::BCsWithTimestamps const&, aodTracks const& tracks) { registry.fill(HIST("hEventCount"), 0.5); @@ -443,6 +465,7 @@ struct FlowGFWPbPb { if (Ntot < 1) return; + // fill event QA before cuts registry.fill(HIST("BeforeCut_globalTracks_centT0C"), collision.centFT0C(), tracks.size()); registry.fill(HIST("BeforeCut_PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); registry.fill(HIST("BeforeCut_globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); @@ -452,25 +475,6 @@ struct FlowGFWPbPb { registry.fill(HIST("BeforeCut_multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); registry.fill(HIST("hEventCount"), 1.5); - Int_t multITSnoTPC = 0, multITSonly = 0, multITSTPC = 0; - - for (auto& track : tracks) { - - if (track.hasITS() && !track.hasTPC()) - multITSnoTPC++; - - if (track.hasITS()) - multITSonly++; - - if (track.hasITS() && track.hasTPC()) - multITSTPC++; - } - - registry.fill(HIST("multITSnoTPC_vs_MultITSTPC_Bef"), multITSTPC, multITSnoTPC); - registry.fill(HIST("multITSonly_vs_MultITSTPC_Bef"), multITSTPC, multITSonly); - registry.fill(HIST("multNTracksITSonly_vs_MultNTracksITSTPC_Bef"), collision.multNTracksITSTPC(), collision.multNTracksITSOnly()); - registry.fill(HIST("multNTracksTPConly_vs_MultNtracksITSTPC_Bef"), collision.multNTracksITSTPC(), collision.multNTracksTPCOnly()); - const auto cent = collision.centFT0C(); if (cfgUseAdditionalEventCut && !eventSelected(o2::aod::mult::MultNTracksPV(), collision, tracks.size(), cent)) @@ -482,7 +486,7 @@ struct FlowGFWPbPb { float l_Random = fRndm->Rndm(); registry.fill(HIST("hVtxZ"), vtxz); registry.fill(HIST("hMult"), Ntot); - registry.fill(HIST("hCent"), collision.centFT0C()); + registry.fill(HIST("hCent"), cent); registry.fill(HIST("cent_vs_Nch"), cent, Ntot); fGFW->Clear(); @@ -490,7 +494,7 @@ struct FlowGFWPbPb { loadCorrections(bc.timestamp()); registry.fill(HIST("hEventCount"), 3.5); - // fill event QA + // fill event QA after cuts registry.fill(HIST("globalTracks_centT0C_Aft"), collision.centFT0C(), tracks.size()); registry.fill(HIST("PVTracks_centT0C_Aft"), collision.centFT0C(), collision.multNTracksPV()); registry.fill(HIST("globalTracks_PVTracks_Aft"), collision.multNTracksPV(), tracks.size()); @@ -499,11 +503,6 @@ struct FlowGFWPbPb { registry.fill(HIST("multV0A_multT0A_Aft"), collision.multFT0A(), collision.multFV0A()); registry.fill(HIST("multT0C_centT0C_Aft"), collision.centFT0C(), collision.multFT0C()); - registry.fill(HIST("multITSnoTPC_vs_MultITSTPC_Aft"), multITSTPC, multITSnoTPC); - registry.fill(HIST("multITSonly_vs_MultITSTPC_Aft"), multITSTPC, multITSonly); - registry.fill(HIST("multNTracksITSonly_vs_MultNTracksITSTPC_Aft"), collision.multAllTracksITSTPC(), collision.multNTracksITSOnly()); - registry.fill(HIST("multNTracksTPConly_vs_MultNtracksITSTPC_Aft"), collision.multAllTracksITSTPC(), collision.multNTracksTPCOnly()); - // track weights float weff = 1, wacc = 1; int Magnetfield = 0; @@ -513,6 +512,7 @@ struct FlowGFWPbPb { Magnetfield = getMagneticField(bc.timestamp()); } + // track loop for (auto& track : tracks) { if (track.tpcNClsFound() < cfgCutTPCclu) @@ -536,8 +536,23 @@ struct FlowGFWPbPb { registry.fill(HIST("hnTPCCrossedRow"), track.tpcNClsCrossedRows()); } - if (WithinPtRef) - fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); + if (GlobalplusITS == true) { + registry.fill(HIST("GlobalplusITS"), collision.centFT0C()); + if (WithinPtRef) + fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); + } + + if (track.hasTPC() && Globalonly == true) { + registry.fill(HIST("Globalonly"), collision.centFT0C()); + if (WithinPtRef) + fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); + } + + if (track.hasITS() && ITSonly == true) { + registry.fill(HIST("ITSonly"), collision.centFT0C()); + if (WithinPtRef) + fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); + } } // End of track loop @@ -562,7 +577,7 @@ struct FlowGFWPbPb { } } // End of process -}; // End of struct +}; // End of struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGCF/Flow/Tasks/FlowPbPbpikp.cxx b/PWGCF/Flow/Tasks/FlowPbPbpikp.cxx index dbe1e308b08..9ad0696091a 100644 --- a/PWGCF/Flow/Tasks/FlowPbPbpikp.cxx +++ b/PWGCF/Flow/Tasks/FlowPbPbpikp.cxx @@ -69,7 +69,7 @@ struct v2ellip { // Confugrable for QA histograms Configurable onlyTOF{"onlyTOF", false, "only TOF tracks"}; Configurable onlyTOFHIT{"onlyTOFHIT", false, "accept only TOF hit tracks at high pt"}; - Configurable onlyTPC{"onlyTPC", true, "only TPC tracks"}; + bool onlyTPC = true; // Configurables for track selections Configurable cfgCutPT{"cfgCutPT", 0.2f, "PT cut on daughter track"}; @@ -91,7 +91,6 @@ struct v2ellip { Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; Configurable TVXEvsel{"TVXEvsel", false, "Triggger selection"}; Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable MID{"MID", false, "Misidentification of tracks"}; // Configurable for histograms Configurable nBins{"nBins", 100, "N bins in all histos"}; @@ -101,8 +100,9 @@ struct v2ellip { { // Axes AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm] for plots"}; - AxisSpec axisv2ref = {5, 0, 5, "v2_{ref}"}; + AxisSpec axisv2ref = {10, 0, 10, "v2_{ref}"}; AxisSpec axisv2diff = {14, 0, 14, "v2_{def}"}; + AxisSpec axisphi = {700, 0, 7, "#phi"}; // Histograms // Event selection @@ -111,9 +111,24 @@ struct v2ellip { // v2 tprofiles for reference and differential flow histos.add("profv2ref", "profv2ref", kTProfile, {axisv2ref}); - histos.add("profv2diff_pr", "profv2diff_pr", kTProfile, {axisv2diff}); - histos.add("profv2diff_pi", "profv2diff_pi", kTProfile, {axisv2diff}); - histos.add("profv2diff_k", "profv2diff_k", kTProfile, {axisv2diff}); + histos.add("profv2diff_pr_10_20", "profv2diff_pr_10_20", kTProfile, {axisv2diff}); + histos.add("profv2diff_pi_10_20", "profv2diff_pi_10_20", kTProfile, {axisv2diff}); + histos.add("profv2diff_k_10_20", "profv2diff_k_10_20", kTProfile, {axisv2diff}); + + histos.add("profv2diff_pr_20_30", "profv2diff_pr_20_30", kTProfile, {axisv2diff}); + histos.add("profv2diff_pi_20_30", "profv2diff_pi_20_30", kTProfile, {axisv2diff}); + histos.add("profv2diff_k_20_30", "profv2diff_k_20_30", kTProfile, {axisv2diff}); + + histos.add("profv2diff_pr_30_40", "profv2diff_pr_30_40", kTProfile, {axisv2diff}); + histos.add("profv2diff_pi_30_40", "profv2diff_pi_30_40", kTProfile, {axisv2diff}); + histos.add("profv2diff_k_30_40", "profv2diff_k_30_40", kTProfile, {axisv2diff}); + + histos.add("profv2diff_pr_40_50", "profv2diff_pr_40_50", kTProfile, {axisv2diff}); + histos.add("profv2diff_pi_40_50", "profv2diff_pi_40_50", kTProfile, {axisv2diff}); + histos.add("profv2diff_k_40_50", "profv2diff_k_40_50", kTProfile, {axisv2diff}); + + // histogram for phi distribution + histos.add("hphi", "hphi", kTH1F, {axisphi}); } template @@ -129,6 +144,10 @@ struct v2ellip { template bool selectionPID(const T& candidate, int PID) { + if (candidate.pt() > 0.4) { + onlyTPC = false; + } + if (PID == 0) { if (onlyTOF) { if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < nsigmaCutTOFPi) { @@ -206,86 +225,6 @@ struct v2ellip { return false; } - template - bool MIDselectionPID(const T& candidate, int PID) - { - if (PID == 0) { - if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < 3.0) { - return true; - } - } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < 3.0) { - return true; - } - if (!candidate.hasTOF() && - std::abs(candidate.tpcNSigmaPi()) < 3.0) { - return true; - } - } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaPi()) < 3.0) { - return true; - } - } else { - if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (3.0 * 3.0)) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < 3.0) { - return true; - } - } - } else if (PID == 1) { - if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < 3.0) { - return true; - } - } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < 3.0) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < 3.0) { - return true; - } - } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaKa()) < 3.0) { - return true; - } - } else { - if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (3.0 * 3.0)) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < 3.0) { - return true; - } - } - } else if (PID == 2) { - if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < 3.0) { - return true; - } - } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < 3.0) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < 3.0) { - return true; - } - } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaPr()) < 3.0) { - return true; - } - } else { - if (candidate.hasTOF() && (candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < (3.0 * 3.0)) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < 3.0) { - return true; - } - } - } - return false; - } - // Defining filters for events (event selection) // Processed events will be already fulfilling the event selection // requirements @@ -367,113 +306,189 @@ struct v2ellip { auto atrack = Atracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto btrack = Btracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - for (auto track1 : atrack) { - if (!selectionTrack(track1)) { + for (auto track : tracks) { + if (!selectionTrack(track)) { + continue; + } + if (selectionPID(track, 0) || selectionPID(track, 1) || selectionPID(track, 2)) { // If track pion, kaon or proton + histos.fill(HIST("hphi"), track.phi()); + } else { continue; } + } // end of track loop - if (!selectionPID(track1, 0) && !selectionPID(track1, 1) && !selectionPID(track1, 2)) { + for (auto track1 : atrack) { + if (!selectionTrack(track1)) { continue; - } // If track not pion, kaon and proton then discard the track - - if (MID) { - if (MIDselectionPID(track1, 0)) { - continue; - } // misidentified as pion - if (MIDselectionPID(track1, 2)) { - continue; - } // misidentified as proton } sum_sinA += TMath::Sin(2.0 * track1.phi()); // sum of sin components of Q vector sum_cosA += TMath::Cos(2.0 * track1.phi()); // sum of cos components of Q vector multA++; // charged particle multiplicity - // pt loop for component sums of p vector, POI multiplicities pt wise - for (auto pt = 0; pt < 14; pt++) { - sum_sindsA[pt] += TMath::Sin(2 * track1.phi()); - sum_cosdsA[pt] += TMath::Cos(2 * track1.phi()); - - if (track1.pt() > ptbins[pt] && track1.pt() <= ptbins[pt + 1] && selectionPID(track1, 2)) { - pn_sumsinA_pr[pt] += TMath::Sin(2 * track1.phi()); - pn_sumcosA_pr[pt] += TMath::Cos(2 * track1.phi()); - mpA_pr[pt]++; - } else if (track1.pt() > ptbins[pt] && track1.pt() <= ptbins[pt + 1] && selectionPID(track1, 0)) { - pn_sumsinA_pi[pt] += TMath::Sin(2 * track1.phi()); - pn_sumcosA_pi[pt] += TMath::Cos(2 * track1.phi()); - mpA_pi[pt]++; - } else if (track1.pt() > ptbins[pt] && track1.pt() <= ptbins[pt + 1] && selectionPID(track1, 1)) { - pn_sumsinA_k[pt] += TMath::Sin(2 * track1.phi()); - pn_sumcosA_k[pt] += TMath::Cos(2 * track1.phi()); - mpA_k[pt]++; - } else { - continue; - } - } // end of pt loop - } // track loop ends + if (selectionPID(track1, 0) || selectionPID(track1, 1) || selectionPID(track1, 2)) { // If track pion, kaon or proton + // pt loop for component sums of p vector, POI multiplicities pt wise + for (auto pt = 0; pt < 14; pt++) { + sum_sindsA[pt] += TMath::Sin(2 * track1.phi()); + sum_cosdsA[pt] += TMath::Cos(2 * track1.phi()); + + if (track1.pt() > ptbins[pt] && track1.pt() <= ptbins[pt + 1] && selectionPID(track1, 0)) { // for pion + pn_sumsinA_pi[pt] += TMath::Sin(2 * track1.phi()); + pn_sumcosA_pi[pt] += TMath::Cos(2 * track1.phi()); + mpA_pi[pt]++; + } else if (track1.pt() > ptbins[pt] && track1.pt() <= ptbins[pt + 1] && selectionPID(track1, 1)) { // for kaon + pn_sumsinA_k[pt] += TMath::Sin(2 * track1.phi()); + pn_sumcosA_k[pt] += TMath::Cos(2 * track1.phi()); + mpA_k[pt]++; + } else if (track1.pt() > ptbins[pt] && track1.pt() <= ptbins[pt + 1] && selectionPID(track1, 2)) { // for proton + pn_sumsinA_pr[pt] += TMath::Sin(2 * track1.phi()); + pn_sumcosA_pr[pt] += TMath::Cos(2 * track1.phi()); + mpA_pr[pt]++; + } else { + continue; + } + } // end of pt loop + } else { + continue; + } + } // track loop ends for (auto track2 : btrack) { if (!selectionTrack(track2)) { continue; } - if (!selectionPID(track2, 0) && !selectionPID(track2, 1) && !selectionPID(track2, 2)) { + sum_sinB += TMath::Sin(2.0 * track2.phi()); // sum of sin components of Q vector + sum_cosB += TMath::Cos(2.0 * track2.phi()); // sum of cos components of Q vector + multB++; // charged particle multiplicity + + if (selectionPID(track2, 0) || selectionPID(track2, 1) || selectionPID(track2, 2)) { // If track pion, kaon or proton + // pt loop for component sums of p vector, POI multiplicities pt wise + for (auto pt = 0; pt < 14; pt++) { + sum_sindsB[pt] += TMath::Sin(2 * track2.phi()); + sum_cosdsB[pt] += TMath::Cos(2 * track2.phi()); + + if (track2.pt() > ptbins[pt] && track2.pt() <= ptbins[pt + 1] && selectionPID(track2, 0)) { // for pion + pn_sumsinB_pi[pt] += TMath::Sin(2 * track2.phi()); + pn_sumcosB_pi[pt] += TMath::Cos(2 * track2.phi()); + mpB_pi[pt]++; + } else if (track2.pt() > ptbins[pt] && track2.pt() <= ptbins[pt + 1] && selectionPID(track2, 1)) { // for kaon + pn_sumsinB_k[pt] += TMath::Sin(2 * track2.phi()); + pn_sumcosB_k[pt] += TMath::Cos(2 * track2.phi()); + mpB_k[pt]++; + } else if (track2.pt() > ptbins[pt] && track2.pt() <= ptbins[pt + 1] && selectionPID(track2, 2)) { // for proton + pn_sumsinB_pr[pt] += TMath::Sin(2 * track2.phi()); + pn_sumcosB_pr[pt] += TMath::Cos(2 * track2.phi()); + mpB_pr[pt]++; + } else { + continue; + } + } // end of pt loop + } else { continue; - } // If track not pion, kaon and proton then discard the track + } + } // track loop ends - if (MID) { - if (MIDselectionPID(track2, 1)) { - continue; - } // misidentified as kaon + if (10.0 < multiplicity && multiplicity <= 20.0) { + // reference flow + if ((multA * multB) != 0) { + histos.fill(HIST("profv2ref"), 1, ((sum_cosA * sum_cosB + sum_sinA * sum_sinB) / (multA * multB)), multA * multB); } - sum_sinB += TMath::Sin(2.0 * track2.phi()); // sum of sin components of Q vector - sum_cosB += TMath::Cos(2.0 * track2.phi()); // sum of cos components of Q vector - multB++; // charged particle multiplicity + // pt wise differential flow + for (auto pt = 0; pt < 14; pt++) { + if ((mpA_pr[pt] * multB) != 0) { + histos.fill(HIST("profv2diff_pr_10_20"), pt + 1, ((pn_sumcosA_pr[pt] * sum_cosB + pn_sumsinA_pr[pt] * sum_sinB) / (mpA_pr[pt] * multB)), mpA_pr[pt] * multB); + } // for proton + if ((mpA_pi[pt] * multB) != 0) { + histos.fill(HIST("profv2diff_pi_10_20"), pt + 1, ((pn_sumcosA_pi[pt] * sum_cosB + pn_sumsinA_pi[pt] * sum_sinB) / (mpA_pi[pt] * multB)), mpA_pi[pt] * multB); + } // for pion + if ((mpA_k[pt] * multB) != 0) { + histos.fill(HIST("profv2diff_k_10_20"), pt + 1, ((pn_sumcosA_k[pt] * sum_cosB + pn_sumsinA_k[pt] * sum_sinB) / (mpA_k[pt] * multB)), mpA_k[pt] * multB); + } // for kaon + } + } // 10 to 20 percent centrality + + if (20.0 < multiplicity && multiplicity <= 30.0) { + // reference flow + if ((multA * multB) != 0) { + histos.fill(HIST("profv2ref"), 2, ((sum_cosA * sum_cosB + sum_sinA * sum_sinB) / (multA * multB)), multA * multB); + } - // pt loop for component sums of p vector, POI multiplicities pt wise + // pt wise differential flow for (auto pt = 0; pt < 14; pt++) { - sum_sindsB[pt] += TMath::Sin(2 * track2.phi()); - sum_cosdsB[pt] += TMath::Cos(2 * track2.phi()); - - if (track2.pt() > ptbins[pt] && track2.pt() <= ptbins[pt + 1] && selectionPID(track2, 2)) { - pn_sumsinB_pr[pt] += TMath::Sin(2 * track2.phi()); - pn_sumcosB_pr[pt] += TMath::Cos(2 * track2.phi()); - mpB_pr[pt]++; - } else if (track2.pt() > ptbins[pt] && track2.pt() <= ptbins[pt + 1] && selectionPID(track2, 0)) { - pn_sumsinB_pi[pt] += TMath::Sin(2 * track2.phi()); - pn_sumcosB_pi[pt] += TMath::Cos(2 * track2.phi()); - mpB_pi[pt]++; - } else if (track2.pt() > ptbins[pt] && track2.pt() <= ptbins[pt + 1] && selectionPID(track2, 1)) { - pn_sumsinB_k[pt] += TMath::Sin(2 * track2.phi()); - pn_sumcosB_k[pt] += TMath::Cos(2 * track2.phi()); - mpB_k[pt]++; - } else { - continue; - } - } // end of pt loop + if ((mpA_pr[pt] * multB) != 0) { + histos.fill(HIST("profv2diff_pr_20_30"), pt + 1, ((pn_sumcosA_pr[pt] * sum_cosB + pn_sumsinA_pr[pt] * sum_sinB) / (mpA_pr[pt] * multB)), mpA_pr[pt] * multB); + } // for proton + if ((mpA_pi[pt] * multB) != 0) { + histos.fill(HIST("profv2diff_pi_20_30"), pt + 1, ((pn_sumcosA_pi[pt] * sum_cosB + pn_sumsinA_pi[pt] * sum_sinB) / (mpA_pi[pt] * multB)), mpA_pi[pt] * multB); + } // for pion + if ((mpA_k[pt] * multB) != 0) { + histos.fill(HIST("profv2diff_k_20_30"), pt + 1, ((pn_sumcosA_k[pt] * sum_cosB + pn_sumsinA_k[pt] * sum_sinB) / (mpA_k[pt] * multB)), mpA_k[pt] * multB); + } // for kaon + } + } // 20 to 30 percent centrality - } // track loop ends + if (30.0 < multiplicity && multiplicity <= 40.0) { + // reference flow + if ((multA * multB) != 0) { + histos.fill(HIST("profv2ref"), 3, ((sum_cosA * sum_cosB + sum_sinA * sum_sinB) / (multA * multB)), multA * multB); + } - // std::cout<<"MultA: "< NAME{#NAME, DEFAULT, HELP}; -struct FlowPbPbTask { +struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") @@ -57,6 +57,7 @@ struct FlowPbPbTask { O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum TPC clusters") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, false, "Use additional track cut on phi") + O2_DEFINE_CONFIGURABLE(cfgGetInteractionRate, bool, false, "Get interaction rate from CCDB") O2_DEFINE_CONFIGURABLE(cfgUseInteractionRateCut, bool, false, "Use events with low interaction rate") O2_DEFINE_CONFIGURABLE(cfgCutIR, float, 50.0, "maximum interaction rate (kHz)") O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") @@ -65,6 +66,10 @@ struct FlowPbPbTask { O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgMagnetField, std::string, "GLO/Config/GRPMagField", "CCDB path to Magnet field object") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + Configurable> cfgUserDefineGFWCorr{"cfgUserDefineGFWCorr", std::vector{"refN02 {2} refP02 {-2}", "refN12 {2} refP12 {-2}"}, "User defined GFW CorrelatorConfig"}; + Configurable> cfgUserDefineGFWName{"cfgUserDefineGFWName", std::vector{"Ch02Gap22", "Ch12Gap22"}, "User defined GFW Name"}; ConfigurableAxis axisVertex{"axisVertex", {40, -20, 20}, "vertex axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; @@ -72,7 +77,7 @@ struct FlowPbPbTask { ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; ConfigurableAxis axisPtHist{"axisPtHist", {100, 0., 10.}, "pt axis for histograms"}; ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}, "pt axis for histograms"}; - ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "centrality axis for histograms"}; + ConfigurableAxis axisIndependent{"axisIndependent", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "X axis for histograms"}; ConfigurableAxis axisCentForQA{"axisCentForQA", {100, 0, 100}, "centrality for QA"}; ConfigurableAxis axisNch{"axisNch", {4000, 0, 4000}, "N_{ch}"}; ConfigurableAxis axisT0C{"axisT0C", {70, 0, 70000}, "N_{ch} (T0C)"}; @@ -182,12 +187,12 @@ struct FlowPbPbTask { registry.add("hDCAxy", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{50, -1, 1}, {50, 0, 10}}}); registry.add("hTrackCorrection2d", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisNch, axisNch}}); // additional Output histograms - registry.add("hMeanPt", "", {HistType::kTProfile, {axisCentrality}}); - registry.add("hMeanPtWithinGap08", "", {HistType::kTProfile, {axisCentrality}}); - registry.add("c22_gap08_Weff", "", {HistType::kTProfile, {axisCentrality}}); - registry.add("c22_gap08_trackMeanPt", "", {HistType::kTProfile, {axisCentrality}}); - registry.add("PtVariance_partA_WithinGap08", "", {HistType::kTProfile, {axisCentrality}}); - registry.add("PtVariance_partB_WithinGap08", "", {HistType::kTProfile, {axisCentrality}}); + registry.add("hMeanPt", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("hMeanPtWithinGap08", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("c22_gap08_Weff", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("c22_gap08_trackMeanPt", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("PtVariance_partA_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("PtVariance_partB_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); // initial array BootstrapArray.resize(cfgNbootstrap); @@ -195,11 +200,11 @@ struct FlowPbPbTask { BootstrapArray[i].resize(kCount_ExtraProfile); } for (int i = 0; i < cfgNbootstrap; i++) { - BootstrapArray[i][kMeanPt_InGap08] = registry.add(Form("BootstrapContainer_%d/hMeanPtWithinGap08", i), "", {HistType::kTProfile, {axisCentrality}}); - BootstrapArray[i][kC22_Gap08_Weff] = registry.add(Form("BootstrapContainer_%d/c22_gap08_Weff", i), "", {HistType::kTProfile, {axisCentrality}}); - BootstrapArray[i][kC22_Gap08_MeanPt] = registry.add(Form("BootstrapContainer_%d/c22_gap08_trackMeanPt", i), "", {HistType::kTProfile, {axisCentrality}}); - BootstrapArray[i][kPtVarParA_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partA_WithinGap08", i), "", {HistType::kTProfile, {axisCentrality}}); - BootstrapArray[i][kPtVarParB_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partB_WithinGap08", i), "", {HistType::kTProfile, {axisCentrality}}); + BootstrapArray[i][kMeanPt_InGap08] = registry.add(Form("BootstrapContainer_%d/hMeanPtWithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kC22_Gap08_Weff] = registry.add(Form("BootstrapContainer_%d/c22_gap08_Weff", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kC22_Gap08_MeanPt] = registry.add(Form("BootstrapContainer_%d/c22_gap08_trackMeanPt", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kPtVarParA_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partA_WithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kPtVarParB_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partB_WithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); } o2::framework::AxisSpec axis = axisPt; @@ -247,13 +252,24 @@ struct FlowPbPbTask { oba->Add(new TNamed("Ch10Gap3232", "Ch10Gap3232")); oba->Add(new TNamed("Ch10Gap4242", "Ch10Gap4242")); oba->Add(new TNamed("Ch10Gap24", "Ch10Gap24")); + std::vector UserDefineGFWCorr = cfgUserDefineGFWCorr; + std::vector UserDefineGFWName = cfgUserDefineGFWName; + if (!UserDefineGFWCorr.empty() && !UserDefineGFWName.empty()) { + for (int i = 0; i < UserDefineGFWName.size(); i++) { + oba->Add(new TNamed(UserDefineGFWName.at(i).c_str(), UserDefineGFWName.at(i).c_str())); + } + } fFC->SetName("FlowContainer"); fFC->SetXAxis(fPtAxis); - fFC->Initialize(oba, axisCentrality, cfgNbootstrap); + fFC->Initialize(oba, axisIndependent, cfgNbootstrap); delete oba; // eta region fGFW->AddRegion("full", -0.8, 0.8, 1, 1); + fGFW->AddRegion("refN00", -0.8, 0., 1, 1); // gap0 negative region + fGFW->AddRegion("refP00", 0., 0.8, 1, 1); // gap0 positve region + fGFW->AddRegion("refN02", -0.8, -0.1, 1, 1); // gap2 negative region + fGFW->AddRegion("refP02", 0.1, 0.8, 1, 1); // gap2 positve region fGFW->AddRegion("refN04", -0.8, -0.2, 1, 1); // gap4 negative region fGFW->AddRegion("refP04", 0.2, 0.8, 1, 1); // gap4 positve region fGFW->AddRegion("refN06", -0.8, -0.3, 1, 1); // gap6 negative region @@ -262,8 +278,11 @@ struct FlowPbPbTask { fGFW->AddRegion("refP08", 0.4, 0.8, 1, 1); fGFW->AddRegion("refN10", -0.8, -0.5, 1, 1); fGFW->AddRegion("refP10", 0.5, 0.8, 1, 1); - fGFW->AddRegion("refP", 0.4, 0.8, 1, 1); + fGFW->AddRegion("refN12", -0.8, -0.6, 1, 1); + fGFW->AddRegion("refP12", 0.6, 0.8, 1, 1); fGFW->AddRegion("refN", -0.8, -0.4, 1, 1); + fGFW->AddRegion("refP", 0.4, 0.8, 1, 1); + fGFW->AddRegion("refM", -0.4, 0.4, 1, 1); fGFW->AddRegion("poiN", -0.8, -0.4, 1 + fPtAxis->GetNbins(), 2); fGFW->AddRegion("olN", -0.8, -0.4, 1, 4); @@ -299,6 +318,18 @@ struct FlowPbPbTask { corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {3 2} refP10 {-3 -2}", "Ch10Gap3232", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {4 2} refP10 {-4 -2}", "Ch10Gap4242", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {2 2} refP10 {-2 -2}", "Ch10Gap24", kFALSE)); + if (!UserDefineGFWCorr.empty() && !UserDefineGFWName.empty()) { + LOGF(info, "User adding GFW CorrelatorConfig:"); + // attentaion: here we follow the index of cfgUserDefineGFWCorr + for (int i = 0; i < UserDefineGFWCorr.size(); i++) { + if (i >= UserDefineGFWName.size()) { + LOGF(fatal, "The names you provided are more than configurations. UserDefineGFWName.size(): %d > UserDefineGFWCorr.size(): %d", UserDefineGFWName.size(), UserDefineGFWCorr.size()); + break; + } + LOGF(info, "%d: %s %s", i, UserDefineGFWCorr.at(i).c_str(), UserDefineGFWName.at(i).c_str()); + corrconfigs.push_back(fGFW->GetCorrelatorConfig(UserDefineGFWCorr.at(i).c_str(), UserDefineGFWName.at(i).c_str(), kFALSE)); + } + } fGFW->CreateRegions(); if (cfgUseAdditionalEventCut) { @@ -465,6 +496,10 @@ struct FlowPbPbTask { // use this cut at low multiplicities with caution return 0; } + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // no collisions in specified time range + return 0; + } float vtxz = -999; if (collision.numContrib() > 1) { vtxz = collision.posZ(); @@ -473,6 +508,7 @@ struct FlowPbPbTask { vtxz = -999; } auto multNTracksPV = collision.multNTracksPV(); + auto occupancy = collision.trackOccupancyInTimeRange(); if (abs(vtxz) > cfgCutVertex) return 0; @@ -484,6 +520,8 @@ struct FlowPbPbTask { return 0; if (multTrk > fMultCutHigh->Eval(centrality)) return 0; + if (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh) + return 0; // V0A T0A 5 sigma cut if (abs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A())) @@ -571,12 +609,14 @@ struct FlowPbPbTask { registry.fill(HIST("hCent"), collision.centFT0C()); fGFW->Clear(); auto bc = collision.bc_as(); - initHadronicRate(bc); - double hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), mRunNumber, "ZNC hadronic") * 1.e-3; // - double seconds = bc.timestamp() * 1.e-3 - mMinSeconds; - if (cfgUseInteractionRateCut && hadronicRate > cfgCutIR) // cut on hadronic rate - return; - gCurrentHadronicRate->Fill(seconds, hadronicRate); + if (cfgGetInteractionRate) { + initHadronicRate(bc); + double hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), mRunNumber, "ZNC hadronic") * 1.e-3; // + double seconds = bc.timestamp() * 1.e-3 - mMinSeconds; + if (cfgUseInteractionRateCut && hadronicRate > cfgCutIR) // cut on hadronic rate + return; + gCurrentHadronicRate->Fill(seconds, hadronicRate); + } loadCorrections(bc.timestamp()); registry.fill(HIST("hEventCount"), 4.5); @@ -601,6 +641,9 @@ struct FlowPbPbTask { // magnet field dependence cut Magnetfield = getMagneticField(bc.timestamp()); } + float independent = cent; + if (cfgUseNch) + independent = static_cast(tracks.size()); for (auto& track : tracks) { if (track.tpcNClsFound() < cfgCutTPCclu) @@ -649,19 +692,19 @@ struct FlowPbPbTask { // Filling TProfile // MeanPt if (weffEvent > 1e-6) - registry.fill(HIST("hMeanPt"), cent, ptSum / weffEvent, weffEvent); + registry.fill(HIST("hMeanPt"), independent, ptSum / weffEvent, weffEvent); if (weffEvent_WithinGap08 > 1e-6) - registry.fill(HIST("hMeanPtWithinGap08"), cent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); + registry.fill(HIST("hMeanPtWithinGap08"), independent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); // v22-Pt // c22_gap8 * pt_withGap8 if (weffEvent_WithinGap08 > 1e-6) - FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, HIST("c22_gap08_Weff"), HIST("c22_gap08_trackMeanPt"), cent); + FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, HIST("c22_gap08_Weff"), HIST("c22_gap08_trackMeanPt"), independent); // PtVariance if (WeffEvent_diff_WithGap08 > 1e-6) { - registry.fill(HIST("PtVariance_partA_WithinGap08"), cent, + registry.fill(HIST("PtVariance_partA_WithinGap08"), independent, (ptSum_Gap08 * ptSum_Gap08 - sum_ptSquare_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, WeffEvent_diff_WithGap08); - registry.fill(HIST("PtVariance_partB_WithinGap08"), cent, + registry.fill(HIST("PtVariance_partB_WithinGap08"), independent, (weffEvent_WithinGap08 * ptSum_Gap08 - sum_pt_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, WeffEvent_diff_WithGap08); } @@ -669,21 +712,21 @@ struct FlowPbPbTask { // Filling Bootstrap Samples int SampleIndex = static_cast(cfgNbootstrap * l_Random); if (weffEvent_WithinGap08 > 1e-6) - BootstrapArray[SampleIndex][kMeanPt_InGap08]->Fill(cent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); + BootstrapArray[SampleIndex][kMeanPt_InGap08]->Fill(independent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); if (weffEvent_WithinGap08 > 1e-6) - FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, BootstrapArray[SampleIndex][kC22_Gap08_Weff], BootstrapArray[SampleIndex][kC22_Gap08_MeanPt], cent); + FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, BootstrapArray[SampleIndex][kC22_Gap08_Weff], BootstrapArray[SampleIndex][kC22_Gap08_MeanPt], independent); if (WeffEvent_diff_WithGap08 > 1e-6) { - BootstrapArray[SampleIndex][kPtVarParA_InGap08]->Fill(cent, + BootstrapArray[SampleIndex][kPtVarParA_InGap08]->Fill(independent, (ptSum_Gap08 * ptSum_Gap08 - sum_ptSquare_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, WeffEvent_diff_WithGap08); - BootstrapArray[SampleIndex][kPtVarParB_InGap08]->Fill(cent, + BootstrapArray[SampleIndex][kPtVarParB_InGap08]->Fill(independent, (weffEvent_WithinGap08 * ptSum_Gap08 - sum_pt_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, WeffEvent_diff_WithGap08); } // Filling Flow Container for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { - FillFC(corrconfigs.at(l_ind), cent, l_Random); + FillFC(corrconfigs.at(l_ind), independent, l_Random); } } }; @@ -691,5 +734,5 @@ struct FlowPbPbTask { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGCF/Flow/Tasks/flowAnalysisGF.cxx b/PWGCF/Flow/Tasks/flowAnalysisGF.cxx index 83f83541a6b..4648d8a49e6 100644 --- a/PWGCF/Flow/Tasks/flowAnalysisGF.cxx +++ b/PWGCF/Flow/Tasks/flowAnalysisGF.cxx @@ -57,7 +57,7 @@ float ptreflow = 0.2, ptrefup = 3.0; float ptlow = 0.2, ptup = 10.0; int etabins = 16; float etalow = -0.8, etaup = 0.8; -int vtxZbins = 40; +int vtxZbins = 20; float vtxZlow = -10.0, vtxZup = 10.0; int phibins = 72; float philow = 0.0; @@ -69,6 +69,7 @@ std::vector centbinning(90); int nBootstrap = 10; GFWRegions regions; GFWCorrConfigs configs; +int eventBin = 0; } // namespace o2::analysis::flowanalysis using namespace o2::analysis::flowanalysis; @@ -93,10 +94,16 @@ struct flowAnalysisGF { O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); O2_DEFINE_CONFIGURABLE(cfgMagField, float, 99999, "Configurable magnetic field; default CCDB will be queried"); // added - O2_DEFINE_CONFIGURABLE(cfgROFCuts, bool, true, "Use addional event selection cuts"); - O2_DEFINE_CONFIGURABLE(cfgDoExtraQA, bool, true, "Make extra QA plots"); O2_DEFINE_CONFIGURABLE(cfgDoubleTrackFunction, bool, true, "Include track cut at low pt"); O2_DEFINE_CONFIGURABLE(cfgTrackCutSize, float, 0.06, "Spread of track cut"); + O2_DEFINE_CONFIGURABLE(cfgMaxOccupancy, int, 500, "Maximum occupancy of selected events"); + O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); + O2_DEFINE_CONFIGURABLE(cfgDoOccupancySel, bool, true, "Bool for event selection on detector occupancy"); + O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, true, "Use additional evenr cut on mult correlations"); + O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "Use kTVXinTRD (reject TRD triggered events)"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "Selects collisions with at least one ITS-TPC track"); Configurable cfgGFWBinning{"cfgGFWBinning", {40, 16, 72, 300, 0, 3000, 0.2, 10.0, 0.2, 3.0, {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5, 5.5, 6, 7, 8, 9, 10}, {0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}}, "Configuration for binning"}; Configurable cfgRegions{"cfgRegions", {{"refN", "refP", "refFull", "poiN", "poiP", "poiFull", "olN", "olP", "olFull"}, {-0.8, 0.5, -0.8, -0.8, -0.8, 0.5, -0.8, -0.8}, {-0.5, 0.8, 0.8, -0.5, 0.8, 0.8, -0.5}, {0, 0, 0, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 2, 2, 2, 4, 4, 4}}, "Configurations for GFW regions"}; @@ -183,13 +190,18 @@ struct flowAnalysisGF { for (int i = 0; i <= nchbins; ++i) { nchbinning.push_back(nchskip * i + nchlow + 0.5); } + AxisSpec nchAxis = {nchbinning, "N_{ch}"}; AxisSpec t0cAxis = {70, 0, 70000, "N_{ch} (T0C)"}; AxisSpec t0aAxis = {200, 0, 200, "N_{ch}"}; AxisSpec multpvAxis = {4000, 0, 4000, "N_{ch} (PV)"}; AxisSpec multAxis = (cfgUseNch) ? nchAxis : centAxis; - AxisSpec dcaZAXis = {200, -2, 2, "DCA_{z} (cm)"}; - AxisSpec dcaXYAXis = {200, -1, 1, "DCA_{xy} (cm)"}; + AxisSpec dcaZAxis = {200, -2, 2, "DCA_{z} (cm)"}; + AxisSpec dcaXYAxis = {200, -1, 1, "DCA_{xy} (cm)"}; + AxisSpec tpcAxis = {200, 0, 200, "TPC Clusters"}; + AxisSpec tpcAxisCl = {10, 0, 10, "TPC Crossed rows / findable Clusters"}; + AxisSpec dEdxAxis = {400, 0, 200, "TPC: dE/dx"}; + AxisSpec itsClAxis = {10, 0, 10, "Number of ITS clusters"}; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -206,35 +218,53 @@ struct flowAnalysisGF { fWeights->Init(true, false); } - registry.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "kTVXinTRD"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kNoTimeFrameBorder"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kNoSameBunchPileup"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "kIsVertexITSTPC"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(9, "after Mult cuts"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(10, "corr + cent"); - if (doprocessMCGen) { - registry.add("pt_gen", "", {HistType::kTH1D, {ptAxis}}); - registry.add("phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("trackMCGen/pt_gen", "", {HistType::kTH1D, {ptAxis}}); + registry.add("trackMCGen/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); } if (doprocessMCReco || doprocessData || doprocessRun2) { - registry.add("phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registry.add("pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); - registry.add("pt_phi_bef", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); - registry.add("pt_phi_aft", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); - registry.add("phi_eta_vtxZ_corrected", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registry.add("globalTracks_centT0C", "", {HistType::kTH2D, {centAxis, nchAxis}}); - registry.add("PVTracks_centT0C", "", {HistType::kTH2D, {centAxis, multpvAxis}}); - registry.add("globalTracks_PVTracks", "", {HistType::kTH2D, {multpvAxis, nchAxis}}); - registry.add("globalTracks_multT0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registry.add("globalTracks_multV0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registry.add("multV0A_multT0A", "", {HistType::kTH2D, {t0aAxis, t0aAxis}}); - registry.add("multT0C_centT0C", "", {HistType::kTH2D, {centAxis, t0cAxis}}); + registry.add("trackQA/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("trackQA/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAxis, dcaZAxis}}); + registry.add("trackQA/pt_phi_bef", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); + registry.add("trackQA/pt_phi_aft", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); + registry.add("trackQA/phi_eta_vtxZ_corrected", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("trackQA/pt_reco", "", {HistType::kTH1D, {ptAxis}}); + + registry.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "sel8"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "occupancy"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kTVXinTRD"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "kIsVertexITSTPC"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(9, "after Mult cuts"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(10, "corr + cent"); + + registry.add("eventQA/nITS_nTPC_Tracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); + + // track QA before and after selections + registry.add("trackQA/before/CrossedTPCRows_pt", "", {HistType::kTH2D, {ptAxis, tpcAxis}}); + registry.add("trackQA/before/NumberSharedClustersTPC_pt", "", {HistType::kTH2D, {ptAxis, tpcAxis}}); + registry.add("trackQA/before/ITSClusters_pt", "", {HistType::kTH2D, {ptAxis, itsClAxis}}); + registry.add("trackQA/before/DCAxy_pt", "", {HistType::kTH2D, {ptAxis, dcaXYAxis}}); + registry.add("trackQA/before/DCAz_pt", "", {HistType::kTH2D, {ptAxis, dcaZAxis}}); + registry.add("trackQA/before/tpcSignal_pt", "", {HistType::kTH2D, {ptAxis, dEdxAxis}}); + registry.add("trackQA/before/phi_pt", "", {HistType::kTH2D, {ptAxis, phiAxis}}); + registry.add("trackQA/before/phi_eta", "", {HistType::kTH2D, {etaAxis, phiAxis}}); + registry.add("trackQA/before/tpcCrossedRowsOverFindableCls_pt", "", {HistType::kTH2D, {ptAxis, tpcAxisCl}}); + registry.addClone("trackQA/before/", "trackQA/after/"); + + // track QA after selections + registry.add("eventQA/before/globalTracks_centT0C", "", {HistType::kTH2D, {centAxis, nchAxis}}); + registry.add("eventQA/before/PVTracks_centT0C", "", {HistType::kTH2D, {centAxis, multpvAxis}}); + registry.add("eventQA/before/globalTracks_PVTracks", "", {HistType::kTH2D, {multpvAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multT0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multV0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "", {HistType::kTH2D, {t0aAxis, t0aAxis}}); + registry.add("eventQA/before/multT0C_centT0C", "", {HistType::kTH2D, {centAxis, t0cAxis}}); + registry.addClone("eventQA/before/", "eventQA/after/"); } if (regions.GetSize() < 0) @@ -286,6 +316,15 @@ struct flowAnalysisGF { } } + static constexpr std::string_view moment[] = { + "before/", + "after/"}; + + enum QAtime { + kBefore, + kAfter + }; + void AddConfigObjectsToObjArray(TObjArray* oba, const std::vector& configs) { for (auto it = configs.begin(); it != configs.end(); ++it) { @@ -358,42 +397,40 @@ struct flowAnalysisGF { template bool eventSelected(TCollision collision, const int& multTrk, const float& centrality) { - if (collision.alias_bit(kTVXinTRD)) { - // TRD triggered - // "CMTVX-B-NOPF-TRD,minbias_TVX" - return 0; - } - registry.fill(HIST("hEventCount"), 2.5); - - if (cfgROFCuts) { - if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - // reject collisions close to Time Frame borders - // https://its.cern.ch/jira/browse/O2-4623 + if (cfgTVXinTRD) { + if (collision.alias_bit(kTVXinTRD)) { + // TRD triggered + // "CMTVX-B-NOPF-TRD,minbias_TVX" return 0; } registry.fill(HIST("hEventCount"), 3.5); + } - if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - // reject events affected by the ITS ROF border - // https://its.cern.ch/jira/browse/O2-4309 - return 0; - } - registry.fill(HIST("hEventCount"), 4.5); - + if (cfgNoSameBunchPileupCut) { if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { // rejects collisions which are associated with the same "found-by-T0" bunch crossing // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof return 0; } - registry.fill(HIST("hEventCount"), 5.5); - + registry.fill(HIST("hEventCount"), 4.5); + } + if (cfgIsGoodZvtxFT0vsPV) { if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference // use this cut at low multiplicities with caution return 0; } + registry.fill(HIST("hEventCount"), 5.5); + } + if (cfgNoCollInTimeRangeStandard) { + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // Rejection of the collisions which have other events nearby + return 0; + } registry.fill(HIST("hEventCount"), 6.5); + } + if (cfgIsVertexITSTPC) { if (!collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { // selects collisions with at least one ITS-TPC track, and thus rejects vertices built from ITS-only tracks return 0; @@ -413,15 +450,18 @@ struct flowAnalysisGF { if (vtxz > vtxZup || vtxz < vtxZlow) return 0; - if (multNTracksPV < fMultPVCutLow->Eval(centrality)) - return 0; - if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) - return 0; - if (multTrk < fMultCutLow->Eval(centrality)) - return 0; - if (multTrk > fMultCutHigh->Eval(centrality)) - return 0; - registry.fill(HIST("hEventCount"), 8.5); + + if (cfgMultCut) { + if (multNTracksPV < fMultPVCutLow->Eval(centrality)) + return 0; + if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) + return 0; + if (multTrk < fMultCutLow->Eval(centrality)) + return 0; + if (multTrk > fMultCutHigh->Eval(centrality)) + return 0; + registry.fill(HIST("hEventCount"), 8.5); + } return 1; } @@ -439,14 +479,14 @@ struct flowAnalysisGF { phimodn += TMath::Pi() / 18.0; // to center gap in the middle phimodn = fmod(phimodn, TMath::Pi() / 9.0); - registry.fill(HIST("pt_phi_bef"), track.pt(), phimodn); + registry.fill(HIST("trackQA/pt_phi_bef"), track.pt(), phimodn); if (phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt())) return false; // reject track if (cfgDoubleTrackFunction) { if (phimodn < fPhiCutHigh2->Eval(track.pt()) && phimodn > fPhiCutLow2->Eval(track.pt())) return false; // reject track } - registry.fill(HIST("pt_phi_aft"), track.pt(), phimodn); + registry.fill(HIST("trackQA/pt_phi_aft"), track.pt(), phimodn); return true; } @@ -485,7 +525,7 @@ struct flowAnalysisGF { } template - void processCollision(datatype dt, TCollision collision, TTracks tracks, const float& centrality, const int& field) + void processCollision(datatype dt, TCollision const& collision, TTracks tracks, const float& centrality, const int& field) { if (tracks.size() < 1) @@ -498,19 +538,46 @@ struct flowAnalysisGF { fFCpt->ClearVector(); float l_Random = fRndm->Rndm(); + std::vector ITS_TPC_tracks(6, 0); + for (auto& track : tracks) { ProcessTrack(track, centrality, vtxz, field); + FillITSTPCQA(track, ITS_TPC_tracks); } + registry.fill(HIST("eventQA/nITS_nTPC_Tracks"), ITS_TPC_tracks[1], ITS_TPC_tracks[2]); FillOutputContainers(dt, (cfgUseNch) ? tracks.size() : centrality, l_Random); } + template + inline void FillITSTPCQA(TrackObject const& track, std::vector& ITS_TPC_tracks) + { + if constexpr (!framework::has_type_v) { + // if track its and tpc required then these three are the same + if (track.hasITS() || track.hasTPC()) + ITS_TPC_tracks[0] += 1; + if (track.hasITS()) + ITS_TPC_tracks[1] += 1; + if (track.hasTPC()) + ITS_TPC_tracks[2] += 1; + if (track.hasITS() && track.hasTPC()) + ITS_TPC_tracks[3] += 1; + if (track.hasITS() && !track.hasTPC()) + ITS_TPC_tracks[4] += 1; + if (track.hasTPC() && !track.hasITS()) + ITS_TPC_tracks[5] += 1; + } + } + template inline void ProcessTrack(TrackObject const& track, const float& centrality, const float& vtxz, const int& field) { float weff = 1, wacc = 1; auto handleReco = [&](auto const& particle) -> bool { + if (cfgFillQA) + FillTrackQA(track, vtxz); + if (cfgUseAdditionalTrackCut && !trackSelected(track, field)) return false; @@ -520,9 +587,8 @@ struct flowAnalysisGF { if (!setCurrentParticleWeights(weff, wacc, particle.phi(), particle.eta(), particle.pt(), vtxz)) return false; - if (cfgFillQA) { - FillTrackQA(track, vtxz); - } + if (cfgFillQA) + FillTrackQA(track, vtxz); FillGFW(particle, weff, wacc); @@ -540,14 +606,14 @@ struct flowAnalysisGF { if (!handleReco(mcParticle)) return; - registry.fill(HIST("phi_eta_vtxZ_corrected"), mcParticle.phi(), mcParticle.eta(), vtxz, wacc); + registry.fill(HIST("trackQA/phi_eta_vtxZ_corrected"), mcParticle.phi(), mcParticle.eta(), vtxz, wacc); } else if constexpr (framework::has_type_v) { if (!track.isPhysicalPrimary() || track.eta() < etalow || track.eta() > etaup || track.pt() < ptlow || track.pt() > ptup) return; if (cfgFillQA) - FillTrackQA(track, vtxz); + FillTrackQA(track, vtxz); FillGFW(track, 1., 1.); } else { @@ -557,7 +623,7 @@ struct flowAnalysisGF { if (!handleReco(track)) return; - registry.fill(HIST("phi_eta_vtxZ_corrected"), track.phi(), track.eta(), vtxz, wacc); + registry.fill(HIST("trackQA/phi_eta_vtxZ_corrected"), track.phi(), track.eta(), vtxz, wacc); } } @@ -576,29 +642,41 @@ struct flowAnalysisGF { return; } - template + template inline void FillTrackQA(TrackObject track, const float vtxz) { if constexpr (framework::has_type_v) { - registry.fill(HIST("phi_eta_vtxZ_gen"), track.phi(), track.eta(), vtxz); - registry.fill(HIST("pt_gen"), track.pt()); + registry.fill(HIST("trackMCGen/phi_eta_vtxZ_gen"), track.phi(), track.eta(), vtxz); + registry.fill(HIST("trackMCGen/pt_gen"), track.pt()); } else { - registry.fill(HIST("phi_eta_vtxZ"), track.phi(), track.eta(), vtxz); - registry.fill(HIST("pt_dcaXY_dcaZ"), track.pt(), track.dcaXY(), track.dcaZ()); + registry.fill(HIST("trackQA/phi_eta_vtxZ"), track.phi(), track.eta(), vtxz); + registry.fill(HIST("trackQA/pt_dcaXY_dcaZ"), track.pt(), track.dcaXY(), track.dcaZ()); + registry.fill(HIST("trackQA/pt_reco"), track.pt()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("CrossedTPCRows_pt"), track.pt(), track.tpcNClsCrossedRows()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("NumberSharedClustersTPC_pt"), track.pt(), track.tpcNClsShared()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("ITSClusters_pt"), track.pt(), track.itsNCls()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("DCAxy_pt"), track.pt(), track.dcaXY()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("DCAz_pt"), track.pt(), track.dcaZ()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("tpcSignal_pt"), track.pt(), track.tpcSignal()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("phi_pt"), track.pt(), track.phi()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("phi_eta"), track.eta(), track.phi()); + registry.fill(HIST("trackQA/") + HIST(moment[qt]) + HIST("tpcCrossedRowsOverFindableCls_pt"), track.pt(), track.tpcCrossedRowsOverFindableCls()); } } - template + template inline void FillEventQA(CollisionObject collision, TracksObject tracks) { - registry.fill(HIST("globalTracks_centT0C"), collision.centFT0C(), tracks.size()); - registry.fill(HIST("PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); - registry.fill(HIST("globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); - registry.fill(HIST("globalTracks_multT0A"), collision.multFT0A(), tracks.size()); - registry.fill(HIST("globalTracks_multV0A"), collision.multFV0A(), tracks.size()); - registry.fill(HIST("multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); - registry.fill(HIST("multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); - return; + + if constexpr (framework::has_type_v) { + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("globalTracks_centT0C"), collision.centFT0C(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("globalTracks_multT0A"), collision.multFT0A(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("globalTracks_multV0A"), collision.multFV0A(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); + registry.fill(HIST("eventQA/") + HIST(moment[qt]) + HIST("multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + } } template @@ -617,13 +695,24 @@ struct flowAnalysisGF { return; registry.fill(HIST("hEventCount"), 1.5); centrality = collision.centFT0C(); + if (cfgFillQA) - FillEventQA(collision, tracks); + FillEventQA(collision, tracks); + } + + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < 0 || occupancy > cfgMaxOccupancy) + return; + registry.fill(HIST("hEventCount"), 2.5); } auto bc = collision.template bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), centrality)) return; + if (cfgFillQA) + FillEventQA(collision, tracks); + loadCorrections(bc.timestamp()); auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; processCollision(kReco, collision, tracks, centrality, field); diff --git a/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx new file mode 100644 index 00000000000..a77c0e11865 --- /dev/null +++ b/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx @@ -0,0 +1,410 @@ +// Copyright 2019-2020 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. + +/// In case of questions please write to: +/// \author Fuchun Cui(fcui@cern.ch) + +#include +#include +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/HistogramRegistry.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include "GFWPowerArray.h" +#include "GFW.h" +#include "GFWCumulant.h" +#include "GFWWeights.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/Core/EventPlaneHelper.h" +#include "ReconstructionDataFormats/Track.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "TList.h" +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +struct FlowGFWOmegaXi { + + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") + O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") + + ConfigurableAxis cfgaxisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis cfgaxisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; + ConfigurableAxis cfgaxisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; + + Configurable> cfgvecwacc{"vecwacc", std::vector{0.879543, 0.893808, 0.993375, 1.09663, 0.983883, 0.984094, 1.11362, 0.963896, 0.911212, 1.02934, 1.00295, 0.950711, 0.996856, 1.11934, 0.993665, 0.99087, 1.11915, 1.0198, 0.966849, 1.03237, 0.989367, 0.948312, 0.970883, 0.984305, 0.920335, 0.929722, 1.07467, 1.00862, 0.977185, 0.870868, 1.06552, 0.962393, 1.01025, 1.09959, 0.984226, 0.986361, 1.0931, 0.994377, 0.976051, 1.05249, 0.995538, 0.886452, 0.936763, 0.993613, 0.94491, 0.966559, 1.10829, 1.01998, 0.991503, 1.07918, 1.05655, 0.973784, 1.00914, 1.11678, 1.00092, 0.95232, 1.09814, 1.02322, 0.958543, 0.947231}, "wacc in phi bins"}; + AxisSpec axisPt{{0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.60, 2.80, 3.00, 3.50, 4.00, 4.50, 5.00, 5.50, 6.00, 7.00, 8.00, 9.00, 10.0}, "pt(GeV)"}; + AxisSpec axisMultiplicity{{0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "Centrality (%)"}; + AxisSpec axisOmegaminusMass{{1.63, 1.635, 1.64, 1.645, 1.65, 1.655, 1.66, 1.665, 1.67, 1.675, 1.68, 1.685, 1.69, 1.695, 1.7, 1.705, 1.71}, "Mass(GeV)"}; + AxisSpec axisXiminusMass{{1.3, 1.305, 1.31, 1.315, 1.32, 1.325, 1.33, 1.335, 1.34, 1.345, 1.35, 1.355, 1.36, 1.365, 1.37}, "Mass(GeV)"}; + + Configurable cfgcheckDauTPC{"checkDauTPC", false, "check if daughter tracks have TPC match"}; + Configurable cfgCasc_rapidity{"Casc_rapidity", 0.5, "rapidity"}; + Configurable cfgNSigmaCascPion{"NSigmaCascPion", 6, "NSigmaCascPion"}; + Configurable cfgNSigmaCascProton{"NSigmaCascProton", 6, "NSigmaCascProton"}; + Configurable cfgNSigmaCascKaon{"NSigmaCascKaon", 6, "NSigmaCascKaon"}; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + + // Connect to ccdb + Service ccdb; + Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + + // Define output + HistogramRegistry registry{"registry"}; + + // define global variables + GFW* fGFW = new GFW(); // GFW class used from main src + std::vector corrconfigs; + + TH1D* mEfficiency = nullptr; + GFWWeights* mAcceptance = nullptr; + bool correctionsLoaded = false; + + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + + EventPlaneHelper helperEP; + std::vector vecwa = cfgvecwacc; + + using TracksPID = soa::Join; + using aodTracks = soa::Filtered>; // tracks filter + using aodCollisions = soa::Filtered>; // collisions filter + using DaughterTracks = soa::Join; + + // Set the pt, mult and phi Axis; + o2::framework::AxisSpec axis = axisPt; + int nPtBins = axis.binEdges.size() - 1; + double* PtBins = &(axis.binEdges)[0]; + TAxis* fPtAxis = new TAxis(nPtBins, PtBins); + + o2::framework::AxisSpec axisMult = axisMultiplicity; + int nMultBins = axisMult.binEdges.size() - 1; + double* MultBins = &(axisMult.binEdges)[0]; + TAxis* fMultAxis = new TAxis(nMultBins, MultBins); + + o2::framework::AxisSpec axisphi = cfgaxisPhi; + int nPhiBins = axisphi.binEdges.size() - 1; + double* PhiBins = &(axisphi.binEdges)[0]; + TAxis* fPhiAxis = new TAxis(nPhiBins, PhiBins); + + o2::framework::AxisSpec axisOmegamass = axisOmegaminusMass; + int nOmegaMassBins = axisOmegamass.binEdges.size() - 1; + double* OmegaMassBins = &(axisOmegamass.binEdges)[0]; + TAxis* fOmegaMass = new TAxis(nOmegaMassBins, OmegaMassBins); + + o2::framework::AxisSpec axisXimass = axisXiminusMass; + int nXiMassBins = axisXimass.binEdges.size() - 1; + double* XiMassBins = &(axisXimass.binEdges)[0]; + TAxis* fXiMass = new TAxis(nXiMassBins, XiMassBins); + + void init(InitContext const&) // Initialization + { + ccdb->setURL(url.value); + ccdb->setCaching(true); + ccdb->setCreatedNotAfter(nolaterthan.value); + + // Add some output objects to the histogram registry + registry.add("hPhi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hEta", "", {HistType::kTH1D, {cfgaxisEta}}); + registry.add("hVtxZ", "", {HistType::kTH1D, {cfgaxisVertex}}); + registry.add("hMult", "", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); + registry.add("hCent", "", {HistType::kTH1D, {{90, 0, 90}}}); + registry.add("hPt", "", {HistType::kTH1D, {axisPt}}); + registry.add("hEtaPhiREF", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); + registry.add("hEtaPhiPOIXi", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); + registry.add("hEtaPhiPOIOmega", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); + // cumulant of flow + registry.add("c22", ";Centrality (%) ; C_{2}{2}", {HistType::kTProfile, {axisMultiplicity}}); + registry.add("c24", ";Centrality (%) ; C_{2}{4}", {HistType::kTProfile, {axisMultiplicity}}); + // pt-diff cumulant of flow + registry.add("Xic22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {axisPt, axisXiminusMass, axisMultiplicity}}); + registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {axisPt, axisOmegaminusMass, axisMultiplicity}}); + // InvMass(GeV) of casc + registry.add("InvMassOmegaMinus", "", {HistType::kTHnSparseF, {axisPt, axisOmegaminusMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassXiMinus", "", {HistType::kTHnSparseF, {axisPt, axisXiminusMass, cfgaxisEta, axisMultiplicity}}); + + fGFW->AddRegion("full", -0.8, 0.8, 1, 1); // ("name", etamin, etamax, ptbinnum, bitmask)eta region -0.8 to 0.8 + // with (-0.5, 0.5) eta gap + fGFW->AddRegion("refN10", -0.8, -0.5, 1, 1); + fGFW->AddRegion("refP10", 0.5, 0.8, 1, 1); + int nXiptMassBins = nPtBins * nXiMassBins; + fGFW->AddRegion("poiXiP", 0.5, 0.8, nXiptMassBins, 2); + int nOmegaptMassBins = nPtBins * nOmegaMassBins; + fGFW->AddRegion("poiOmegaP", 0.5, 0.8, nOmegaptMassBins, 4); + // pushback + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {2} refN10 {-2}", "ChFull220", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {2 2} refN10 {-2 -2}", "ChFull240", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiP {2} refN10 {-2}", "Ch10Gap22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaP {2} refN10 {-2}", "Ch10Gap22", kTRUE)); + // + fGFW->CreateRegions(); // finalize the initialization + + // used for event selection + fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6must ]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); + fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x + 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); + fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 3.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); + fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); + } + + template + void FillProfile(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const double& cent) + { + float dnx = 0; + float val = 0; + dnx = fGFW->Calculate(corrconf, 0, kTRUE).real(); + if (dnx == 0) + return; + if (!corrconf.pTDif) { + val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; + if (TMath::Abs(val) < 1) { + registry.fill(tarName, cent, val, dnx); + } + return; + } + return; + } + + template + void FillProfilepT(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const int& ptbin, const int& partical, const float& cent) + { + int nMassBins = 0; + TAxis* fMass = nullptr; + if (partical == 3312) { + nMassBins = nXiMassBins; + fMass = fXiMass; + } else if (partical == 3334) { + nMassBins = nOmegaMassBins; + fMass = fOmegaMass; + } else { + LOGF(error, "Error, partical = 3312 for Xi and 3334 for Omega"); + return; + } + for (int massbin = 1; massbin <= nMassBins; massbin++) { + float dnx = 0; + float val = 0; + dnx = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nPtBins), kTRUE).real(); + if (dnx == 0) + continue; + val = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nPtBins), kFALSE).real() / dnx; + if (TMath::Abs(val) < 1) { + registry.fill(tarName, fPtAxis->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); + } + } + return; + } + + void loadCorrections(uint64_t timestamp) + { + if (correctionsLoaded) + return; + if (cfgAcceptance.value.empty() == false) { + mAcceptance = ccdb->getForTimeStamp(cfgAcceptance, timestamp); + if (mAcceptance) + LOGF(info, "Loaded acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance); + else + LOGF(warning, "Could not load acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance); + } + if (cfgEfficiency.value.empty() == false) { + mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (mEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)mEfficiency); + } + correctionsLoaded = true; + } + + template + bool setCurrentParticleWeights(float& weight_nue, float& weight_nua, TrackObject track, float vtxz) + { + float eff = 1.; + if (mEfficiency) + eff = mEfficiency->GetBinContent(mEfficiency->FindBin(track.pt())); + else + eff = 1.0; + if (eff == 0) + return false; + weight_nue = 1. / eff; + if (mAcceptance) + weight_nua = mAcceptance->GetNUA(track.phi(), track.eta(), vtxz); + else + weight_nua = 1; + return true; + } + // event selection + template + bool eventSelected(TCollision collision, const int multTrk, const float centrality) + { + if (collision.alias_bit(kTVXinTRD)) { + // TRD triggered + return false; + } + if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + // reject collisions close to Time Frame borders + // https://its.cern.ch/jira/browse/O2-4623 + return false; + } + if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + // reject events affected by the ITS ROF border + // https://its.cern.ch/jira/browse/O2-4309 + return false; + } + if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // rejects collisions which are associated with the same "found-by-T0" bunch crossing + // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof + return false; + } + if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference + // use this cut at low multiplicities with caution + return false; + } + float vtxz = -999; + if (collision.numContrib() > 1) { + vtxz = collision.posZ(); + float zRes = TMath::Sqrt(collision.covZZ()); + if (zRes > 0.25 && collision.numContrib() < 20) + vtxz = -999; + } + auto multNTracksPV = collision.multNTracksPV(); + + if (abs(vtxz) > cfgCutVertex) + return false; + if (multNTracksPV < fMultPVCutLow->Eval(centrality)) + return false; + if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) + return false; + if (multTrk < fMultCutLow->Eval(centrality)) + return false; + if (multTrk > fMultCutHigh->Eval(centrality)) + return false; + + // V0A T0A 5 sigma cut + if (abs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A())) + return 0; + + return true; + } + + void process(aodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, aodTracks const& tracks, aod::CascDataExt const& Cascades, DaughterTracks&) + { + int Ntot = tracks.size(); + if (Ntot < 1) + return; + fGFW->Clear(); + const auto cent = collision.centFT0C(); + + if (eventSelected(collision, tracks.size(), cent)) + return; + auto bc = collision.bc_as(); + loadCorrections(bc.timestamp()); + float vtxz = collision.posZ(); + registry.fill(HIST("hVtxZ"), vtxz); + registry.fill(HIST("hMult"), Ntot); + registry.fill(HIST("hCent"), collision.centFT0C()); + + float weff = 1; + float wacc = 1; + // fill GFW ref flow + for (auto& track : tracks) { + if (!setCurrentParticleWeights(weff, wacc, track, vtxz)) + continue; + int phibin = fPhiAxis->FindBin(track.phi()) - 1; + wacc = 1 / vecwa[phibin]; + registry.fill(HIST("hPhi"), track.phi()); + registry.fill(HIST("hEta"), track.eta()); + registry.fill(HIST("hEtaPhiREF"), track.eta(), track.phi()); + registry.fill(HIST("hPt"), track.pt()); + int ptbin = fPtAxis->FindBin(track.pt()) - 1; + if ((track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)) { + fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) + } + } + // fill GFW of casc flow + for (auto& casc : Cascades) { + auto bachelor = casc.bachelor_as(); + auto posdau = casc.posTrack_as(); + auto negdau = casc.negTrack_as(); + // check TPC + if (cfgcheckDauTPC && (!posdau.hasTPC() || !negdau.hasTPC() || !bachelor.hasTPC())) { + continue; + } + if (TMath::Abs(casc.yOmega()) < cfgCasc_rapidity && TMath::Abs(bachelor.tpcNSigmaKa()) < cfgNSigmaCascKaon && TMath::Abs(posdau.tpcNSigmaPr()) < cfgNSigmaCascProton && TMath::Abs(negdau.tpcNSigmaPi()) < cfgNSigmaCascPion) { + registry.fill(HIST("hEtaPhiPOIOmega"), casc.eta(), casc.phi()); + registry.fill(HIST("InvMassOmegaMinus"), casc.pt(), casc.mOmega(), casc.eta(), cent); + if ((casc.pt() < cfgCutPtPOIMax) && (casc.pt() > cfgCutPtPOIMin) && (casc.mOmega() > 1.63) && (casc.mOmega() < 1.71)) { + fGFW->Fill(casc.eta(), fPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nPtBins), casc.phi(), wacc * weff, 4); + } + } + if (TMath::Abs(casc.yXi()) < cfgCasc_rapidity && TMath::Abs(bachelor.tpcNSigmaKa()) < cfgNSigmaCascKaon && TMath::Abs(posdau.tpcNSigmaPr()) < cfgNSigmaCascProton && TMath::Abs(negdau.tpcNSigmaPi()) < cfgNSigmaCascPion) { + registry.fill(HIST("hEtaPhiPOIXi"), casc.eta(), casc.phi()); + registry.fill(HIST("InvMassXiMinus"), casc.pt(), casc.mXi(), casc.eta(), cent); + if ((casc.pt() < cfgCutPtPOIMax) && (casc.pt() > cfgCutPtPOIMin) && (casc.mXi() > 1.30) && (casc.mXi() < 1.37)) { + fGFW->Fill(casc.eta(), fPtAxis->FindBin(casc.pt()) - 1 + ((fXiMass->FindBin(casc.mXi()) - 1) * nPtBins), casc.phi(), wacc * weff, 2); + } + } + } + // Filling cumulant with ROOT TProfile + FillProfile(corrconfigs.at(0), HIST("c22"), cent); + FillProfile(corrconfigs.at(1), HIST("c24"), cent); + for (int i = 1; i <= nPtBins; i++) // loop for all ptBins + { + FillProfilepT(corrconfigs.at(2), HIST("Xic22dpt"), i, 3312, cent); + FillProfilepT(corrconfigs.at(3), HIST("Omegac22dpt"), i, 3334, cent); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/GenericFramework/Core/FlowPtContainer.cxx b/PWGCF/GenericFramework/Core/FlowPtContainer.cxx index d7b6b8dd114..6088da403a4 100644 --- a/PWGCF/GenericFramework/Core/FlowPtContainer.cxx +++ b/PWGCF/GenericFramework/Core/FlowPtContainer.cxx @@ -20,8 +20,12 @@ FlowPtContainer::FlowPtContainer() : TNamed("name", "name"), mpar(0), fillCounter(0), fEventWeight(kEventWeight::kUnity), + fUseCentralMoments(true), + sumP(), corrNum(), - corrDen() {} + corrDen(), + cmNum(), + cmDen() {} FlowPtContainer::~FlowPtContainer() { delete fCMTermList; @@ -36,8 +40,12 @@ FlowPtContainer::FlowPtContainer(const char* name) : TNamed(name, name), mpar(0), fillCounter(0), fEventWeight(kEventWeight::kUnity), + fUseCentralMoments(true), + sumP(), corrNum(), - corrDen() {} + corrDen(), + cmNum(), + cmDen() {} FlowPtContainer::FlowPtContainer(const char* name, const char* title, int nbinsx, double* xbins, const int& m, const GFWCorrConfigs& configs) : TNamed(name, title), fCMTermList(0), fCorrList(0), @@ -47,8 +55,12 @@ FlowPtContainer::FlowPtContainer(const char* name, const char* title, int nbinsx mpar(m), fillCounter(0), fEventWeight(kEventWeight::kUnity), + fUseCentralMoments(true), + sumP(), corrNum(), - corrDen() + corrDen(), + cmNum(), + cmDen() { Initialise(nbinsx, xbins, m, configs); }; @@ -61,8 +73,12 @@ FlowPtContainer::FlowPtContainer(const char* name, const char* title, int nbinsx mpar(m), fillCounter(0), fEventWeight(kEventWeight::kUnity), + fUseCentralMoments(true), + sumP(), corrNum(), - corrDen() + corrDen(), + cmNum(), + cmDen() { Initialise(nbinsx, xlow, xhigh, m, configs); }; @@ -90,17 +106,25 @@ void FlowPtContainer::Initialise(const o2::framework::AxisSpec axis, const int& delete fCovList; fCovList = new TList(); fCovList->SetOwner(kTRUE); - for (int m = 0; m < mpar; ++m) + for (int m = 0; m < mpar; ++m) { fCorrList->Add(new BootstrapProfile(Form("mpt%i", m + 1), Form("corr_%ipar", m + 1), nMultiBins, &multiBins[0])); + } for (int m = 0; m < 4; ++m) { - for (int i = 0; i <= m; ++i) + for (int i = 0; i <= m; ++i) { fCMTermList->Add(new BootstrapProfile(Form("cm%i_Mpt%i", m + 1, i), Form("cm%i_Mpt%i", m + 1, i), nMultiBins, &multiBins[0])); + } } for (int i = 0; i < configs.GetSize(); ++i) { for (auto m(1); m <= mpar; ++m) { if (!(configs.GetpTCorrMasks()[i] & (1 << (m - 1)))) continue; - fCovList->Add(new BootstrapProfile(Form("%s_mpt%i", configs.GetHeads()[i].c_str(), m), Form("%s_mpt%i", configs.GetHeads()[i].c_str(), m), nMultiBins, &multiBins[0])); + if (fUseCentralMoments) { + for (auto j = 0; j < m; ++j) { + fCovList->Add(new BootstrapProfile(Form("%spt%i_Mpt%i", configs.GetHeads()[i].c_str(), m, m - j - 1), Form("%spt%i_Mpt%i", configs.GetHeads()[i].c_str(), m, m - j - 1), nMultiBins, &multiBins[0])); + } + } else { + fCovList->Add(new BootstrapProfile(Form("%spt%i", configs.GetHeads()[i].c_str(), m), Form("%spt%i", configs.GetHeads()[i].c_str(), m), nMultiBins, &multiBins[0])); + } } } if (nsub) { @@ -126,17 +150,25 @@ void FlowPtContainer::Initialise(int nbinsx, double* xbins, const int& m, const delete fCorrList; fCorrList = new TList(); fCorrList->SetOwner(kTRUE); - for (int m = 0; m < mpar; ++m) + for (int m = 0; m < mpar; ++m) { fCorrList->Add(new BootstrapProfile(Form("mpt%i", m + 1), Form("mpt%i", m + 1), nbinsx, xbins)); + } for (int m = 0; m < 4; ++m) { - for (int i = 0; i <= m; ++i) + for (int i = 0; i <= m; ++i) { fCMTermList->Add(new BootstrapProfile(Form("cm%i_Mpt%i", m + 1, i), Form("cm%i_Mpt%i", m + 1, i), nbinsx, xbins)); + } } for (int i = 0; i < configs.GetSize(); ++i) { for (auto m(1); m <= mpar; ++m) { if (!(configs.GetpTCorrMasks()[i] & (1 << (m - 1)))) continue; - fCovList->Add(new BootstrapProfile(Form("%s_mpt%i", configs.GetHeads()[i].c_str(), m + 1), Form("%s_mpt%i", configs.GetHeads()[i].c_str(), m + 1), nbinsx, xbins)); + if (fUseCentralMoments) { + for (auto j = 0; j < m; ++j) { + fCovList->Add(new BootstrapProfile(Form("%spt%i_Mpt%i", configs.GetHeads()[i].c_str(), m, m - j - 1), Form("%spt%i_Mpt%i", configs.GetHeads()[i].c_str(), m, m - j - 1), nbinsx, xbins)); + } + } else { + fCovList->Add(new BootstrapProfile(Form("%spt%i", configs.GetHeads()[i].c_str(), m), Form("%spt%i", configs.GetHeads()[i].c_str(), m), nbinsx, xbins)); + } } } if (nsub) { @@ -161,17 +193,25 @@ void FlowPtContainer::Initialise(int nbinsx, double xlow, double xhigh, const in delete fCorrList; fCorrList = new TList(); fCorrList->SetOwner(kTRUE); - for (int m = 0; m < mpar; ++m) + for (int m = 0; m < mpar; ++m) { fCorrList->Add(new BootstrapProfile(Form("mpt%i", m + 1), Form("mpt%i", m + 1), nbinsx, xlow, xhigh)); + } for (int m = 0; m < 4; ++m) { - for (int i = 0; i <= m; ++i) + for (int i = 0; i <= m; ++i) { fCMTermList->Add(new BootstrapProfile(Form("cm%i_Mpt%i", m + 1, i), Form("cm%i_Mpt%i", m + 1, i), nbinsx, xlow, xhigh)); + } } for (int i = 0; i < configs.GetSize(); ++i) { for (auto m(1); m <= mpar; ++m) { if (!(configs.GetpTCorrMasks()[i] & (1 << (m - 1)))) continue; - fCovList->Add(new BootstrapProfile(Form("%s_mpt%i", configs.GetHeads()[i].c_str(), m + 1), Form("%s_mpt%i", configs.GetHeads()[i].c_str(), m + 1), nbinsx, xlow, xhigh)); + if (fUseCentralMoments) { + for (auto j = 0; j < m; ++j) { + fCovList->Add(new BootstrapProfile(Form("%spt%i_Mpt%i", configs.GetHeads()[i].c_str(), m, m - j - 1), Form("%spt%i_Mpt%i", configs.GetHeads()[i].c_str(), m, m - j - 1), nbinsx, xlow, xhigh)); + } + } else { + fCovList->Add(new BootstrapProfile(Form("%spt%i", configs.GetHeads()[i].c_str(), m), Form("%spt%i", configs.GetHeads()[i].c_str(), m), nbinsx, xlow, xhigh)); + } } } if (nsub) { @@ -186,7 +226,7 @@ void FlowPtContainer::Initialise(int nbinsx, double xlow, double xhigh, const in }; void FlowPtContainer::Fill(const double& w, const double& pt) { - for (auto i = 0; i < sumP.size(); ++i) { + for (size_t i = 0; i < sumP.size(); ++i) { sumP[i] += pow(w, i % (mpar + 1)) * pow(pt, i / (mpar + 1)); } return; @@ -226,7 +266,7 @@ void FlowPtContainer::FillPtProfiles(const double& centmult, const double& rn) } return; } -void FlowPtContainer::FillVnPtProfiles(const double& centmult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask) +void FlowPtContainer::FillVnPtCorrProfiles(const double& centmult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask) { if (!mask) return; @@ -239,6 +279,21 @@ void FlowPtContainer::FillVnPtProfiles(const double& centmult, const double& flo } return; } +void FlowPtContainer::FillVnDeltaPtProfiles(const double& centmult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask) +{ + if (!mask) + return; + for (auto m(1); m <= mpar; ++m) { + if (!(mask & (1 << (m - 1)))) + continue; + for (auto i = 0; i < m; ++i) { + if (cmDen[m - 1] != 0) + dynamic_cast(fCovList->At(fillCounter))->FillProfile(centmult, flowval * cmNum[m * (m - 1) / 2 + (m - i)], (fEventWeight == kUnity) ? 1.0 : flowtuples * cmDen[m - 1], rn); + ++fillCounter; + } + } + return; +} void FlowPtContainer::FillCMProfiles(const double& centmult, const double& rn) { if (sumP[GetVectorIndex(0, 0)] == 0) @@ -247,35 +302,46 @@ void FlowPtContainer::FillCMProfiles(const double& centmult, const double& rn) double tau2 = sumP[GetVectorIndex(3, 0)] / pow(sumP[GetVectorIndex(1, 0)], 3); double tau3 = sumP[GetVectorIndex(4, 0)] / pow(sumP[GetVectorIndex(1, 0)], 4); // double tau4 = sumP[GetVectorIndex(5,0)]/pow(sumP[GetVectorIndex(1,0)],5); - double weight1 = 1 - tau1; - double weight2 = 1 - 3 * tau1 + 2 * tau2; - double weight3 = 1 - 6 * tau1 + 3 * tau1 * tau1 + 8 * tau2 - 6 * tau3; + cmDen.push_back(sumP[GetVectorIndex(1, 0)]); + cmDen.push_back(1 - tau1); + cmDen.push_back(1 - 3 * tau1 + 2 * tau2); + cmDen.push_back(1 - 6 * tau1 + 3 * tau1 * tau1 + 8 * tau2 - 6 * tau3); // double weight4 = 1 - 10*tau1 + 15*tau1*tau1 + 20*tau2 - 20*tau1*tau2 - 30*tau3 + 24*tau4; - if (mpar < 1 || sumP[GetVectorIndex(1, 0)] == 0) + if (mpar < 1 || cmDen[0] == 0) return; - dynamic_cast(fCMTermList->At(0))->FillProfile(centmult, sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)], (fEventWeight == kEventWeight::kUnity) ? 1.0 : sumP[GetVectorIndex(1, 0)], rn); - if (mpar < 2 || sumP[GetVectorIndex(2, 0)] == 0 || weight1 == 0) + cmNum.push_back(sumP[GetVectorIndex(1, 1)] / cmDen[0]); + dynamic_cast(fCMTermList->At(0))->FillProfile(centmult, cmNum[0], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[0], rn); + if (mpar < 2 || sumP[GetVectorIndex(2, 0)] == 0 || cmDen[1] == 0) return; - dynamic_cast(fCMTermList->At(1))->FillProfile(centmult, 1 / weight1 * (sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight1, rn); - dynamic_cast(fCMTermList->At(2))->FillProfile(centmult, 1 / weight1 * (-2 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 2 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight1, rn); - if (mpar < 3 || sumP[GetVectorIndex(3, 0)] == 0 || weight2 == 0) + cmNum.push_back(1 / cmDen[1] * (sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)])); + dynamic_cast(fCMTermList->At(1))->FillProfile(centmult, cmNum[1], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[1], rn); + cmNum.push_back(1 / cmDen[1] * (-2 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 2 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)])); + dynamic_cast(fCMTermList->At(2))->FillProfile(centmult, cmNum[2], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[1], rn); + if (mpar < 3 || sumP[GetVectorIndex(3, 0)] == 0 || cmDen[2] == 0) return; - dynamic_cast(fCMTermList->At(3))->FillProfile(centmult, 1 / weight2 * (sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 3 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 2 * tau2 * sumP[GetVectorIndex(3, 3)] / sumP[GetVectorIndex(3, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight2, rn); - dynamic_cast(fCMTermList->At(4))->FillProfile(centmult, 1 / weight2 * (-3 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 3 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] + 6 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau2 * sumP[GetVectorIndex(3, 2)] / sumP[GetVectorIndex(3, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight2, rn); - dynamic_cast(fCMTermList->At(5))->FillProfile(centmult, 1 / weight2 * (3 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] - 3 * tau1 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 6 * tau2 * sumP[GetVectorIndex(3, 1)] / sumP[GetVectorIndex(3, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight2, rn); - if (mpar < 4 || sumP[GetVectorIndex(4, 0)] == 0 || weight3 == 0) + cmNum.push_back(1 / cmDen[2] * (sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 3 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 2 * tau2 * sumP[GetVectorIndex(3, 3)] / sumP[GetVectorIndex(3, 0)])); + dynamic_cast(fCMTermList->At(3))->FillProfile(centmult, cmNum[3], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[2], rn); + cmNum.push_back(1 / cmDen[2] * (-3 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 3 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] + 6 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau2 * sumP[GetVectorIndex(3, 2)] / sumP[GetVectorIndex(3, 0)])); + dynamic_cast(fCMTermList->At(4))->FillProfile(centmult, cmNum[4], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[2], rn); + cmNum.push_back(1 / cmDen[2] * (3 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] - 3 * tau1 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 6 * tau2 * sumP[GetVectorIndex(3, 1)] / sumP[GetVectorIndex(3, 0)])); + dynamic_cast(fCMTermList->At(5))->FillProfile(centmult, cmNum[5], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[2], rn); + if (mpar < 4 || sumP[GetVectorIndex(4, 0)] == 0 || cmDen[3] == 0) return; - dynamic_cast(fCMTermList->At(6))->FillProfile(centmult, 1 / weight3 * (sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 3 * tau1 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] + 8 * tau2 * sumP[GetVectorIndex(3, 3)] / sumP[GetVectorIndex(3, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau3 * sumP[GetVectorIndex(4, 4)] / sumP[GetVectorIndex(4, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight3, rn); - dynamic_cast(fCMTermList->At(7))->FillProfile(centmult, 1 / weight3 * (-4 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 12 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 12 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 12 * tau1 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] - 8 * tau2 * sumP[GetVectorIndex(3, 3)] / sumP[GetVectorIndex(3, 0)] - 24 * tau2 * sumP[GetVectorIndex(3, 2)] / sumP[GetVectorIndex(3, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 24 * tau3 * sumP[GetVectorIndex(4, 3)] / sumP[GetVectorIndex(4, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight3, rn); - dynamic_cast(fCMTermList->At(8))->FillProfile(centmult, 1 / weight3 * (6 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] - 24 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 6 * tau1 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] + 12 * tau1 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] + 24 * tau2 * sumP[GetVectorIndex(3, 2)] / sumP[GetVectorIndex(3, 0)] + 24 * tau2 * sumP[GetVectorIndex(3, 1)] / sumP[GetVectorIndex(3, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 36 * tau3 * sumP[GetVectorIndex(4, 2)] / sumP[GetVectorIndex(4, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight3, rn); - dynamic_cast(fCMTermList->At(9))->FillProfile(centmult, 1 / weight3 * (-4 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 12 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] + 12 * tau1 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 12 * tau1 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] - 24 * tau2 * sumP[GetVectorIndex(3, 1)] / sumP[GetVectorIndex(3, 0)] - 8 * tau2 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 24 * tau3 * sumP[GetVectorIndex(4, 1)] / sumP[GetVectorIndex(4, 0)]), (fEventWeight == kEventWeight::kUnity) ? 1.0 : weight3, rn); + cmNum.push_back(1 / cmDen[3] * (sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 3 * tau1 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] + 8 * tau2 * sumP[GetVectorIndex(3, 3)] / sumP[GetVectorIndex(3, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau3 * sumP[GetVectorIndex(4, 4)] / sumP[GetVectorIndex(4, 0)])); + dynamic_cast(fCMTermList->At(6))->FillProfile(centmult, cmNum[6], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[3], rn); + cmNum.push_back(1 / cmDen[3] * (-4 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 12 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 12 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 12 * tau1 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] - 8 * tau2 * sumP[GetVectorIndex(3, 3)] / sumP[GetVectorIndex(3, 0)] - 24 * tau2 * sumP[GetVectorIndex(3, 2)] / sumP[GetVectorIndex(3, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 24 * tau3 * sumP[GetVectorIndex(4, 3)] / sumP[GetVectorIndex(4, 0)])); + dynamic_cast(fCMTermList->At(7))->FillProfile(centmult, cmNum[7], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[3], rn); + cmNum.push_back(1 / cmDen[3] * (6 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] - 24 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 6 * tau1 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 6 * tau1 * tau1 * sumP[GetVectorIndex(2, 2)] / sumP[GetVectorIndex(2, 0)] + 12 * tau1 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] + 24 * tau2 * sumP[GetVectorIndex(3, 2)] / sumP[GetVectorIndex(3, 0)] + 24 * tau2 * sumP[GetVectorIndex(3, 1)] / sumP[GetVectorIndex(3, 0)] * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 36 * tau3 * sumP[GetVectorIndex(4, 2)] / sumP[GetVectorIndex(4, 0)])); + dynamic_cast(fCMTermList->At(8))->FillProfile(centmult, cmNum[8], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[3], rn); + cmNum.push_back(1 / cmDen[3] * (-4 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 12 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] + 12 * tau1 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] - 12 * tau1 * tau1 * sumP[GetVectorIndex(2, 1)] / sumP[GetVectorIndex(2, 0)] - 24 * tau2 * sumP[GetVectorIndex(3, 1)] / sumP[GetVectorIndex(3, 0)] - 8 * tau2 * sumP[GetVectorIndex(1, 1)] / sumP[GetVectorIndex(1, 0)] + 24 * tau3 * sumP[GetVectorIndex(4, 1)] / sumP[GetVectorIndex(4, 0)])); + dynamic_cast(fCMTermList->At(9))->FillProfile(centmult, cmNum[9], (fEventWeight == kEventWeight::kUnity) ? 1.0 : cmDen[3], rn); return; } double FlowPtContainer::OrderedAddition(std::vector vec) { double sum = 0; std::sort(vec.begin(), vec.end()); - for (int i = 0; i < vec.size(); i++) { + for (size_t i = 0; i < vec.size(); i++) { sum += vec[i]; } return sum; diff --git a/PWGCF/GenericFramework/Core/FlowPtContainer.h b/PWGCF/GenericFramework/Core/FlowPtContainer.h index 981c1d0540c..18cf8ae82ea 100644 --- a/PWGCF/GenericFramework/Core/FlowPtContainer.h +++ b/PWGCF/GenericFramework/Core/FlowPtContainer.h @@ -49,11 +49,22 @@ class FlowPtContainer : public TNamed void CalculateCorrelations(); void CalculateCMTerms(); void FillPtProfiles(const Double_t& lMult, const Double_t& rn); - void FillVnPtProfiles(const double& lMult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask); + void FillVnPtCorrProfiles(const double& lMult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask); + void FillVnDeltaPtProfiles(const double& centmult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask); + void FillVnPtProfiles(const double& centmult, const double& flowval, const double& flowtuples, const double& rn, uint8_t mask) + { + if (fUseCentralMoments) + FillVnDeltaPtProfiles(centmult, flowval, flowtuples, rn, mask); + else + FillVnPtCorrProfiles(centmult, flowval, flowtuples, rn, mask); + } void FillCMProfiles(const double& lMult, const double& rn); TList* GetCorrList() { return fCorrList; } TList* GetCMTermList() { return fCMTermList; } + TList* GetCovList() { return fCovList; } void SetEventWeight(const unsigned int& lWeight) { fEventWeight = lWeight; } + void SetUseCentralMoments(bool newval) { fUseCentralMoments = newval; } + bool usesCentralMoments() { return fUseCentralMoments; } void RebinMulti(Int_t nbins); void RebinMulti(Int_t nbins, double* binedges); TH1* getCentralMomentHist(int ind, int m); @@ -70,6 +81,8 @@ class FlowPtContainer : public TNamed { sumP.clear(); sumP.resize((mpar + 1) * (mpar + 1)); + cmNum.clear(); + cmDen.clear(); fillCounter = 0; }; @@ -82,11 +95,14 @@ class FlowPtContainer : public TNamed int mpar; int fillCounter; unsigned int fEventWeight; + bool fUseCentralMoments; void MergeBSLists(TList* source, TList* target); TH1* raiseHistToPower(TH1* inh, double p); std::vector sumP; //! std::vector corrNum; //! std::vector corrDen; //! + std::vector cmNum; //! + std::vector cmDen; //! static constexpr float fFactorial[9] = {1., 1., 2., 6., 24., 120., 720., 5040., 40320.}; static constexpr int fSign[9] = {1, -1, 1, -1, 1, -1, 1, -1, 1}; diff --git a/PWGCF/GenericFramework/Core/GFWConfig.h b/PWGCF/GenericFramework/Core/GFWConfig.h index 9c086acbef1..779d06b604e 100644 --- a/PWGCF/GenericFramework/Core/GFWConfig.h +++ b/PWGCF/GenericFramework/Core/GFWConfig.h @@ -35,7 +35,7 @@ int CheckSameSize(const std::vector& first) template int CheckSameSize(const std::vector& first, const std::vector&... rest) { - int size = first.size(); + size_t size = first.size(); bool allSameSize = ((size == rest.size()) && ...); return allSameSize ? size : -1; @@ -145,7 +145,7 @@ class GFWRegions auto Print() const { - for (auto i = 0; i < names.size(); ++i) { + for (size_t i = 0; i < names.size(); ++i) { LOGF(info, "{%s, %.1f, %.1f, %d, %d}", names[i].c_str(), etaminvals[i], etamaxvals[i], pTDifs[i], bitmasks[i]); } return; @@ -190,7 +190,7 @@ class GFWCorrConfigs auto Print() const { - for (auto i = 0; i < corrs.size(); ++i) { + for (size_t i = 0; i < corrs.size(); ++i) { LOGF(info, "{%s,%s,%d,%d}", heads[i].c_str(), corrs[i].c_str(), pTDifs[i], pTCorrMasks[i]); } return; diff --git a/PWGCF/GenericFramework/Core/GFWPowerArray.cxx b/PWGCF/GenericFramework/Core/GFWPowerArray.cxx index 82291e507a2..609b235ec6f 100644 --- a/PWGCF/GenericFramework/Core/GFWPowerArray.cxx +++ b/PWGCF/GenericFramework/Core/GFWPowerArray.cxx @@ -52,7 +52,7 @@ void GFWPowerArray::RecursiveFunction(HarSet& masterVector, HarSet hars, int off { HarSet compVec = AddConstant(hars, offset); FlushVectorToMaster(masterVector, compVec, MaxPower); - for (int i = 0; i < hars.size(); i++) + for (size_t i = 0; i < hars.size(); i++) RecursiveFunction(masterVector, TrimVec(hars, i), offset + hars.at(i), MaxPower); ; }; diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index d18d08309bf..5bc41f81886 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -83,6 +83,7 @@ struct GenericFramework { O2_DEFINE_CONFIGURABLE(cfgFillQA, bool, false, "Fill QA histograms") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, false, "Use additional track cut on phi") + O2_DEFINE_CONFIGURABLE(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgDCAxy, float, 0.2, "Cut on DCA in the transverse direction (cm)"); @@ -239,6 +240,7 @@ struct GenericFramework { fFC_gen->Initialize(oba, multAxis, cfgNbootstrap); } delete oba; + fFCpt->SetUseCentralMoments(cfgUseCentralMoments); fFCpt->Initialise(multAxis, cfgMpar, configs, cfgNbootstrap); // Event selection - Alex if (cfgUseAdditionalEventCut) { diff --git a/PWGCF/JCorran/Core/CMakeLists.txt b/PWGCF/JCorran/Core/CMakeLists.txt index 9f6f99e9e74..6c4e10529bb 100644 --- a/PWGCF/JCorran/Core/CMakeLists.txt +++ b/PWGCF/JCorran/Core/CMakeLists.txt @@ -14,6 +14,7 @@ o2physics_add_library(JCorran JFFlucAnalysisO2Hist.cxx FlowJSPCAnalysis.cxx FlowJHistManager.cxx + JEPFlowAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) o2physics_target_root_dictionary(JCorran @@ -22,4 +23,5 @@ o2physics_target_root_dictionary(JCorran FlowJHistManager.h FlowJSPCAnalysis.h FlowJSPCObservables.h + JEPFlowAnalysis.h LINKDEF JCORRANLinkDef.h) diff --git a/PWGCF/JCorran/Core/JCORRANLinkDef.h b/PWGCF/JCorran/Core/JCORRANLinkDef.h index 7cadfacca79..d0e9bef308d 100755 --- a/PWGCF/JCorran/Core/JCORRANLinkDef.h +++ b/PWGCF/JCorran/Core/JCORRANLinkDef.h @@ -21,5 +21,6 @@ #pragma link C++ class FlowJHistManager + ; #pragma link C++ class FlowJSPCAnalysis + ; #pragma link C++ class FlowJSPCObservables + ; +#pragma link C++ class JEPFlowAnalysis + ; #endif // PWGCF_JCORRAN_CORE_JCORRANLINKDEF_H_ diff --git a/PWGCF/JCorran/Core/JEPFlowAnalysis.cxx b/PWGCF/JCorran/Core/JEPFlowAnalysis.cxx new file mode 100644 index 00000000000..6d027002e8c --- /dev/null +++ b/PWGCF/JCorran/Core/JEPFlowAnalysis.cxx @@ -0,0 +1,43 @@ +// Copyright 2019-2020 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. + +#include "JEPFlowAnalysis.h" + +using namespace o2; +using namespace o2::framework; +using namespace std; + +void JEPFlowAnalysis::FillVnHistograms(const Int_t harmN, Float_t cent, Float_t det, Float_t pT, Float_t vn, Float_t vn_sin) +{ + switch (harmN) { + case 2: { + mHistRegistry->fill(HIST("fV2EP"), vn, det, pT, cent, 1.); + mHistRegistry->fill(HIST("fV2EP_sin"), vn_sin, det, pT, cent, 1.); + } break; + case 3: { + mHistRegistry->fill(HIST("fV3EP"), vn, det, pT, cent, 1.); + mHistRegistry->fill(HIST("fV3EP_sin"), vn_sin, det, pT, cent, 1.); + } break; + case 4: { + mHistRegistry->fill(HIST("fV4EP"), vn, det, pT, cent, 1.); + mHistRegistry->fill(HIST("fV4EP_sin"), vn_sin, det, pT, cent, 1.); + } break; + default: + break; + } +} + +void JEPFlowAnalysis::FillResolutionHistograms(Float_t cent, Float_t harmN, Float_t ResNumA, Float_t ResNumB, Float_t ResDenom) +{ + mHistRegistry->fill(HIST("fResNumA"), ResNumA, harmN, cent, 1.); + mHistRegistry->fill(HIST("fResNumB"), ResNumB, harmN, cent, 1.); + mHistRegistry->fill(HIST("fResDenom"), ResDenom, harmN, cent, 1.); +} diff --git a/PWGCF/JCorran/Core/JEPFlowAnalysis.h b/PWGCF/JCorran/Core/JEPFlowAnalysis.h new file mode 100644 index 00000000000..f1bc994099c --- /dev/null +++ b/PWGCF/JCorran/Core/JEPFlowAnalysis.h @@ -0,0 +1,63 @@ +// Copyright 2019-2020 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. + +// \author Maxim Virta (maxim.virta@cern.ch) + +#ifndef PWGCF_JCORRAN_CORE_JEPFLOWANALYSIS_H_ +#define PWGCF_JCORRAN_CORE_JEPFLOWANALYSIS_H_ + +#include + +// O2 headers. // +#include "Framework/HistogramRegistry.h" + +using namespace o2; +using namespace o2::framework; +using namespace std; + +class JEPFlowAnalysis +{ + public: + JEPFlowAnalysis() = default; + void SetHistRegistry(HistogramRegistry* histReg) { mHistRegistry = histReg; } + + void FillHistograms(const Int_t fCentBin, Float_t det, Float_t v2, Float_t v3, Float_t v4); + void FillVnHistograms(const Int_t harmN, Float_t fCent, Float_t det, Float_t pT, Float_t vn, Float_t vn_sin); + void FillResolutionHistograms(Float_t fCent, Float_t harmN, Float_t ResNumA, Float_t ResNumB, Float_t ResDenom); + TComplex Q(const Int_t harmN, const Int_t p); + + void CreateHistograms() + { + if (!mHistRegistry) { + LOGF(error, "Histogram registry missing. Quitting..."); + return; + } + + mHistRegistry->add("FullCentrality", "FullCentrality", HistType::kTH1D, {{100, 0., 100.}}, true); + mHistRegistry->add("fV2EP", "", {HistType::kTHnD, {{200, -1.05, 1.05}, {3, 0.5, 3.5}, {100, 0.2, 12.}, {20, 0., 100.}}}, true); // x: v2_cos, y: detector, z: pT, t: centrality + mHistRegistry->add("fV3EP", "", {HistType::kTHnD, {{200, -1.05, 1.05}, {3, 0.5, 3.5}, {100, 0.2, 12.}, {20, 0., 100.}}}, true); // x: v2_cos, y: detector, z: pT, t: centrality + mHistRegistry->add("fV4EP", "", {HistType::kTHnD, {{200, -1.05, 1.05}, {3, 0.5, 3.5}, {100, 0.2, 12.}, {20, 0., 100.}}}, true); // x: v2_cos, y: detector, z: pT, t: centrality + mHistRegistry->add("fV2EP_sin", "", {HistType::kTHnD, {{200, -1.05, 1.05}, {3, 0.5, 3.5}, {100, 0.2, 12.}, {20, 0., 100.}}}, true); // x: v2_sin, y: detector, z: pT, t: centrality + mHistRegistry->add("fV3EP_sin", "", {HistType::kTHnD, {{200, -1.05, 1.05}, {3, 0.5, 3.5}, {100, 0.2, 12.}, {20, 0., 100.}}}, true); // x: v2_sin, y: detector, z: pT, t: centrality + mHistRegistry->add("fV4EP_sin", "", {HistType::kTHnD, {{200, -1.05, 1.05}, {3, 0.5, 3.5}, {100, 0.2, 12.}, {20, 0., 100.}}}, true); // x: v2_sin, y: detector, z: pT, t: centrality + mHistRegistry->add("fResNumA", "", {HistType::kTH3D, {{100, -1.05, 1.05}, {3, 1.5, 4.5}, {20, 0., 100.}}}, true); // x: resolution, y: harmonic, t: centrality + mHistRegistry->add("fResNumB", "", {HistType::kTH3D, {{100, -1.05, 1.05}, {3, 1.5, 4.5}, {20, 0., 100.}}}, true); // x: resolution, y: harmonic, t: centrality + mHistRegistry->add("fResDenom", "", {HistType::kTH3D, {{100, -1.05, 1.05}, {3, 1.5, 4.5}, {20, 0., 100.}}}, true); // x: resolution, y: harmonic, t: centrality + mHistRegistry->add("phi", "Phi", {HistType::kTH1D, {{100, 0., TMath::TwoPi()}}}, true); + } + + private: + HistogramRegistry* mHistRegistry; + + ClassDefNV(JEPFlowAnalysis, 1); +}; + +#endif // PWGCF_JCORRAN_CORE_JEPFLOWANALYSIS_H_ diff --git a/PWGCF/JCorran/Core/JFFlucAnalysis.cxx b/PWGCF/JCorran/Core/JFFlucAnalysis.cxx index 9520751d6f1..c3ca3595718 100644 --- a/PWGCF/JCorran/Core/JFFlucAnalysis.cxx +++ b/PWGCF/JCorran/Core/JFFlucAnalysis.cxx @@ -127,7 +127,7 @@ TComplex JFFlucAnalysis::Four(int n1, int n2, int n3, int n4) #undef C //________________________________________________________________________ -void JFFlucAnalysis::UserExec(Option_t* /*popt*/) +void JFFlucAnalysis::UserExec(Option_t* /*popt*/) // NOLINT(readability/casting) false positive: https://github.com/cpplint/cpplint/issues/131 { TComplex corr[kNH][nKL]; TComplex ncorr[kNH][nKL]; @@ -282,33 +282,36 @@ void JFFlucAnalysis::UserExec(Option_t* /*popt*/) pht[HIST_THN_V7V2starV5star]->Fill(fCent, nV7V2starV5star.Re(), ebe_3p_weight); pht[HIST_THN_V7V3starV4star]->Fill(fCent, nV7V3starV4star.Re(), ebe_3p_weight); - Double_t event_weight_four = 1.0; - Double_t event_weight_two = 1.0; Double_t event_weight_two_gap = 1.0; if (flags & kFlucEbEWeighting) { - event_weight_four = Four(0, 0, 0, 0).Re(); - event_weight_two = Two(0, 0).Re(); event_weight_two_gap = (Qa[0][1] * Qb[0][1]).Re(); } for (UInt_t ih = 2; ih < kNH; ih++) { - for (UInt_t ihh = 2, mm = (ih < kcNH ? ih : static_cast(kcNH)); ihh < mm; ihh++) { - TComplex scfour = Four(ih, ihh, -ih, -ihh) / Four(0, 0, 0, 0).Re(); - - pht[HIST_THN_SC_with_QC_4corr]->Fill(fCent, ih, ihh, scfour.Re(), event_weight_four); - } - - TComplex sctwo = Two(ih, -ih) / Two(0, 0).Re(); - pht[HIST_THN_SC_with_QC_2corr]->Fill(fCent, ih, sctwo.Re(), event_weight_two); - TComplex sctwoGap = (Qa[ih][1] * TComplex::Conjugate(Qb[ih][1])) / (Qa[0][1] * Qb[0][1]).Re(); pht[HIST_THN_SC_with_QC_2corr_gap]->Fill(fCent, ih, sctwoGap.Re(), event_weight_two_gap); } } + + Double_t event_weight_four = 1.0; + Double_t event_weight_two = 1.0; + if (flags & kFlucEbEWeighting) { + event_weight_four = Four(0, 0, 0, 0).Re(); + event_weight_two = Two(0, 0).Re(); + } + + for (UInt_t ih = 2; ih < kNH; ih++) { + for (UInt_t ihh = 2, mm = (ih < kcNH ? ih : static_cast(kcNH)); ihh < mm; ihh++) { + TComplex scfour = Four(ih, ihh, -ih, -ihh) / Four(0, 0, 0, 0).Re(); + pht[HIST_THN_SC_with_QC_4corr]->Fill(fCent, ih, ihh, scfour.Re(), event_weight_four); + } + TComplex sctwo = Two(ih, -ih) / Two(0, 0).Re(); + pht[HIST_THN_SC_with_QC_2corr]->Fill(fCent, ih, sctwo.Re(), event_weight_two); + } } //________________________________________________________________________ -void JFFlucAnalysis::Terminate(Option_t* /*popt*/) +void JFFlucAnalysis::Terminate(Option_t* /*popt*/) // NOLINT(readability/casting) false positive: https://github.com/cpplint/cpplint/issues/131 { // } diff --git a/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx b/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx index 40b3b048be8..181dbe6a05f 100644 --- a/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx +++ b/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx @@ -34,12 +34,12 @@ JFFlucAnalysisO2Hist::JFFlucAnalysisO2Hist(HistogramRegistry& registry, AxisSpec pht[HIST_THN_PHIETA] = std::get>(registry.add(Form("%s/h_phieta", folder.Data()), "(corrected) multiplicity/centrality, phi, eta", {HistType::kTHnF, {axisMultiplicity, phiAxis, etaAxis}})).get(); AxisSpec hAxis = {kNH, -0.5, static_cast(kNH - 1) + 0.5, "#it{n}"}; AxisSpec kAxis = {nKL, -0.5, static_cast(nKL - 1) + 0.5, "#it{k}"}; - AxisSpec vnAxis = {1024, -1.0, 1.0, "#it{V}_#it{n}"}; - pht[HIST_THN_SC_with_QC_4corr] = std::get>(registry.add(Form("%s/h_SC_with_QC_4corr", folder.Data()), "SC_with_QC_4corr", {HistType::kTHnF, {axisMultiplicity, hAxis, hAxis, {1024, -1.5, 1.5, "correlation"}}})).get(); - pht[HIST_THN_SC_with_QC_2corr] = std::get>(registry.add(Form("%s/h_SC_with_QC_2corr", folder.Data()), "SC_with_QC_2corr", {HistType::kTHnF, {axisMultiplicity, hAxis, {1024, -1.5, 1.5, "correlation"}}})).get(); - pht[HIST_THN_SC_with_QC_2corr_gap] = std::get>(registry.add(Form("%s/h_SC_with_QC_2corr_gap", folder.Data()), "SC_with_QC_2corr_gap", {HistType::kTHnF, {axisMultiplicity, hAxis, {1024, -1.5, 1.5, "correlation"}}})).get(); + AxisSpec vnAxis = {2048, -0.1, 0.1, "#it{V}_#it{n}"}; + pht[HIST_THN_SC_with_QC_4corr] = std::get>(registry.add(Form("%s/h_SC_with_QC_4corr", folder.Data()), "SC_with_QC_4corr", {HistType::kTHnF, {axisMultiplicity, hAxis, hAxis, {2048, -0.001, 0.001, "correlation"}}})).get(); + pht[HIST_THN_SC_with_QC_2corr] = std::get>(registry.add(Form("%s/h_SC_with_QC_2corr", folder.Data()), "SC_with_QC_2corr", {HistType::kTHnF, {axisMultiplicity, hAxis, {2048, -0.1, 0.1, "correlation"}}})).get(); + pht[HIST_THN_SC_with_QC_2corr_gap] = std::get>(registry.add(Form("%s/h_SC_with_QC_2corr_gap", folder.Data()), "SC_with_QC_2corr_gap", {HistType::kTHnF, {axisMultiplicity, hAxis, {2048, -0.1, 0.1, "correlation"}}})).get(); for (UInt_t i = HIST_THN_V4V2star_2; i < HIST_THN_COUNT; ++i) - pht[i] = std::get>(registry.add(Form("%s/h_corrC%02u", folder.Data(), i - HIST_THN_V4V2star_2), "correlator", {HistType::kTHnF, {axisMultiplicity, {1024, -3.0, 3.0, "correlation"}}})).get(); + pht[i] = std::get>(registry.add(Form("%s/h_corrC%02u", folder.Data(), i - HIST_THN_V4V2star_2), "correlator", {HistType::kTHnF, {axisMultiplicity, {2048, -3.0, 3.0, "correlation"}}})).get(); for (UInt_t i = 0; i < HIST_THN_COUNT; ++i) pht[i]->Sumw2(); diff --git a/PWGCF/JCorran/Tasks/CMakeLists.txt b/PWGCF/JCorran/Tasks/CMakeLists.txt index bb123a2d5a6..18284bd2f4c 100644 --- a/PWGCF/JCorran/Tasks/CMakeLists.txt +++ b/PWGCF/JCorran/Tasks/CMakeLists.txt @@ -28,3 +28,8 @@ o2physics_add_dpl_workflow(flow-nuacreation SOURCES flowJNUACreation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::JCorran COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(epflow-analysis + SOURCES jEPFlowAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::JCorran + COMPONENT_NAME Analysis) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx new file mode 100644 index 00000000000..f3f43744f19 --- /dev/null +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -0,0 +1,132 @@ +// Copyright 2019-2020 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. +/// \author Maxim Virta (maxim.virta@cern.ch) +/// \since Jul 2024 + +#include "Framework/AnalysisTask.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/HistogramRegistry.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/TrackSelection.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Common/DataModel/Qvectors.h" +#include "Common/Core/EventPlaneHelper.h" + +#include "FlowJHistManager.h" +#include "JEPFlowAnalysis.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace std; + +using MyCollisions = soa::Join; + +using MyTracks = aod::Tracks; + +struct jEPFlowAnalysis { + + HistogramRegistry EPFlowHistograms{"EPFlow", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + JEPFlowAnalysis epAnalysis; + EventPlaneHelper helperEP; + FlowJHistManager histManager; + Bool_t debug = kFALSE; + + // Set Configurables here + struct : ConfigurableGroup { + Configurable cfgPtMin{"cfgPtMin", 0.2f, "Minimum pT used for track selection."}; + Configurable cfgPtMax{"cfgPtMax", 5.0f, "Maximum pT used for track selection."}; + Configurable cfgEtaMax{"cfgEtaMax", 1.f, "Maximum eta used for track selection."}; + } cfgTrackCuts; + + Configurable cfgAddEvtSel{"cfgAddEvtSel", true, "Use event selection"}; + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "Total number of detectors in qVectorsTable"}; + + Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; + Configurable cfgRefAName{"cfgRefAName", "TPCPos", "The name of detector for reference A"}; + Configurable cfgRefBName{"cfgRefBName", "TPCNeg", "The name of detector for reference B"}; + + Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (aod::track::pt < cfgTrackCuts.cfgPtMax) && (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax); + + int DetId; + int RefAId; + int RefBId; + int harmInd; + + template + int GetDetId(const T& name) + { + if (name.value == "FT0C") { + return 0; + } else if (name.value == "FT0A") { + return 1; + } else if (name.value == "FT0M") { + return 2; + } else if (name.value == "FV0A") { + return 3; + } else if (name.value == "TPCPos") { + return 4; + } else if (name.value == "TPCNeg") { + return 5; + } else if (name.value == "TPCTot") { + return 6; + } else { + return 0; + } + } + + void init(InitContext const&) + { + DetId = GetDetId(cfgDetName); + RefAId = GetDetId(cfgRefAName); + RefBId = GetDetId(cfgRefBName); + + epAnalysis.SetHistRegistry(&EPFlowHistograms); + epAnalysis.CreateHistograms(); + } + + void process(MyCollisions::iterator const& coll, soa::Filtered const& tracks) + { + if (cfgAddEvtSel && (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup))) + return; + + Float_t cent = coll.cent(); + EPFlowHistograms.fill(HIST("FullCentrality"), cent); + Float_t EPs[3] = {0.}; + for (int i = 2; i < 5; i++) { // loop over different harmonic orders + harmInd = cfgnTotalSystem * 4 * (i - 2) + 3; // harmonic index to access corresponding Q-vector as all Q-vectors are in same vector + EPs[0] = helperEP.GetEventPlane(coll.qvecRe()[DetId + harmInd], coll.qvecIm()[DetId + harmInd], i); + EPs[1] = helperEP.GetEventPlane(coll.qvecRe()[RefAId + harmInd], coll.qvecIm()[RefAId + harmInd], i); + EPs[2] = helperEP.GetEventPlane(coll.qvecRe()[RefBId + harmInd], coll.qvecIm()[RefBId + harmInd], i); + + Float_t resNumA = helperEP.GetResolution(EPs[0], EPs[1], i); + Float_t resNumB = helperEP.GetResolution(EPs[0], EPs[2], i); + Float_t resDenom = helperEP.GetResolution(EPs[1], EPs[2], i); + epAnalysis.FillResolutionHistograms(cent, static_cast(i), resNumA, resNumB, resDenom); + for (uint j = 0; j < 3; j++) { // loop over detectors used + for (auto& track : tracks) { + Float_t vn = TMath::Cos((i) * (track.phi() - EPs[j])); + Float_t vn_sin = TMath::Sin((i) * (track.phi() - EPs[j])); + epAnalysis.FillVnHistograms(i, cent, static_cast(j + 1), track.pt(), vn, vn_sin); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 5c00be5d9c2..770ed87472f 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -38,7 +38,7 @@ struct : ConfigurableGroup { Configurable cfFillQAEventHistograms2D{"cfFillQAEventHistograms2D", false, "if false, all QA 2D event histograms are not filled. if true, only the ones for which fBookQAEventHistograms2D[...] is true, are filled"}; Configurable> cfBookQAEventHistograms2D{"cfBookQAEventHistograms2D", {"MultTPC_vs_NContributors-1", "Vertex_z_vs_MultTPC-1", "Vertex_z_vs_NContributors-1", "CentFT0M_vs_CentNTPV-1", "CentRun2V0M_vs_CentRun2SPDTracklets-1", "CentRun2V0M_vs_NContributors-1"}, "book (1) or do not book (0) this QA 2D event histogram"}; Configurable cfFillQAParticleHistograms2D{"cfFillQAParticleHistograms2D", false, "if false, all QA 2D particle histograms are not filled. if true, only the ones for which fBookQAParticleHistograms2D[...] is true, are filled"}; - Configurable> cfBookQAParticleHistograms2D{"cfBookQAParticleHistograms2D", {"dcaXY_vs_Pt-1"}, "nook (1) or do not book (0) this QA 2D particle histogram"}; + Configurable> cfBookQAParticleHistograms2D{"cfBookQAParticleHistograms2D", {"dcaXY_vs_Pt-1"}, "book (1) or do not book (0) this QA 2D particle histogram"}; } cf_qa; // *) Event histograms: @@ -90,7 +90,7 @@ struct : ConfigurableGroup { // *) Particle cuts: struct : ConfigurableGroup { - Configurable> cfUseParticleCuts{"cfUseParticleCuts", {"Phi-1", "Pt-1", "Eta-1", "Charge-1", "tpcNClsFindable-1", "tpcNClsShared-1", "tpcNClsFound-1", "tpcNClsCrossedRows-1", "itsNCls-1", "itsNClsInnerBarrel-1", "tpcCrossedRowsOverFindableCls-1", "tpcFoundOverFindableCls-1", "tpcFractionSharedCls-1", "dcaXY-1", "dcaZ-1", "PDG-1", "trackCutFlagFb1-0", "trackCutFlagFb2-0", "isQualityTrack-0", "isPrimaryTrack-0", "isInAcceptanceTrack-0", "isGlobalTrack-0"}, "Use (1) or do not use (0) particle cuts"}; + Configurable> cfUseParticleCuts{"cfUseParticleCuts", {"Phi-1", "Pt-1", "Eta-1", "Charge-1", "tpcNClsFindable-1", "tpcNClsShared-1", "tpcNClsFound-1", "tpcNClsCrossedRows-1", "itsNCls-1", "itsNClsInnerBarrel-1", "tpcCrossedRowsOverFindableCls-1", "tpcFoundOverFindableCls-1", "tpcFractionSharedCls-1", "dcaXY-1", "dcaZ-1", "PDG-1", "trackCutFlagFb1-0", "trackCutFlagFb2-0", "isQualityTrack-0", "isPrimaryTrack-0", "isInAcceptanceTrack-0", "isGlobalTrack-0", "PtDependentDCAxyParameterization-0"}, "Use (1) or do not use (0) particle cuts"}; Configurable cfUseParticleCutCounterAbsolute{"cfUseParticleCutCounterAbsolute", false, "profile and save how many times each particle cut counter triggered (absolute). Use with care, as this is computationally heavy"}; Configurable cfUseParticleCutCounterSequential{"cfUseParticleCutCounterSequential", false, "profile and save how many times each particle cut counter triggered (sequential). Use with care, as this is computationally heavy"}; Configurable> cfPhi{"cfPhi", {0.0, TMath::TwoPi()}, "phi range: {min, max}[rad], with convention: min <= phi < max"}; @@ -115,6 +115,7 @@ struct : ConfigurableGroup { Configurable cfisPrimaryTrack{"cfisPrimaryTrack", false, "TBI 20240510 add description"}; Configurable cfisInAcceptanceTrack{"cfisInAcceptanceTrack", false, "TBI 20240510 add description"}; Configurable cfisGlobalTrack{"cfisGlobalTrack", false, "TBI 20240510 add description"}; + Configurable cfPtDependentDCAxyParameterization{"cfPtDependentDCAxyParameterization", "some formula TBI add some default formula, e.g. 0.0105+0.0350/x^1.1", "set here formula for pt-dependence DCAxy cut, in the following example format 0.0105+0.0350/x^1.1"}; // TBI 20240426 do I need to add separate support for booleans to use each specific cut? } cf_pc; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index 4efe331b831..2d4d7536cc6 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -149,6 +149,7 @@ struct ParticleCuts { Double_t fdParticleCuts[eParticleCuts_N][2] = {{0.}}; // particles cuts defined via [min,max) . Remark: I use here eParticleHistograms_N , not to duplicate these enums for ParticleCuts. TString fsParticleCuts[eParticleCuts_N] = {""}; // particles cuts defined via booleans via string TH1D* fParticleCutCounterHist[2][eCutCounter_N] = {{NULL}}; //!At(1)->GetName()).EqualTo("0")) { delete oa; return kFALSE; @@ -602,7 +603,8 @@ void DefaultBooking() ph.fBookParticleHistograms[edcaXY] = Alright(lBookParticleHistograms[edcaXY]) && ph.fFillParticleHistograms; ph.fBookParticleHistograms[edcaZ] = Alright(lBookParticleHistograms[edcaZ]) && ph.fFillParticleHistograms; ph.fBookParticleHistograms[ePDG] = Alright(lBookParticleHistograms[ePDG]) && ph.fFillParticleHistograms; - // Remark: I do not need here anythig for etrackCutFlagFb1, etrackCutFlagFb2, ... eisGlobalTrack, because they are booleans + // Remark #1: I do not need here anythig for etrackCutFlagFb1, etrackCutFlagFb2, ... eisGlobalTrack, because they are booleans + // Remark #2: Nothing special here for ePtDependentDCAxyParameterization, because that is a string. // d) Particle histograms 2D: // By default all 2D particle histograms are booked. Set this flag to kFALSE to switch off booking of all 2D particle histograms: @@ -1127,6 +1129,7 @@ void DefaultCuts() pc.fUseParticleCuts[eisPrimaryTrack] = Alright(lUseParticleCuts[eisPrimaryTrack]); pc.fUseParticleCuts[eisInAcceptanceTrack] = Alright(lUseParticleCuts[eisInAcceptanceTrack]); pc.fUseParticleCuts[eisGlobalTrack] = Alright(lUseParticleCuts[eisGlobalTrack]); + pc.fUseParticleCuts[ePtDependentDCAxyParameterization] = Alright(lUseParticleCuts[ePtDependentDCAxyParameterization]); // **) particles cuts defined via booleans: pc.fUseParticleCuts[etrackCutFlagFb1] = pc.fUseParticleCuts[etrackCutFlagFb1] && cf_pc.cftrackCutFlagFb1; @@ -1202,7 +1205,7 @@ void DefaultCuts() pc.fdParticleCuts[ePDG][eMax] = lPDG[eMax]; // **) particles cuts defined via string: - // pc.fsParticleCuts[...] = ... ; + pc.fsParticleCuts[ePtDependentDCAxyParameterization] = cf_pc.cfPtDependentDCAxyParameterization; } // void DefaultCuts() @@ -1350,6 +1353,11 @@ void InsanityChecks() } } + // **) When it comes to DCAxy cut, ensure that either flat or pt-dependent cut is used, but not both: + if (pc.fUseParticleCuts[edcaXY] && pc.fUseParticleCuts[ePtDependentDCAxyParameterization]) { + LOGF(fatal, "\033[1;31m%s at line %d : use either flat or pt-dependent DCAxy cut, but not both \033[0m", __FUNCTION__, __LINE__); + } + // *) Insanity checks on booking: // ... @@ -2002,7 +2010,8 @@ void BookParticleCutsHistograms() // a) Book the profile holding flags; // b) Book particle cut counter maps; - // c) Book the particle cut counter (absolute). + // c) Book the particle cut counter (absolute); + // d) Book the formula for pt-dependent DCAxy cut. if (tc.fVerbose) { LOGF(info, "\033[1;32m%s\033[0m", __FUNCTION__); @@ -2067,6 +2076,15 @@ void BookParticleCutsHistograms() } // for (Int_t rs = 0; rs < 2; rs++) // reco/sim + // d) Book the formula for pt-dependent DCAxy cut: + if (pc.fUseParticleCuts[ePtDependentDCAxyParameterization]) { + pc.fPtDependentDCAxyFormula = new TFormula("fPtDependentDCAxyFormula", pc.fsParticleCuts[ePtDependentDCAxyParameterization].Data()); + // As a quick insanity check, try immediately to evaluate something from this formula: + if (std::isnan(pc.fPtDependentDCAxyFormula->Eval(1.44))) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + } // if(pc.fUseParticleCuts[ePtDependentDCAxyParameterization]) { + } // void BookParticleCutsHistograms() //============================================================ @@ -4285,10 +4303,10 @@ bool ValidTrack(T const& track) // c) Additional validity checks for all tracks (in Run 3, 2 and 1), use only during debugging: if (tc.fInsanityCheckForEachParticle) { - // *) isnan() check (remember that 'nan' is 0./0., inf-inf, etc. However 'inf' itself is NOT a 'nan', therefore isnan(1./0.) is false, isnan(0./0.) is true, etc.): - if (isnan(track.phi()) || isnan(track.pt()) || isnan(track.eta())) { + // *) std::isnan() check (remember that 'nan' is 0./0., inf-inf, etc. However 'inf' itself is NOT a 'nan', therefore std::isnan(1./0.) is false, std::isnan(0./0.) is true, etc.): + if (std::isnan(track.phi()) || std::isnan(track.pt()) || std::isnan(track.eta())) { if (tc.fVerboseForEachParticle) { - LOGF(info, "\033[1;31m%s isnan(track.phi()) || isnan(track.pt()) || isnan(track.eta())\033[0m", __FUNCTION__); + LOGF(info, "\033[1;31m%s std::isnan(track.phi()) || std::isnan(track.pt()) || std::isnan(track.eta())\033[0m", __FUNCTION__); LOGF(error, "track.phi() = %f\ntrack.pt() = %f\ntrack.eta() = %f", track.phi(), track.pt(), track.eta()); } return kFALSE; @@ -4622,6 +4640,17 @@ Bool_t ParticleCuts(T const& track, eCutModus cutModus) } } + // *) PtDependentDCAxyParameterization: + if (pc.fUseParticleCuts[ePtDependentDCAxyParameterization]) { + if (cutModus == eCutCounterBinning) { + ParticleCut(eRec, ePtDependentDCAxyParameterization, eCutCounterBinning); + } else if (TMath::Abs(track.dcaXY()) > pc.fPtDependentDCAxyFormula->Eval(track.pt())) { + if (!ParticleCut(eRec, ePtDependentDCAxyParameterization, cutModus)) { + return kFALSE; + } + } + } + // ... // ... and corresponding MC truth simulated: diff --git a/PWGCF/MultiparticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/MultiparticleCorrelations/Tasks/CMakeLists.txt index 397e25796c1..4240aaf37e0 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/MultiparticleCorrelations/Tasks/CMakeLists.txt @@ -18,3 +18,8 @@ o2physics_add_dpl_workflow(multiparticle-correlations-ar SOURCES multiparticle-correlations-ar.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(threeparticle-correlations + SOURCES ThreeParticleCorrelations.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx new file mode 100644 index 00000000000..face9b469d2 --- /dev/null +++ b/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx @@ -0,0 +1,348 @@ +// Copyright 2019-2020 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. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct ThreePartCorr { + + // Histogram registry + HistogramRegistry MECorrRegistry{"MECorrRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry SECorrRegistry{"SECorrRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry QARegistry{"QARegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + // Collision filters + Filter CollCent = aod::cent::centFT0C > 0.0f && aod::cent::centFT0C < 90.0f; + Filter CollZvtx = nabs(aod::collision::posZ) < 7.0f; + + // V0 filters + Filter V0Pt = aod::v0data::pt > 0.6f && aod::v0data::pt < 12.0f; + Filter V0Eta = nabs(aod::v0data::eta) < 0.72f; + + // Track filters + Filter TrackPt = aod::track::pt > 0.2f && aod::track::pt < 3.0f; + Filter TrackEta = nabs(aod::track::eta) < 0.8f; + + // Table aliases + using MyFilteredCollisions = soa::Filtered>; + using MyFilteredCollision = MyFilteredCollisions::iterator; + using MyFilteredV0s = soa::Filtered; + using MyFilteredTracks = soa::Filtered>; + + // Mixed-events binning policy + SliceCache cache; + ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "ME Centrality binning"}; + ConfigurableAxis ConfZvtxBins{"ConfZvtxBins", {VARIABLE_WIDTH, -7.0f, -5.0f, -3.0f, -1.0f, 0.0f, 1.0f, 3.0f, 5.0f, 7.0f}, "ME Zvtx binning"}; + using BinningType = ColumnBinningPolicy; + + BinningType CollBinning{{ConfCentBins, ConfZvtxBins}, true}; + Pair pair{CollBinning, 5, -1, &cache}; + + // Particle masses + Double_t massLambda = 1.115683; + + // Correlation variables + Int_t T_Sign; + Double_t CandMass; + Double_t* A_PID; + + Double_t DeltaPhi, DeltaEta; + + //================================================================================================================================================================================================================ + + void init(InitContext const&) + { + + const AxisSpec CentralityAxis{ConfCentBins}; + const AxisSpec ZvtxAxis{ConfZvtxBins}; + const AxisSpec PhiAxis{36, (-1. / 2) * M_PI, (3. / 2) * M_PI}; + const AxisSpec EtaAxis{32, -1.52, 1.52}; + const AxisSpec PtAxis{120, 0, 12}; + const AxisSpec LambdaInvMassAxis{100, 1.08, 1.16}; + + QARegistry.add("hTrackPt", "hTrackPt", {HistType::kTH1D, {{100, 0, 4}}}); + QARegistry.add("hTrackEta", "hTrackEta", {HistType::kTH1D, {{100, -1, 1}}}); + QARegistry.add("hTrackPhi", "hTrackPhi", {HistType::kTH1D, {{100, (-1. / 2) * M_PI, (5. / 2) * M_PI}}}); + QARegistry.add("hEventCentrality", "hEventCentrality", {HistType::kTH1D, {{CentralityAxis}}}); + QARegistry.add("hEventZvtx", "hEventZvtx", {HistType::kTH1D, {{ZvtxAxis}}}); + + QARegistry.add("hdEdx", "hdEdx", {HistType::kTH2D, {{56, 0.2, 3.0}, {180, 20, 200}}}); + QARegistry.add("hdEdxPion", "hdEdxPion", {HistType::kTH2D, {{56, 0.2, 3.0}, {180, 20, 200}}}); + QARegistry.add("hdEdxKaon", "hdEdxKaon", {HistType::kTH2D, {{56, 0.2, 3.0}, {180, 20, 200}}}); + QARegistry.add("hdEdxProton", "hdEdxProton", {HistType::kTH2D, {{56, 0.2, 3.0}, {180, 20, 200}}}); + QARegistry.add("hBeta", "hBeta", {HistType::kTH2D, {{56, 0.2, 3.0}, {70, 0.4, 1.1}}}); + QARegistry.add("hBetaPion", "hBetaPion", {HistType::kTH2D, {{56, 0.2, 3.0}, {70, 0.4, 1.1}}}); + QARegistry.add("hBetaKaon", "hBetaKaon", {HistType::kTH2D, {{56, 0.2, 3.0}, {70, 0.4, 1.1}}}); + QARegistry.add("hBetaProton", "hBetaProton", {HistType::kTH2D, {{56, 0.2, 3.0}, {70, 0.4, 1.1}}}); + // QARegistry.add("hNSigmaPion", "hNSigmaPion", {HistType::kTH2D, {{28, 0.2, 3.0}, {201, -5.025, 5.025}}}); + // QARegistry.add("hNSigmaKaon", "hNSigmaKaon", {HistType::kTH2D, {{28, 0.2, 3.0}, {201, -5.025, 5.025}}}); + // QARegistry.add("hNSigmaProton", "hNSigmaProton", {HistType::kTH2D, {{28, 0.2, 3.0}, {201, -5.025, 5.025}}}); + + QARegistry.add("hInvMassLambda", "hInvMassLambda", {HistType::kTH3D, {{LambdaInvMassAxis}, {PtAxis}, {CentralityAxis}}}); + QARegistry.add("hInvMassAntiLambda", "hInvMassAntiLambda", {HistType::kTH3D, {{LambdaInvMassAxis}, {PtAxis}, {CentralityAxis}}}); + + SECorrRegistry.add("hSameLambdaPion_SGNL", "Same-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + SECorrRegistry.add("hSameLambdaPion_SB", "Same-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + SECorrRegistry.add("hSameLambdaKaon_SGNL", "Same-event #Lambda - K correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + SECorrRegistry.add("hSameLambdaKaon_SB", "Same-event #Lambda - K correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + SECorrRegistry.add("hSameLambdaProton_SGNL", "Same-event #Lambda - p correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + SECorrRegistry.add("hSameLambdaProton_SB", "Same-event #Lambda - p correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + + MECorrRegistry.add("hMixLambdaPion_SGNL", "Mixed-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + MECorrRegistry.add("hMixLambdaPion_SB", "Mixed-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + MECorrRegistry.add("hMixLambdaKaon_SGNL", "Mixed-event #Lambda - K correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + MECorrRegistry.add("hMixLambdaKaon_SB", "Mixed-event #Lambda - K correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + MECorrRegistry.add("hMixLambdaProton_SGNL", "Mixed-event #Lambda - p correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + MECorrRegistry.add("hMixLambdaProton_SB", "Mixed-event #Lambda - p correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + } + + //================================================================================================================================================================================================================ + + void processSame(MyFilteredCollision const& collision, MyFilteredV0s const& v0s, MyFilteredTracks const& tracks) + { + + QARegistry.fill(HIST("hEventCentrality"), collision.centFT0C()); + QARegistry.fill(HIST("hEventZvtx"), collision.posZ()); + + // Start of the Track QA + for (const auto& track : tracks) { + A_PID = TrackPID(track); + if (A_PID[1] < 4.0) { + QARegistry.fill(HIST("hTrackPt"), track.pt()); + QARegistry.fill(HIST("hTrackEta"), track.eta()); + QARegistry.fill(HIST("hTrackPhi"), track.phi()); + QARegistry.fill(HIST("hdEdx"), track.p(), track.tpcSignal()); + QARegistry.fill(HIST("hBeta"), track.p(), track.beta()); + if (A_PID[0] == 0.0) { // Pions + QARegistry.fill(HIST("hdEdxPion"), track.p(), track.tpcSignal()); + QARegistry.fill(HIST("hBetaPion"), track.p(), track.beta()); + // QARegistry.fill(HIST("hNSigmaPion"), track.pt(), track.tpcNSigmaPi()); + } else if (A_PID[0] == 1.0) { // Kaons + QARegistry.fill(HIST("hdEdxKaon"), track.p(), track.tpcSignal()); + QARegistry.fill(HIST("hBetaKaon"), track.p(), track.beta()); + // QARegistry.fill(HIST("hNSigmaKaon"), track.pt(), track.tpcNSigmaKa()); + } else if (A_PID[0] == 2.0) { // Protons + QARegistry.fill(HIST("hdEdxProton"), track.p(), track.tpcSignal()); + QARegistry.fill(HIST("hBetaProton"), track.p(), track.beta()); + // QARegistry.fill(HIST("hNSigmaProton"), track.pt(), track.tpcNSigmaPr()); + } + } + } + // End of the Track QA + + // Start of the V0-Track Correlations + for (const auto& trigger : v0s) { + if (V0Filters(trigger)) { + + T_Sign = V0Sign(trigger); + if (T_Sign == 1) { + CandMass = trigger.mLambda(); + QARegistry.fill(HIST("hInvMassLambda"), trigger.mLambda(), trigger.pt(), collision.centFT0C()); + } else if (T_Sign == -1) { + CandMass = trigger.mAntiLambda(); + QARegistry.fill(HIST("hInvMassAntiLambda"), trigger.mAntiLambda(), trigger.pt(), collision.centFT0C()); + } + + for (const auto& associate : tracks) { + if (TrackFilters(trigger, associate)) { + + A_PID = TrackPID(associate); + DeltaPhi = DeltaPhiShift(trigger.phi(), associate.phi()); + DeltaEta = trigger.eta() - associate.eta(); + + if (CandMass >= 1.10 && CandMass <= 1.13) { + if (A_PID[0] == 0) { // Pions + SECorrRegistry.fill(HIST("hSameLambdaPion_SGNL"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 1) { // Kaons + SECorrRegistry.fill(HIST("hSameLambdaKaon_SGNL"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 2) { // Protons + SECorrRegistry.fill(HIST("hSameLambdaProton_SGNL"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); + } + } else { + if (A_PID[0] == 0) { // Pions + SECorrRegistry.fill(HIST("hSameLambdaPion_SB"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 1) { // Kaons + SECorrRegistry.fill(HIST("hSameLambdaKaon_SB"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 2) { // Protons + SECorrRegistry.fill(HIST("hSameLambdaProton_SB"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); + } + } + } + } + } + } + // End of the V0-Track Correlations + } + PROCESS_SWITCH(ThreePartCorr, processSame, "Process same-event correlations", true); + + void processMixed(MyFilteredCollisions const& collisions, MyFilteredV0s const& v0s, MyFilteredTracks const& tracks) + { + + LOGF(info, "Input data Collisions %d, V0s %d, Tracks %d ", collisions.size(), v0s.size(), tracks.size()); + + // Start of the Mixed-events Correlations + for (const auto& [coll_1, v0_1, coll_2, track_2] : pair) { + for (const auto& [trigger, associate] : soa::combinations(soa::CombinationsFullIndexPolicy(v0_1, track_2))) { + if (V0Filters(trigger) && TrackFilters(trigger, associate)) { + + T_Sign = V0Sign(trigger); + if (T_Sign == 1) { + CandMass = trigger.mLambda(); + } else if (T_Sign == -1) { + CandMass = trigger.mAntiLambda(); + } + + A_PID = TrackPID(associate); + DeltaPhi = DeltaPhiShift(trigger.phi(), associate.phi()); + DeltaEta = trigger.eta() - associate.eta(); + + if (CandMass >= 1.10 && CandMass <= 1.13) { + if (A_PID[0] == 0) { // Pions + MECorrRegistry.fill(HIST("hMixLambdaPion_SGNL"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 1) { // Kaons + MECorrRegistry.fill(HIST("hMixLambdaKaon_SGNL"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 2) { // Protons + MECorrRegistry.fill(HIST("hMixLambdaProton_SGNL"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); + } + } else { + if (A_PID[0] == 0) { // Pions + MECorrRegistry.fill(HIST("hMixLambdaPion_SB"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 1) { // Kaons + MECorrRegistry.fill(HIST("hMixLambdaKaon_SB"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); + } else if (A_PID[0] == 2) { // Protons + MECorrRegistry.fill(HIST("hMixLambdaProton_SB"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); + } + } + } + } + } + // End of the Mixed-events Correlations + } + PROCESS_SWITCH(ThreePartCorr, processMixed, "Process mixed-event correlations", true); + + //================================================================================================================================================================================================================ + + Double_t DeltaPhiShift(Double_t TriggerPhi, Double_t AssociatePhi) + { + + Double_t dPhi = TriggerPhi - AssociatePhi; + + if (dPhi < (-1. / 2) * M_PI) { + dPhi = dPhi + 2 * M_PI; + } else if (dPhi > (3. / 2) * M_PI) { + dPhi = dPhi - 2 * M_PI; + } + + return dPhi; + } + + template + Double_t* TrackPID(const TrackCand& Track) + { + + static Double_t ID[2]; // {PID, NSigma} + + Double_t NSigmaTPC[3], NSigma[3]; + Double_t NSigmaTOF[3] = {0.0, 0.0, 0.0}; + NSigmaTPC[0] = Track.tpcNSigmaPi(); + NSigmaTPC[1] = Track.tpcNSigmaKa(); + NSigmaTPC[2] = Track.tpcNSigmaPr(); + if (Track.hasTOF()) { + NSigmaTOF[0] = Track.tofNSigmaPi(); + NSigmaTOF[1] = Track.tofNSigmaKa(); + NSigmaTOF[2] = Track.tofNSigmaPr(); + } + + NSigma[0] = TMath::Sqrt(pow(NSigmaTPC[0], 2) + pow(NSigmaTOF[0], 2)); + NSigma[1] = TMath::Sqrt(pow(NSigmaTPC[1], 2) + pow(NSigmaTOF[1], 2)); + NSigma[2] = TMath::Sqrt(pow(NSigmaTPC[2], 2) + pow(NSigmaTOF[2], 2)); + + if (NSigma[0] <= std::min(NSigma[1], NSigma[2])) { // Pions + ID[0] = 0.0; + ID[1] = NSigma[0]; + } else if (NSigma[1] <= std::min(NSigma[0], NSigma[2])) { // Kaons + ID[0] = 1.0; + ID[1] = NSigma[1]; + } else if (NSigma[2] <= std::min(NSigma[0], NSigma[1])) { // Protons + ID[0] = 2.0; + ID[1] = NSigma[2]; + } + + return ID; + } + + template + Int_t V0Sign(const V0Cand& V0) + { + + if (TMath::Abs(V0.mLambda() - massLambda) <= TMath::Abs(V0.mAntiLambda() - massLambda)) { + return 1; + } else if (TMath::Abs(V0.mLambda() - massLambda) > TMath::Abs(V0.mAntiLambda() - massLambda)) { + return -1; + } + + return 0; + } + + template + Bool_t V0Filters(const V0Cand& V0) + { + + if (V0Sign(V0) == 1) { + const auto& posDaughter = V0.template posTrack_as(); + if (TMath::Abs(posDaughter.tpcNSigmaPr()) > 4.0) { + return kFALSE; + } + // if(V0.mLambda() < 1.10 || V0.mLambda() > 1.13) { return kFALSE; } + } else if (V0Sign(V0) == -1) { + const auto& negDaughter = V0.template negTrack_as(); + if (TMath::Abs(negDaughter.tpcNSigmaPr()) > 4.0) { + return kFALSE; + } + // if(V0.mAntiLambda() < 1.10 || V0.mAntiLambda() > 1.13) { return kFALSE; } + } + + return kTRUE; + } + + template + Bool_t TrackFilters(const V0Cand& V0, const TrackCand& Track) + { + + if (Track.globalIndex() == V0.posTrackId() || Track.globalIndex() == V0.negTrackId()) { + return kFALSE; + } + if (TrackPID(Track)[1] > 4.0) { + return kFALSE; + } + + return kTRUE; + } +}; + +//================================================================================================================================================================================================================== + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} + +//================================================================================================================================================================================================================== diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx index 25502c7249e..aac8b255ef4 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx @@ -189,7 +189,7 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to // ------------------------------------------- // C) Process only simulated data: - void processSim(CollisionSim const& collision, aod::BCs const&, TracksSim const& tracks) + void processSim(CollisionSim const& /*collision*/, aod::BCs const&, TracksSim const& /*tracks*/) { // Steer(collision, tracks); // TBI 20240517 not ready yet, but I do not really need this one urgently, since RecSim is working, and I need that one for efficiencies... } @@ -216,7 +216,7 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to // ------------------------------------------- // F) Process only converted simulated Run 2 data: - void processSim_Run2(CollisionSim const& collision) // TBI 20240517 extend this subscription eventually + void processSim_Run2(CollisionSim const& /*collision*/) // TBI 20240517 extend this subscription eventually { // Steer(collision, tracks); // TBI 20240517 not ready yet, but I do not really need this one urgently, since RecSim_Run2 is working, and I need that one for efficiencies... } @@ -234,7 +234,7 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to // ------------------------------------------- // H) Process both converted reconstructed and corresponding MC truth simulated Run 1 data; - void processRecSim_Run1(CollisionRecSim_Run1 const& collision, aod::BCs const&, TracksRecSim const& tracks, aod::McParticles const&, aod::McCollisions const&) + void processRecSim_Run1(CollisionRecSim_Run1 const& /*collision*/, aod::BCs const&, TracksRecSim const& /*tracks*/, aod::McParticles const&, aod::McCollisions const&) { // Steer(collision, tracks); // TBI 20240517 not ready yet, but for benchmarking in any case I need only "Rec" } diff --git a/PWGCF/TableProducer/dptdptfilter.cxx b/PWGCF/TableProducer/dptdptfilter.cxx index ff5930aa9cc..400f92a2c39 100644 --- a/PWGCF/TableProducer/dptdptfilter.cxx +++ b/PWGCF/TableProducer/dptdptfilter.cxx @@ -583,7 +583,8 @@ struct DptDptFilterTracks { fPDG = TDatabasePDG::Instance(); /* required ambiguous tracks checks? */ - if (dofilterDetectorLevelWithoutPIDAmbiguous || dofilterDetectorLevelWithPIDAmbiguous || dofilterRecoWithoutPIDAmbiguous || dofilterRecoWithPIDAmbiguous) { + if (dofilterDetectorLevelWithoutPIDAmbiguous || dofilterDetectorLevelWithPIDAmbiguous || dofilterDetectorLevelWithFullPIDAmbiguous || + dofilterRecoWithoutPIDAmbiguous || dofilterRecoWithPIDAmbiguous || dofilterRecoWithFullPIDAmbiguous) { checkAmbiguousTracks = true; } diff --git a/PWGCF/TableProducer/dptdptfilter.h b/PWGCF/TableProducer/dptdptfilter.h index a08c0c682c0..60fb6e592c4 100644 --- a/PWGCF/TableProducer/dptdptfilter.h +++ b/PWGCF/TableProducer/dptdptfilter.h @@ -94,12 +94,16 @@ enum CentMultEstimatorType { /// \enum TriggerSelectionType /// \brief The type of trigger to apply for event selection enum TriggerSelectionType { - kNONE = 0, ///< do not use trigger selection - kMB, ///< Minimum bias trigger - kVTXTOFMATCHED, ///< at least one vertex contributor is matched to TOF - kVTXTRDMATCHED, ///< at least one vertex contributor is matched to TRD - kVTXTRDTOFMATCHED, ///< at least one vertex contributor is matched to TRD and TOF - knEventSelection ///< number of triggers for event selection + kNONE = 0, ///< do not use trigger selection + kMB, ///< Minimum bias trigger + kMBEXTRA, ///< Additional Run3 event quality + kVTXTOFMATCHED, ///< at least one vertex contributor is matched to TOF + kVTXTRDMATCHED, ///< at least one vertex contributor is matched to TRD + kVTXTRDTOFMATCHED, ///< at least one vertex contributor is matched to TRD and TOF + kEXTRAVTXTOFMATCHED, ///< Additional Run3 event quality and at least one vertex contributor is matched to TOF + kEXTRAVTXTRDMATCHED, ///< Additional Run3 event quality and at least one vertex contributor is matched to TRD + kEXTRAVTXTRDTOFMATCHED, ///< Additional Run3 event quality and at least one vertex contributor is matched to TRD and TOF + knEventSelection ///< number of triggers for event selection }; /// \enum StrongDebugging @@ -312,12 +316,20 @@ inline TriggerSelectionType getTriggerSelection(std::string const& triggstr) { if (triggstr.empty() || triggstr == "MB") { return kMB; + } else if (triggstr == "MBEXTRA") { + return kMBEXTRA; } else if (triggstr == "VTXTOFMATCHED") { return kVTXTOFMATCHED; } else if (triggstr == "VTXTRDMATCHED") { return kVTXTRDMATCHED; } else if (triggstr == "VTXTRDTOFMATCHED") { return kVTXTRDTOFMATCHED; + } else if (triggstr == "EXTRAVTXTOFMATCHED") { + return kEXTRAVTXTOFMATCHED; + } else if (triggstr == "EXTRAVTXTRDMATCHED") { + return kEXTRAVTXTRDMATCHED; + } else if (triggstr == "EXTRAVTXTRDTOFMATCHED") { + return kEXTRAVTXTRDTOFMATCHED; } else if (triggstr == "None") { return kNONE; } else { @@ -481,9 +493,10 @@ inline bool triggerSelectionReco(CollisionObject const& collision) case kppRun3: case kPbPbRun3: { auto run3Accepted = [](auto const& coll) { + return coll.sel8(); + }; + auto run3ExtraAccepted = [](auto const& coll) { return coll.sel8() && - coll.selection_bit(aod::evsel::kNoITSROFrameBorder) && - coll.selection_bit(aod::evsel::kNoTimeFrameBorder) && coll.selection_bit(aod::evsel::kNoSameBunchPileup) && coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && coll.selection_bit(aod::evsel::kIsVertexITSTPC); @@ -494,6 +507,11 @@ inline bool triggerSelectionReco(CollisionObject const& collision) trigsel = true; } break; + case kMBEXTRA: + if (run3ExtraAccepted(collision)) { + trigsel = true; + } + break; case kVTXTOFMATCHED: if (run3Accepted(collision) && collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { trigsel = true; @@ -509,6 +527,21 @@ inline bool triggerSelectionReco(CollisionObject const& collision) trigsel = true; } break; + case kEXTRAVTXTOFMATCHED: + if (run3ExtraAccepted(collision) && collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + trigsel = true; + } + break; + case kEXTRAVTXTRDMATCHED: + if (run3ExtraAccepted(collision) && collision.selection_bit(aod::evsel::kIsVertexTRDmatched)) { + trigsel = true; + } + break; + case kEXTRAVTXTRDTOFMATCHED: + if (run3ExtraAccepted(collision) && collision.selection_bit(aod::evsel::kIsVertexTRDmatched) && collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + trigsel = true; + } + break; case kNONE: trigsel = true; break; @@ -628,51 +661,38 @@ inline float extractMultiplicity(CollisionObject const& collision, CentMultEstim /// \brief Centrality/multiplicity percentile template + requires(o2::aod::HasRun2Centrality) float getCentMultPercentile(CollisionObject collision) { - if constexpr (framework::has_type_v || - framework::has_type_v || - framework::has_type_v) { - switch (fCentMultEstimator) { - case kV0M: - return collision.centRun2V0M(); - break; - case kCL0: - return collision.centRun2CL0(); - break; - case kCL1: - return collision.centRun2CL1(); - break; - default: - return 105.0; - break; - } + switch (fCentMultEstimator) { + case kV0M: + return collision.centRun2V0M(); + case kCL0: + return collision.centRun2CL0(); + case kCL1: + return collision.centRun2CL1(); + default: + return 105.0; } - if constexpr (framework::has_type_v || - framework::has_type_v || - framework::has_type_v || - framework::has_type_v || - framework::has_type_v) { - switch (fCentMultEstimator) { - case kFV0A: - return collision.centFV0A(); - break; - case kFT0M: - return collision.centFT0M(); - break; - case kFT0A: - return collision.centFT0A(); - break; - case kFT0C: - return collision.centFT0C(); - break; - case kNTPV: - return collision.centNTPV(); - break; - default: - return 105.0; - break; - } +} + +template + requires(o2::aod::HasCentrality) +float getCentMultPercentile(CollisionObject collision) +{ + switch (fCentMultEstimator) { + case kFV0A: + return collision.centFV0A(); + case kFT0M: + return collision.centFT0M(); + case kFT0A: + return collision.centFT0A(); + case kFT0C: + return collision.centFT0C(); + case kNTPV: + return collision.centNTPV(); + default: + return 105.0; } } @@ -820,7 +840,7 @@ inline bool matchTrackType(TrackObject const& track) } }; auto checkDcaZcut = [&](auto const& track) { - return ((maxDcaZPtDep) ? abs(track.dcaZ()) <= maxDcaZPtDep(track.pt()) : true); + return ((maxDcaZPtDep) ? std::fabs(track.dcaZ()) <= maxDcaZPtDep(track.pt()) : true); }; /* tight pT dependent DCAz cut */ @@ -990,6 +1010,7 @@ struct PIDSpeciesSelection { LOGF(info, " maxTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTPC[0], last->mMaxNSigmasTPC[1], last->mMaxNSigmasTPC[2], last->mMaxNSigmasTPC[3], last->mMaxNSigmasTPC[4]); LOGF(info, " minTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTOF[0], last->mMinNSigmasTOF[1], last->mMinNSigmasTOF[2], last->mMinNSigmasTOF[3], last->mMinNSigmasTOF[4]); LOGF(info, " maxTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTOF[0], last->mMaxNSigmasTOF[1], last->mMaxNSigmasTOF[2], last->mMaxNSigmasTOF[3], last->mMaxNSigmasTOF[4]); + LOGF(info, " %.1f < pT < %.1f", last->mPtMin, last->mPtMax); } void AddExclude(uint8_t sp, const o2::analysis::TrackSelectionPIDCfg* incfg) { @@ -1004,6 +1025,7 @@ struct PIDSpeciesSelection { LOGF(info, " maxTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTPC[0], last->mMaxNSigmasTPC[1], last->mMaxNSigmasTPC[2], last->mMaxNSigmasTPC[3], last->mMaxNSigmasTPC[4]); LOGF(info, " minTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTOF[0], last->mMinNSigmasTOF[1], last->mMinNSigmasTOF[2], last->mMinNSigmasTOF[3], last->mMinNSigmasTOF[4]); LOGF(info, " maxTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTOF[0], last->mMaxNSigmasTOF[1], last->mMaxNSigmasTOF[2], last->mMaxNSigmasTOF[3], last->mMaxNSigmasTOF[4]); + LOGF(info, " %.1f < pT < %.1f", last->mPtMin, last->mPtMax); } template int8_t whichSpecies(TrackObject const& track) @@ -1178,6 +1200,15 @@ struct PIDSpeciesSelection { } } } + /* check a species transverse momentum cut */ + if (!(id < 0)) { + /* identified */ + if ((track.pt() < config[id]->mPtMin) || config[id]->mPtMax < track.pt()) { + /* rejected */ + outpiddebug(4, species[id], -1); + return -127; + } + } /* out debug info if needed */ if (id < 0) { /* not identified */ @@ -1207,6 +1238,11 @@ struct PIDSpeciesSelection { if (config.size() > 0) { for (uint8_t ix = 0; ix < config.size(); ++ix) { if (pdgcode == pdgcodes[species[ix]]) { + /* check a species transverse momentum cut */ + if ((part.pt() < config[ix]->mPtMin) || config[ix]->mPtMax < part.pt()) { + /* rejected */ + return -127; + } return ix; } } diff --git a/PWGCF/TableProducer/filterCorrelations.cxx b/PWGCF/TableProducer/filterCorrelations.cxx index 5335004e168..9cbde25a20c 100644 --- a/PWGCF/TableProducer/filterCorrelations.cxx +++ b/PWGCF/TableProducer/filterCorrelations.cxx @@ -59,7 +59,7 @@ struct FilterCF { O2_DEFINE_CONFIGURABLE(cfgCutMCPt, float, 0.5f, "Minimal pT for particles") O2_DEFINE_CONFIGURABLE(cfgCutMCEta, float, 0.8f, "Eta range for particles") O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 1, "Verbosity level (0 = major, 1 = per collision)") - O2_DEFINE_CONFIGURABLE(cfgTrigger, int, 7, "Trigger choice: (0 = none, 7 = sel7, 8 = sel8, 9 = sel8 + kNoSameBunchPileup + kIsGoodZvtxFT0vsPV, 10 = sel8 before April, 2024, 11 = sel8 for MC)") + O2_DEFINE_CONFIGURABLE(cfgTrigger, int, 7, "Trigger choice: (0 = none, 7 = sel7, 8 = sel8, 9 = sel8 + kNoSameBunchPileup + kIsGoodZvtxFT0vsPV, 10 = sel8 before April, 2024, 11 = sel8 for MC, 12 = sel8 with low occupancy cut)") O2_DEFINE_CONFIGURABLE(cfgCollisionFlags, uint16_t, aod::collision::CollisionFlagsRun2::Run2VertexerTracks, "Request collision flags if non-zero (0 = off, 1 = Run2VertexerTracks)") O2_DEFINE_CONFIGURABLE(cfgTransientTables, bool, false, "Output transient tables for collision and track IDs") O2_DEFINE_CONFIGURABLE(cfgTrackSelection, int, 0, "Type of track selection (0 = Run 2/3 without systematics | 1 = Run 3 with systematics)") @@ -104,6 +104,12 @@ struct FilterCF { return collision.selection_bit(aod::evsel::kIsTriggerTVX); } else if (cfgTrigger == 11) { // sel8 selection for MC return collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder); + } else if (cfgTrigger == 12) { // relevant only for Pb-Pb with occupancy cuts and rejection of the collisions which have other events nearby + int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy >= 0 && occupancy < 500) + return collision.sel8() && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard); + else + return false; } return false; } @@ -271,6 +277,25 @@ struct FilterCF { delete[] mcParticleLabels; } PROCESS_SWITCH(FilterCF, processMC, "Process MC", false); + + void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& particles) + { + float multiplicity = 0.0f; + for (auto& particle : particles) { + if (!particle.isPhysicalPrimary() || std::abs(particle.eta()) > cfgCutMCEta || particle.pt() < cfgCutMCPt) + continue; + int8_t sign = 0; + if (TParticlePDG* pdgparticle = pdg->GetParticle(particle.pdgCode())) + if ((sign = pdgparticle->Charge()) != 0) + multiplicity += 1.0f; + outputMcParticles(outputMcCollisions.lastIndex() + 1, truncateFloatFraction(particle.pt(), FLOAT_PRECISION), + truncateFloatFraction(particle.eta(), FLOAT_PRECISION), + truncateFloatFraction(particle.phi(), FLOAT_PRECISION), + sign, particle.pdgCode(), particle.flags()); + } + outputMcCollisions(mcCollision.posZ(), multiplicity); + } + PROCESS_SWITCH(FilterCF, processMCGen, "Process MCGen", false); }; struct MultiplicitySelector { @@ -300,6 +325,9 @@ struct MultiplicitySelector { if (doprocessFT0A) { enabledFunctions++; } + if (doprocessMCGen) { + enabledFunctions++; + } if (enabledFunctions != 1) { LOGP(fatal, "{} multiplicity selectors enabled but we need exactly 1.", enabledFunctions); @@ -343,6 +371,12 @@ struct MultiplicitySelector { } } PROCESS_SWITCH(MultiplicitySelector, processRun2V0M, "Select V0M centrality as multiplicity", true); + + void processMCGen(aod::McCollision const&, aod::McParticles const& particles) + { + output(particles.size()); + } + PROCESS_SWITCH(MultiplicitySelector, processMCGen, "Select MC particle count as multiplicity", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index a83558740e2..d6e0e94752b 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -149,6 +149,7 @@ struct CorrelationTask { registry.add("etaphiTrigger", "multiplicity/centrality vs eta vs phi (triggers)", {HistType::kTH3F, {{100, 0, 100, "multiplicity/centrality"}, {100, -2, 2, "#eta"}, {200, 0, 2 * M_PI, "#varphi"}}}); registry.add("invMass", "2-prong invariant mass (GeV/c^2)", {HistType::kTH3F, {axisInvMassHistogram, axisPtTrigger, axisMultiplicity}}); } + registry.add("multiplicity", "multiplicity vs track count", {HistType::kTH1F, {{1000, 0, 100, "/multiplicity/centrality"}}}); const int maxMixBin = AxisSpec(axisMultiplicity).getNbins() * AxisSpec(axisVertex).getNbins(); registry.add("eventcount_same", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); @@ -221,6 +222,7 @@ struct CorrelationTask { template void fillQA(const TCollision& /*collision*/, float multiplicity, const TTracks& tracks) { + registry.fill(HIST("multiplicity"), multiplicity); for (auto& track1 : tracks) { registry.fill(HIST("yields"), multiplicity, track1.pt(), track1.eta()); registry.fill(HIST("etaphi"), multiplicity, track1.eta(), track1.phi()); @@ -794,6 +796,8 @@ struct CorrelationTask { } } + fillQA(mcCollision, multiplicity, mcParticles); + same->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); fillCorrelations(same, mcParticles, mcParticles, multiplicity, mcCollision.posZ(), 0, 1.0f); diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx index 7bcdf88ff4c..e5f2aa908ca 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx @@ -88,6 +88,8 @@ TH1F* fhDeltaNA[kIdBfNoOfSpecies] = {nullptr}; TH2F* fhNSigmaTPC[kIdBfNoOfSpecies] = {nullptr}; TH2F* fhNSigmaTOF[kIdBfNoOfSpecies] = {nullptr}; +TH2F* fhNSigmaCombo[kIdBfNoOfSpecies] = {nullptr}; +TH2F* fhNSigmaTPC_IdTrks[kIdBfNoOfSpecies] = {nullptr}; TH1F* fhEtaB = nullptr; TH1F* fhEtaA = nullptr; @@ -739,6 +741,14 @@ struct IdentifiedBfFilterTracks { TString::Format("N Sigma from TOF vs P for %s;N #sigma;p (GeV/c)", speciesTitle[sp]).Data(), 48, -6, 6, ptbins, ptlow, ptup); + fhNSigmaCombo[sp] = new TH2F(TString::Format("fhNSigmaCombo_%s", speciesName[sp]).Data(), + TString::Format("N Sigma from Combo vs P for %s;N #sigma;p (GeV/c)", speciesTitle[sp]).Data(), + 48, -6, 6, + ptbins, ptlow, ptup); + fhNSigmaTPC_IdTrks[sp] = new TH2F(TString::Format("fhNSigmaTPC_IdTrks_%s", speciesName[sp]).Data(), + TString::Format("N Sigma from TPC vs P for Identified %s;N #sigma;p (GeV/c)", speciesTitle[sp]).Data(), + 48, -6, 6, + ptbins, ptlow, ptup); fhdEdxA[sp] = new TH2F(TString::Format("fhdEdxA_%s", speciesName[sp]).Data(), TString::Format("dE/dx vs P reconstructed %s; P (GeV/c); dE/dx (a.u.)", speciesTitle[sp]).Data(), ptbins, ptlow, ptup, 1000, 0.0, 1000.0); @@ -787,6 +797,8 @@ struct IdentifiedBfFilterTracks { fOutputList->Add(fhDeltaNA[sp]); fOutputList->Add(fhNSigmaTPC[sp]); fOutputList->Add(fhNSigmaTOF[sp]); + fOutputList->Add(fhNSigmaCombo[sp]); + fOutputList->Add(fhNSigmaTPC_IdTrks[sp]); fOutputList->Add(fhdEdxA[sp]); fOutputList->Add(fhdEdxIPTPCA[sp]); } @@ -1146,21 +1158,32 @@ inline MatchRecoGenSpecies IdentifiedBfFilterTracks::IdentifyParticle(ParticleOb } template -inline MatchRecoGenSpecies IdentifiedBfFilterTracks::IdentifyTrack(TrackObject const& track) +void fillNSigmaHistos(TrackObject const& track) { - using namespace o2::analysis::identifiedbffilter; - if (!onlyTOF) { - fhNSigmaTPC[kIdBfElectron]->Fill(track.tpcNSigmaEl(), track.tpcInnerParam()); - fhNSigmaTPC[kIdBfPion]->Fill(track.tpcNSigmaPi(), track.tpcInnerParam()); - fhNSigmaTPC[kIdBfKaon]->Fill(track.tpcNSigmaKa(), track.tpcInnerParam()); - fhNSigmaTPC[kIdBfProton]->Fill(track.tpcNSigmaPr(), track.tpcInnerParam()); - } + fhNSigmaTPC[kIdBfElectron]->Fill(track.tpcNSigmaEl(), track.tpcInnerParam()); + fhNSigmaTPC[kIdBfPion]->Fill(track.tpcNSigmaPi(), track.tpcInnerParam()); + fhNSigmaTPC[kIdBfKaon]->Fill(track.tpcNSigmaKa(), track.tpcInnerParam()); + fhNSigmaTPC[kIdBfProton]->Fill(track.tpcNSigmaPr(), track.tpcInnerParam()); + fhNSigmaTOF[kIdBfElectron]->Fill(track.tofNSigmaEl(), track.tpcInnerParam()); fhNSigmaTOF[kIdBfPion]->Fill(track.tofNSigmaPi(), track.tpcInnerParam()); fhNSigmaTOF[kIdBfKaon]->Fill(track.tofNSigmaKa(), track.tpcInnerParam()); fhNSigmaTOF[kIdBfProton]->Fill(track.tofNSigmaPr(), track.tpcInnerParam()); + fhNSigmaCombo[kIdBfElectron]->Fill(sqrtf(track.tofNSigmaEl() * track.tofNSigmaEl() + track.tpcNSigmaEl() * track.tpcNSigmaEl()), track.tpcInnerParam()); + fhNSigmaCombo[kIdBfPion]->Fill(sqrtf(track.tofNSigmaPi() * track.tofNSigmaPi() + track.tpcNSigmaPi() * track.tpcNSigmaPi()), track.tpcInnerParam()); + fhNSigmaCombo[kIdBfKaon]->Fill(sqrtf(track.tofNSigmaKa() * track.tofNSigmaKa() + track.tpcNSigmaKa() * track.tpcNSigmaKa()), track.tpcInnerParam()); + fhNSigmaCombo[kIdBfProton]->Fill(sqrtf(track.tofNSigmaPr() * track.tofNSigmaPr() + track.tpcNSigmaPr() * track.tpcNSigmaPr()), track.tpcInnerParam()); +} + +template +inline MatchRecoGenSpecies IdentifiedBfFilterTracks::IdentifyTrack(TrackObject const& track) +{ + using namespace o2::analysis::identifiedbffilter; + + fillNSigmaHistos(track); + float nsigmas[kIdBfNoOfSpecies]; if (track.p() < 0.8 && !reqTOF && !onlyTOF) { nsigmas[kIdBfElectron] = track.tpcNSigmaEl(); @@ -1231,18 +1254,18 @@ inline MatchRecoGenSpecies IdentifiedBfFilterTracks::IdentifyTrack(TrackObject c fhDoublePID->Fill(sp_min_nsigma, spDouble); return kWrongSpecies; // Return wrong species value } else { - if (track.hasTOF() && onlyTOF) { + if (track.hasTOF() && (reqTOF || onlyTOF)) { if (sp_min_nsigma == 0) { - fhNSigmaTPC[sp_min_nsigma]->Fill(track.tpcNSigmaEl(), track.tpcInnerParam()); + fhNSigmaTPC_IdTrks[sp_min_nsigma]->Fill(track.tpcNSigmaEl(), track.tpcInnerParam()); } if (sp_min_nsigma == 1) { - fhNSigmaTPC[sp_min_nsigma]->Fill(track.tpcNSigmaPi(), track.tpcInnerParam()); + fhNSigmaTPC_IdTrks[sp_min_nsigma]->Fill(track.tpcNSigmaPi(), track.tpcInnerParam()); } if (sp_min_nsigma == 2) { - fhNSigmaTPC[sp_min_nsigma]->Fill(track.tpcNSigmaKa(), track.tpcInnerParam()); + fhNSigmaTPC_IdTrks[sp_min_nsigma]->Fill(track.tpcNSigmaKa(), track.tpcInnerParam()); } if (sp_min_nsigma == 3) { - fhNSigmaTPC[sp_min_nsigma]->Fill(track.tpcNSigmaPr(), track.tpcInnerParam()); + fhNSigmaTPC_IdTrks[sp_min_nsigma]->Fill(track.tpcNSigmaPr(), track.tpcInnerParam()); } } return sp_min_nsigma; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.h b/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.h index 55036a6ae38..439edfc6854 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.h @@ -515,54 +515,40 @@ inline float extractMultiplicity(CollisionObject const& collision, CentMultEstim ////////////////////////////////////////////////////////////////////////////////// /// Centrality selection ////////////////////////////////////////////////////////////////////////////////// - /// \brief Centrality/multiplicity percentile template + requires(o2::aod::HasRun2Centrality) float getCentMultPercentile(CollisionObject collision) { - if constexpr (framework::has_type_v || - framework::has_type_v || - framework::has_type_v) { - switch (fCentMultEstimator) { - case kV0M: - return collision.centRun2V0M(); - break; - case kCL0: - return collision.centRun2CL0(); - break; - case kCL1: - return collision.centRun2CL1(); - break; - default: - return 105.0; - break; - } + switch (fCentMultEstimator) { + case kV0M: + return collision.centRun2V0M(); + case kCL0: + return collision.centRun2CL0(); + case kCL1: + return collision.centRun2CL1(); + default: + return 105.0; } - if constexpr (framework::has_type_v || - framework::has_type_v || - framework::has_type_v || - framework::has_type_v || - framework::has_type_v) { - switch (fCentMultEstimator) { - case kFV0A: - return collision.centFV0A(); - break; - case kFT0M: - return collision.centFT0M(); - break; - case kFT0A: - return collision.centFT0A(); - break; - case kFT0C: - return collision.centFT0C(); - break; - case kNTPV: - return collision.centNTPV(); - break; - default: - return 105.0; - break; - } +} + +template + requires(o2::aod::HasCentrality) +float getCentMultPercentile(CollisionObject collision) +{ + switch (fCentMultEstimator) { + case kFV0A: + return collision.centFV0A(); + case kFT0M: + return collision.centFT0M(); + case kFT0A: + return collision.centFT0A(); + case kFT0C: + return collision.centFT0C(); + case kNTPV: + return collision.centNTPV(); + default: + return 105.0; } } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index 877ef23b236..f6742441246 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -18,6 +18,11 @@ o2physics_add_dpl_workflow(r2p24id PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambdacorr + SOURCES lambdaR2Correlation.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(identifiedbf SOURCES identifiedbf.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx new file mode 100644 index 00000000000..668487f53f4 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -0,0 +1,1160 @@ +// Copyright 2019-2020 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. + +/// \file lambdaCorrelationAnalysis.cxx +/// \brief R2 correlation of Lambda baryons. +/// \author Yash Patley + +#include + +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/Core/RecoDecay.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +namespace o2::aod +{ +namespace lambdacollision +{ +DECLARE_SOA_COLUMN(Cent, cent, float); +} +DECLARE_SOA_TABLE(LambdaCollisions, "AOD", "LAMBDACOLS", o2::soa::Index<>, + lambdacollision::Cent, + aod::collision::PosX, + aod::collision::PosY, + aod::collision::PosZ); +using LambdaCollision = LambdaCollisions::iterator; + +namespace lambdamcgencollision +{ +} +DECLARE_SOA_TABLE(LambdaMCGenCollisions, "AOD", "LMCGENCOLS", o2::soa::Index<>, + o2::aod::mccollision::PosX, + o2::aod::mccollision::PosY, + o2::aod::mccollision::PosZ); +using LambdaMCGenCollision = LambdaMCGenCollisions::iterator; + +namespace lambdatrack +{ +DECLARE_SOA_INDEX_COLUMN(LambdaCollision, lambdaCollision); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(PosTrackId, postrackid, int64_t); +DECLARE_SOA_COLUMN(NegTrackId, negtrackid, int64_t); +DECLARE_SOA_COLUMN(V0Type, v0type, int8_t); +} // namespace lambdatrack +DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, + lambdatrack::LambdaCollisionId, + lambdatrack::Pt, + lambdatrack::Rap, + lambdatrack::Phi, + lambdatrack::Mass, + lambdatrack::PosTrackId, + lambdatrack::NegTrackId, + lambdatrack::V0Type); +using LambdaTrack = LambdaTracks::iterator; + +namespace lambdamcgentrack +{ +DECLARE_SOA_INDEX_COLUMN(LambdaMCGenCollision, lambdaMcGenCollision); +} +DECLARE_SOA_TABLE(LambdaMCGenTracks, "AOD", "LMCGENTRACKS", o2::soa::Index<>, + lambdamcgentrack::LambdaMCGenCollisionId, + o2::aod::mcparticle::Pt, + lambdatrack::Rap, + o2::aod::mcparticle::Phi, + lambdatrack::Mass, + lambdatrack::PosTrackId, + lambdatrack::NegTrackId, + lambdatrack::V0Type); +using LambdaMCGenTrack = LambdaMCGenTracks::iterator; + +} // namespace o2::aod + +enum PidType { + kPion = 0, + kProton +}; + +enum ParticleType { + kLambda = 0, + kAntiLambda +}; + +enum ParticlePairType { + kLambdaAntiLambda = 0, + kLambdaLambda, + kAntiLambdaAntiLambda +}; + +enum RecGenType { + kRec = 0, + kGen +}; + +struct lambdaCorrTableProducer { + + Produces lambdaCollisionTable; + Produces lambdaTrackTable; + Produces lambdaMCGenCollisionTable; + Produces lambdaMCGenTrackTable; + + // Collisions + Configurable cfg_z_vtx{"cfg_z_vtx", 10.0, "z vertex cut"}; + Configurable cfg_sel8_sel{"cfg_sel8_sel", true, "Sel8 (T0A + T0C) Selection"}; + Configurable cfg_trigger_tvx_sel{"cfg_trigger_tvx_sel", false, "Trigger Time and Vertex Selection"}; + Configurable cfg_tf_border{"cfg_tf_border", false, "Timeframe Border Selection"}; + Configurable cfg_noitsro_border{"cfg_noitsro_border", false, "No ITSRO Border Cut"}; + Configurable cfg_itstpc_vtx{"cfg_itstpc_vtx", false, "ITS+TPC Vertex Selection"}; + Configurable cfg_pileup_reject{"cfg_pileup_reject", false, "Pileup rejection"}; + Configurable cfg_zvtx_time_diff{"cfg_zvtx_time_diff", false, "z-vtx time diff selection"}; + + // Tracks + Configurable cfg_pt_min{"cfg_pt_min", 0.2, "p_{T} minimum"}; + Configurable cfg_pt_max{"cfg_pt_max", 4.0, "p_{T} minimum"}; + Configurable cfg_eta_cut{"cfg_eta_cut", 0.8, "Pseudorapidity cut"}; + Configurable cfg_min_crossed_rows{"cfg_min_crossed_rows", 70, "min crossed rows"}; + Configurable cfg_tpc_nsigma{"cfg_tpc_nsigma", 2.0, "TPC NSigma Selection Cut"}; + Configurable cfg_shift_nsigma{"cfg_shift_nsigma", false, "shift nsigma"}; + + // nsigma corrections + // Lambda + Configurable> cfg_lambda_pr_nsigma_corr_pt{"cfg_lambda_pr_nsigma_corr_pt", {0.2, 0.4, 0.6, 0.8, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0, 4.0}, "lambda pr nsgima pt bins"}; + Configurable> cfg_lambda_pr_nsgima_corrfact{"cfg_lambda_pr_nsgima_corrfact", {1.9, 2.15, 1.85, 1.7, 1.75, 1.5, 1.3, 1.3, 1.5, 1.3}, "lambda pr nsigma correction factors"}; + Configurable> cfg_lambda_pi_nsigma_corr_pt{"cfg_lambda_pi_nsigma_corr_pt", {0.2, 0.4, 0.6, 0.8, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0, 4.0}, "lambda pi nsgima pt bins"}; + Configurable> cfg_lambda_pi_nsgima_corrfact{"cfg_lambda_pi_nsgima_corrfact", {0.85, 1.0, 1.1, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, "lambda pi nsigma correction factors"}; + + // Anti-Lambda + Configurable> cfg_antilambda_pr_nsigma_corr_pt{"cfg_antilambda_pr_nsigma_corr_pt", {0.2, 0.4, 0.6, 0.8, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0, 4.0}, "antilambda pr nsgima pt bins"}; + Configurable> cfg_antilambda_pr_nsgima_corrfact{"cfg_antilambda_pr_nsgima_corrfact", {2.1, 1.9, 1.9, 1.85, 1.65, 1.35, 1.3, 1.3, 1.5, 1.2}, "antilambda pr nsigma correction factors"}; + Configurable> cfg_antilambda_pi_nsigma_corr_pt{"cfg_antilambda_pi_nsigma_corr_pt", {0.2, 0.4, 0.6, 0.8, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0, 4.0}, "antilambda pi nsgima pt bins"}; + Configurable> cfg_antilambda_pi_nsgima_corrfact{"cfg_antilambda_pi_nsgima_corrfact", {0.85, 1.1, 1.2, 1.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, "antilambda pi nsigma correction factors"}; + + // V0s + Configurable cfg_min_dca_V0_daughters{"cfg_min_dca_V0_daughters", 1.0, "min DCA between V0 daughters"}; + Configurable cfg_min_dca_pos_to_PV{"cfg_min_dca_pos_to_PV", 0.1, "Minimum V0 Positive Track DCAr cut to PV"}; + Configurable cfg_min_dca_neg_to_PV{"cfg_min_dca_neg_to_PV", 0.1, "Minimum V0 Negative Track DCAr cut to PV"}; + Configurable cfg_min_dca_V0_to_PV{"cfg_min_dca_V0_to_PV", 0.6, "Minimum DCA V0 to PV"}; + Configurable cfg_min_V0_radius{"cfg_min_V0_radius", 0.0, "Minimum V0 radius from PV"}; + Configurable cfg_max_V0_radius{"cfg_max_V0_radius", 50.0, "Maximum V0 radius from PV"}; + Configurable cfg_min_ctau{"cfg_min_ctau", 0.0, "Minimum ctau"}; + Configurable cfg_max_ctau{"cfg_max_ctau", 50.0, "Maximum ctau"}; + Configurable cfg_min_V0_cosPA{"cfg_min_V0_cosPA", 0.998, "Minimum V0 CosPA to PV"}; + Configurable cfg_lambda_mass_window{"cfg_lambda_mass_window", 0.007, "Mass Window to select Lambda"}; + Configurable cfg_kshort_rej{"cfg_kshort_rej", 0.005, "Reject K0Short Candidates"}; + Configurable cfg_kshort_rej_flag{"cfg_kshort_rej_flag", false, "K0short Mass Rej Flag"}; + Configurable cfg_armpod_flag{"cfg_armpod_flag", true, "Armentros-Podolanski Cut Flag"}; + Configurable cfg_armpod_val{"cfg_armpod_val", 0.5, "Armentros-Podolanski Slope Parameter"}; + + // V0s kinmatic acceptance + Configurable cfg_v0_pt_min{"cfg_v0_pt_min", 0.3, "Minimum V0 pT"}; + Configurable cfg_v0_pt_max{"cfg_v0_pt_max", 3.0, "Minimum V0 pT"}; + Configurable cfg_v0_rap_max{"cfg_v0_rap_max", 0.8, "|rap| cut"}; + + // bool eta/rapidity + Configurable cfg_do_eta_analysis{"cfg_do_eta_analysis", false, "Eta Analysis"}; + + // V0s MC + Configurable cfg_primary_lambda{"cfg_primary_lambda", true, "Primary Lambda"}; + Configurable cfg_secondary_lambda{"cfg_secondary_lambda", false, "Secondary Lambda"}; + Configurable cfg_has_mc_flag{"cfg_has_mc_flag", false, "Has Mc Tag"}; + + // Global Variable Initialization + std::vector v_pt_bins_lambda_pr = static_cast>(cfg_lambda_pr_nsigma_corr_pt); + std::vector v_corr_factor_lambda_pr = static_cast>(cfg_lambda_pr_nsgima_corrfact); + int n_lambda_pr = v_corr_factor_lambda_pr.size(); + std::vector v_pt_bins_lambda_pi = static_cast>(cfg_lambda_pi_nsigma_corr_pt); + std::vector v_corr_factor_lambda_pi = static_cast>(cfg_lambda_pi_nsgima_corrfact); + int n_lambda_pi = v_corr_factor_lambda_pi.size(); + + std::vector v_pt_bins_antilambda_pr = static_cast>(cfg_antilambda_pr_nsigma_corr_pt); + std::vector v_corr_factor_antilambda_pr = static_cast>(cfg_antilambda_pr_nsgima_corrfact); + int n_antilambda_pr = v_corr_factor_antilambda_pr.size(); + std::vector v_pt_bins_antilambda_pi = static_cast>(cfg_antilambda_pi_nsigma_corr_pt); + std::vector v_corr_factor_antilambda_pi = static_cast>(cfg_antilambda_pi_nsgima_corrfact); + int n_antilambda_pi = v_corr_factor_antilambda_pi.size(); + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + const AxisSpec axisCol(6, 0, 6, ""); + const AxisSpec axisCent(105, 0, 105, "FT0M (%)"); + const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); + const AxisSpec axisVz(220, -11, 11, "V_{z} (cm)"); + const AxisSpec axisPID(8000, -4000, 4000, "PdgCode"); + + const AxisSpec axisV0Mass(100, 1.06, 1.16, "Inv Mass (GeV/#it{c}^{2})"); + const AxisSpec axisV0Pt(200, 0., 5., "p_{T} (GeV/#it{c})"); + const AxisSpec axisV0Rap(16, -0.8, 0.8, "rap"); + const AxisSpec axisV0Phi(36, 0., 2. * TMath::Pi(), "#phi (rad)"); + + const AxisSpec axisRadius(400, 0, 200, "r(cm)"); + const AxisSpec axisCosPA(100, 0.99, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisDcaV0PV(1000, -5., 5., "dca (cm)"); + const AxisSpec axisDcaProngPV(1000, -50., 50., "dca (cm)"); + const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); + const AxisSpec axisCTau(400, 0, 200, "c#tau (cm)"); + const AxisSpec axisGCTau(400, 0, 200, "#gammac#tau (cm)"); + const AxisSpec axisAlpha(40, -1, 1, "#alpha"); + const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); + + const AxisSpec axisMomPID(80, 0, 4, "p (GeV/#it{c})"); + const AxisSpec axisNsigma(401, -10.025, 10.025, {"n#sigma"}); + const AxisSpec axisdEdx(360, 20, 200, "#frac{dE}{dx}"); + + // Create Histograms. + // Event histograms + histos.add("Event/h1d_collision_posZ", "V_{z}-distribution", kTH1F, {axisVz}); + histos.add("Event/h1d_collisions_info", "# of Collisions", kTH1F, {axisCol}); + + // QA + histos.add("QA_Checks/h1d_tracks_info", "# of tracks", kTH1F, {axisCol}); + histos.add("QA_Checks/h1d_lambda_mass", "M_{#Lambda}", kTH1F, {axisV0Mass}); + histos.add("QA_Checks/h2d_n1_V0_ptmass", "p_{T} vs M_{#Lambda}", kTH2F, {axisV0Mass, axisV0Pt}); + histos.add("QA_Checks/h2d_before_topo_cuts_pt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("QA_Checks/h2d_after_topo_cuts_pt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("QA_Checks/h2d_before_masswincut_pt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("QA_Checks/h2d_after_masswincut_pt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + + // QA Lambda + histos.add("QA_Sel_Lambda/h1d_V0_inv_mass", "V_{0} mass", kTH1F, {axisV0Mass}); + histos.add("QA_Sel_Lambda/h1d_V0_pt", "V_{0} p_{T}", kTH1F, {axisV0Pt}); + histos.add("QA_Sel_Lambda/h1d_V0_eta", "#eta-distribution", kTH1F, {axisV0Rap}); + histos.add("QA_Sel_Lambda/h1d_V0_rap", "y-distribution", kTH1F, {axisV0Rap}); + histos.add("QA_Sel_Lambda/h1d_V0_phi", "#phi-distribution", kTH1F, {axisV0Phi}); + histos.add("QA_Sel_Lambda/h2d_n1_V0_pteta", "p_{T} vs #eta", kTH2F, {axisV0Rap, axisV0Pt}); + histos.add("QA_Sel_Lambda/h2d_n1_V0_ptrap", "p_{T} vs y", kTH2F, {axisV0Rap, axisV0Pt}); + histos.add("QA_Sel_Lambda/h2d_n1_V0_ptphi", "p_{T} vs #phi", kTH2F, {axisV0Phi, axisV0Pt}); + + histos.add("QA_Sel_Lambda/h1d_dca_V0_daughters", "DCA between V0 daughters", kTH1F, {axisDcaDau}); + histos.add("QA_Sel_Lambda/h1d_dca_pos_to_PV", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("QA_Sel_Lambda/h1d_dca_neg_to_PV", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("QA_Sel_Lambda/h1d_dca_V0_to_PV", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); + histos.add("QA_Sel_Lambda/h1d_V0_cospa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); + histos.add("QA_Sel_Lambda/h1d_V0_radius", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); + histos.add("QA_Sel_Lambda/h1d_V0_ctau", "V_{0} c#tau", kTH1F, {axisCTau}); + histos.add("QA_Sel_Lambda/h1d_V0_gctau", "V_{0} #gammac#tau", kTH1F, {axisGCTau}); + histos.add("QA_Sel_Lambda/h2d_qt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + + histos.add("QA_Sel_Lambda/h1d_pos_prong_pt", "Pos-Prong p_{T}", kTH1F, {axisV0Pt}); + histos.add("QA_Sel_Lambda/h1d_neg_prong_pt", "Neg-Prong p_{T}", kTH1F, {axisV0Pt}); + histos.add("QA_Sel_Lambda/h1d_pos_prong_eta", "Pos-Prong #eta-distribution", kTH1F, {axisV0Rap}); + histos.add("QA_Sel_Lambda/h1d_neg_prong_eta", "Neg-Prong #eta-distribution", kTH1F, {axisV0Rap}); + histos.add("QA_Sel_Lambda/h1d_pos_prong_phi", "Pos-Prong #phi-distribution", kTH1F, {axisV0Phi}); + histos.add("QA_Sel_Lambda/h1d_neg_prong_phi", "Neg-Prong #phi-distribution", kTH1F, {axisV0Phi}); + + histos.add("QA_Sel_Lambda/h2d_pos_prong_dEdx_vs_p", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("QA_Sel_Lambda/h2d_neg_prong_dEdx_vs_p", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("QA_Sel_Lambda/h2d_nsigma_pr_tpc", "TPC n#sigma Proton", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA_Sel_Lambda/h2d_nsigma_pi_tpc", "TPC n#sigma Pion", kTH2F, {axisMomPID, axisNsigma}); + + // QA Anti-Lambda + histos.addClone("QA_Sel_Lambda/", "QA_Sel_AntiLambda/"); + + // MC Generated Histograms + if (doprocessMCGen) { + // McReco Histos + histos.add("QA_Checks/h1d_tracks_pid_before_mccuts", "PIDs", kTH2F, {axisPID, axisV0Pt}); + histos.add("QA_Checks/h1d_tracks_pid_phyprim", "PIDs", kTH2F, {axisPID, axisV0Pt}); + histos.add("QA_Checks/h1d_tracks_pid_after_sel", "PIDs", kTH2F, {axisPID, axisV0Pt}); + + // McGen Histos + histos.add("McGen/h1d_collisions_info", "# of collisions", kTH1F, {axisCol}); + histos.add("McGen/h1d_collision_posZ", "V_{z}-distribution", kTH1F, {axisVz}); + histos.add("McGen/h1d_mass_lambda", "M_{#Lambda}", kTH1F, {axisV0Mass}); + histos.add("McGen/h1d_pt_lambda", "#Lambda p_{T}", kTH1F, {axisV0Pt}); + histos.add("McGen/h1d_eta_lambda", "#Lambda #eta-distribution", kTH1F, {axisV0Rap}); + histos.add("McGen/h1d_y_lambda", "#Lambda y-distribution", kTH1F, {axisV0Rap}); + histos.add("McGen/h1d_phi_lambda", "#Lambda #phi-distribution", kTH1F, {axisV0Phi}); + histos.add("McGen/h2d_pteta_lambda", "#Lambda p_{T} vs #eta", kTH2F, {axisV0Rap, axisV0Pt}); + histos.add("McGen/h2d_ptrap_lambda", "#Lambda p_{T} vs y", kTH2F, {axisV0Rap, axisV0Pt}); + histos.add("McGen/h2d_ptphi_lambda", "#Lambda p_{T} vs #phi", kTH2F, {axisV0Phi, axisV0Pt}); + histos.add("McGen/h1d_mass_antilambda", "M_{#bar{#Lambda}}", kTH1F, {axisV0Mass}); + histos.add("McGen/h1d_pt_antilambda", "#bar{#Lambda} p_{T}", kTH1F, {axisV0Pt}); + histos.add("McGen/h1d_eta_antilambda", "#bar{#Lambda} #eta-distribution", kTH1F, {axisV0Rap}); + histos.add("McGen/h1d_y_antilambda", "#bar{#Lambda} y-distribution", kTH1F, {axisV0Rap}); + histos.add("McGen/h1d_phi_antilambda", "#bar{#Lambda} #phi-distribution", kTH1F, {axisV0Phi}); + histos.add("McGen/h2d_pteta_antilambda", "#bar{#Lambda} p_{T} vs #eta", kTH2F, {axisV0Rap, axisV0Pt}); + histos.add("McGen/h2d_ptrap_antilambda", "#bar{#Lambda} p_{T} vs y", kTH2F, {axisV0Rap, axisV0Pt}); + histos.add("McGen/h2d_ptphi_antilambda", "#bar{#Lambda} p_{T} vs #phi", kTH2F, {axisV0Phi, axisV0Pt}); + } + } + + template + bool selCol(C const& col) + { + + if (fabs(col.posZ()) > cfg_z_vtx) { + return false; + } + + if (!col.sel8() && cfg_sel8_sel) { + return false; + } + + if (!col.selection_bit(aod::evsel::kIsTriggerTVX) && cfg_trigger_tvx_sel) { + return false; + } + + if (!col.selection_bit(aod::evsel::kNoTimeFrameBorder) && cfg_tf_border) { + return false; + } + + if (!col.selection_bit(aod::evsel::kNoITSROFrameBorder) && cfg_noitsro_border) { + return false; + } + + if (!col.selection_bit(aod::evsel::kIsVertexITSTPC) && cfg_itstpc_vtx) { + return false; + } + + if (!col.selection_bit(aod::evsel::kNoSameBunchPileup) && cfg_pileup_reject) { + return false; + } + + if (!col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && cfg_zvtx_time_diff) { + return false; + } + + return true; + } + + template + bool topologicalCutsV0(C const& col, V const& v0, T const&) + { + + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + if (postrack.pt() < cfg_pt_min || postrack.pt() > cfg_pt_max) { + return false; + } + + if (negtrack.pt() < cfg_pt_min || negtrack.pt() > cfg_pt_max) { + return false; + } + + if (fabs(postrack.eta()) > cfg_eta_cut) { + return false; + } + + if (fabs(negtrack.eta()) > cfg_eta_cut) { + return false; + } + + if (postrack.tpcNClsCrossedRows() < cfg_min_crossed_rows) { + return false; + } + + if (negtrack.tpcNClsCrossedRows() < cfg_min_crossed_rows) { + return false; + } + + if (v0.dcaV0daughters() > cfg_min_dca_V0_daughters) { + return false; + } + + if (fabs(v0.dcapostopv()) < cfg_min_dca_pos_to_PV) { + return false; + } + + if (fabs(v0.dcanegtopv()) < cfg_min_dca_neg_to_PV) { + return false; + } + + if (v0.dcav0topv() > cfg_min_dca_V0_to_PV) { + return false; + } + + if ((v0.v0radius() > cfg_max_V0_radius) || (v0.v0radius() < cfg_min_V0_radius)) { + return false; + } + + // ctau + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + if (ctau < cfg_min_ctau || ctau > cfg_max_ctau) { + return false; + } + + if (v0.v0cosPA() < cfg_min_V0_cosPA) { + return false; + } + + return true; + } + + void shift_nsigma(float& nsigma, float pt, std::vector v_pt_bins, std::vector v_corr_factor) + { + int n = v_corr_factor.size(); + for (int i = 0; i < n; ++i) { + if (pt > v_pt_bins[i] && pt <= v_pt_bins[i + 1]) { + nsigma = nsigma - v_corr_factor[i]; + } + } + } + + template + bool selPIDTrack(T const& postrack, T const& negtrack) + { + + static constexpr std::string_view sub_dir[] = {"QA_Sel_Lambda/", "QA_Sel_AntiLambda/"}; + + bool return_flag = false; + float tpcNSigmaPr = 0., tpcNSigmaPi = 0.; + float tpcMomPr = 0., tpcMomPi = 0.; + + switch (part) { + // postrack = Proton, negtrack = Pion + case kLambda: + tpcMomPr = postrack.tpcInnerParam(); + tpcNSigmaPr = postrack.tpcNSigmaPr(); + tpcMomPi = negtrack.tpcInnerParam(); + tpcNSigmaPi = negtrack.tpcNSigmaPi(); + + if (cfg_shift_nsigma) { + shift_nsigma(tpcNSigmaPr, tpcMomPr, v_pt_bins_lambda_pr, v_corr_factor_lambda_pr); + shift_nsigma(tpcNSigmaPi, tpcMomPi, v_pt_bins_lambda_pi, v_corr_factor_lambda_pi); + } + + break; + + // negtrack = Proton, postrack = Pion + case kAntiLambda: + tpcMomPr = negtrack.tpcInnerParam(); + tpcNSigmaPr = negtrack.tpcNSigmaPr(); + tpcMomPi = postrack.tpcInnerParam(); + tpcNSigmaPi = postrack.tpcNSigmaPi(); + + if (cfg_shift_nsigma) { + shift_nsigma(tpcNSigmaPr, tpcMomPr, v_pt_bins_antilambda_pr, v_corr_factor_antilambda_pr); + shift_nsigma(tpcNSigmaPi, tpcMomPi, v_pt_bins_antilambda_pi, v_corr_factor_antilambda_pi); + } + + break; + } + + if (fabs(tpcNSigmaPr) < cfg_tpc_nsigma && fabs(tpcNSigmaPi) < cfg_tpc_nsigma) { + return_flag = true; + } + + if (return_flag) { + histos.fill(HIST(sub_dir[part]) + HIST("h2d_nsigma_pr_tpc"), tpcMomPr, tpcNSigmaPr); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_nsigma_pi_tpc"), tpcMomPi, tpcNSigmaPi); + } + + return return_flag; + } + + template + bool checkKinCuts(T const& v0track, float& rap) + { + + // pT cut + if (v0track.pt() <= cfg_v0_pt_min || v0track.pt() >= cfg_v0_pt_max) { + return false; + } + + // apply rapidity/pseudorapidity acceptance + if (cfg_do_eta_analysis) { + rap = v0track.eta(); + } else { + rap = v0track.yLambda(); + } + + if (fabs(rap) >= cfg_v0_rap_max) { + return false; + } + + return true; + } + + template + void fillQALambda(C const& col, V const& v0, T const&) + { + + static constexpr std::string_view sub_dir[] = {"QA_Sel_Lambda/", "QA_Sel_AntiLambda/"}; + + // daugthers + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + float mass = 0.; + + if constexpr (part == kLambda) { + mass = v0.mLambda(); + } else { + mass = v0.mAntiLambda(); + } + + // ctau + TLorentzVector p; + p.SetXYZM(v0.px(), v0.py(), v0.pz(), mass); + float gamma = p.E() / mass; + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + float gctau = ctau * gamma; + + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_inv_mass"), mass); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_pt"), v0.pt()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_eta"), v0.eta()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_rap"), v0.yLambda()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_phi"), v0.phi()); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_n1_V0_pteta"), v0.eta(), v0.pt()); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_n1_V0_ptrap"), v0.yLambda(), v0.pt()); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_n1_V0_ptphi"), v0.phi(), v0.pt()); + + histos.fill(HIST(sub_dir[part]) + HIST("h1d_dca_V0_daughters"), v0.dcaV0daughters()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_dca_pos_to_PV"), v0.dcapostopv()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_dca_neg_to_PV"), v0.dcanegtopv()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_dca_V0_to_PV"), v0.dcav0topv()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_cospa"), v0.v0cosPA()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_radius"), v0.v0radius()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_ctau"), ctau); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_V0_gctau"), gctau); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_qt_vs_alpha"), v0.alpha(), v0.qtarm()); + + histos.fill(HIST(sub_dir[part]) + HIST("h1d_pos_prong_pt"), postrack.pt()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_pos_prong_eta"), postrack.eta()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_pos_prong_phi"), postrack.phi()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_neg_prong_pt"), negtrack.pt()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_neg_prong_eta"), negtrack.eta()); + histos.fill(HIST(sub_dir[part]) + HIST("h1d_neg_prong_phi"), negtrack.phi()); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_pos_prong_dEdx_vs_p"), postrack.tpcInnerParam(), postrack.tpcSignal()); + histos.fill(HIST(sub_dir[part]) + HIST("h2d_neg_prong_dEdx_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcSignal()); + } + + template + void selV0Particle(C const& collision, V const& v0track, T const& tracks) + { + + // apply kinematic cuts + float rap = 0.; + if (!checkKinCuts(v0track, rap)) { + return; + } + + // initialize daughter tracks + auto postrack = v0track.template posTrack_as(); + auto negtrack = v0track.template negTrack_as(); + + // initialize mass and v0lambda/v0antilambda + float mass = 0.; + ParticleType v0part; + + // apply daughter particle id + // check for Lambda / Anti-Lambda + if (selPIDTrack(postrack, negtrack)) { + mass = v0track.mLambda(); + v0part = kLambda; + } else if (selPIDTrack(postrack, negtrack)) { + mass = v0track.mAntiLambda(); + v0part = kAntiLambda; + } else { + return; + } + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 3.5); + histos.fill(HIST("QA_Checks/h2d_before_masswincut_pt_vs_alpha"), v0track.alpha(), v0track.qtarm()); + + // apply Armentros-Podolanski Selection + if (cfg_armpod_flag && (fabs(v0track.alpha()) < v0track.qtarm() / cfg_armpod_val)) { + return; + } + + // apply kshort rejection hypothesis + if (cfg_kshort_rej_flag && (fabs(v0track.mK0Short() - MassK0Short) <= cfg_kshort_rej)) { + return; + } + + // fill mass histograms + histos.fill(HIST("QA_Checks/h1d_lambda_mass"), mass); + + // apply masswindow cut (Selection of Lambda/AntiLambda) + if (fabs(mass - MassLambda0) >= cfg_lambda_mass_window) { + return; + } + + histos.fill(HIST("QA_Checks/h2d_after_masswincut_pt_vs_alpha"), v0track.alpha(), v0track.qtarm()); + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 4.5); + + // apply MC Reco cuts + if constexpr (reco) { + auto v0mcpart = v0track.mcParticle(); + + histos.fill(HIST("QA_Checks/h1d_tracks_pid_before_mccuts"), v0mcpart.pdgCode(), v0mcpart.pt()); + + if (cfg_primary_lambda && !v0mcpart.isPhysicalPrimary()) { + return; + } else if (cfg_secondary_lambda && v0mcpart.isPhysicalPrimary()) { + return; + } + + histos.fill(HIST("QA_Checks/h1d_tracks_pid_phyprim"), v0mcpart.pdgCode(), v0mcpart.pt()); + + if (v0part == kLambda && v0mcpart.pdgCode() != 3122) { + return; + } else if (v0part == kAntiLambda && v0mcpart.pdgCode() != -3122) { + return; + } + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 5.5); + histos.fill(HIST("QA_Checks/h1d_tracks_pid_after_sel"), v0mcpart.pdgCode(), v0mcpart.pt()); + } + + if (v0part == kLambda) { + fillQALambda(collision, v0track, tracks); + } else { + fillQALambda(collision, v0track, tracks); + } + + // fill pT vs mass histogram + histos.fill(HIST("QA_Checks/h2d_n1_V0_ptmass"), mass, v0track.pt()); + + // Fill Lambda/AntiLambda Table + lambdaTrackTable(lambdaCollisionTable.lastIndex(), v0track.pt(), rap, v0track.phi(), mass, postrack.index(), negtrack.index(), (int8_t)v0part); + } + + using Collisions = soa::Join; + using Tracks = soa::Join; + + void processData(Collisions::iterator const& collision, aod::V0Datas const& V0s, Tracks const& tracks) + { + + histos.fill(HIST("Event/h1d_collisions_info"), 1.5); + + // select collision + if (!selCol(collision)) { + return; + } + + histos.fill(HIST("Event/h1d_collisions_info"), 2.5); + histos.fill(HIST("Event/h1d_collision_posZ"), collision.posZ()); + + lambdaCollisionTable(collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ()); + + for (auto const& v0 : V0s) { + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 1.5); + histos.fill(HIST("QA_Checks/h2d_before_topo_cuts_pt_vs_alpha"), v0.alpha(), v0.qtarm()); + + // apply topological cuts on v0 candidates + if (!topologicalCutsV0(collision, v0, tracks)) { + continue; + } + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 2.5); + histos.fill(HIST("QA_Checks/h2d_after_topo_cuts_pt_vs_alpha"), v0.alpha(), v0.qtarm()); + + selV0Particle(collision, v0, tracks); + } + } + + PROCESS_SWITCH(lambdaCorrTableProducer, processData, "Process for DATA", true); + + Preslice> perCol = aod::track::collisionId; + Preslice perMCCol = aod::mcparticle::mcCollisionId; + + SliceCache cache1; + + // Service pdgDB; + + using CollisionsWithMcLabels = soa::Join; + // using McCollisions = soa::Join; + using McCollisions = aod::McCollisions; + using McV0Tracks = soa::Join; + using TracksMC = soa::Join; + + void processMCReco(CollisionsWithMcLabels const& collisions, McCollisions const&, McV0Tracks const& V0s, aod::McParticles const& /*mcParticles*/, TracksMC const& tracks) + { + + for (auto const& collision : collisions) { + + histos.fill(HIST("Event/h1d_collisions_info"), 1.5); + + // select collision + if (!selCol(collision)) { + continue; + } + + histos.fill(HIST("Event/h1d_collisions_info"), 2.5); + + // check for corresponding MCGen Collision + if (cfg_has_mc_flag && !collision.has_mcCollision()) { + continue; + } + + histos.fill(HIST("Event/h1d_collisions_info"), 3.5); + histos.fill(HIST("Event/h1d_collision_posZ"), collision.posZ()); + + lambdaCollisionTable(collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ()); + + // auto const& mcCollision = collision.mcCollision_as(); + + // v0-track loop + auto v0sThisCollision = V0s.sliceBy(perCol, collision.globalIndex()); + for (auto const& v0 : v0sThisCollision) { + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 0.5); + + // check for corresponding MCGen Particle + if (cfg_has_mc_flag && !v0.has_mcParticle()) { + continue; + } + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 1.5); + histos.fill(HIST("QA_Checks/h2d_before_topo_cuts_pt_vs_alpha"), v0.alpha(), v0.qtarm()); + + // apply topological cuts on v0 candidates + if (!topologicalCutsV0(collision, v0, tracks)) { + continue; + } + + histos.fill(HIST("QA_Checks/h1d_tracks_info"), 2.5); + histos.fill(HIST("QA_Checks/h2d_after_topo_cuts_pt_vs_alpha"), v0.alpha(), v0.qtarm()); + + selV0Particle(collision, v0, tracks); + } + } + } + + PROCESS_SWITCH(lambdaCorrTableProducer, processMCReco, "Process for MC Reconstructed", false); + + void processMCGen(McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles) + { + + histos.fill(HIST("McGen/h1d_collisions_info"), 1.5); + + // apply collision cuts + if (fabs(mcCollision.posZ()) > cfg_z_vtx) { + return; + } + + histos.fill(HIST("McGen/h1d_collisions_info"), 2.5); + histos.fill(HIST("McGen/h1d_collision_posZ"), mcCollision.posZ()); + lambdaMCGenCollisionTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + + TLorentzVector p; + int64_t postrackid = 0, negtrackid = 0; + + for (auto const& mcpart : mcParticles) { + + // check for Primary Lambdas/AntiLambdas + if (cfg_primary_lambda && !mcpart.isPhysicalPrimary()) { + continue; + } else if (cfg_secondary_lambda && mcpart.isPhysicalPrimary()) { + continue; + } + + // apply kinematic acceptance + if (mcpart.pt() < cfg_v0_pt_min || mcpart.pt() > cfg_v0_pt_max) { + continue; + } + + float rap = 0.; + if (cfg_do_eta_analysis) { + rap = mcpart.eta(); + } else { + rap = mcpart.y(); + } + + if (fabs(rap) > cfg_v0_rap_max) { + continue; + } + + p.SetPxPyPzE(mcpart.px(), mcpart.py(), mcpart.pz(), mcpart.e()); + + // find daughter ids + auto mcpart_daughters = mcpart.daughters_as(); + + for (auto const& mcpart_daughter : mcpart_daughters) { + if (mcpart.pdgCode() == 3122) { + if (mcpart_daughter.pdgCode() == 2212) { + postrackid = mcpart_daughter.index(); + } else { + negtrackid = mcpart_daughter.index(); + } + } else if (mcpart.pdgCode() == -3122) { + if (mcpart_daughter.pdgCode() == -2212) { + negtrackid = mcpart_daughter.index(); + } else { + postrackid = mcpart_daughter.index(); + } + } + } + + // Fill histograms + if (mcpart.pdgCode() == 3122) { + histos.fill(HIST("McGen/h1d_mass_lambda"), p.M()); + histos.fill(HIST("McGen/h1d_pt_lambda"), mcpart.pt()); + histos.fill(HIST("McGen/h1d_eta_lambda"), mcpart.eta()); + histos.fill(HIST("McGen/h1d_y_lambda"), mcpart.y()); + histos.fill(HIST("McGen/h1d_phi_lambda"), mcpart.phi()); + histos.fill(HIST("McGen/h2d_pteta_lambda"), mcpart.eta(), mcpart.pt()); + histos.fill(HIST("McGen/h2d_ptrap_lambda"), mcpart.y(), mcpart.pt()); + histos.fill(HIST("McGen/h2d_ptphi_lambda"), mcpart.phi(), mcpart.pt()); + lambdaMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.pt(), rap, mcpart.phi(), p.M(), postrackid, negtrackid, (int8_t)kLambda); + } else if (mcpart.pdgCode() == -3122) { + histos.fill(HIST("McGen/h1d_mass_antilambda"), p.M()); + histos.fill(HIST("McGen/h1d_pt_antilambda"), mcpart.pt()); + histos.fill(HIST("McGen/h1d_eta_antilambda"), mcpart.eta()); + histos.fill(HIST("McGen/h1d_y_antilambda"), mcpart.y()); + histos.fill(HIST("McGen/h1d_phi_antilambda"), mcpart.phi()); + histos.fill(HIST("McGen/h2d_pteta_antilambda"), mcpart.eta(), mcpart.pt()); + histos.fill(HIST("McGen/h2d_ptrap_antilambda"), mcpart.y(), mcpart.pt()); + histos.fill(HIST("McGen/h2d_ptphi_antilambda"), mcpart.phi(), mcpart.pt()); + lambdaMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.pt(), rap, mcpart.phi(), p.M(), postrackid, negtrackid, (int8_t)kAntiLambda); + } + } + } + + PROCESS_SWITCH(lambdaCorrTableProducer, processMCGen, "Process for MC Generated", false); +}; + +struct lambdaCorrelationAnalysis { + + // Global Configurables + Configurable cfg_nRapBins{"cfg_nRapBins", 16, "N Rapidity Bins"}; + Configurable cfg_Rap_Min{"cfg_Rap_Min", -0.8, "Minimum Rapidity"}; + Configurable cfg_Rap_Max{"cfg_Rap_Max", 0.8, "Maximum Rapidity"}; + Configurable cfg_nPhiBins{"cfg_nPhiBins", 64, "N Phi Bins"}; + Configurable cfg_Phi_Min{"cfg_Phi_Min", 0, "Minimum Phi"}; + Configurable cfg_Phi_Max{"cfg_Phi_Max", 2 * TMath::Pi(), "Maximum Phi"}; + + // remove lambda with shared daughters + Configurable cfg_remove_lambda{"cfg_remove_lambda", true, "Flag to remove lambda"}; + + // pt dependent efficiencies + Configurable cfg_eff_corr_flag{"cfg_eff_corr_flag", true, "Efficiency Correction Flag"}; + Configurable> cfg_pt_bins{"cfg_pt_bins", {0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5, 1.8, 2.1, 2.4, 3.0}, "pT bins for efficiencies"}; + Configurable> cfg_lambda_eff{"cfg_lambda_eff", {0., 0.00222727, 0.0163334, 0.0331841, 0.0482283, 0.060019, 0.0702906, 0.0804265, 0.0889718}, "Lambda Efficiencies"}; + Configurable> cfg_antilambda_eff{"cfg_antilambda_eff", {0., 0.0020531, 0.0149579, 0.0305412, 0.0449607, 0.0565642, 0.0666078, 0.0768982, 0.0855416}, "AntiLambda Efficiencies"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Initialize global variables + float nrapbins = 0.; + float kminrap = 0.; + float kmaxrap = 0.; + float nphibins = 0.; + float kminphi = 0.; + float kmaxphi = 0.; + float rapbinwidth = 0.; + float phibinwidth = 0.; + + std::vector v_pt_bins = static_cast>(cfg_pt_bins); + std::vector v_lambda_eff = static_cast>(cfg_lambda_eff); + std::vector v_antilambda_eff = static_cast>(cfg_antilambda_eff); + + void init(InitContext const&) + { + nrapbins = static_cast(cfg_nRapBins); + kminrap = static_cast(cfg_Rap_Min); + kmaxrap = static_cast(cfg_Rap_Max); + nphibins = static_cast(cfg_nPhiBins); + kminphi = static_cast(cfg_Phi_Min); + kmaxphi = static_cast(cfg_Phi_Max); + + rapbinwidth = (kmaxrap - kminrap) / nrapbins; + phibinwidth = (kmaxphi - kminphi) / nphibins; + + int knrapphibins = static_cast(cfg_nRapBins) * static_cast(cfg_nPhiBins); + float kminrapphi = 0.; + float kmaxrapphi = knrapphibins; + + const AxisSpec axisCheck(1, 0, 1, ""); + const AxisSpec axisPosZ(220, -11, 11, "V_{z} (cm)"); + const AxisSpec axisCent(105, 0, 105, "FT0M (%)"); + const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); + const AxisSpec axisMass(100, 1.06, 1.16, "Inv Mass (GeV/#it{c}^{2})"); + const AxisSpec axisPt(60, 0.2, 3.2, "p_{T} (GeV/#it{c})"); + const AxisSpec axisRap(cfg_nRapBins, cfg_Rap_Min, cfg_Rap_Max, "rap"); + const AxisSpec axisPhi(cfg_nPhiBins, cfg_Phi_Min, cfg_Phi_Max, "#phi (rad)"); + const AxisSpec axisRapPhi(knrapphibins, kminrapphi, kmaxrapphi, "rap #phi"); + + // Create Histograms. + // Event + histos.add("Event/Reco/h1d_collision_posz", "V_{Z} Distribution", kTH1F, {axisPosZ}); + histos.add("Event/Reco/h1d_ft0m_mult_percentile", "FT0M (%)", kTH1F, {axisCent}); + histos.add("Event/Reco/h1d_lambda_multiplicity", "#Lambda - Multiplicity", kTH1I, {axisMult}); + histos.add("Event/Reco/h1d_antilambda_multiplicity", "#bar{#Lambda} - Multiplicity", kTH1I, {axisMult}); + histos.add("Event/Reco/h1d_lambda_sdau", "#Lambda - Multiplicity", kTH1I, {axisMult}); + histos.add("Event/Reco/h1d_antilambda_sdau", "#bar{#Lambda} - Multiplicity", kTH1I, {axisMult}); + histos.add("Event/Reco/h1d_lambda_totmult", "#Lambda - Multiplicity", kTH1I, {axisMult}); + histos.add("Event/Reco/h1d_antilambda_totmult", "#bar{#Lambda} - Multiplicity", kTH1I, {axisMult}); + + // single and two particle densities + // 1D Histograms + histos.add("Reco/h1d_n1_pt_LaP", "#rho_{1}^{#Lambda}", kTH1D, {axisPt}); + histos.add("Reco/h1d_n1_pt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH1D, {axisPt}); + histos.add("Reco/h1d_n1_rap_LaP", "#rho_{1}^{#Lambda}", kTH1D, {axisRap}); + histos.add("Reco/h1d_n1_rap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH1D, {axisRap}); + histos.add("Reco/h1d_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH1D, {axisPhi}); + histos.add("Reco/h1d_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH1D, {axisPhi}); + + // 2D Histograms + histos.add("Reco/h2d_n1_LaP", "#rho_{1}^{#Lambda}", kTH2D, {axisRap, axisPhi}); + histos.add("Reco/h2d_n1_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2D, {axisRap, axisPhi}); + histos.add("Reco/h2d_n2_LaP_LaM", "#rho_{2}^{#Lambda - #bar{#Lambda}}", kTH2D, {axisRapPhi, axisRapPhi}); + histos.add("Reco/h2d_n2_LaP_LaP", "#rho_{2}^{#Lambda - #Lambda}", kTH2D, {axisRapPhi, axisRapPhi}); + histos.add("Reco/h2d_n2_LaM_LaM", "#rho_{2}^{#bar{#Lambda} - #bar{#Lambda}}", kTH2D, {axisRapPhi, axisRapPhi}); + histos.add("Reco/h2d_n2_pt1pt2_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2D, {axisPt, axisPt}); + histos.add("Reco/h2d_n2_pt1pt2_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH2D, {axisPt, axisPt}); + histos.add("Reco/h2d_n2_pt1pt2_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2D, {axisPt, axisPt}); + histos.add("Reco/h2d_n2_eta1eta2_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2D, {axisRap, axisRap}); + histos.add("Reco/h2d_n2_eta1eta2_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH2D, {axisRap, axisRap}); + histos.add("Reco/h2d_n2_eta1eta2_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2D, {axisRap, axisRap}); + histos.add("Reco/h2d_n2_phi1phi2_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2D, {axisPhi, axisPhi}); + histos.add("Reco/h2d_n2_phi1phi2_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH2D, {axisPhi, axisPhi}); + histos.add("Reco/h2d_n2_phi1phi2_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2D, {axisPhi, axisPhi}); + histos.add("Reco/h2d_n2_pt1eta2_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2D, {axisPt, axisRap}); + histos.add("Reco/h2d_n2_pt1eta2_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH2D, {axisPt, axisRap}); + histos.add("Reco/h2d_n2_pt1eta2_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2D, {axisPt, axisRap}); + histos.add("Reco/h2d_n2_pt1phi2_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2D, {axisPt, axisPhi}); + histos.add("Reco/h2d_n2_pt1phi2_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH2D, {axisPt, axisPhi}); + histos.add("Reco/h2d_n2_pt1phi2_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2D, {axisPt, axisPhi}); + + // MCGen + if (doprocessMCGen) { + histos.addClone("Event/Reco/", "Event/McGen/"); + histos.addClone("Reco/", "McGen/"); + } + } + + template + bool selLambda(T const& v, V const& vs) + { + // check whether to remove lambda or not + if (!cfg_remove_lambda) { + return true; + } + + bool ret_flag = true; + + for (auto const& x : vs) { + if ((v.index() != x.index()) && (v.postrackid() == x.postrackid() || v.negtrackid() == x.negtrackid())) { + if (std::abs(v.mass() - MassLambda0) > std::abs(x.mass() - MassLambda0)) { + ret_flag = false; + break; + } + } + } + + return ret_flag; + } + + template + void get_corr_factor(float& eff, float pt) + { + + if (cfg_eff_corr_flag) { + eff = 1.; + return; + } + + int n = v_lambda_eff.size(); + + for (int i = 0; i < n; ++i) { + if (pt > v_pt_bins[i] && pt <= v_pt_bins[i + 1]) { + if constexpr (part == kLambda) { + eff = v_lambda_eff[i]; + } else if constexpr (part == kAntiLambda) { + eff = v_antilambda_eff[i]; + } + } else { + eff = 1.; + } + } + } + + template + void fillPairHistos(U& p1, U& p2) + { + + static constexpr std::string_view sub_dir_recgen[] = {"Reco/", "McGen/"}; + static constexpr std::string_view sub_dir_hist[] = {"LaP_LaM", "LaP_LaP", "LaM_LaM"}; + + int rapbin1 = static_cast((p1.rap() - kminrap) / rapbinwidth); + int rapbin2 = static_cast((p2.rap() - kminrap) / rapbinwidth); + + int phibin1 = static_cast(p1.phi() / phibinwidth); + int phibin2 = static_cast(p2.phi() / phibinwidth); + + float eff_1 = 1., eff_2 = 1.; + + if constexpr (rec_gen == kRec) { + if (part_pair == kLambdaAntiLambda) { + get_corr_factor(eff_1, p1.pt()); + get_corr_factor(eff_2, p2.pt()); + } else if (part_pair == kLambdaLambda) { + get_corr_factor(eff_1, p1.pt()); + get_corr_factor(eff_2, p2.pt()); + } else if (part_pair == kAntiLambdaAntiLambda) { + get_corr_factor(eff_1, p1.pt()); + get_corr_factor(eff_2, p2.pt()); + } + } + + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n2_pt1pt2_") + HIST(sub_dir_hist[part_pair]), p1.pt(), p2.pt(), eff_1 * eff_2); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n2_eta1eta2_") + HIST(sub_dir_hist[part_pair]), p1.rap(), p2.rap(), eff_1 * eff_2); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n2_phi1phi2_") + HIST(sub_dir_hist[part_pair]), p1.phi(), p2.phi(), eff_1 * eff_2); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n2_pt1eta2_") + HIST(sub_dir_hist[part_pair]), p1.pt(), p2.rap(), eff_1 * eff_2); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n2_pt1phi2_") + HIST(sub_dir_hist[part_pair]), p1.pt(), p2.phi(), eff_1 * eff_2); + + if (rapbin1 >= 0 && rapbin2 >= 0 && phibin1 >= 0 && phibin2 >= 0 && rapbin1 < nrapbins && rapbin2 < nrapbins && phibin1 < nphibins && phibin2 < nphibins) { + + int rapphix = rapbin1 * nphibins + phibin1; + int rapphiy = rapbin2 * nphibins + phibin2; + + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n2_") + HIST(sub_dir_hist[part_pair]), rapphix + 0.5, rapphiy + 0.5, eff_1 * eff_2); + } + } + + template + void analyzeSingles(T const& tracks) + { + + static constexpr std::string_view sub_dir_recgen[] = {"Reco/", "McGen/"}; + static constexpr std::string_view sub_dir_hist[] = {"LaP", "LaM"}; + + int ntrk1 = 0, ntrk2 = 0, ntrk3 = 0; + float eff = 1.; + + for (auto const& track : tracks) { + ++ntrk3; + if (!selLambda(track, tracks)) { + ++ntrk1; + continue; + } + ++ntrk2; + if constexpr (rec_gen == kRec) { + get_corr_factor(eff, track.pt()); + } + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_n1_pt_") + HIST(sub_dir_hist[part]), track.pt() / eff); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_n1_rap_") + HIST(sub_dir_hist[part]), track.rap(), eff); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_n1_phi_") + HIST(sub_dir_hist[part]), track.phi(), eff); + histos.fill(HIST(sub_dir_recgen[rec_gen]) + HIST("h2d_n1_") + HIST(sub_dir_hist[part]), track.rap(), track.phi(), eff); + } + + if (ntrk1 != 0) { + if (part == kLambda) { + histos.fill(HIST("Event/") + HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_lambda_sdau"), ntrk1); + } else { + histos.fill(HIST("Event/") + HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_antilambda_sdau"), ntrk1); + } + } + + if (ntrk2 != 0) { + if (part == kLambda) { + histos.fill(HIST("Event/") + HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_lambda_multiplicity"), ntrk2); + } else { + histos.fill(HIST("Event/") + HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_antilambda_multiplicity"), ntrk2); + } + } + + if (ntrk3 != 0) { + if (part == kLambda) { + histos.fill(HIST("Event/") + HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_lambda_totmult"), ntrk3); + } else { + histos.fill(HIST("Event/") + HIST(sub_dir_recgen[rec_gen]) + HIST("h1d_antilambda_totmult"), ntrk3); + } + } + } + + template + void analyzePairs(T const& trks_1, T const& trks_2) + { + for (auto const& trk_1 : trks_1) { + if (!selLambda(trk_1, trks_1)) { + continue; + } + for (auto const& trk_2 : trks_2) { + if (samelambda && ((trk_1.index() == trk_2.index()))) { + continue; + } + if (!selLambda(trk_2, trks_2)) { + continue; + } + fillPairHistos(trk_1, trk_2); + } + } + } + + using Lambda_Collisions = aod::LambdaCollisions; + using Lambda_Tracks = aod::LambdaTracks; + + SliceCache cache; + + Partition part_lambda_tracks = (aod::lambdatrack::v0type == (int8_t)kLambda); + Partition part_anti_lambda_tracks = (aod::lambdatrack::v0type == (int8_t)kAntiLambda); + + void processDataReco(Lambda_Collisions::iterator const& collision, Lambda_Tracks const&) + { + + histos.fill(HIST("Event/Reco/h1d_collision_posz"), collision.posZ()); + histos.fill(HIST("Event/Reco/h1d_ft0m_mult_percentile"), collision.cent()); + + auto lambda_tracks = part_lambda_tracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto anti_lambda_tracks = part_anti_lambda_tracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + + analyzeSingles(lambda_tracks); + analyzeSingles(anti_lambda_tracks); + analyzePairs(lambda_tracks, anti_lambda_tracks); + analyzePairs(lambda_tracks, lambda_tracks); + analyzePairs(anti_lambda_tracks, anti_lambda_tracks); + } + + PROCESS_SWITCH(lambdaCorrelationAnalysis, processDataReco, "Process for Data and MCReco", true); + + using LambdaMCGenCollisions = aod::LambdaMCGenCollisions; + using LambdaMCGenTracks = aod::LambdaMCGenTracks; + + SliceCache cachemc; + Partition part_lambda_mcgen_tracks = aod::lambdatrack::v0type == (int8_t)kLambda; + Partition part_antilambda_mcgen_tracks = aod::lambdatrack::v0type == (int8_t)kAntiLambda; + + void processMCGen(LambdaMCGenCollisions::iterator const& mcgencol, LambdaMCGenTracks const&) + { + + histos.fill(HIST("Event/McGen/h1d_collision_posz"), mcgencol.posZ()); + + auto lambda_mcgen_tracks = part_lambda_mcgen_tracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); + auto antilambda_mcgen_tracks = part_antilambda_mcgen_tracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); + + analyzeSingles(lambda_mcgen_tracks); + analyzeSingles(antilambda_mcgen_tracks); + analyzePairs(lambda_mcgen_tracks, antilambda_mcgen_tracks); + analyzePairs(lambda_mcgen_tracks, lambda_mcgen_tracks); + analyzePairs(antilambda_mcgen_tracks, antilambda_mcgen_tracks); + } + + PROCESS_SWITCH(lambdaCorrelationAnalysis, processMCGen, "Process for MC Generated", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 45331fde2ef..b92617fc70e 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -14,6 +14,7 @@ #include "PWGDQ/Core/CutsLibrary.h" #include #include +#include #include "AnalysisCompositeCut.h" #include "VarManager.h" @@ -362,6 +363,25 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("JpsiPWGSkimmedCuts3")) { + cut->AddCut(GetAnalysisCut("jpsiKineSkimmed")); + cut->AddCut(GetAnalysisCut("electronTrackQualitySkimmed2")); + cut->AddCut(GetAnalysisCut("electronPIDLooseSkimmed2")); + return cut; + } + + if (!nameStr.compare("pidElectron_ionut")) { + cut->AddCut(GetAnalysisCut("pidcalib_ele")); + cut->AddCut(GetAnalysisCut("jpsiStandardKine3")); + return cut; + } + + if (!nameStr.compare("pidPion_ionut")) { + cut->AddCut(GetAnalysisCut("pidcalib_pion")); + cut->AddCut(GetAnalysisCut("jpsiStandardKine3")); + return cut; + } + if (!nameStr.compare("jpsiO2MCdebugCuts13_Corr")) { cut->AddCut(GetAnalysisCut("jpsiStandardKine")); cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); // no cut on ITS clusters @@ -385,6 +405,13 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("emu_electronCuts")) { + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug4")); + cut->AddCut(GetAnalysisCut("electronPIDnsigmaSkewed")); + return cut; + } + if (!nameStr.compare("jpsiKineAndQuality")) { cut->AddCut(GetAnalysisCut("jpsiStandardKine")); cut->AddCut(GetAnalysisCut("electronStandardQuality")); @@ -507,6 +534,23 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("singleGapTrackCuts3")) { + cut->AddCut(GetAnalysisCut("PIDStandardKine2")); + cut->AddCut(GetAnalysisCut("SPDany")); + + AnalysisCompositeCut* cut_notpc = new AnalysisCompositeCut("NoTPC", "NoTPC", kTRUE); + cut_notpc->AddCut(GetAnalysisCut("noTPC")); + + AnalysisCompositeCut* cut_tpcpid = new AnalysisCompositeCut("pid_TPC", "pid_TPC", kTRUE); + cut_tpcpid->AddCut(GetAnalysisCut("pionQuality")); + + AnalysisCompositeCut* cut_OR = new AnalysisCompositeCut("OR", "OR", kFALSE); + cut_OR->AddCut(cut_notpc); + cut_OR->AddCut(cut_tpcpid); + cut->AddCut(cut_OR); + return cut; + } + if (!nameStr.compare("PIDCalib")) { cut->AddCut(GetAnalysisCut("PIDStandardKine")); // standard kine cuts usually are applied via Filter in the task cut->AddCut(GetAnalysisCut("electronStandardQuality")); @@ -516,9 +560,9 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) } if (!nameStr.compare("NoPID")) { - cut->AddCut(GetAnalysisCut("PIDStandardKine")); // standard kine cuts usually are applied via Filter in the task - cut->AddCut(GetAnalysisCut("electronStandardQuality")); - cut->AddCut(GetAnalysisCut("standardPrimaryTrack")); + cut->AddCut(GetAnalysisCut("PIDStandardKine2")); // standard kine cuts usually are applied via Filter in the task + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly2")); + cut->AddCut(GetAnalysisCut("dcaCut1_ionut")); return cut; } @@ -588,16 +632,10 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("kaonPosPID4DCAz")) { + if (!nameStr.compare("kaonPosPID4Pt05")) { cut->AddCut(GetAnalysisCut("kaonPID_TPCnTOF")); cut->AddCut(GetAnalysisCut("posTrack")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); - return cut; - } - - if (!nameStr.compare("kaonPosPID5")) { - cut->AddCut(GetAnalysisCut("kaonPIDnsigma")); - cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("muonLowPt")); return cut; } @@ -607,22 +645,10 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("kaonNegPID4DCAz")) { + if (!nameStr.compare("kaonNegPID4Pt05")) { cut->AddCut(GetAnalysisCut("kaonPID_TPCnTOF")); cut->AddCut(GetAnalysisCut("negTrack")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); - return cut; - } - - if (!nameStr.compare("kaonNegPID5")) { - cut->AddCut(GetAnalysisCut("kaonPIDnsigma")); - cut->AddCut(GetAnalysisCut("negTrack")); - return cut; - } - - if (!nameStr.compare("kaonPID4_PVC")) { - cut->AddCut(GetAnalysisCut("kaonPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("primaryVertexContributor")); + cut->AddCut(GetAnalysisCut("muonLowPt")); return cut; } @@ -656,13 +682,6 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("pionPosPIDDCAz")) { - cut->AddCut(GetAnalysisCut("pionPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("posTrack")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); - return cut; - } - if (!nameStr.compare("pionPosPID2")) { cut->AddCut(GetAnalysisCut("pionPIDnsigma")); cut->AddCut(GetAnalysisCut("posTrack")); @@ -675,70 +694,62 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("pionNegPIDDCAz")) { - cut->AddCut(GetAnalysisCut("pionPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("negTrack")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); - return cut; - } - if (!nameStr.compare("pionNegPID2")) { cut->AddCut(GetAnalysisCut("pionPIDnsigma")); cut->AddCut(GetAnalysisCut("negTrack")); return cut; } - if (!nameStr.compare("pionPID_PVC")) { - cut->AddCut(GetAnalysisCut("pionPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("primaryVertexContributor")); + if (!nameStr.compare("protonPosPID")) { + cut->AddCut(GetAnalysisCut("protonPID_TPCnTOF")); + cut->AddCut(GetAnalysisCut("posTrack")); return cut; } - if (!nameStr.compare("pionPosPID2_PVC")) { - cut->AddCut(GetAnalysisCut("pionPIDnsigma")); - cut->AddCut(GetAnalysisCut("primaryVertexContributor")); + if (!nameStr.compare("protonPosPIDPt05")) { + cut->AddCut(GetAnalysisCut("protonPID_TPCnTOF")); cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("muonLowPt")); return cut; } - if (!nameStr.compare("pionNegPID2_PVC")) { - cut->AddCut(GetAnalysisCut("pionPIDnsigma")); - cut->AddCut(GetAnalysisCut("primaryVertexContributor")); + if (!nameStr.compare("protonNegPID")) { + cut->AddCut(GetAnalysisCut("protonPID_TPCnTOF")); cut->AddCut(GetAnalysisCut("negTrack")); return cut; } - if (!nameStr.compare("protonPosPID")) { + if (!nameStr.compare("protonNegPIDPt05")) { cut->AddCut(GetAnalysisCut("protonPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("negTrack")); + cut->AddCut(GetAnalysisCut("muonLowPt")); return cut; } - if (!nameStr.compare("protonPosPIDDCAz")) { - cut->AddCut(GetAnalysisCut("protonPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("posTrack")); + if (!nameStr.compare("PrimaryTrack_DCAz")) { cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); return cut; } - if (!nameStr.compare("protonNegPID")) { - cut->AddCut(GetAnalysisCut("protonPID_TPCnTOF")); - cut->AddCut(GetAnalysisCut("negTrack")); + if (!nameStr.compare("posPrimaryTrack_DCAz")) { + cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); + cut->AddCut(GetAnalysisCut("posTrack")); return cut; } - if (!nameStr.compare("PrimaryTrack_DCAz")) { + if (!nameStr.compare("negPrimaryTrack_DCAz")) { cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); + cut->AddCut(GetAnalysisCut("negTrack")); return cut; } - if (!nameStr.compare("pionPosPrimaryNoPID")) { + if (!nameStr.compare("posStandardPrimaryTrackDCA")) { cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCA")); cut->AddCut(GetAnalysisCut("posTrack")); return cut; } - if (!nameStr.compare("pionNegPrimaryNoPID")) { + if (!nameStr.compare("negStandardPrimaryTrackDCA")) { cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCA")); cut->AddCut(GetAnalysisCut("negTrack")); return cut; @@ -754,6 +765,39 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("pTLow04")) { + cut->AddCut(GetAnalysisCut("pTLow04")); + return cut; + } + + if (!nameStr.compare("pTLow03")) { + cut->AddCut(GetAnalysisCut("pTLow03")); + return cut; + } + + if (!nameStr.compare("pTLow02")) { + cut->AddCut(GetAnalysisCut("pTLow02")); + return cut; + } + + if (!nameStr.compare("pTLow05DCAzHigh03")) { + cut->AddCut(GetAnalysisCut("muonLowPt")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); + return cut; + } + + if (!nameStr.compare("pTLow04DCAzHigh03")) { + cut->AddCut(GetAnalysisCut("pTLow04")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); + return cut; + } + + if (!nameStr.compare("pTLow03DCAzHigh03")) { + cut->AddCut(GetAnalysisCut("pTLow03")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_DCAz")); + return cut; + } + // NOTE Below there are several TPC pid cuts used for studies of the Run3 TPC post PID calib. if (!nameStr.compare("Jpsi_TPCPost_calib_debug1")) { cut->AddCut(GetAnalysisCut("jpsi_trackCut_debug")); @@ -798,6 +842,18 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("Jpsi_TPCPost_calib_debug8")) { + cut->AddCut(GetAnalysisCut("jpsi_trackCut_debug3")); + cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug8")); + return cut; + } + + if (!nameStr.compare("Jpsi_TPCPost_calib_debug9")) { + cut->AddCut(GetAnalysisCut("jpsi_trackCut_debug4")); + cut->AddCut(GetAnalysisCut("electronPIDLooseSkimmed3")); + return cut; + } + if (!nameStr.compare("LMee_TPCPost_calib_debug1")) { cut->AddCut(GetAnalysisCut("lmee_trackCut_debug")); cut->AddCut(GetAnalysisCut("lmee_TPCPID_debug1")); @@ -833,6 +889,24 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + for (int iCut = 0; iCut < 10; iCut++) { + if (!nameStr.compare(Form("jpsiEleSel%d_ionut", iCut))) { + cut->AddCut(GetAnalysisCut("kineJpsiEle_ionut")); + cut->AddCut(GetAnalysisCut("dcaCut1_ionut")); + cut->AddCut(GetAnalysisCut("trackQuality_ionut")); + cut->AddCut(GetAnalysisCut(Form("pidJpsiEle%d_ionut", iCut))); + return cut; + } + + if (!nameStr.compare(Form("jpsiEleSelTight%d_ionut", iCut))) { + cut->AddCut(GetAnalysisCut("kineJpsiEle_ionut")); + cut->AddCut(GetAnalysisCut("dcaCut1_ionut")); + cut->AddCut(GetAnalysisCut("trackQualityTight_ionut")); + cut->AddCut(GetAnalysisCut(Form("pidJpsiEle%d_ionut", iCut))); + return cut; + } + } + //--------------------------------------------------------------- // Cuts for the selection of legs from dalitz decay // @@ -1249,6 +1323,13 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare(Form("lmee%s_TrackCuts_Resol", vecTypetrack.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("openEtaSel")); // No pt cut and wider eta cut to produce resolution maps + cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrack.at(icase).Data()))); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + return cut; + } + // 4 cuts to separate pos & neg tracks in pos & neg eta range if (!nameStr.compare(Form("lmee_posTrack_posEta_selection%s", vecTypetrack.at(icase).Data()))) { cut->AddCut(GetAnalysisCut("posTrack")); @@ -1463,6 +1544,26 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + for (unsigned int i = 0; i < 30; i++) { + if (!nameStr.compare(Form("ElSelCutVar%s%i", vecPIDcase.at(icase).Data(), i))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut(Form("lmeeCutVarTrackCuts%i", i))); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma_cutVar%s%i", vecPIDcase.at(icase).Data(), i))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma_cutVar%s%i", vecPIDcase.at(icase).Data(), i))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + } + for (size_t jcase = 0; jcase < vecTypetrackWithPID.size(); jcase++) { // All previous cut with TightGlobalTrackRun3 if (!nameStr.compare(Form("ITSTPC%s_TPCPIDalone%s_PbPb", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { @@ -1545,16 +1646,16 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare(Form("lmee%s_lowB_eNSigmaRun3%s_strongNSigE", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { - cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + if (!nameStr.compare(Form("lmee%s_eNSigmaRun3%s_strongNSigE_rejBadTOF", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrackWithPID.at(jcase).Data()))); - cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); // to reject looper using DCAz + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); cut_pid_OR->AddCut(cut_tpc_nSigma); @@ -1563,34 +1664,24 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare(Form("lmee%s_lowB_eNSigmaRun3%s_strongNSigE_rejBadTOF", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { - cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + if (!nameStr.compare(Form("lmee%s_eNSigmaRun3%s_TOFreq", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrackWithPID.at(jcase).Data()))); - cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); // to reject looper using DCAz - - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); - - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); - - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + cut->AddCut(GetAnalysisCut(Form("electronPID_TPC_TOFnsigma%s", vecPIDcase.at(icase).Data()))); return cut; } - if (!nameStr.compare(Form("lmee%s_eNSigmaRun3%s_strongNSigE_rejBadTOF", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { - cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + if (!nameStr.compare(Form("lmee%s_eNSigmaRun3%s_Resol", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("openEtaSel")); // No pt cut and wider eta cut to produce resolution maps cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrackWithPID.at(jcase).Data()))); cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))); AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))); AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); cut_pid_OR->AddCut(cut_tpc_nSigma); @@ -1671,6 +1762,42 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare(Form("lmee%s_lowB_eNSigmaRun3%s_strongNSigE", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrackWithPID.at(jcase).Data()))); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); // to reject looper using DCAz + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee%s_lowB_eNSigmaRun3%s_strongNSigE_rejBadTOF", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrackWithPID.at(jcase).Data()))); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); // to reject looper using DCAz + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + if (!nameStr.compare(Form("lmee%s_TOFreqRun3%s_strongNSigEPbPb_rejBadTOF_pt04", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data()))) { cut->AddCut(GetAnalysisCut("lmeeStandardKine_pt04")); cut->AddCut(GetAnalysisCut(Form("lmeeQCTrackCuts%s", vecTypetrackWithPID.at(jcase).Data()))); @@ -2410,6 +2537,18 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("muonQualityCuts3SigmaPDCA")) { + cut->AddCut(GetAnalysisCut("muonQualityCuts3SigmaPDCA")); + return cut; + } + + if (!nameStr.compare("muonLowPt3SigmaPDCA")) { + cut->AddCut(GetAnalysisCut("muonLowPt")); + cut->AddCut(GetAnalysisCut("muonQualityCuts3SigmaPDCA")); + cut->AddCut(GetAnalysisCut("MCHMID")); + return cut; + } + if (!nameStr.compare("muonLowPt10SigmaPDCA")) { cut->AddCut(GetAnalysisCut("muonLowPt")); cut->AddCut(GetAnalysisCut("muonQualityCuts10SigmaPDCA")); @@ -3081,6 +3220,10 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) std::string nameStr = cutName; // --------------------------------------------------------------- // Event cuts + if (!nameStr.compare("noEventCut")) { + return cut; + } + if (!nameStr.compare("eventNoTFBorder")) { cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); return cut; @@ -3110,6 +3253,7 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) if (!nameStr.compare("eventStandardSel8WithITSROFRecomputedCut")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); cut->AddCut(VarManager::kIsNoITSROFBorderRecomputed, 0.5, 1.5); return cut; } @@ -3121,6 +3265,22 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("eventStandardSel8NoTFBNoITSROFB")) { + cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoITSROFBorder, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("eventStandardSel8NoTFBNoITSROFBrecomp")) { + cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoITSROFBorderRecomputed, 0.5, 1.5); + return cut; + } + if (!nameStr.compare("eventStandardSel8PbPbQuality")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); @@ -3143,6 +3303,18 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("eventStandardSel8PbPbQualityFirmTrackOccupancy")) { + cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoITSROFBorder, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoSameBunch, 0.5, 1.5); + cut->AddCut(VarManager::kIsGoodZvtxFT0vsPV, 0.5, 1.5); + cut->AddCut(VarManager::kCentFT0C, 0.0, 90.0); + cut->AddCut(VarManager::kTrackOccupancyInTimeRange, 0., 2000); + + return cut; + } if (!nameStr.compare("eventStandardSel8PbPbQualityLooseTrackOccupancy")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); @@ -3172,7 +3344,7 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) 50000.}; for (size_t icase = 0; icase < vecOccupancies.size() - 1; icase++) { - if (!nameStr.compare(Form("eventStandardSel8PbPbQualityTrackOccupancySlice%i", icase))) { + if (!nameStr.compare(Form("eventStandardSel8PbPbQualityTrackOccupancySlice%lu", icase))) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); @@ -3465,6 +3637,21 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("pTLow04")) { + cut->AddCut(VarManager::kPt, 0.4, 1000.0); + return cut; + } + + if (!nameStr.compare("pTLow03")) { + cut->AddCut(VarManager::kPt, 0.3, 1000.0); + return cut; + } + + if (!nameStr.compare("pTLow02")) { + cut->AddCut(VarManager::kPt, 0.2, 1000.0); + return cut; + } + // ----------------------------------------------- // Barrel track quality cuts @@ -3540,6 +3727,31 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("jpsi_trackCut_debug3")) { + cut->AddCut(VarManager::kEta, -0.9, 0.9); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 90., 159); + cut->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); + cut->AddCut(VarManager::kTPCnclsCR, 70., 159); + cut->AddCut(VarManager::kITSncls, 2.5, 7.5); + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kTrackDCAxy, -0.05, 0.05); + cut->AddCut(VarManager::kTrackDCAz, -1.0, 1.0); + return cut; + } + + if (!nameStr.compare("jpsi_trackCut_debug4")) { + cut->AddCut(VarManager::kEta, -0.9, 0.9); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 90., 159); + cut->AddCut(VarManager::kITSncls, 2.5, 7.5); + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kTrackDCAxy, -1, 1); + cut->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); + return cut; + } + if (!nameStr.compare("lmee_trackCut_debug")) { cut->AddCut(VarManager::kEta, -0.9, 0.9); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); @@ -3690,6 +3902,25 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + // List of 30 variations in ITS and TPC parameters + std::vector cutVar_ITSchi2 = {6., 6., 5., 4., 4., 6., 6., 5., 4., 5., 4., 5., 6., 5., 6., 5., 6., 5., 5., 4., 6., 4., 6., 5., 6., 4., 4., 6., 4., 5.}; + std::vector cutVar_TPCchi2 = {5., 5., 4., 3., 5., 4., 5., 3., 5., 4., 5., 3., 3., 5., 4., 5., 3., 5., 5., 5., 3., 5., 5., 4., 3., 4., 5., 5., 5., 3.}; + std::vector cutVar_ITSnCl = {4.5, 5.5, 5.5, 4.5, 6.5, 4.5, 4.5, 4.5, 4.5, 5.5, 4.5, 5.5, 5.5, 5.5, 5.5, 4.5, 5.5, 6.5, 5.5, 4.5, 4.5, 5.5, 5.5, 5.5, 6.5, 5.5, 4.5, 4.5, 6.5, 6.5}; + std::vector cutVar_TPCnClsCR = {90., 80., 80., 80., 90., 80., 70., 90., 70., 80., 70., 90., 90., 70., 90., 90., 70., 80., 90., 80., 80., 90., 70., 70., 70., 80., 90., 70., 70., 80.}; + std::vector cutVar_TPCnCls = {80., 100., 80., 90., 90., 80., 80., 80., 80., 90., 100., 100., 80., 80., 80., 80., 100., 90., 100., 90., 90., 100., 100., 80., 100., 90., 90., 100., 90., 90.}; + + for (unsigned int i = 0; i < cutVar_ITSchi2.size(); i++) { + if (!nameStr.compare(Form("lmeeCutVarTrackCuts%i", i))) { + cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); + cut->AddCut(VarManager::kITSchi2, 0.0, cutVar_ITSchi2.at(i)); + cut->AddCut(VarManager::kTPCchi2, 0.0, cutVar_TPCchi2.at(i)); + cut->AddCut(VarManager::kITSncls, cutVar_ITSnCl.at(i), 7.5); + cut->AddCut(VarManager::kTPCnclsCR, cutVar_TPCnClsCR.at(i), 161.); + cut->AddCut(VarManager::kTPCncls, cutVar_TPCnCls.at(i), 170.); + return cut; + } + } + if (!nameStr.compare("electronStandardQualityForO2MCdebug")) { cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); @@ -3711,6 +3942,13 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("electronStandardQualityForO2MCdebug4")) { + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 70, 161.); + return cut; + } + if (!nameStr.compare("electronStandardQualityITSOnly")) { cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); @@ -3731,6 +3969,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("electronStandardQualityTPCOnly2")) { + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 100, 161.); + return cut; + } + if (!nameStr.compare("NoelectronStandardQualityTPCOnly")) { cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0, true, VarManager::kTPCncls, 70, 161.); return cut; @@ -3745,6 +3989,13 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("electronTrackQualitySkimmed2")) { + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kTPCncls, 60, 161); + return cut; + } + if (!nameStr.compare("pionQualityCut1")) { cut->AddCut(VarManager::kPt, 0.15, 1000.0); cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); @@ -3772,6 +4023,94 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("trackQuality_ionut")) { + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kTPCncls, 70, 161); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kTPCchi2, 0.0, 2.0); + return cut; + } + + if (!nameStr.compare("trackQualityTight_ionut")) { + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kTPCncls, 100, 161); + cut->AddCut(VarManager::kITSchi2, 0.0, 3.0); + cut->AddCut(VarManager::kTPCchi2, 0.0, 2.0); + cut->AddCut(VarManager::kITSncls, 5.0, 8.0); + return cut; + } + + if (!nameStr.compare("kineJpsiEle_ionut")) { + cut->AddCut(VarManager::kP, 1.0, 15.0); + cut->AddCut(VarManager::kEta, -0.9, 0.9); + return cut; + } + + if (!nameStr.compare("pidJpsiEle0_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2.0, 4.0, false, VarManager::kPin, 1.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaEl, -1.0, 4.0, false, VarManager::kPin, 4.0, 150.0); + cut->AddCut(VarManager::kTPCnSigmaEl, 98.1, 98.11, false, VarManager::kPin, 0.0, 1.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle1_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -1.5, 4.0, false, VarManager::kPin, 1.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaEl, -1.0, 4.0, false, VarManager::kPin, 4.0, 150.0); + cut->AddCut(VarManager::kTPCnSigmaEl, 98.1, 98.11, false, VarManager::kPin, 0.0, 1.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle2_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -1.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle3_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -0.5, 4.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle4_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, 0.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle5_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, 0.5, 4.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle6_ionut")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -1.0, 4.0); + cut->AddCut(VarManager::kTOFnSigmaEl, -1.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaPr, -4.0, 4.0, true); + return cut; + } + + if (!nameStr.compare("pidJpsiEle7_ionut")) { + cut->AddCut(VarManager::kTOFnSigmaEl, -3.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaEl, -1.0, 4.0); + return cut; + } + + if (!nameStr.compare("pidJpsiEle8_ionut")) { + cut->AddCut(VarManager::kTOFnSigmaEl, -3.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaEl, -1.5, 4.0); + return cut; + } + + if (!nameStr.compare("pidJpsiEle9_ionut")) { + cut->AddCut(VarManager::kTOFnSigmaEl, -3.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaEl, -2.0, 4.0); + return cut; + } + if (!nameStr.compare("standardPrimaryTrackDCAz")) { cut->AddCut(VarManager::kTrackDCAxy, -3.0, 3.0); cut->AddCut(VarManager::kTrackDCAz, -1.0, 1.0); @@ -3907,6 +4246,14 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) cut->AddCut(VarManager::kTPCnSigmaPr, 1.5, 999, false, VarManager::kPin, 3.0, 999); return cut; } + + if (!nameStr.compare("electronPIDLooseSkimmed3")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3.0, 3.0); + cut->AddCut(VarManager::kTPCnSigmaPi, 3.0, 999, false, VarManager::kPin, 0, 3.0); + cut->AddCut(VarManager::kTPCnSigmaPr, 3.0, 999, false, VarManager::kPin, 0, 3.0); + return cut; + } + if (!nameStr.compare("jpsi_TPCPID_debug6")) { cut->AddCut(VarManager::kTPCnSigmaEl, -2.0, 3.0); cut->AddCut(VarManager::kTPCnSigmaPi, 3.0, 999); @@ -3921,6 +4268,14 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("jpsi_TPCPID_debug8")) { + cut->AddCut(VarManager::kTOFbeta, 0.975, 1.025, false, VarManager::kPin, 0.0, 3.0); + cut->AddCut(VarManager::kTPCnSigmaEl, -3.0, 4.0); + cut->AddCut(VarManager::kTPCnSigmaPi, 2.0, 999, false, VarManager::kPin, 3.0, 999.0); + cut->AddCut(VarManager::kTPCnSigmaPr, 2.0, 999, false, VarManager::kPin, 3.0, 999.0); + return cut; + } + if (!nameStr.compare("pidCut_lowP_Corr")) { cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3.0, 3.0, false, VarManager::kP, 0.0, 5.0); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, 3.0, 999, false, VarManager::kP, 0.0, 5.0); @@ -4232,6 +4587,38 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + // List of nSigma values for lower and upper edge of El, Pi, Ka, Pr, TPC PID selections/rejection + std::vector cutVar_TPCnSigmaEl_low = {-4., -4., -4., -2., -3., -2., -3., -4., -2., -4., -3., -3., -3., -4., -3., -3., -4., -3., -4., -4., -3., -4., -3., -3., -2., -4., -4., -3., -4., -2}; + std::vector cutVar_TPCnSigmaEl_up = {2., 3., 2., 2., 2., 2., 2., 4., 2., 2., 4., 3., 3., 2., 4., 2., 2., 4., 3., 4., 2., 4., 2., 3., 2., 3., 4., 2., 3., 2}; + std::vector cutVar_TPCnSigmaPi_low = {-3., -2., -3., -4., -4., -3., -4., -2., -2., -2., -3., -3., -2., -2., -4., -3., -3., -2., -3., -2., -4., -2., -4., -4., -3., -3., -3., -2., -4., -4}; + std::vector cutVar_TPCnSigmaPi_up = {3., 3., 4., 4., 3., 2., 4., 4., 3., 4., 4., 3., 4., 4., 3., 2., 4., 2., 4., 2., 3., 4., 2., 2., 3., 2., 3., 4., 2., 4}; + std::vector cutVar_TPCnSigmaKa_low = {-4., -2., -2., -2., -4., -3., -2., -4., -3., -3., -4., -2., -3., -3., -4., -2., -4., -2., -3., -4., -4., -2., -2., -3., -2., -2., -3., -3., -2., -4}; + std::vector cutVar_TPCnSigmaKa_up = {4., 3., 2., 3., 4., 3., 4., 4., 4., 4., 4., 4., 4., 4., 2., 4., 4., 2., 2., 4., 3., 3., 2., 4., 2., 4., 3., 3., 3., 3}; + std::vector cutVar_TPCnSigmaPr_low = {-4., -2., -2., -3., -4., -4., -3., -2., -2., -4., -4., -2., -3., -4., -2., -3., -3., -2., -3., -3., -2., -2., -2., -2., -2., -3., -2., -3., -3., -3}; + std::vector cutVar_TPCnSigmaPr_up = {2., 2., 3., 2., 3., 3., 3., 2., 4., 3., 3., 4., 4., 3., 4., 4., 3., 4., 2., 3., 4., 4., 3., 4., 3., 2., 3., 3., 2., 3}; + + for (unsigned int i = 0; i < cutVar_TPCnSigmaEl_low.size(); i++) { + if (!nameStr.compare(Form("electronPID_TPCnsigma_cutVar%s%i", vecPIDcase.at(icase).Data(), i))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, cutVar_TPCnSigmaKa_low.at(i), cutVar_TPCnSigmaKa_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, cutVar_TPCnSigmaPr_low.at(i), cutVar_TPCnSigmaPr_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, cutVar_TPCnSigmaKa_low.at(i), cutVar_TPCnSigmaKa_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, cutVar_TPCnSigmaPr_low.at(i), cutVar_TPCnSigmaPr_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, cutVar_TPCnSigmaKa_low.at(i), cutVar_TPCnSigmaKa_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, cutVar_TPCnSigmaPr_low.at(i), cutVar_TPCnSigmaPr_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + } + if (!nameStr.compare(Form("lmee_pp_502TeV_TPC%s", vecPIDcase.at(icase).Data()))) { if (icase == 0) { cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); @@ -4579,6 +4966,46 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + // List of nSigma values for lower and upper edge of TPC: El, Pi and TOF: El PID selections/rejection + std::vector cutVar_TPCnSigmaEl_low = {-4., -4., -4., -2., -3., -2., -3., -4., -2., -4., -3., -3., -3., -4., -3., -3., -4., -3., -4., -4., -3., -4., -3., -3., -2., -4., -4., -3., -4., -2}; + std::vector cutVar_TPCnSigmaEl_up = {2., 3., 2., 2., 2., 2., 2., 4., 2., 2., 4., 3., 3., 2., 4., 2., 2., 4., 3., 4., 2., 4., 2., 3., 2., 3., 4., 2., 3., 2}; + std::vector cutVar_TPCnSigmaPi_low = {-3., -2., -3., -4., -4., -3., -4., -2., -2., -2., -3., -3., -2., -2., -4., -3., -3., -2., -3., -2., -4., -2., -4., -4., -3., -3., -3., -2., -4., -4}; + std::vector cutVar_TPCnSigmaPi_up = {3., 3., 4., 4., 3., 2., 4., 4., 3., 4., 4., 3., 4., 4., 3., 2., 4., 2., 4., 2., 3., 4., 2., 2., 3., 2., 3., 4., 2., 4}; + std::vector cutVar_TOFnSigmaEl_low = {-4., -2., -4., -4., -3., -2., -4., -4., -4., -2., -2., -4., -3., -3., -4., -4., -4., -2., -4., -4., -2., -2., -3., -4., -4., -2., -4., -2., -3., -3}; + std::vector cutVar_TOFnSigmaEl_up = {4., 2., 4., 2., 4., 3., 2., 3., 3., 3., 4., 3., 2., 3., 4., 3., 3., 3., 4., 4., 2., 2., 2., 3., 3., 3., 2., 3., 2., 4}; + + for (unsigned int i = 0; i < cutVar_TOFnSigmaEl_low.size(); i++) { + if (!nameStr.compare(Form("electronPID_TOFnsigma_cutVar%s%i", vecPIDcase.at(icase).Data(), i))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, cutVar_TOFnSigmaEl_low.at(i), cutVar_TOFnSigmaEl_up.at(i), false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, cutVar_TOFnSigmaEl_low.at(i), cutVar_TOFnSigmaEl_up.at(i), false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + } + + if (!nameStr.compare(Form("electronPID_TPC_TOFnsigma%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { // previously known as electronPID_TOFnsigma_tight + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + if (!nameStr.compare(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { if (icase == 0) { cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); @@ -4773,6 +5200,16 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("muonQualityCuts3SigmaPDCA")) { + cut->AddCut(VarManager::kEta, -4.0, -2.5); + cut->AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 89.5); + cut->AddCut(VarManager::kMuonPDca, 0.0, 300.0, false, VarManager::kMuonRAtAbsorberEnd, 17.6, 26.5); + cut->AddCut(VarManager::kMuonPDca, 0.0, 201.0, false, VarManager::kMuonRAtAbsorberEnd, 26.5, 89.5); + cut->AddCut(VarManager::kMuonChi2, 0.0, 1e6); + cut->AddCut(VarManager::kMuonChi2MatchMCHMID, 0.0, 1e6); // matching MCH-MID + return cut; + } + if (!nameStr.compare("muonQualityCuts10SigmaPDCA")) { cut->AddCut(VarManager::kEta, -4.0, -2.5); cut->AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 89.5); diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index c4ae6e3c96d..303dbe3a6d8 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -54,16 +54,17 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("time")) { hm->AddHistogram(histClass, "CollTime", "Coll. time wrt BC", false, 100, 0.0, 100.0, VarManager::kCollisionTime); - hm->AddHistogram(histClass, "CollTimeRes", "Coll. time resolution", false, 100, 0.0, 100.0, VarManager::kCollisionTimeRes); + hm->AddHistogram(histClass, "CollTimeRes", "Coll. time resolution", false, 100, 0.0, 200.0, VarManager::kCollisionTimeRes); hm->AddHistogram(histClass, "CollTime_VtxZ", "Coll. time wrt BC vs vtx-z", false, 50, -15.0, 15., VarManager::kVtxZ, 100, 0.0, 100.0, VarManager::kCollisionTime); hm->AddHistogram(histClass, "CollTimeRes_VtxZ", "Coll. time resolution ", false, 50, -15.0, 15., VarManager::kVtxZ, 100, 0.0, 100.0, VarManager::kCollisionTimeRes); - hm->AddHistogram(histClass, "CollTimeRes_MultTPC", "Coll. time resolution ", false, 50, 0.0, 500., VarManager::kMultTPC, 100, 0.0, 100.0, VarManager::kCollisionTimeRes); - hm->AddHistogram(histClass, "CollTimeRes_MultPV", "Coll. time resolution ", false, 50, 0.0, 500., VarManager::kVtxNcontribReal, 100, 0.0, 100.0, VarManager::kCollisionTimeRes); + hm->AddHistogram(histClass, "CollTimeRes_MultTPC", "Coll. time resolution ", false, 50, 0.0, 50000., VarManager::kMultTPC, 100, 0.0, 200.0, VarManager::kCollisionTimeRes); + hm->AddHistogram(histClass, "CollTimeRes_MultPV", "Coll. time resolution ", false, 100, 0.0, 4000., VarManager::kVtxNcontribReal, 100, 0.0, 200.0, VarManager::kCollisionTimeRes); + hm->AddHistogram(histClass, "TimeFromSOR", "Time since SOR", false, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR); } if (subGroupStr.Contains("vtx")) { hm->AddHistogram(histClass, "VtxX", "Vtx X", false, 200, -0.1, 0.1, VarManager::kVtxX); hm->AddHistogram(histClass, "VtxY", "Vtx Y", false, 200, -0.1, 0.1, VarManager::kVtxY); - hm->AddHistogram(histClass, "VtxYVtxX", "Vtx Y vs Vtx X", false, 100, -0.1, 0.1, VarManager::kVtxX, 100, -0.1, 0.1, VarManager::kVtxY); + hm->AddHistogram(histClass, "VtxYVtxX", "Vtx Y vs Vtx X", false, 200, -0.06, 0.0, VarManager::kVtxX, 200, -0.03, 0.03, VarManager::kVtxY); } if (subGroupStr.Contains("vtxpp")) { hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); @@ -72,44 +73,54 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 20000.0, VarManager::kVtxNcontrib); } if (subGroupStr.Contains("cent")) { - hm->AddHistogram(histClass, "CentV0M", "CentV0M", false, 100, 0., 100., VarManager::kCentVZERO); - hm->AddHistogram(histClass, "CentV0M_vtxZ", "CentV0M vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentVZERO); hm->AddHistogram(histClass, "CentFT0C", "CentFT0C", false, 100, 0., 100., VarManager::kCentFT0C); hm->AddHistogram(histClass, "CentFT0C_vtxZ", "CentFT0C vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentFT0C); - hm->AddHistogram(histClass, "CentFT0C_MultTPC", "CentFT0C vs MultTPC", false, 100, 0., 100., VarManager::kCentFT0C, 50, 0., 50., VarManager::kMultTPC); + hm->AddHistogram(histClass, "CentFT0C_MultTPC", "CentFT0C vs MultTPC", false, 100, 0., 100., VarManager::kCentFT0C, 100, 0., 50000., VarManager::kMultTPC); hm->AddHistogram(histClass, "CentFT0C_Run", "Cent FT0C", true, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, 100, 0., 100., VarManager::kCentFT0C, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); } if (subGroupStr.Contains("mult")) { if (subGroupStr.Contains("pp")) { - hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 300, 0.0, 500.0, VarManager::kMultTPC); - hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 300, 0.0, 500.0, VarManager::kMultFV0A); - hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 300, 0.0, 200.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 250, 0.0, 500.0, VarManager::kMultTPC); + hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 250, 0.0, 500.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 300, 0.0, 300.0, VarManager::kMultFT0A); hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 300, 0.0, 300.0, VarManager::kMultFT0C); hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 300, 0.0, 300.0, VarManager::kMultFDDA); - hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 300, 0.0, 50.0, VarManager::kMultFDDC); - hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 100, 0.0, 250.0, VarManager::kMultTracklets); - hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 50, 0.0, 50.0, VarManager::kMultFDDC); + hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 250, 0.0, 250.0, VarManager::kMultTracklets); + hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontribReal); hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); hm->AddHistogram(histClass, "MultTPC_MultFV0A", "MultTPC vs MultFV0A", false, 100, 0, 500.0, VarManager::kMultTPC, 100, 0, 500.0, VarManager::kMultFV0A); hm->AddHistogram(histClass, "MultTPC_MultFT0A", "MultTPC vs MultFT0A", false, 100, 0, 500.0, VarManager::kMultTPC, 100, 0, 200.0, VarManager::kMultFT0A); hm->AddHistogram(histClass, "MultTPC_MultFT0C", "MultTPC vs MultFT0C", false, 100, 0, 500.0, VarManager::kMultTPC, 100, 0, 300.0, VarManager::kMultFT0C); hm->AddHistogram(histClass, "MultFT0A_MultFT0C", "MultFT0A vs MultFT0C", false, 100, 0, 200.0, VarManager::kMultFT0A, 100, 0, 300.0, VarManager::kMultFT0C); } else { - hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 100, 0.0, 25000.0, VarManager::kMultTPC); - hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 100, 0.0, 25000.0, VarManager::kMultFV0A); - hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 100, 0.0, 25000.0, VarManager::kMultFT0A); - hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 100, 0.0, 25000.0, VarManager::kMultFT0C); - hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 100, 0.0, 25000.0, VarManager::kMultFDDA); - hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 100, 0.0, 25000.0, VarManager::kMultFDDC); - hm->AddHistogram(histClass, "MultZNA", "MultZNA", false, 100, 0.0, 25000.0, VarManager::kMultZNA); - hm->AddHistogram(histClass, "MultZNC", "MultZNC", false, 100, 0.0, 25000.0, VarManager::kMultZNC); + hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 200, 0.0, 50000.0, VarManager::kMultTPC); + hm->AddHistogram(histClass, "MultTPC_vsTimeSOR", "MultTPC vs time from SOR", true, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, 0.0, 50000.0, VarManager::kMultTPC); + hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 200, 0.0, 300000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 200, 0.0, 300000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 200, 0.0, 100000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 100, 0.0, 100000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 100, 0.0, 100000.0, VarManager::kMultFDDC); + hm->AddHistogram(histClass, "MultZNA", "MultZNA", false, 400, 0.0, 400.0, VarManager::kMultZNA); + hm->AddHistogram(histClass, "MultZNC", "MultZNC", false, 400, 0.0, 400.0, VarManager::kMultZNC); + hm->AddHistogram(histClass, "MultZNA_ZNC", "MultZNA vs ZNC", false, 400, 0.0, 400.0, VarManager::kMultZNA, 400, 0.0, 400.0, VarManager::kMultZNC); hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 100, 0.0, 25000.0, VarManager::kMultTracklets); - hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 10000.0, VarManager::kVtxNcontribReal); - hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 10000.0, VarManager::kVtxNcontrib); - hm->AddHistogram(histClass, "MultTPC_MultFV0A", "MultTPC vs MultFV0A", false, 100, 0, 25000.0, VarManager::kMultTPC, 100, 0, 25000.0, VarManager::kMultFV0A); - hm->AddHistogram(histClass, "MultTPC_MultFT0A", "MultTPC vs MultFT0A", false, 100, 0, 25000.0, VarManager::kMultTPC, 100, 0, 25000.0, VarManager::kMultFT0A); - hm->AddHistogram(histClass, "MultTPC_MultFT0C", "MultTPC vs MultFT0C", false, 100, 0, 25000.0, VarManager::kMultTPC, 100, 0, 25000.0, VarManager::kMultFT0C); - hm->AddHistogram(histClass, "MultFT0A_MultFT0C", "MultFT0A vs MultFT0C", false, 100, 0, 25000.0, VarManager::kMultFT0A, 100, 0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors (real)", false, 100, 0.0, 5000.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "VtxNContribReal_vsTimeSOR", "VtxNContribReal vs time from SOR", true, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, 0.0, 5000.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 20000.0, VarManager::kVtxNcontrib); + hm->AddHistogram(histClass, "MultTPC_MultFV0A", "MultTPC vs MultFV0A", false, 100, 0, 50000.0, VarManager::kMultTPC, 100, 0, 300000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultTPC_MultFT0A", "MultTPC vs MultFT0A", false, 100, 0, 50000.0, VarManager::kMultTPC, 100, 0, 300000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultTPC_MultFT0C", "MultTPC vs MultFT0C", false, 100, 0, 50000.0, VarManager::kMultTPC, 100, 0, 100000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultFT0A_MultFT0C", "MultFT0A vs MultFT0C", false, 100, 0, 100000.0, VarManager::kMultFT0A, 100, 0, 300000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "VtxNContribReal_MultTPC", "Vtx n contributors (real) vs mult TPC", false, 100, 0.0, 5000.0, VarManager::kVtxNcontribReal, 200, 0.0, 50000.0, VarManager::kMultTPC); + hm->AddHistogram(histClass, "VtxNContribReal_ZNA", "Vtx n contributors (real) vs ZNA", false, 100, 0.0, 5000.0, VarManager::kVtxNcontribReal, 200, 0.0, 400.0, VarManager::kMultZNA); + hm->AddHistogram(histClass, "VtxNContribReal_ZNC", "Vtx n contributors (real) vs ZNC", false, 100, 0.0, 5000.0, VarManager::kVtxNcontribReal, 200, 0.0, 400.0, VarManager::kMultZNC); + hm->AddHistogram(histClass, "MultZNA_FT0C", "MultZNA vs FT0C", false, 400, 0.0, 400.0, VarManager::kMultZNA, 200, 0.0, 100000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultZNC_FT0C", "MultZNC vs FT0C", false, 400, 0.0, 400.0, VarManager::kMultZNC, 200, 0.0, 100000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "TPCpileupZA", "TPC pileup Z, A-side", false, 200, -50.0, 50.0, VarManager::kNTPCpileupZA); + hm->AddHistogram(histClass, "TPCpileupZC", "TPC pileup Z, C-side", false, 200, -50.0, 50.0, VarManager::kNTPCpileupZC); + hm->AddHistogram(histClass, "TPCpileupNcontribA", "TPC pileup n-contributors, A-side", false, 300, 0.0, 3000.0, VarManager::kNTPCpileupContribA); + hm->AddHistogram(histClass, "TPCpileupNcontribC", "TPC pileup n-contributors, C-side", false, 300, 0.0, 3000.0, VarManager::kNTPCpileupContribC); } } if (subGroupStr.Contains("ftmulpbpb")) { @@ -123,7 +134,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "MultFT0A_VtxNContrib", "MultFT0A vs VtxNContrib", false, 100, 0, 180000.0, VarManager::kMultFT0A, 100, 0, 10000.0, VarManager::kVtxNcontrib); } if (subGroupStr.Contains("occupancy")) { - hm->AddHistogram(histClass, "ITStrackOccupancy", "ITStrackOccupancy", false, 300, 0.0, 30000.0, VarManager::kTrackOccupancyInTimeRange); + hm->AddHistogram(histClass, "ITStrackOccupancy", "ITStrackOccupancy", false, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange); } if (subGroupStr.Contains("mc")) { hm->AddHistogram(histClass, "MCVtxX_VtxX", "Vtx X (MC vs rec)", false, 100, -0.5, 0.5, VarManager::kVtxX, 100, -0.5, 0.5, VarManager::kMCVtxX); @@ -141,6 +152,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "MCVtxX_VtxY", "Vtx X vs Vtx Y", false, 200, 15.0, 15.0, VarManager::kMCVtxZ, 200, -0.2, 0.2, VarManager::kMCVtxY); hm->AddHistogram(histClass, "MCImpPar", "MC impact param", false, 20, 0.0, 20.0, VarManager::kMCEventImpParam); } + if (subGroupStr.Contains("subgen")) { + hm->AddHistogram(histClass, "SubGenID", "SubGenerator ID", false, 11, -0.5, 10.5, VarManager::kMCEventSubGeneratorId); + } if (subGroupStr.Contains("qvector")) { int varZNA[3] = {VarManager::kQ1ZNAX, VarManager::kQ1ZNAY, VarManager::kCentFT0C}; int varZNC[3] = {VarManager::kQ1ZNCX, VarManager::kQ1ZNCY, VarManager::kCentFT0C}; @@ -154,6 +168,19 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "IntercalibZNA_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -50.0, 50.0, VarManager::KIntercalibZNA); hm->AddHistogram(histClass, "IntercalibZNC_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -50.0, 50.0, VarManager::KIntercalibZNC); + hm->AddHistogram(histClass, "EnergyCommonZNA", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyCommonZNA); + hm->AddHistogram(histClass, "EnergyCommonZNC", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyCommonZNC); + + hm->AddHistogram(histClass, "EnergyZNA1", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNA1); + hm->AddHistogram(histClass, "EnergyZNA2", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNA2); + hm->AddHistogram(histClass, "EnergyZNA3", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNA3); + hm->AddHistogram(histClass, "EnergyZNA4", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNA4); + + hm->AddHistogram(histClass, "EnergyZNC1", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNC1); + hm->AddHistogram(histClass, "EnergyZNC2", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNC2); + hm->AddHistogram(histClass, "EnergyZNC3", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNC3); + hm->AddHistogram(histClass, "EnergyZNC4", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 2000, 0, 2000, VarManager::kEnergyZNC4); + hm->AddHistogram(histClass, "Q2X0A", "", false, 500, -10.0, 10.0, VarManager::kQ2X0A); hm->AddHistogram(histClass, "Q2Y0A", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0A); hm->AddHistogram(histClass, "Q2X0B", "", false, 500, -10.0, 10.0, VarManager::kQ2X0B); @@ -336,6 +363,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "IsITSrefit", "", false, 2, -0.5, 1.5, VarManager::kIsITSrefit); hm->AddHistogram(histClass, "IsSPDany", "", false, 2, -0.5, 1.5, VarManager::kIsSPDany); hm->AddHistogram(histClass, "IsSPDfirst", "", false, 2, -0.5, 1.5, VarManager::kIsSPDfirst); + hm->AddHistogram(histClass, "ITSncls_vsTimeFromSOR", "Number of cluster in ITS vs time from SOR", true, 10000, 0.0, 1000, VarManager::kTimeFromSOR, 8, -0.5, 7.5, VarManager::kITSncls); if (subGroupStr.Contains("cluster")) { hm->AddHistogram(histClass, "ITSClusterMap", "", false, 128, -0.5, 127.5, VarManager::kITSClusterMap); hm->AddHistogram(histClass, "ITSClustermap_vs_pin", "ITSClustermap vs pin", false, 200, 0.0, 20.0, VarManager::kPin, 128, -0.5, 127.5, VarManager::kITSClusterMap); @@ -366,6 +394,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("tpc")) { hm->AddHistogram(histClass, "TPCncls", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls); + hm->AddHistogram(histClass, "TPCncls_vsTimeFromSOR", "Number of cluster in TPC vs time from SOR", true, 10000, 0.0, 1000., VarManager::kTimeFromSOR, 160, -0.5, 159.5, VarManager::kTPCncls); hm->AddHistogram(histClass, "TPCncls_Phi", "Number of cluster in TPC vs #varphi", true, 720, 0.0, TMath::TwoPi(), VarManager::kPhi, 10, 0.0, 200.0, VarManager::kTPCncls); hm->AddHistogram(histClass, "TPCncls_PhiPt", "Number of cluster in TPC vs p_{T} and #varphi", true, 20, 0.0, 10.0, VarManager::kPt, 720, 0.0, TMath::TwoPi(), VarManager::kPhi, 10, 0.0, 200.0, VarManager::kTPCncls); hm->AddHistogram(histClass, "TPCncls_Run", "Number of cluster in TPC", true, (VarManager::GetNRuns() > 0 ? VarManager::GetNRuns() : 1), 0.5, 0.5 + VarManager::GetNRuns(), VarManager::kRunId, @@ -417,24 +446,39 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "TPCnSigPi_pIN", "TPC n-#sigma(#pi) vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaPi); hm->AddHistogram(histClass, "TPCnSigKa_pIN", "TPC n-#sigma(K) vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaKa); hm->AddHistogram(histClass, "TPCnSigPr_pIN", "TPC n-#sigma(p) vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaPr); - hm->AddHistogram(histClass, "TPCnSigEl_Corr_pIN", "TPC n-#sigma(e) Corr. vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaEl_Corr); - hm->AddHistogram(histClass, "TPCnSigPi_Corr_pIN", "TPC n-#sigma(#pi) Corr. vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaPi_Corr); - hm->AddHistogram(histClass, "TPCnSigPr_Corr_pIN", "TPC n-#sigma(p) Corr. vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaPr_Corr); + if (subGroupStr.Contains("tpcpid_fine_Corr")) { + hm->AddHistogram(histClass, "TPCnSigEl_Corr_pIN", "TPC n-#sigma(e) Corr. vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaEl_Corr); + hm->AddHistogram(histClass, "TPCnSigPi_Corr_pIN", "TPC n-#sigma(#pi) Corr. vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaPi_Corr); + hm->AddHistogram(histClass, "TPCnSigPr_Corr_pIN", "TPC n-#sigma(p) Corr. vs pIN", false, nbins_pIN, pIN_bins, VarManager::kPin, nbins_nSigma, nSigma_bins, VarManager::kTPCnSigmaPr_Corr); + } } else { hm->AddHistogram(histClass, "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, 0.0, 200., VarManager::kTPCsignal); hm->AddHistogram(histClass, "TPCnSigEle_pIN", "TPC n-#sigma(e) vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaEl); + hm->AddHistogram(histClass, "TPCnSigEle_timeFromSOR", "TPC n-#sigma(e) vs time from SOR", true, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, -5.0, 5.0, VarManager::kTPCnSigmaEl); hm->AddHistogram(histClass, "TPCnSigPi_pIN", "TPC n-#sigma(#pi) vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_timeFromSOR", "TPC n-#sigma(#pi) vs time from SOR", true, 1000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_eta", "TPC n-#sigma(#pi) vs #eta", false, 20, -1.0, 1.0, VarManager::kEta, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_etaPin_prof", " vs (#eta,p_{IN}), --s--", true, 20, -1.0, 1.0, VarManager::kEta, 20, 0.0, 10.0, VarManager::kPin, 10, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_etaCent_prof", " vs (#eta,cent), --s--", true, 20, -1.0, 1.0, VarManager::kEta, 20, 0.0, 100.0, VarManager::kCentFT0C, 10, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_etaContrib_prof", " vs (#eta,n-contrib real), --s--", true, 20, -1.0, 1.0, VarManager::kEta, 20, 0.0, 4000.0, VarManager::kVtxNcontribReal, 10, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_etaZA_prof", " vs (#eta,ZA), --s--", true, 20, -1.0, 1.0, VarManager::kEta, 30, -15.0, 15.0, VarManager::kNTPCpileupZA, 10, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_etaNZA_prof", " vs (#eta,NZA), --s--", true, 20, -1.0, 1.0, VarManager::kEta, 30, 0.0, 1500.0, VarManager::kNTPCpileupContribA, 10, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_centFT0C", "TPC n-#sigma(#pi) vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_itsOccup", "TPC n-#sigma(#pi) vs vtx. contrib real", false, 50, 0.0, 4000.0, VarManager::kVtxNcontribReal, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_pileupZA", "TPC n-#sigma(#pi) vs pileup ZA", false, 60, -15.0, 15.0, VarManager::kNTPCpileupZA, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_pileupZC", "TPC n-#sigma(#pi) vs pileup ZC", false, 60, -15.0, 15.0, VarManager::kNTPCpileupZC, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_pileupNA", "TPC n-#sigma(#pi) vs n.pileup contrib A", false, 60, 0.0, 1500.0, VarManager::kNTPCpileupContribA, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); + hm->AddHistogram(histClass, "TPCnSigPi_pileupNC", "TPC n-#sigma(#pi) vs n.pileup contrib C", false, 60, 0.0, 1500.0, VarManager::kNTPCpileupContribC, 200, -5.0, 5.0, VarManager::kTPCnSigmaPi); hm->AddHistogram(histClass, "TPCnSigKa_pIN", "TPC n-#sigma(K) vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaKa); hm->AddHistogram(histClass, "TPCnSigPr_pIN", "TPC n-#sigma(p) vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaPr); - hm->AddHistogram(histClass, "TPCnSigEl_Corr_pIN", "TPC n-#sigma(e) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaEl_Corr); - hm->AddHistogram(histClass, "TPCnSigPi_Corr_pIN", "TPC n-#sigma(#pi) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaPi_Corr); - hm->AddHistogram(histClass, "TPCnSigKa_Corr_pIN", "TPC n-#sigma(K) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaKa_Corr); - hm->AddHistogram(histClass, "TPCnSigPr_Corr_pIN", "TPC n-#sigma(p) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaPr_Corr); - } - hm->AddHistogram(histClass, "TPCnSigEl_Corr_Eta", "TPC n-#sigma(e) Corr. vs Eta", false, 20, -1.0, 1.0, VarManager::kEta, 100, -5.0, 5.0, VarManager::kTPCnSigmaEl_Corr); - hm->AddHistogram(histClass, "TPCnSigPi_Corr_Eta", "TPC n-#sigma(#pi) Corr. vs Eta", false, 20, -1.0, 1.0, VarManager::kEta, 100, -5.0, 5.0, VarManager::kTPCnSigmaPi_Corr); - hm->AddHistogram(histClass, "TPCnSigKa_Corr_Eta", "TPC n-#sigma(K) Corr. vs Eta", false, 20, -1.0, 1.0, VarManager::kEta, 100, -5.0, 5.0, VarManager::kTPCnSigmaKa_Corr); - hm->AddHistogram(histClass, "TPCnSigPr_Corr_Eta", "TPC n-#sigma(p) Corr. vs Eta", false, 20, -1.0, 1.0, VarManager::kEta, 100, -5.0, 5.0, VarManager::kTPCnSigmaPr_Corr); + hm->AddHistogram(histClass, "TPCnSigPr_timeFromSOR", "TPC n-#sigma(p) vs time from SOR", true, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, -5.0, 5.0, VarManager::kTPCnSigmaPr); + if (subGroupStr.Contains("tpcpid_Corr")) { + hm->AddHistogram(histClass, "TPCnSigEl_Corr_pIN", "TPC n-#sigma(e) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaEl_Corr); + hm->AddHistogram(histClass, "TPCnSigPi_Corr_pIN", "TPC n-#sigma(#pi) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaPi_Corr); + hm->AddHistogram(histClass, "TPCnSigKa_Corr_pIN", "TPC n-#sigma(K) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaKa_Corr); + hm->AddHistogram(histClass, "TPCnSigPr_Corr_pIN", "TPC n-#sigma(p) Corr. vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 100, -5.0, 5.0, VarManager::kTPCnSigmaPr_Corr); + } + } } if (subGroupStr.Contains("postcalib")) { const int kNvarsPID = 4; @@ -630,14 +674,18 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("dca")) { hm->AddHistogram(histClass, "DCAxy", "DCA_{xy}", false, 400, -2.0, 2.0, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "DCAxy_vsTimeFromSOR", "DCA_{xy} vs time from SOR", true, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, -2.0, 2.0, VarManager::kTrackDCAxy); hm->AddHistogram(histClass, "DCAz", "DCA_{z}", false, 800, -4.0, 4.0, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "DCAz_vsTimeFromSOR", "DCA_{z} vs time from SOR", true, 10000, 0.0, 1000.0, VarManager::kTimeFromSOR, 10, -2.0, 2.0, VarManager::kTrackDCAz); hm->AddHistogram(histClass, "DCAsigXY", "DCA_{XY} [#sigma]", false, 200, -20.0, 20.0, VarManager::kTrackDCAsigXY); hm->AddHistogram(histClass, "DCAsigZ", "DCA_{Z} [#sigma]", false, 200, -20.0, 20.0, VarManager::kTrackDCAsigZ); + hm->AddHistogram(histClass, "DCAxy_DCAz", "DCA_{xy} vs DCA_{z}", false, 200, -4.0, 4.0, VarManager::kTrackDCAxy, 200, -4.0, 4.0, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "DCAsigXY_DCAsigZ", "DCA_{XY} [#sigma] vs DCA_{Z} [#sigma]", false, 200, -20.0, 20.0, VarManager::kTrackDCAsigXY, 200, -20.0, 20.0, VarManager::kTrackDCAsigZ); if (subGroupStr.Contains("pt")) { hm->AddHistogram(histClass, "Pt_DCAxy", "p_{T} vs DCA_{xy}", false, 200, 0.0, 20.0, VarManager::kPt, 400, -2.0, 2.0, VarManager::kTrackDCAxy); hm->AddHistogram(histClass, "Pt_DCAz", "p_{T} vs DCA_{z}", false, 200, 0.0, 20.0, VarManager::kPt, 800, -4.0, 4.0, VarManager::kTrackDCAz); - hm->AddHistogram(histClass, "Pt_DCAsigXY", "p_{T} vs DCA_{XY} [#sigma]", false, 200, 0.0, 20.0, VarManager::kPt, 100, -10.0, 10.0, VarManager::kTrackDCAsigXY); // JJ:edit - hm->AddHistogram(histClass, "Pt_DCAsigZ", "p_{T} vs DCA_{Z} [#sigma]", false, 200, 0.0, 20.0, VarManager::kPt, 100, -10.0, 10.0, VarManager::kTrackDCAsigZ); + hm->AddHistogram(histClass, "Pt_DCAsigXY", "p_{T} vs DCA_{XY} [#sigma]", false, 200, 0.0, 20.0, VarManager::kPt, 200, -20.0, 20.0, VarManager::kTrackDCAsigXY); // JJ:edit + hm->AddHistogram(histClass, "Pt_DCAsigZ", "p_{T} vs DCA_{Z} [#sigma]", false, 200, 0.0, 20.0, VarManager::kPt, 200, -20.0, 20.0, VarManager::kTrackDCAsigZ); hm->AddHistogram(histClass, "Pt_DCAresXY", "p_{T} vs #DeltaDCA_{XY}", false, 200, 0.0, 10.0, VarManager::kPt, 100, -0.03, 0.03, VarManager::kTrackDCAresXY); hm->AddHistogram(histClass, "Pt_DCAresZ", "p_{T} vs #DeltaDCA_{Z}", false, 200, 0.0, 10.0, VarManager::kPt, 100, -0.03, 0.03, VarManager::kTrackDCAresZ); } @@ -764,12 +812,24 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_HighRange", "", false, 375, 0.0, 15.0, VarManager::kMass); hm->AddHistogram(histClass, "Pt", "", false, 2000, 0.0, 20., VarManager::kPt); hm->AddHistogram(histClass, "Mass_Pt", "", false, 125, 0.0, 5.0, VarManager::kMass, 40, 0.0, 20.0, VarManager::kPt); + double massBins[76]; + for (int i = 0; i < 76; i++) { + massBins[i] = 1.5 + i * 0.04; + } + double ptBins[70]; + for (int i = 0; i <= 50; i++) { + ptBins[i] = i * 0.01; + } + for (int i = 1; i <= 19; i++) { + ptBins[50 + i] = 0.5 + i * 0.5; + } + hm->AddHistogram(histClass, "Mass_PtFine", "", false, 75, massBins, VarManager::kMass, 69, ptBins, VarManager::kPt); hm->AddHistogram(histClass, "Eta_Pt", "", false, 40, -2.0, 2.0, VarManager::kEta, 40, 0.0, 20.0, VarManager::kPt); hm->AddHistogram(histClass, "Mass_VtxZ", "", true, 30, -15.0, 15.0, VarManager::kVtxZ, 500, 0.0, 5.0, VarManager::kMass); if (subGroupStr.Contains("pbpb")) { - hm->AddHistogram(histClass, "Mass_CentFT0C", "", false, 500, 0.0, 5.0, VarManager::kMass, 20, 0.0, 100.0, VarManager::kCentFT0C); - hm->AddHistogram(histClass, "Pt_CentFT0C", "", false, 500, 0.0, 1.5, VarManager::kPt, 20, 0.0, 100.0, VarManager::kCentFT0C); - hm->AddHistogram(histClass, "Mass_Pt_CentFT0C", "", false, 500, 0.0, 5.0, VarManager::kMass, 400, 0.0, 40.0, VarManager::kPt, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Mass_CentFT0C", "", false, 125, 0.0, 5.0, VarManager::kMass, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Pt_CentFT0C", "", false, 100, 0.0, 10.0, VarManager::kPt, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Mass_Pt_CentFT0C", "", false, 75, 1.5, 4.5, VarManager::kMass, 20, 0.0, 10.0, VarManager::kPt, 10, 0.0, 100.0, VarManager::kCentFT0C); } if (subGroupStr.Contains("mult")) { hm->AddHistogram(histClass, "Mass_Pt_MultFV0A", "", false, 200, 0.0, 5.0, VarManager::kMass, 40, 0.0, 40.0, VarManager::kPt, 100, 0.0, 25000.0, VarManager::kMultFV0A); @@ -920,27 +980,63 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("dimuon-polarization-he")) { int varspTHE[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaHE, VarManager::kPhiHE}; - int varsFT0CMulHE[4] = {VarManager::kMass, VarManager::kMultFT0C, VarManager::kCosThetaHE, VarManager::kPhiHE}; + int varsFT0CCentHE[4] = {VarManager::kMass, VarManager::kCentFT0C, VarManager::kCosThetaHE, VarManager::kPhiHE}; int binspT[4] = {100, 20, 20, 20}; - int binsMul[4] = {100, 20, 20, 20}; + int binsCent[4] = {100, 20, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminMul[4] = {1., 0., -1., -3.14}; - double xmaxMul[4] = {5., 2000., 1., +3.14}; + double xminCent[4] = {1., 0., -1., -3.14}; + double xmaxCent[4] = {5., 100., 1., +3.14}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaHE_phiHE", "", 4, varspTHE, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_MultFT0C_cosThetaHE_phiHE", "", 4, varsFT0CMulHE, binsMul, xminMul, xmaxMul, 0, -1, kFALSE); + hm->AddHistogram(histClass, "Mass_CentFT0C_cosThetaHE_phiHE", "", 4, varsFT0CCentHE, binsCent, xminCent, xmaxCent, 0, -1, kFALSE); } if (subGroupStr.Contains("dimuon-polarization-cs")) { int varspTCS[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaCS, VarManager::kPhiCS}; - int varsFT0CMulCS[4] = {VarManager::kMass, VarManager::kMultFT0C, VarManager::kCosThetaCS, VarManager::kPhiCS}; + int varsFT0CCentCS[4] = {VarManager::kMass, VarManager::kCentFT0C, VarManager::kCosThetaCS, VarManager::kPhiCS}; int binspT[4] = {100, 20, 20, 20}; - int binsMul[4] = {100, 20, 20, 20}; + int binsCent[4] = {100, 20, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminMul[4] = {1., 0., -1., -3.14}; - double xmaxMul[4] = {5., 2000., 1., +3.14}; + double xminCent[4] = {1., 0., -1., -3.14}; + double xmaxCent[4] = {5., 100., 1., +3.14}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaCS_phiCS", "", 4, varspTCS, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_MultFT0C_cosThetaCS_phiCS", "", 4, varsFT0CMulCS, binsMul, xminMul, xmaxMul, 0, -1, kFALSE); + hm->AddHistogram(histClass, "Mass_CentFT0C_cosThetaCS_phiCS", "", 4, varsFT0CCentCS, binsCent, xminCent, xmaxCent, 0, -1, kFALSE); + } + if (subGroupStr.Contains("dimuon-rap")) { + int vars[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kRap}; + int binspT[4] = {150, 200, 10, 8}; + double xminpT[4] = {2., 0., 0, 2.0}; + double xmaxpT[4] = {5., 20., 100, 4.5}; + hm->AddHistogram(histClass, "Mass_Pt_Cent_Rap", "", 4, vars, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + } + if (subGroupStr.Contains("dimuon-polarization-he-pbpb")) { + int varsHEpbpb[5] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kCosThetaHE, VarManager::kPhiHE}; + int binspT[5] = {150, 30, 10, 10, 10}; + double xminpT[5] = {2., 0., 0, -1., -3.14}; + double xmaxpT[5] = {5., 3., 100, 1., 3.14}; + hm->AddHistogram(histClass, "Mass_Pt_Cent_cosThetaHE", "", 5, varsHEpbpb, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + } + + if (subGroupStr.Contains("dimuon-polarization-cs-pbpb")) { + int varsCSpbpb[5] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kCosThetaCS, VarManager::kPhiCS}; + int binspT[5] = {150, 30, 10, 10, 10}; + double xminpT[5] = {2., 0., 0, -1., -3.14}; + double xmaxpT[5] = {5., 3., 100, 1., 3.14}; + hm->AddHistogram(histClass, "Mass_Pt_Cent_cosThetaCS", "", 5, varsCSpbpb, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + } + if (subGroupStr.Contains("dimuon-rap-polarization-he-pbpb")) { + int varsHEpbpb[5] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kCosThetaHE, VarManager::kRap}; + int binspT[5] = {150, 30, 10, 10, 8}; + double xminpT[5] = {2., 0., 0, -1., 2.0}; + double xmaxpT[5] = {5., 3., 100, 1., 4.5}; + hm->AddHistogram(histClass, "Mass_Pt_Cent_cosThetaHE_Rap", "", 5, varsHEpbpb, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + } + if (subGroupStr.Contains("dimuon-rap-polarization-cs-pbpb")) { + int varsCSpbpb[5] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kCosThetaCS, VarManager::kRap}; + int binspT[5] = {150, 30, 10, 10, 8}; + double xminpT[5] = {2., 0., 0, -1., 2.0}; + double xmaxpT[5] = {5., 3., 100, 1., 4.5}; + hm->AddHistogram(histClass, "Mass_Pt_Cent_cosThetaCS_Rap", "", 5, varsCSpbpb, binspT, xminpT, xmaxpT, 0, -1, kFALSE); } if (subGroupStr.Contains("multiplicity-fvoa")) { int varsFV0AMulHE[4] = {VarManager::kMass, VarManager::kMultFV0A, VarManager::kCosThetaHE, VarManager::kPhiHE}; @@ -997,6 +1093,17 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_V2", "", 6, varV2, bins, minBins, maxBins, 0, -1, kTRUE); hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_V3", "", 6, varV3, bins, minBins, maxBins, 0, -1, kTRUE); } + if (subGroupStr.Contains("cumulant")) { + int var[4] = {VarManager::kMass, VarManager::kPt, VarManager::kRap, VarManager::kCentFT0C}; + int bins[4] = {250, 60, 6, 18}; + double minBins[4] = {0.0, 0.0, 2.5, 0.0}; + double maxBins[4] = {5.0, 30.0, 4.0, 90.0}; + hm->AddHistogram(histClass, "Mass_Pt_Rapidity_CentFT0C", "", 4, var, bins, minBins, maxBins, 0, -1, kTRUE); + hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_Corr2REF", "", true, 250, 0.0, 5.0, VarManager::kMass, 60, 0.0, 30.0, VarManager::kPt, 18, 0.0, 90.0, VarManager::kCentFT0C, "", "", "", VarManager::kCORR2REF, VarManager::kM11REFoverMp); + hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_Corr4REF", "", true, 250, 0.0, 5.0, VarManager::kMass, 60, 0.0, 30.0, VarManager::kPt, 18, 0.0, 90.0, VarManager::kCentFT0C, "", "", "", VarManager::kCORR4REF, VarManager::kM1111REFoverMp); + hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_Corr2POI", "", true, 250, 0.0, 5.0, VarManager::kMass, 60, 0.0, 30.0, VarManager::kPt, 18, 0.0, 90.0, VarManager::kCentFT0C, "", "", "", VarManager::kCORR2POIMp, VarManager::kM01POIoverMp); + hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_Corr4POI", "", true, 250, 0.0, 5.0, VarManager::kMass, 60, 0.0, 30.0, VarManager::kPt, 18, 0.0, 90.0, VarManager::kCentFT0C, "", "", "", VarManager::kCORR4POIMp, VarManager::kM0111POIoverMp); + } if (subGroupStr.Contains("res-flow-dimuon")) { int varV2[6] = {VarManager::kMass, VarManager::kPt, VarManager::kRap, VarManager::kCentFT0C, VarManager::kR2SP_AB, VarManager::kR2EP_AB}; int varV3[6] = {VarManager::kMass, VarManager::kPt, VarManager::kRap, VarManager::kCentFT0C, VarManager::kR3SP, VarManager::kR3EP}; @@ -1023,6 +1130,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_VtxZ", "", true, 30, -15.0, 15.0, VarManager::kVtxZ, 750, 0.0, 30.0, VarManager::kMass); hm->AddHistogram(histClass, "DeltaPhiPair", "", false, 130, -6.5, 6.5, VarManager::kDeltaPhiPair); } + if (subGroupStr.Contains("correlation-emu")) { + hm->AddHistogram(histClass, "DeltaPhiPair2", "", false, 600, -0.5 * TMath::Pi(), 1.5 * TMath::Pi(), VarManager::kDeltaPhiPair2); + } if (subGroupStr.Contains("dielectrons")) { if (subGroupStr.Contains("prefilter")) { hm->AddHistogram(histClass, "MassLow_OpeningAngle", "", false, 150, 0., 0.15, VarManager::kMass, 80, 0., 0.8, VarManager::kOpeningAngle); @@ -1123,26 +1233,13 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("opencharm")) { if (subGroupStr.Contains("dmeson")) { - double mD0_bins[51]; - for (int i = 0; i <= 50; i++) { - mD0_bins[i] = 1.7 + i * 0.006; - } - int nbins_mD0 = sizeof(mD0_bins) / sizeof(*mD0_bins) - 1; - - double ptD0_bins[31]; - for (int i = 0; i <= 16; i++) - ptD0_bins[i] = 0.125 * i; - for (int i = 1; i <= 8; i++) - ptD0_bins[16 + i] = 2 + 0.25 * i; - for (int i = 1; i <= 4; i++) - ptD0_bins[24 + i] = 4 + 1 * i; - ptD0_bins[29] = 8; - ptD0_bins[30] = 20; - int nbins_ptD0 = sizeof(ptD0_bins) / sizeof(*ptD0_bins) - 1; - hm->AddHistogram(histClass, "MassD0region", "", false, nbins_mD0, mD0_bins, VarManager::kMass); - hm->AddHistogram(histClass, "MassD0region_Pt", "", false, nbins_mD0, mD0_bins, VarManager::kMass, nbins_ptD0, ptD0_bins, VarManager::kPt); - hm->AddHistogram(histClass, "MassD0region_eta", "", false, 50, 1.7, 2.0, VarManager::kMass, 40, -2., 2., VarManager::kEta); - hm->AddHistogram(histClass, "MassD0region_TauxyzProj", "", false, 50, 1.7, 2.0, VarManager::kMass, 1000, -0.03, 0.03, VarManager::kVertexingTauxyzProjected); + hm->AddHistogram(histClass, "MassD0region", "", false, 140, 1.5, 2.2, VarManager::kMass); + hm->AddHistogram(histClass, "MassD0region_Pt", "", false, 70, 1.5, 2.2, VarManager::kMass, 160, 0., 20., VarManager::kPt); + hm->AddHistogram(histClass, "MassD0region_Rapidity", "", false, 140, 1.5, 2.2, VarManager::kMass, 10, -0.8, 0.8, VarManager::kRap); + hm->AddHistogram(histClass, "MassD0region_eta", "", false, 140, 1.5, 2.2, VarManager::kMass, 40, -2., 2., VarManager::kEta); + hm->AddHistogram(histClass, "MassD0region_TauxyzProj", "", false, 140, 1.5, 2.2, VarManager::kMass, 200, -0.03, 0.03, VarManager::kVertexingTauxyzProjected); + hm->AddHistogram(histClass, "MassD0region_VtxNContribReal", "", false, 140, 1.5, 2.2, VarManager::kMass, 50, 0, 50, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "MassD0region_Rapidity_AveragePt", "", true, 140, 1.5, 2.2, VarManager::kMass, 10, -0.8, 0.8, VarManager::kRap, 150, 0.0, 30.0, VarManager::kPt); } if (subGroupStr.Contains("lambdac")) { hm->AddHistogram(histClass, "MassLambdacRegion", "", false, 50, 2.15, 2.4, VarManager::kMass); @@ -1196,41 +1293,38 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "DeltaEta_DeltaPhi", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhi); hm->AddHistogram(histClass, "DeltaEta_DeltaPhiSym", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhiSym); } - if (subGroupStr.Contains("opencharm")) { - hm->AddHistogram(histClass, "Delta_Mass_DstarD0region", "", false, 50, 0.14, 0.16, VarManager::kDeltaMass); - } - } + if (subGroupStr.Contains("dilepton-hadron-array-correlation")) { + const int kInvMassBins = 500; + double InvMassBinLims[kInvMassBins + 1]; + for (int i = 0; i <= kInvMassBins; i++) + InvMassBinLims[i] = 0 + i * 0.01; - if (!groupStr.CompareTo("dilepton-hadron-array-correlation")) { - const int kInvMassBins = 500; - double InvMassBinLims[kInvMassBins + 1]; - for (int i = 0; i <= kInvMassBins; i++) - InvMassBinLims[i] = 0 + i * 0.01; + const int kDelEtaBins = 20; + double DelEtaBinLims[kDelEtaBins + 1]; + for (int i = 0; i <= kDelEtaBins; i++) + DelEtaBinLims[i] = -2 + i * 0.2; - const int kDelEtaBins = 20; - double DelEtaBinLims[kDelEtaBins + 1]; - for (int i = 0; i <= kDelEtaBins; i++) - DelEtaBinLims[i] = -2 + i * 0.2; + const int kDelPhiBins = 52; + double DelPhiBinLims[] = {-1.69647, -1.57080, -1.44513, -1.31947, -1.19381, -1.06814, -0.94248, -0.81681, -0.69115, -0.56549, -0.43982, -0.31416, -0.18850, -0.06283, 0.06283, 0.18850, 0.31416, 0.43982, 0.56549, 0.69115, 0.81681, 0.94248, 1.06814, 1.19381, 1.31947, 1.44513, 1.57080, 1.69646, 1.82212, 1.94779, 2.07345, 2.19911, 2.32478, 2.45044, 2.57611, 2.70177, 2.82743, 2.95310, 3.07876, 3.20442, 3.33009, 3.45575, 3.58142, 3.70708, 3.83274, 3.95841, 4.08407, 4.20973, 4.33540, 4.46106, 4.58673, 4.71239, 4.8380600}; - const int kDelPhiBins = 50; - double DelPhiBinLims[kDelPhiBins + 1]; - for (int i = 0; i <= kDelPhiBins; i++) - DelPhiBinLims[i] = -8 + i * 0.32; + const int kPtBins = 45; + double PtBinLims[kPtBins + 1] = {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.5, 5, 7.5, 10, 20}; - const int kPtBins = 20; - double PtBinLims[kPtBins + 1]; - for (int i = 0; i <= kPtBins; i++) - PtBinLims[i] = 0 + i * 1; + TArrayD nJPsiHadCorr[4]; + nJPsiHadCorr[0] = TArrayD(kInvMassBins + 1, InvMassBinLims); + nJPsiHadCorr[1] = TArrayD(kDelEtaBins + 1, DelEtaBinLims); + nJPsiHadCorr[2] = TArrayD(kDelPhiBins + 1, DelPhiBinLims); + nJPsiHadCorr[3] = TArrayD(kPtBins + 1, PtBinLims); - TArrayD nJPsiHadCorr[4]; - nJPsiHadCorr[0] = TArrayD(kInvMassBins + 1, InvMassBinLims); - nJPsiHadCorr[1] = TArrayD(kDelEtaBins + 1, DelEtaBinLims); - nJPsiHadCorr[2] = TArrayD(kDelPhiBins + 1, DelPhiBinLims); - nJPsiHadCorr[3] = TArrayD(kPtBins + 1, PtBinLims); - - int varsJPsiHadCorr[4] = {VarManager::kPairMassDau, VarManager::kDeltaEta, VarManager::kDeltaPhi, VarManager::kPairPtDau}; - hm->AddHistogram(histClass, "InvMass_DelEta_DelPhi", "", 4, varsJPsiHadCorr, nJPsiHadCorr); + int varsJPsiHadCorr[4] = {VarManager::kPairMassDau, VarManager::kDeltaEta, VarManager::kDeltaPhi, VarManager::kPairPtDau}; + hm->AddHistogram(histClass, "InvMass_DelEta_DelPhi", "", 4, varsJPsiHadCorr, nJPsiHadCorr); // Without efficiency + // hm->AddHistogram(histClass, "InvMass_DelEta_DelPhi", "", 4, varsJPsiHadCorr, nJPsiHadCorr, nullptr, VarManager::kJpsiHadronEff); + } + if (subGroupStr.Contains("opencharm")) { + hm->AddHistogram(histClass, "Delta_Mass_DstarD0region", "", false, 50, 0.14, 0.16, VarManager::kDeltaMass); + } } + if (!groupStr.CompareTo("dilepton-charmhadron")) { if (subGroupStr.EqualTo("jpsitomumu")) { hm->AddHistogram(histClass, "hMassVsPtJPsi", "", false, 100, 0.f, 50.f, VarManager::kPt, 300, 2.f, 5.f, VarManager::kMass); @@ -1263,11 +1357,36 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (!groupStr.CompareTo("dilepton-dihadron")) { if (subGroupStr.EqualTo("xtojpsipipi")) { hm->AddHistogram(histClass, "hMass_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadMass); - hm->AddHistogram(histClass, "hPt_X3872", "", false, 200, 0.0, 20.0, VarManager::kQuadPt); - hm->AddHistogram(histClass, "hMass_Pt_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadMass, 150, 0.0, 15.0, VarManager::kQuadPt); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass); + hm->AddHistogram(histClass, "hPt_X3872", "", false, 150, 0.0, 15.0, VarManager::kQuadPt); + hm->AddHistogram(histClass, "hMass_Pt_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 150, 0.0, 15.0, VarManager::kQuadPt); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Pt_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, 0.0, 15.0, VarManager::kQuadPt); hm->AddHistogram(histClass, "hCostheta_Jpsi_Dihadron", "", false, 100, -1.0, 1.0, VarManager::kCosthetaDileptonDitrack); - hm->AddHistogram(histClass, "hPtDilepton_PtDihadron", "", false, 200, 0, 20, VarManager::kPairPt, 100, 0, 10, VarManager::kDitrackPt); - hm->AddHistogram(histClass, "hPtDilepton_MassDihadron", "", false, 200, 0, 20, VarManager::kPairPt, 100, 3.0, 5.0, VarManager::kDitrackMass); + hm->AddHistogram(histClass, "hPtDilepton_PtDihadron", "", false, 150, 0, 15.0, VarManager::kPairPt, 100, 0, 10, VarManager::kDitrackPt); + hm->AddHistogram(histClass, "hPtDilepton_MassDihadron", "", false, 150, 0, 15.0, VarManager::kPairPt, 150, 0.0, 3.0, VarManager::kDitrackMass); + hm->AddHistogram(histClass, "hQ_X3872", "", false, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hDeltaR1_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR1); + hm->AddHistogram(histClass, "hDeltaR2_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR2); + hm->AddHistogram(histClass, "hMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hMass_DeltaR1_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kDeltaR1); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_DeltaR1_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kDeltaR1); + hm->AddHistogram(histClass, "hMass_DeltaR2_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kDeltaR2); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_DeltaR2_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kDeltaR2); + hm->AddHistogram(histClass, "hMass_X3872_MassDihadron", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 150, 0.0, 3.0, VarManager::kDitrackMass); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_X3872_MassDihadron", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, 0.0, 3.0, VarManager::kDitrackMass); + hm->AddHistogram(histClass, "hRap_X3872", "", false, 1000, 0.0, 5.0, VarManager::kRap); + hm->AddHistogram(histClass, "hMass_Rap_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 1000, 0.0, 5.0, VarManager::kRap); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Rap_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 1000, 0.0, 5.0, VarManager::kRap); + hm->AddHistogram(histClass, "hDCAxyTrack1", "", false, 100, -0.1, 0.1, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "hDCAzTrack1", "", false, 100, -0.1, 0.1, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_DCAxyTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, -0.1, 0.1, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_DCAzTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, -0.1, 0.1, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "hMass_DCAxyTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, -0.1, 0.1, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "hMass_DCAzTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, -0.1, 0.1, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "hPtTrack1", "", false, 100, 0.0, 10.0, VarManager::kPt); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_PtTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kPt); + hm->AddHistogram(histClass, "hMass_PtTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kPt); } } if (!groupStr.CompareTo("dilepton-photon-mass")) { diff --git a/PWGDQ/Core/MCProng.cxx b/PWGDQ/Core/MCProng.cxx index 14fa645eb77..b9e79931aed 100644 --- a/PWGDQ/Core/MCProng.cxx +++ b/PWGDQ/Core/MCProng.cxx @@ -146,7 +146,11 @@ void MCProng::Print() const for (int i = 0; i < fNGenerations; i++) { std::cout << "Generation #" << i << " PDGcode(" << fPDGcodes[i] << ") CheckBothCharges(" << fCheckBothCharges[i] << ") ExcludePDG(" << fExcludePDG[i] << ") SourceBits(" << fSourceBits[i] << ") ExcludeSource(" << fExcludeSource[i] - << ") UseANDonSource(" << fUseANDonSourceBitMap[i] << ") CheckGenerationsInTime(" << fCheckGenerationsInTime << ") PDGInHistory(" << fPDGInHistory[i] << ") ExcludePDGInHistory(" << fExcludePDGInHistory[i] << ")" << std::endl; + << ") UseANDonSource(" << fUseANDonSourceBitMap[i] << ") CheckGenerationsInTime(" << fCheckGenerationsInTime << ")"; + for (int j = 0; j < fPDGInHistory.size(); j++) { + std::cout << " #" << j << " PDGInHistory(" << fPDGInHistory[j] << ") ExcludePDGInHistory(" << fExcludePDGInHistory[j] << ")"; + } + std::cout << std::endl; } } diff --git a/PWGDQ/Core/MCSignal.cxx b/PWGDQ/Core/MCSignal.cxx index a86b0f8aa8d..e66ebea3687 100644 --- a/PWGDQ/Core/MCSignal.cxx +++ b/PWGDQ/Core/MCSignal.cxx @@ -21,6 +21,7 @@ MCSignal::MCSignal() : TNamed("", ""), fProngs({}), fNProngs(0), fCommonAncestorIdxs({}), + fExcludeCommonAncestor(false), fTempAncestorLabel(-1) { } @@ -30,17 +31,19 @@ MCSignal::MCSignal(int nProngs, const char* name /*= ""*/, const char* title /*= fProngs({}), fNProngs(nProngs), fCommonAncestorIdxs({}), + fExcludeCommonAncestor(false), fTempAncestorLabel(-1) { fProngs.reserve(nProngs); } //________________________________________________________________________________________________ -MCSignal::MCSignal(const char* name, const char* title, std::vector prongs, std::vector commonAncestors) : TNamed(name, title), - fProngs(prongs), - fNProngs(prongs.size()), - fCommonAncestorIdxs(commonAncestors), - fTempAncestorLabel(-1) +MCSignal::MCSignal(const char* name, const char* title, std::vector prongs, std::vector commonAncestors, bool excludeCommonAncestor) : TNamed(name, title), + fProngs(prongs), + fNProngs(prongs.size()), + fCommonAncestorIdxs(commonAncestors), + fExcludeCommonAncestor(excludeCommonAncestor), + fTempAncestorLabel(-1) { } @@ -67,10 +70,11 @@ void MCSignal::AddProng(MCProng prong, short commonAncestor) void MCSignal::PrintConfig() { cout << "Name/Title: " << fName << " / " << fTitle << endl; + cout << "Exclude common ancestor combinations: " << fExcludeCommonAncestor << endl; cout << "Printing " << fNProngs << "/" << fProngs.size() << " prongs:" << endl; int i = 0; for (auto& pr : fProngs) { - cout << "Prong #" << i << " commonAncestor" << fCommonAncestorIdxs[i] << " ================ " << endl; + cout << "Prong #" << i << " commonAncestor: " << fCommonAncestorIdxs[i] << " ================ " << endl; i++; pr.Print(); } diff --git a/PWGDQ/Core/MCSignal.h b/PWGDQ/Core/MCSignal.h index 787aa443b22..c2fa8227de2 100644 --- a/PWGDQ/Core/MCSignal.h +++ b/PWGDQ/Core/MCSignal.h @@ -67,7 +67,7 @@ class MCSignal : public TNamed public: MCSignal(); MCSignal(int nProngs, const char* name = "", const char* title = ""); - MCSignal(const char* name, const char* title, std::vector prongs, std::vector commonAncestors); + MCSignal(const char* name, const char* title, std::vector prongs, std::vector commonAncestors, bool excludeCommonAncestor = false); MCSignal(const MCSignal& c) = default; ~MCSignal() override = default; @@ -100,6 +100,7 @@ class MCSignal : public TNamed std::vector fProngs; unsigned int fNProngs; std::vector fCommonAncestorIdxs; + bool fExcludeCommonAncestor; int fTempAncestorLabel; template @@ -139,14 +140,15 @@ bool MCSignal::CheckProng(int i, bool checkSources, const T& track) if (i == 0) { fTempAncestorLabel = currentMCParticle.globalIndex(); } else { - if (currentMCParticle.globalIndex() != fTempAncestorLabel) { + if (currentMCParticle.globalIndex() != fTempAncestorLabel && !fExcludeCommonAncestor) + return false; + else if (currentMCParticle.globalIndex() == fTempAncestorLabel && fExcludeCommonAncestor) return false; - } } } // Update the currentMCParticle by moving either back in time (towards mothers, grandmothers, etc) - // or in time (towards daughters) depending on how this was configured in the MSignal + // or in time (towards daughters) depending on how this was configured in the MC Signal if (!fProngs[i].fCheckGenerationsInTime) { // make sure that a mother exists in the stack before moving one generation further in history if (!currentMCParticle.has_mothers() && j < fProngs[i].fNGenerations - 1) { diff --git a/PWGDQ/Core/MCSignalLibrary.cxx b/PWGDQ/Core/MCSignalLibrary.cxx index 7d2fb3520d3..7a33333b0a7 100644 --- a/PWGDQ/Core/MCSignalLibrary.cxx +++ b/PWGDQ/Core/MCSignalLibrary.cxx @@ -456,6 +456,24 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "Electrons from Lambda_c decays", {prong}, {-1}); return signal; } + if (!nameStr.compare("eFromXiC0")) { + MCProng prong(2, {11, Pdg::kXiC0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "Electrons from Xi_c_0 decays", {prong}, {-1}); + return signal; + } + if (!nameStr.compare("eFromXiCPlus")) { + MCProng prong(2, {11, Pdg::kXiCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "Electrons from Xi_c_+ decays", {prong}, {-1}); + return signal; + } + if (!nameStr.compare("eFromXiCPlusPlus")) { + MCProng prong(2, {11, Pdg::kXiCCPlusPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "Electrons from Xi_c_++ decays", {prong}, {-1}); + return signal; + } if (!nameStr.compare("eFromHb")) { MCProng prong(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); prong.SetSourceBit(0, MCProng::kPhysicalPrimary); @@ -724,6 +742,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from D0 decays, no beauty in history", {prong, prong}, {-1, -1}); return signal; } + // D0->e and D0->e if (!nameStr.compare("eeFromPi0FromD0")) { MCProng prong(2, {kElectron, kPi0, Pdg::kD0}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false, {502}, {true}); @@ -731,6 +750,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from D0 to Pi0 decays, no beauty in history", {prong, prong}, {1, 1}); return signal; } + // D+/- -> e and D+/- -> e if (!nameStr.compare("eeFromChargedD")) { MCProng prong(2, {kElectron, Pdg::kDPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); @@ -738,6 +758,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from D+/- decays, no beauty in history", {prong, prong}, {-1, -1}); return signal; } + // D0 -> e and D+/- -> e if (!nameStr.compare("eeFromD0andChargedD")) { MCProng prongD0(2, {kElectron, Pdg::kD0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); @@ -747,6 +768,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "one e from D0 and one e from D+/- decays, no beauty in history", {prongD0, prongDch}, {-1, -1}); return signal; } + // D+/- -> e and D0 -> e if (!nameStr.compare("eeFromD0andChargedDBis")) { MCProng prongD0(2, {kElectron, Pdg::kD0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); @@ -756,6 +778,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "one e from D+/- and one e from D0 decays, no beauty in history (inverse signal)", {prongDch, prongD0}, {-1, -1}); return signal; } + // D_s->e and D_s->e if (!nameStr.compare("eeFromDs")) { MCProng prong(2, {kElectron, Pdg::kDS}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); @@ -763,6 +786,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from Ds +/- decays, no beauty in history", {prong, prong}, {-1, -1}); return signal; } + // Lambda_c->e and Lambda_c->e if (!nameStr.compare("eeFromLambdaC")) { MCProng prong(2, {kElectron, Pdg::kLambdaCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); @@ -770,40 +794,88 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from Lambda_c, no beauty in history", {prong, prong}, {-1, -1}); return signal; } + // Lambda_c->e and D0->e if (!nameStr.compare("eeFromLambdaCandD0")) { MCProng prongLc(2, {kElectron, Pdg::kLambdaCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); MCProng prongD0(2, {kElectron, Pdg::kD0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); prongLc.SetSourceBit(0, MCProng::kPhysicalPrimary); prongD0.SetSourceBit(0, MCProng::kPhysicalPrimary); - signal = new MCSignal(name, "ee pairs from Lambda_c, no beauty in history", {prongLc, prongD0}, {-1, -1}); + signal = new MCSignal(name, "one e from Lambda_c and one e from D0 decays, no beauty in history", {prongLc, prongD0}, {-1, -1}); return signal; } + // D0->e and Lambda_c->e if (!nameStr.compare("eeFromLambdaCandD0Bis")) { MCProng prongLc(2, {kElectron, Pdg::kLambdaCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); MCProng prongD0(2, {kElectron, Pdg::kD0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); prongLc.SetSourceBit(0, MCProng::kPhysicalPrimary); prongD0.SetSourceBit(0, MCProng::kPhysicalPrimary); - signal = new MCSignal(name, "ee pairs from Lambda_c, no beauty in history", {prongLc, prongD0}, {-1, -1}); + signal = new MCSignal(name, "one e from Lambda_c and one e from D0 decays, no beauty in history (inverse signal)", {prongD0, prongLc}, {-1, -1}); return signal; } + // Lambda_c->e and D+/- -> e if (!nameStr.compare("eeFromLambdaCandChargedD")) { MCProng prongLc(2, {kElectron, Pdg::kLambdaCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); MCProng prongDch(2, {kElectron, Pdg::kDPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); prongLc.SetSourceBit(0, MCProng::kPhysicalPrimary); prongDch.SetSourceBit(0, MCProng::kPhysicalPrimary); - signal = new MCSignal(name, "ee pairs from Lambda_c, no beauty in history", {prongLc, prongDch}, {-1, -1}); + signal = new MCSignal(name, "one e from Lambda_c and one e from D+/- decays, no beauty in history", {prongLc, prongDch}, {-1, -1}); return signal; } + // D+/- -> e and Lambda_c->e if (!nameStr.compare("eeFromLambdaCandChargedDBis")) { MCProng prongLc(2, {kElectron, Pdg::kLambdaCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); MCProng prongDch(2, {kElectron, Pdg::kDPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); prongLc.SetSourceBit(0, MCProng::kPhysicalPrimary); prongDch.SetSourceBit(0, MCProng::kPhysicalPrimary); - signal = new MCSignal(name, "ee pairs from Lambda_c, no beauty in history", {prongLc, prongDch}, {-1, -1}); + signal = new MCSignal(name, "one e from Lambda_c and one e from D+/- decays, no beauty in history (inverse signal)", {prongDch, prongLc}, {-1, -1}); + return signal; + } + + // Xic0 ->e and Xic0 ->e + if (!nameStr.compare("eeFromXiC0")) { + MCProng prong(2, {kElectron, Pdg::kXiC0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from Xi_c0, no beauty in history", {prong, prong}, {-1, -1}); + return signal; + } + + // Xi_c+ ->e and Xi_c+ ->e + if (!nameStr.compare("eeFromXiCPlus")) { + MCProng prong(2, {kElectron, Pdg::kXiCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from Xi_c+, no beauty in history", {prong, prong}, {-1, -1}); + return signal; + } + + // Xi_c0 ->e and Xi_c+ ->e + if (!nameStr.compare("eeFromXiC0andXiCPlus")) { + MCProng prongXiCPlus(2, {kElectron, Pdg::kXiCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + MCProng prongXiC0(2, {kElectron, Pdg::kXiC0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prongXiCPlus.SetSourceBit(0, MCProng::kPhysicalPrimary); + prongXiC0.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "one e from Xi_c+ and one e from Xi_c0 decays, no beauty in history", {prongXiCPlus, prongXiC0}, {-1, -1}); + return signal; + } + + // Xi_c+ ->e and Xi_c0 ->e + if (!nameStr.compare("eeFromXiC0andXiCPlusBis")) { + MCProng prongXiCPlus(2, {kElectron, Pdg::kXiCPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + MCProng prongXiC0(2, {kElectron, Pdg::kXiC0}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prongXiCPlus.SetSourceBit(0, MCProng::kPhysicalPrimary); + prongXiC0.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "one e from Xi_c+ and one e from Xi_c0 decays, no beauty in history (inverse signal)", {prongXiC0, prongXiCPlus}, {-1, -1}); + return signal; + } + + // Xi_cc++ ->e and Xi_cc++ ->e + if (!nameStr.compare("eeFromXiCPlusPlus")) { + MCProng prong(2, {kElectron, Pdg::kXiCCPlusPlus}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from Xi_cc++, no beauty in history", {prong, prong}, {-1, -1}); return signal; } @@ -832,33 +904,108 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) } // Any b to any c in history b -> c -> e - if (!nameStr.compare("eeFromBtoCandBtoC")) { + if (!nameStr.compare("eeFromAnyBtoCandAnyBtoC")) { MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); // check if mother pdg code is in history prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs with any beauty to charm in decay chain", {prong, prong}, {-1, -1}); // signal at pair level return signal; } - // Any b->e and Any b->c->e - if (!nameStr.compare("eeFromBandBtoC")) { - MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); // check if mother pdg code is in history + // b->c->e, b->c->e + if (!nameStr.compare("eeFromBtoCandBtoC")) { + MCProng prong(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs with any beauty to charm in decay chain", {prong, prong}, {-1, -1}); // signal at pair level + return signal; + } + + // Any b->e and Any b->X->c->e + // Looking at such decays: B -> (e) D -> (e)e and bar{B} -> e + // Signal allows combinations of ee from the same B meson + // + the combination of e fom B and e from bar{B} + if (!nameStr.compare("eeFromBandAnyBtoC")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); MCProng prongBtoC(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); // check if mother pdg code is in history prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); - signal = new MCSignal(name, "ee pairs from b->e and b->c->e", {prongB, prongBtoC}, {-1, -1}); // signal at pair level + signal = new MCSignal(name, "ee pairs from b->e and b->X->c->e", {prongB, prongBtoC}, {-1, -1}); // signal at pair level return signal; } - // Any b->e and Any b->c->e - if (!nameStr.compare("eeFromBandBtoCBis")) { - MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); // check if mother pdg code is in history + // Any b->e and Any b->X->c->e + if (!nameStr.compare("eeFromBandAnyBtoCBis")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); MCProng prongBtoC(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); // check if mother pdg code is in history prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->X->c->e and b->e", {prongBtoC, prongB}, {-1, -1}); // signal at pair level + return signal; + } + + // b->e and b->c->e + if (!nameStr.compare("eeFromBandBtoC")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "direkt ee pairs from b->e and b->c->e", {prongB, prongBtoC}, {-1, -1}); // signal at pair level + return signal; + } + + // b->e and b->c->e + if (!nameStr.compare("eeFromBandBtoCBis")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from b->c->e and b->e", {prongBtoC, prongB}, {-1, -1}); // signal at pair level return signal; } + // b->e and b->c->e (same mother/grandmother) + // require that the mother is the grandmother of the other electron + if (!nameStr.compare("eeFromBandBtoCsameGM")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->e and b->c->e, mother = grandmother", {prongB, prongBtoC}, {1, 2}, false); // signal at pair level, accept commonAncestor Pairs + return signal; + } + + // b->e and b->c->e (same mother/grandmother) + // require that the mother is the grandmother of the other electron + if (!nameStr.compare("eeFromBandBtoCsameGMBis")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->c->e and b->e, mother = grandmother", {prongBtoC, prongB}, {2, 1}, false); // signal at pair level, accept commonAncestor Pairs + return signal; + } + + // b->e and b->c->e (different mother/grandmother) + // require that the mother is not the grandmother of the other electron + if (!nameStr.compare("eeFromBandBtoCdiffGM")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->e and b->c->e, mother != grandmother", {prongB, prongBtoC}, {1, 2}, true); // signal at pair level, exclude commonAncestor Pairs + return signal; + } + + // b->e and b->c->e (different mother/grandmother) + // require that the mother is not the grandmother of the other electron + if (!nameStr.compare("eeFromBandBtoCdiffGMBis")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}, false); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->c->e and b->e, mother != grandmother", {prongBtoC, prongB}, {2, 1}, true); // signal at pair level, exclude commonAncestor Pairs + return signal; + } + // b->e and b->e if (!nameStr.compare("eeFromBB")) { MCProng prong(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index b0f613ce068..3026f9408a2 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -34,6 +34,8 @@ int VarManager::fgITSROFbias = 0; int VarManager::fgITSROFlength = 100; int VarManager::fgITSROFBorderMarginLow = 0; int VarManager::fgITSROFBorderMarginHigh = 0; +uint64_t VarManager::fgSOR = 0; +uint64_t VarManager::fgEOR = 0; o2::vertexing::DCAFitterN<2> VarManager::fgFitterTwoProngBarrel; o2::vertexing::DCAFitterN<3> VarManager::fgFitterThreeProngBarrel; o2::vertexing::FwdDCAFitterN<2> VarManager::fgFitterTwoProngFwd; @@ -228,6 +230,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kRunId] = ""; fgVariableNames[kBC] = "Bunch crossing"; fgVariableUnits[kBC] = ""; + fgVariableNames[kTimeFromSOR] = "time since SOR"; + fgVariableUnits[kTimeFromSOR] = "min."; + fgVariableNames[kBCOrbit] = "Bunch crossing"; + fgVariableUnits[kBCOrbit] = ""; fgVariableNames[kIsPhysicsSelection] = "Physics selection"; fgVariableUnits[kIsPhysicsSelection] = ""; fgVariableNames[kVtxX] = "Vtx X "; @@ -236,6 +242,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kVtxY] = "cm"; fgVariableNames[kVtxZ] = "Vtx Z "; fgVariableUnits[kVtxZ] = "cm"; + fgVariableNames[kCollisionTime] = "collision time wrt BC"; + fgVariableUnits[kCollisionTime] = "ns"; + fgVariableNames[kCollisionTimeRes] = "collision time resolution"; + fgVariableUnits[kCollisionTimeRes] = "ns"; fgVariableNames[kVtxNcontrib] = "Vtx contrib."; fgVariableUnits[kVtxNcontrib] = ""; fgVariableNames[kVtxNcontribReal] = "Real Vtx contrib."; @@ -283,6 +293,7 @@ void VarManager::SetDefaultVarNames() fgVariableNames[kCentFT0C] = "Centrality FT0C"; fgVariableUnits[kCentFT0C] = "%"; fgVariableNames[kMCEventGeneratorId] = "MC Generator ID"; + fgVariableNames[kMCEventSubGeneratorId] = "MC SubGenerator ID"; fgVariableNames[kMCVtxX] = "MC Vtx X"; fgVariableNames[kMCVtxY] = "MC Vtx Y"; fgVariableNames[kMCVtxZ] = "MC Vtx Z"; @@ -290,6 +301,7 @@ void VarManager::SetDefaultVarNames() fgVariableNames[kMCEventWeight] = "MC event weight"; fgVariableNames[kMCEventImpParam] = "MC impact parameter"; fgVariableUnits[kMCEventGeneratorId] = ""; + fgVariableUnits[kMCEventSubGeneratorId] = ""; fgVariableUnits[kMCVtxX] = "cm"; fgVariableUnits[kMCVtxY] = "cm"; fgVariableUnits[kMCVtxZ] = "cm"; @@ -739,26 +751,32 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kS31A] = ""; fgVariableNames[kM11REF] = "M_{11}^{REF} "; fgVariableUnits[kM11REF] = ""; - fgVariableNames[kM01POI] = "M_{01}^{POI} "; + fgVariableNames[kM01POI] = "M^{'}_{01}^{POI} "; fgVariableUnits[kM01POI] = ""; fgVariableNames[kM1111REF] = "M_{1111}^{REF} "; fgVariableUnits[kM1111REF] = ""; - fgVariableNames[kM0111POI] = "M_{0111}^{POI} "; + fgVariableNames[kM0111POI] = "M^{'}_{0111}^{POI} "; fgVariableUnits[kM0111POI] = ""; fgVariableNames[kCORR2REF] = "<2> "; fgVariableUnits[kCORR2REF] = ""; - fgVariableNames[kCORR2POI] = " <2'> "; + fgVariableNames[kCORR2POI] = "<2'> "; fgVariableUnits[kCORR2POI] = ""; - fgVariableNames[kCORR4REF] = " <4>"; + fgVariableNames[kCORR4REF] = "<4> "; fgVariableUnits[kCORR4REF] = ""; fgVariableNames[kCORR4POI] = "<4'> "; fgVariableUnits[kCORR4POI] = ""; - fgVariableNames[kC4REF] = "c_{2}(4)"; - fgVariableUnits[kC4REF] = ""; - fgVariableNames[kC4POI] = "d_{2}(4)"; - fgVariableUnits[kC4POI] = ""; - fgVariableNames[kV4] = "v_{2}(4)"; - fgVariableUnits[kV4] = ""; + fgVariableNames[kM11REFoverMp] = "M_{11}^{REF}/M_{p} "; + fgVariableUnits[kM11REFoverMp] = ""; + fgVariableNames[kM01POIoverMp] = "M^{'}_{01}^{POI}/M_{p} "; + fgVariableUnits[kM01POIoverMp] = ""; + fgVariableNames[kM1111REFoverMp] = "M_{1111}^{REF}/M_{p} "; + fgVariableUnits[kM1111REFoverMp] = ""; + fgVariableNames[kM0111POIoverMp] = "M^{'}_{0111}^{POI}/M_{p} "; + fgVariableUnits[kM0111POIoverMp] = ""; + fgVariableNames[kCORR2POIMp] = "<2'> M_{p} "; + fgVariableUnits[kCORR2POIMp] = ""; + fgVariableNames[kCORR4POIMp] = "<4'> M_{p} "; + fgVariableUnits[kCORR4POIMp] = ""; fgVariableNames[kCos2DeltaPhi] = "cos 2(#varphi-#Psi_{2}^{A}) "; fgVariableUnits[kCos2DeltaPhi] = ""; fgVariableNames[kCos3DeltaPhi] = "cos 3(#varphi-#Psi_{3}^{A}) "; @@ -831,6 +849,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kCosThetaCS] = ""; fgVariableNames[kPhiCS] = "#varphi_{CS}"; fgVariableUnits[kPhiCS] = "rad."; + fgVariableNames[kDeltaPhiPair2] = "#Delta#phi"; + fgVariableUnits[kDeltaPhiPair2] = "rad."; fgVariableNames[kPsiPair] = "#Psi_{pair}"; fgVariableUnits[kPsiPair] = "rad."; fgVariableNames[kDeltaPhiPair] = "#Delta#phi"; @@ -889,4 +909,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kDitrackMass] = "GeV/c2"; fgVariableNames[kDitrackPt] = "p_{T}"; fgVariableUnits[kDitrackPt] = "GeV/c"; + fgVariableNames[kQ] = "mass difference"; + fgVariableUnits[kQ] = "GeV/c2"; + fgVariableNames[kDeltaR1] = "angular distance prong 1"; + fgVariableUnits[kDeltaR1] = ""; + fgVariableNames[kDeltaR2] = "angular distance prong 2"; + fgVariableUnits[kDeltaR2] = ""; } diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 0a478ade27f..e0a6085f44e 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -101,6 +101,7 @@ class VarManager : public TObject ReducedZdc = BIT(17), CollisionMultExtra = BIT(18), ReducedEventMultExtra = BIT(19), + CollisionQvectCentr = BIT(20), Track = BIT(0), TrackCov = BIT(1), TrackExtra = BIT(2), @@ -174,6 +175,7 @@ class VarManager : public TObject // Event wise variables kTimestamp, + kTimeFromSOR, // Time since Start of Run (SOR) in minutes kCollisionTime, kCollisionTimeRes, kBC, @@ -240,6 +242,7 @@ class VarManager : public TObject kNTPCtracksInPast, kNTPCtracksInFuture, kMCEventGeneratorId, + kMCEventSubGeneratorId, kMCVtxX, kMCVtxY, kMCVtxZ, @@ -343,6 +346,14 @@ class VarManager : public TObject kEnergyCommonZNC, kEnergyCommonZPA, kEnergyCommonZPC, + kEnergyZNA1, + kEnergyZNA2, + kEnergyZNA3, + kEnergyZNA4, + kEnergyZNC1, + kEnergyZNC2, + kEnergyZNC3, + kEnergyZNC4, kTimeZNA, kTimeZNC, kTimeZPA, @@ -430,7 +441,11 @@ class VarManager : public TObject kTOFbeta, kTrackLength, kTrackDCAxy, + kTrackDCAxyProng1, + kTrackDCAxyProng2, kTrackDCAz, + kTrackDCAzProng1, + kTrackDCAzProng2, kTrackDCAsigXY, kTrackDCAsigZ, kTrackDCAresXY, @@ -561,6 +576,7 @@ class VarManager : public TObject kCosThetaCS, kPhiHE, kPhiCS, + kDeltaPhiPair2, kPsiPair, kDeltaPhiPair, kOpeningAngle, @@ -593,9 +609,12 @@ class VarManager : public TObject kCORR2POI, kCORR4REF, kCORR4POI, - kC4REF, - kC4POI, - kV4, + kM11REFoverMp, + kM01POIoverMp, + kM1111REFoverMp, + kM0111POIoverMp, + kCORR2POIMp, + kCORR4POIMp, kPsi2A, kPsi2APOS, kPsi2ANEG, @@ -647,12 +666,16 @@ class VarManager : public TObject // Dilepton-track-track variables kQuadMass, + kQuadDefaultDileptonMass, kQuadPt, kQuadEta, kQuadPhi, kCosthetaDileptonDitrack, kDitrackMass, kDitrackPt, + kQ, + kDeltaR1, + kDeltaR2, // DQ-HF correlation variables kMassCharmHadron, @@ -836,7 +859,6 @@ class VarManager : public TObject fgFitterThreeProngBarrel.setMinParamChange(minParamChange); fgFitterThreeProngBarrel.setMinRelChi2Change(minRelChi2Change); fgFitterThreeProngBarrel.setUseAbsDCA(useAbsDCA); - cout << "!!! fgFitterThreeProngBarrel bz = " << fgFitterThreeProngBarrel.getBz() << endl; fgUsedKF = false; } @@ -869,6 +891,8 @@ class VarManager : public TObject static void FillBC(T const& bc, float* values = nullptr); template static void FillEvent(T const& event, float* values = nullptr); + template + static void FillEventTrackEstimators(TEvent const& collision, TAssoc const& groupedTrackIndices, TTracks const& tracks, float* values = nullptr); template static void FillTwoEvents(T const& event1, T const& event2, float* values = nullptr); template @@ -889,6 +913,10 @@ class VarManager : public TObject static void FillGlobalMuonRefit(T1 const& muontrack, T2 const& mfttrack, const C& collision, float* values = nullptr); template static void FillPair(T1 const& t1, T2 const& t2, float* values = nullptr); + template + static void FillPairCollision(C const& collision, T1 const& t1, T2 const& t2, float* values = nullptr); + template + static void FillPairCollisionMatCorr(C const& collision, T1 const& t1, T2 const& t2, M const& materialCorr, P const& propagator, float* values = nullptr); template static void FillTriple(T1 const& t1, T2 const& t2, T3 const& t3, float* values = nullptr, PairCandidateType pairType = kTripleCandidateToEEPhoton); template @@ -918,6 +946,8 @@ class VarManager : public TObject template static void FillQVectorFromCentralFW(C const& collision, float* values = nullptr); template + static void FillNewQVectorFromCentralFW(C const& collision, float* values = nullptr); + template static void FillSpectatorPlane(C const& collision, float* values = nullptr); template static void FillPairVn(T1 const& t1, T2 const& t2, float* values = nullptr); @@ -964,6 +994,12 @@ class VarManager : public TObject fgITSROFBorderMarginHigh = marginHigh; } + static void SetSORandEOR(uint64_t sor, uint64_t eor) + { + fgSOR = sor; + fgEOR = eor; + } + public: VarManager(); ~VarManager() override; @@ -987,6 +1023,8 @@ class VarManager : public TObject static int fgITSROFlength; // ITS ROF length (from ALPIDE parameters) static int fgITSROFBorderMarginLow; // ITS ROF border low margin static int fgITSROFBorderMarginHigh; // ITS ROF border high margin + static uint64_t fgSOR; // Timestamp for start of run + static uint64_t fgEOR; // Timestamp for end of run static void FillEventDerived(float* values = nullptr); static void FillTrackDerived(float* values = nullptr); @@ -1253,11 +1291,12 @@ void VarManager::FillBC(T const& bc, float* values) if (!values) { values = fgValues; } - values[VarManager::kRunNo] = bc.runNumber(); - values[VarManager::kBC] = bc.globalBC(); + values[kRunNo] = bc.runNumber(); + values[kBC] = bc.globalBC(); values[kBCOrbit] = bc.globalBC() % o2::constants::lhc::LHCMaxBunches; - values[VarManager::kTimestamp] = bc.timestamp(); - values[VarManager::kRunIndex] = GetRunIndex(bc.runNumber()); + values[kTimestamp] = bc.timestamp(); + values[kTimeFromSOR] = (fgSOR > 0 ? (bc.timestamp() - fgSOR) / 60000. : -1.0); + values[kRunIndex] = GetRunIndex(bc.runNumber()); } template @@ -1294,7 +1333,7 @@ void VarManager::FillEvent(T const& event, float* values) values[kIsVertexTOFmatched] = event.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); } if (fgUsedVars[kIsSel8]) { - values[kIsSel8] = event.selection_bit(o2::aod::evsel::kIsTriggerTVX); + values[kIsSel8] = event.selection_bit(o2::aod::evsel::kIsTriggerTVX) && event.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && event.selection_bit(o2::aod::evsel::kNoTimeFrameBorder); } if (fgUsedVars[kIsINT7]) { values[kIsINT7] = (event.alias_bit(kINT7) > 0); @@ -1414,7 +1453,7 @@ void VarManager::FillEvent(T const& event, float* values) values[kIsVertexTOFmatched] = (event.selection_bit(o2::aod::evsel::kIsVertexTOFmatched) > 0); } if (fgUsedVars[kIsSel8]) { - values[kIsSel8] = (event.selection_bit(o2::aod::evsel::kIsTriggerTVX) > 0); + values[kIsSel8] = event.selection_bit(o2::aod::evsel::kIsTriggerTVX) && event.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && event.selection_bit(o2::aod::evsel::kNoITSROFrameBorder); } if (fgUsedVars[kIsDoubleGap]) { values[kIsDoubleGap] = (event.tag_bit(56 + kDoubleGap) > 0); @@ -1432,6 +1471,7 @@ void VarManager::FillEvent(T const& event, float* values) values[kBC] = event.globalBC(); values[kBCOrbit] = event.globalBC() % o2::constants::lhc::LHCMaxBunches; values[kTimestamp] = event.timestamp(); + values[kTimeFromSOR] = (fgSOR > 0 ? (event.timestamp() - fgSOR) / 60000. : -1.0); values[kCentVZERO] = event.centRun2V0M(); values[kCentFT0C] = event.centFT0C(); if (fgUsedVars[kIsNoITSROFBorderRecomputed]) { @@ -1588,10 +1628,19 @@ void VarManager::FillEvent(T const& event, float* values) values[kPsi2ANEG] = Psi2ANEG; values[kPsi2B] = Psi2B; values[kPsi2C] = Psi2C; + + values[kR2SP_AB] = (values[kQ2X0A] * values[kQ2X0B] + values[kQ2Y0A] * values[kQ2Y0B]); + values[kR2SP_AC] = (values[kQ2X0A] * values[kQ2X0C] + values[kQ2Y0A] * values[kQ2Y0C]); + values[kR2SP_BC] = (values[kQ2X0B] * values[kQ2X0C] + values[kQ2Y0B] * values[kQ2Y0C]); + + values[kR2EP_AB] = TMath::Cos(2 * (Psi2A - Psi2B)); + values[kR2EP_AC] = TMath::Cos(2 * (Psi2A - Psi2C)); + values[kR2EP_BC] = TMath::Cos(2 * (Psi2B - Psi2C)); } if constexpr ((fillMap & CollisionMC) > 0) { values[kMCEventGeneratorId] = event.generatorsID(); + values[kMCEventSubGeneratorId] = event.getSubGeneratorId(); values[kMCVtxX] = event.posX(); values[kMCVtxY] = event.posY(); values[kMCVtxZ] = event.posZ(); @@ -1602,6 +1651,7 @@ void VarManager::FillEvent(T const& event, float* values) if constexpr ((fillMap & ReducedEventMC) > 0) { values[kMCEventGeneratorId] = event.generatorsID(); + values[kMCEventGeneratorId] = -999; // to be added in reduced events values[kMCVtxX] = event.mcPosX(); values[kMCVtxY] = event.mcPosY(); values[kMCVtxZ] = event.mcPosZ(); @@ -1624,6 +1674,56 @@ void VarManager::FillEvent(T const& event, float* values) FillEventDerived(values); } +template +void VarManager::FillEventTrackEstimators(TEvent const& collision, TAssoc const& assocs, TTracks const& /*tracks*/, float* values) +{ + // Compute median Z for the large dcaZ tracks in the TPC + // This is for studies of the pileup impact on the TPC + + if (!values) { + values = fgValues; + } + + if constexpr ((fillMap & Track) > 0 && (fillMap & TrackDCA) > 0) { + + std::vector tracksP; + std::vector tracksM; + + for (const auto& assoc : assocs) { + auto track = assoc.template track_as(); + // compute the dca of this track wrt the collision + auto trackPar = getTrackPar(track); + std::array dca{1e10f, 1e10f}; + trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, fgMagField, &dca); + + // if it is a displaced track longitudinally, add it to the track vector + if (abs(dca[0]) < 3.0 && abs(dca[1]) > 4.0) { + if (track.tgl() > 0.1) { + tracksP.push_back(track.z()); + } + if (track.tgl() < -0.1) { + tracksM.push_back(track.z()); + } + } + } // end loop over associations + + // compute the number of pileup contributors and the median z for pileup + if (tracksP.size() > 0) { + std::sort(tracksP.begin(), tracksP.end()); + auto midP = tracksP.size() / 2; + values[kNTPCpileupContribA] = tracksP.size(); + values[kNTPCpileupZA] = (tracksP.size() % 2 ? (tracksP[midP] + tracksP[midP - 1]) / 2 : tracksP[midP]); + } + + if (tracksM.size() > 0) { + std::sort(tracksM.begin(), tracksM.end()); + values[kNTPCpileupContribC] = tracksM.size(); + auto midM = tracksM.size() / 2; + values[kNTPCpileupZC] = (tracksM.size() % 2 ? (tracksM[midM] + tracksM[midM - 1]) / 2 : tracksM[midM]); + } + } +} + template void VarManager::FillTwoEvents(T const& ev1, T const& ev2, float* values) { @@ -1688,7 +1788,7 @@ void VarManager::FillTwoMixEvents(T1 const& ev1, T1 const& ev2, T2 const& /*trac values[kQ2Y0A2] = ev2.q2y0a(); } - if (isnan(VarManager::fgValues[VarManager::kTwoR2SP1]) == true || isnan(VarManager::fgValues[VarManager::kTwoR2EP1]) == true) { + if (std::isnan(VarManager::fgValues[VarManager::kTwoR2SP1]) == true || std::isnan(VarManager::fgValues[VarManager::kTwoR2EP1]) == true) { values[kTwoR2SP1] = -999.; values[kTwoR2SP2] = -999.; values[kTwoR2EP1] = -999.; @@ -2164,15 +2264,12 @@ void VarManager::FillTrackCollision(T const& track, C const& collision, float* v } if constexpr ((fillMap & MuonCov) > 0 || (fillMap & ReducedMuonCov) > 0) { - o2::dataformats::GlobalFwdTrack propmuon = PropagateMuon(track, collision); o2::dataformats::GlobalFwdTrack propmuonAtDCA = PropagateMuon(track, collision, kToDCA); float dcaX = (propmuonAtDCA.getX() - collision.posX()); float dcaY = (propmuonAtDCA.getY() - collision.posY()); float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); values[kMuonPDca] = track.p() * dcaXY; - values[kMuonDCAx] = dcaX; - values[kMuonDCAy] = dcaY; } } @@ -2328,12 +2425,24 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) values[kMass] = v12.M(); values[kPt] = v12.Pt(); values[kEta] = v12.Eta(); - values[kPhi] = v12.Phi(); + // values[kPhi] = v12.Phi(); + values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; values[kRap] = -v12.Rapidity(); double Ptot1 = TMath::Sqrt(v1.Px() * v1.Px() + v1.Py() * v1.Py() + v1.Pz() * v1.Pz()); double Ptot2 = TMath::Sqrt(v2.Px() * v2.Px() + v2.Py() * v2.Py() + v2.Pz() * v2.Pz()); values[kDeltaPtotTracks] = Ptot1 - Ptot2; + if (fgUsedVars[kDeltaPhiPair2]) { + double phipair2 = v1.Phi() - v2.Phi(); + if (phipair2 > 3 * TMath::Pi() / 2) { + values[kDeltaPhiPair2] = phipair2 - 2 * TMath::Pi(); + } else if (phipair2 < -TMath::Pi() / 2) { + values[kDeltaPhiPair2] = phipair2 + 2 * TMath::Pi(); + } else { + values[kDeltaPhiPair2] = phipair2; + } + } + if (fgUsedVars[kPsiPair]) { values[kDeltaPhiPair] = (t1.sign() * fgMagField > 0.) ? (v1.Phi() - v2.Phi()) : (v2.Phi() - v1.Phi()); double xipair = TMath::ACos((v1.Px() * v2.Px() + v1.Py() * v2.Py() + v1.Pz() * v2.Pz()) / v1.P() / v2.P()); @@ -2443,6 +2552,116 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) } } +template +void VarManager::FillPairCollision(const C& collision, T1 const& t1, T2 const& t2, float* values) +{ + if (!values) { + values = fgValues; + } + + if constexpr ((pairType == kDecayToEE) && ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0)) { + + if (fgUsedVars[kQuadDCAabsXY] || fgUsedVars[kQuadDCAsigXY] || fgUsedVars[kQuadDCAabsZ] || fgUsedVars[kQuadDCAsigZ] || fgUsedVars[kQuadDCAsigXYZ] || fgUsedVars[kSignQuadDCAsigXY]) { + + auto trackPart1 = getTrackPar(t1); + std::array dca1{1e10f, 1e10f}; + trackPart1.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, fgMagField, &dca1); + + auto trackPart2 = getTrackPar(t2); + std::array dca2{1e10f, 1e10f}; + trackPart2.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, fgMagField, &dca2); + + // Recalculated quantities + double dca1XY = dca1[0]; + double dca2XY = dca2[0]; + double dca1Z = dca1[1]; + double dca2Z = dca2[1]; + double dca1sigXY = dca1XY / std::sqrt(t1.cYY()); + double dca2sigXY = dca2XY / std::sqrt(t2.cYY()); + double dca1sigZ = dca1Z / std::sqrt(t1.cZZ()); + double dca2sigZ = dca2Z / std::sqrt(t2.cZZ()); + + values[kQuadDCAabsXY] = std::sqrt((dca1XY * dca1XY + dca2XY * dca2XY) / 2); + values[kQuadDCAsigXY] = std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); + values[kQuadDCAabsZ] = std::sqrt((dca1Z * dca1Z + dca2Z * dca2Z) / 2); + values[kQuadDCAsigZ] = std::sqrt((dca1sigZ * dca1sigZ + dca2sigZ * dca2sigZ) / 2); + values[kSignQuadDCAsigXY] = t1.sign() * t2.sign() * TMath::Sign(1., dca1sigXY) * TMath::Sign(1., dca2sigXY) * std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); + + double det1 = t1.cYY() * t1.cZZ() - t1.cZY() * t1.cZY(); + double det2 = t2.cYY() * t2.cZZ() - t2.cZY() * t2.cZY(); + if ((det1 < 0) || (det2 < 0)) { + values[kQuadDCAsigXYZ] = -999; + } else { + double chi2t1 = (dca1XY * dca1XY * t1.cZZ() + dca1Z * dca1Z * t1.cYY() - 2. * dca1XY * dca1Z * t1.cZY()) / det1; + double chi2t2 = (dca2XY * dca2XY * t2.cZZ() + dca2Z * dca2Z * t2.cYY() - 2. * dca2XY * dca2Z * t2.cZY()) / det2; + + double dca1sigXYZ = std::sqrt(std::abs(chi2t1) / 2.); + double dca2sigXYZ = std::sqrt(std::abs(chi2t2) / 2.); + + values[kQuadDCAsigXYZ] = std::sqrt((dca1sigXYZ * dca1sigXYZ + dca2sigXYZ * dca2sigXYZ) / 2); + } + } + } +} + +template +void VarManager::FillPairCollisionMatCorr(C const& collision, T1 const& t1, T2 const& t2, M const& materialCorr, P const& propagator, float* values) +{ + if (!values) { + values = fgValues; + } + + if constexpr ((pairType == kDecayToEE) && ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0)) { + + if (fgUsedVars[kQuadDCAabsXY] || fgUsedVars[kQuadDCAsigXY] || fgUsedVars[kQuadDCAabsZ] || fgUsedVars[kQuadDCAsigZ] || fgUsedVars[kQuadDCAsigXYZ] || fgUsedVars[kSignQuadDCAsigXY]) { + + auto trackPart1 = getTrackPar(t1); + std::array dca1{1e10f, 1e10f}; + std::array pVect1 = {t1.px(), t1.py(), t1.pz()}; + // trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, fgMagField, &dca); + propagator->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackPart1, 2.f, materialCorr, &dca1); + getPxPyPz(trackPart1, pVect1); + + auto trackPart2 = getTrackPar(t2); + std::array dca2{1e10f, 1e10f}; + std::array pVect2 = {t2.px(), t2.py(), t2.pz()}; + // trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, fgMagField, &dca); + propagator->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackPart2, 2.f, materialCorr, &dca2); + getPxPyPz(trackPart2, pVect2); + + // Recalculated quantities + double dca1XY = dca1[0]; + double dca2XY = dca2[0]; + double dca1Z = dca1[1]; + double dca2Z = dca2[1]; + double dca1sigXY = dca1XY / std::sqrt(t1.cYY()); + double dca2sigXY = dca2XY / std::sqrt(t2.cYY()); + double dca1sigZ = dca1Z / std::sqrt(t1.cZZ()); + double dca2sigZ = dca2Z / std::sqrt(t2.cZZ()); + + values[kQuadDCAabsXY] = std::sqrt((dca1XY * dca1XY + dca2XY * dca2XY) / 2); + values[kQuadDCAsigXY] = std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); + values[kQuadDCAabsZ] = std::sqrt((dca1Z * dca1Z + dca2Z * dca2Z) / 2); + values[kQuadDCAsigZ] = std::sqrt((dca1sigZ * dca1sigZ + dca2sigZ * dca2sigZ) / 2); + values[kSignQuadDCAsigXY] = t1.sign() * t2.sign() * TMath::Sign(1., dca1sigXY) * TMath::Sign(1., dca2sigXY) * std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); + + double det1 = t1.cYY() * t1.cZZ() - t1.cZY() * t1.cZY(); + double det2 = t2.cYY() * t2.cZZ() - t2.cZY() * t2.cZY(); + if ((det1 < 0) || (det2 < 0)) { + values[kQuadDCAsigXYZ] = -999; + } else { + double chi2t1 = (dca1XY * dca1XY * t1.cZZ() + dca1Z * dca1Z * t1.cYY() - 2. * dca1XY * dca1Z * t1.cZY()) / det1; + double chi2t2 = (dca2XY * dca2XY * t2.cZZ() + dca2Z * dca2Z * t2.cYY() - 2. * dca2XY * dca2Z * t2.cZY()) / det2; + + double dca1sigXYZ = std::sqrt(std::abs(chi2t1) / 2.); + double dca2sigXYZ = std::sqrt(std::abs(chi2t2) / 2.); + + values[kQuadDCAsigXYZ] = std::sqrt((dca1sigXYZ * dca1sigXYZ + dca2sigXYZ * dca2sigXYZ) / 2); + } + } + } +} + template void VarManager::FillTriple(T1 const& t1, T2 const& t2, T3 const& t3, float* values, PairCandidateType pairType) { @@ -2543,7 +2762,8 @@ void VarManager::FillPairME(T1 const& t1, T2 const& t2, float* values) values[kMass] = v12.M(); values[kPt] = v12.Pt(); values[kEta] = v12.Eta(); - values[kPhi] = v12.Phi(); + // values[kPhi] = v12.Phi(); + values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; values[kRap] = -v12.Rapidity(); // TODO: provide different computations for vn @@ -2701,14 +2921,7 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, t2.c1PtX(), t2.c1PtY(), t2.c1PtPhi(), t2.c1PtTgl(), t2.c1Pt21Pt2()}; SMatrix55 t2covs(v2.begin(), v2.end()); o2::track::TrackParCovFwd pars2{t2.z(), t2pars, t2covs, chi22}; - if (std::abs(t2.cXX()) < 1.0e-6) { - // TODO: Some rare fwd-tracks have very small covariances and the DCAFitter throws a fatal! - // This is a protection, but please check for the reason and eventually change the behaviour. - // At the moment, when these tracks are encountered, the vertexing quantities are initialized to default values (-999) - procCode = 0; - } else { - procCode = fgFitterTwoProngFwd.process(pars1, pars2); - } + procCode = fgFitterTwoProngFwd.process(pars1, pars2); } else { return; } @@ -3030,7 +3243,8 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, values[kMass] = v12.M(); values[kPt] = v12.Pt(); values[kEta] = v12.Eta(); - values[kPhi] = v12.Phi(); + // values[kPhi] = v12.Phi(); + values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; } else { values[kPt1] = t1.pt(); values[kEta1] = t1.eta(); @@ -3635,13 +3849,13 @@ void VarManager::FillQVectorFromCentralFW(C const& collision, float* values) float yQVecFT0m = collision.qvecFT0MIm(); // already normalised float xQVecFV0a = collision.qvecFV0ARe(); // already normalised float yQVecFV0a = collision.qvecFV0AIm(); // already normalised - float xQVecBPos = collision.qvecBPosRe(); // already normalised - float yQVecBPos = collision.qvecBPosIm(); // already normalised - float xQVecBNeg = collision.qvecBNegRe(); // already normalised - float yQVecBNeg = collision.qvecBNegIm(); // already normalised + float xQVecBPos = collision.qvecTPCposRe(); // already normalised + float yQVecBPos = collision.qvecTPCposIm(); // already normalised + float xQVecBNeg = collision.qvecTPCnegRe(); // already normalised + float yQVecBNeg = collision.qvecTPCnegIm(); // already normalised - values[kQ2X0A] = (collision.nTrkBPos() * xQVecBPos + collision.nTrkBNeg() * xQVecBNeg) / (collision.nTrkBPos() + collision.nTrkBNeg()); - values[kQ2Y0A] = (collision.nTrkBPos() * yQVecBPos + collision.nTrkBNeg() * yQVecBNeg) / (collision.nTrkBPos() + collision.nTrkBNeg()); + values[kQ2X0A] = collision.qvecTPCallRe(); + values[kQ2Y0A] = collision.qvecTPCallIm(); values[kQ2X0APOS] = xQVecBPos; values[kQ2Y0APOS] = yQVecBPos; values[kQ2X0ANEG] = xQVecBNeg; @@ -3650,9 +3864,9 @@ void VarManager::FillQVectorFromCentralFW(C const& collision, float* values) values[kQ2Y0B] = yQVecFT0a; values[kQ2X0C] = xQVecFT0c; values[kQ2Y0C] = yQVecFT0c; - values[kMultA] = collision.nTrkBPos() + collision.nTrkBNeg(); - values[kMultAPOS] = collision.nTrkBPos(); - values[kMultANEG] = collision.nTrkBNeg(); + values[kMultA] = collision.nTrkTPCpos() + collision.nTrkTPCneg(); + values[kMultAPOS] = collision.nTrkTPCpos(); + values[kMultANEG] = collision.nTrkTPCneg(); values[kMultB] = collision.sumAmplFT0A(); // Be careful, this is weighted sum of multiplicity values[kMultC] = collision.sumAmplFT0C(); // Be careful, this is weighted sum of multiplicity @@ -3735,6 +3949,26 @@ void VarManager::FillSpectatorPlane(C const& collision, float* values) } float znaCommon = collision.energyCommonZNA() < 0 ? -1.f : collision.energyCommonZNA(); float zncCommon = collision.energyCommonZNC() < 0 ? -1.f : collision.energyCommonZNC(); + float zpaCommon = collision.energyCommonZPA() < 0 ? -1.f : collision.energyCommonZPA(); + float zpcCommon = collision.energyCommonZPC() < 0 ? -1.f : collision.energyCommonZPC(); + + // Store ZNA and ZNC energies for calibrations + values[kEnergyCommonZNA] = znaCommon; + values[kEnergyCommonZNC] = zncCommon; + values[kEnergyCommonZPA] = zpaCommon; + values[kEnergyCommonZPC] = zpcCommon; + values[kEnergyZNA1] = znaEnergy[0]; + values[kEnergyZNA2] = znaEnergy[1]; + values[kEnergyZNA3] = znaEnergy[2]; + values[kEnergyZNA4] = znaEnergy[3]; + values[kEnergyZNC1] = zncEnergy[0]; + values[kEnergyZNC2] = zncEnergy[1]; + values[kEnergyZNC3] = zncEnergy[2]; + values[kEnergyZNC4] = zncEnergy[3]; + values[kTimeZNA] = collision.timeZNA(); + values[kTimeZNC] = collision.timeZNC(); + values[kTimeZPA] = collision.timeZPA(); + values[kTimeZPC] = collision.timeZPC(); constexpr float beamEne = 5.36 * 0.5; constexpr float x[4] = {-1.75, 1.75, -1.75, 1.75}; @@ -3858,23 +4092,23 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values[kCos2DeltaPhiMu1] = std::cos(2 * (v1.Phi() - v12.Phi())); values[kCos2DeltaPhiMu2] = std::cos(2 * (v2.Phi() - v12.Phi())); - if (isnan(VarManager::fgValues[VarManager::kU2Q2]) == true) { + if (std::isnan(VarManager::fgValues[VarManager::kU2Q2]) == true) { values[kU2Q2] = -999.; values[kR2SP_AB] = -999.; values[kR2SP_AC] = -999.; values[kR2SP_BC] = -999.; } - if (isnan(VarManager::fgValues[VarManager::kU3Q3]) == true) { + if (std::isnan(VarManager::fgValues[VarManager::kU3Q3]) == true) { values[kU3Q3] = -999.; values[kR3SP] = -999.; } - if (isnan(VarManager::fgValues[VarManager::kCos2DeltaPhi]) == true) { + if (std::isnan(VarManager::fgValues[VarManager::kCos2DeltaPhi]) == true) { values[kCos2DeltaPhi] = -999.; values[kR2EP_AB] = -999.; values[kR2EP_AC] = -999.; values[kR2EP_BC] = -999.; } - if (isnan(VarManager::fgValues[VarManager::kCos3DeltaPhi]) == true) { + if (std::isnan(VarManager::fgValues[VarManager::kCos3DeltaPhi]) == true) { values[kCos3DeltaPhi] = -999.; values[kR3EP] = -999.; } @@ -3889,6 +4123,14 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values[kM0111POI] = values[kMultDimuons] * (values[kS31A] - 3. * values[kS11A] * values[kS12A] + 2. * values[kS13A]); values[kCORR2POI] = (P2 * conj(Q21)).real() / values[kM01POI]; values[kCORR4POI] = (P2 * Q21 * conj(Q21) * conj(Q21) - P2 * Q21 * conj(Q42) - 2. * values[kS12A] * P2 * conj(Q21) + 2. * P2 * conj(Q23)).real() / values[kM0111POI]; + values[kM01POIoverMp] = values[kMultDimuons] > 0 && !(std::isnan(values[kM01POI]) || std::isinf(values[kM01POI])) ? values[kM01POI] / values[kMultDimuons] : 0; + values[kM0111POIoverMp] = values[kMultDimuons] > 0 && !(std::isnan(values[kM0111POI]) || std::isinf(values[kM0111POI])) ? values[kM0111POI] / values[kMultDimuons] : 0; + values[kM11REFoverMp] = values[kMultDimuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF])) ? values[kM11REF] / values[kMultDimuons] : 0; + values[kM1111REFoverMp] = values[kMultDimuons] > 0 && !(std::isnan(values[kM1111REF]) || std::isinf(values[kM1111REF])) ? values[kM1111REF] / values[kMultDimuons] : 0; + values[kCORR2POIMp] = std::isnan(values[kCORR2POI]) || std::isinf(values[kCORR2POI]) ? 0 : values[kCORR2POI] * values[kMultDimuons]; + values[kCORR4POIMp] = std::isnan(values[kCORR4POI]) || std::isinf(values[kCORR4POI]) ? 0 : values[kCORR4POI] * values[kMultDimuons]; + values[kCORR2REF] = std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) ? 0 : values[kCORR2REF]; + values[kCORR4REF] = std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF]) ? 0 : values[kCORR4REF]; } } @@ -4036,16 +4278,16 @@ void VarManager::FillDileptonTrackTrack(T1 const& dilepton, T2 const& hadron1, T values = fgValues; } - double DefaultdileptonMass = 3.096; + double defaultDileptonMass = 3.096; double hadronMass1 = o2::constants::physics::MassPionCharged; double hadronMass2 = o2::constants::physics::MassPionCharged; if (candidateType == kXtoJpsiPiPi) { - DefaultdileptonMass = 3.096; + defaultDileptonMass = 3.096; hadronMass1 = o2::constants::physics::MassPionCharged; hadronMass2 = o2::constants::physics::MassPionCharged; } if (candidateType == kChictoJpsiEE) { - DefaultdileptonMass = 3.096; + defaultDileptonMass = 3.096; hadronMass1 = o2::constants::physics::MassElectron; hadronMass2 = o2::constants::physics::MassElectron; } @@ -4054,18 +4296,31 @@ void VarManager::FillDileptonTrackTrack(T1 const& dilepton, T2 const& hadron1, T ROOT::Math::PtEtaPhiMVector v2(hadron1.pt(), hadron1.eta(), hadron1.phi(), hadronMass1); ROOT::Math::PtEtaPhiMVector v3(hadron2.pt(), hadron2.eta(), hadron2.phi(), hadronMass2); ROOT::Math::PtEtaPhiMVector v123 = v1 + v2 + v3; - values[kQuadMass] = v123.M() - v1.M() + DefaultdileptonMass; + values[kQuadMass] = v123.M(); + values[kQuadDefaultDileptonMass] = v123.M() - v1.M() + defaultDileptonMass; values[kQuadPt] = v123.Pt(); values[kQuadEta] = v123.Eta(); values[kQuadPhi] = v123.Phi(); - if (fgUsedVars[kCosthetaDileptonDitrack] || fgUsedVars[kPairMass] || fgUsedVars[kPairPt] || fgUsedVars[kDitrackPt] || fgUsedVars[kDitrackMass]) { + values[kTrackDCAxyProng1] = hadron1.dcaXY(); + values[kTrackDCAzProng1] = hadron1.dcaZ(); + values[kPt1] = hadron1.pt(); + + values[kTrackDCAxyProng2] = hadron2.dcaXY(); + values[kTrackDCAzProng2] = hadron2.dcaZ(); + values[kPt2] = hadron2.pt(); + + if (fgUsedVars[kCosthetaDileptonDitrack] || fgUsedVars[kPairMass] || fgUsedVars[kPairPt] || fgUsedVars[kDitrackPt] || fgUsedVars[kDitrackMass] || fgUsedVars[kQ] || fgUsedVars[kDeltaR1] || fgUsedVars[kDeltaR2] || fgUsedVars[kRap]) { ROOT::Math::PtEtaPhiMVector v23 = v2 + v3; values[kPairMass] = v1.M(); values[kPairPt] = v1.Pt(); values[kDitrackMass] = v23.M(); values[kDitrackPt] = v23.Pt(); values[kCosthetaDileptonDitrack] = (v1.Px() * v123.Px() + v1.Py() * v123.Py() + v1.Pz() * v123.Pz()) / (v1.P() * v123.P()); + values[kQ] = v123.M() - defaultDileptonMass - v23.M(); + values[kDeltaR1] = sqrt(pow(v1.Eta() - v2.Eta(), 2) + pow(v1.Phi() - v2.Phi(), 2)); + values[kDeltaR2] = sqrt(pow(v1.Eta() - v3.Eta(), 2) + pow(v1.Phi() - v3.Phi(), 2)); + values[kRap] = v123.Rapidity(); } } diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 27e4ee5bb7a..ba3add306c7 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -40,6 +40,7 @@ namespace reducedevent { // basic event information +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_BITMAP_COLUMN(Tag, tag, 64); //! Bit-field for storing event information (e.g. high level info, cut decisions) DECLARE_SOA_COLUMN(MCPosX, mcPosX, float); //! MC event position X DECLARE_SOA_COLUMN(MCPosY, mcPosY, float); //! MC event position Y @@ -51,6 +52,17 @@ DECLARE_SOA_COLUMN(NTPCpileupZC, nTPCpileupZC, float); //! Median Z p DECLARE_SOA_COLUMN(NTPCtracksInPast, nTPCtracksInPast, int); //! Number of TPC tracks in the past events (configurable, but e.g. one drift time) DECLARE_SOA_COLUMN(NTPCtracksInFuture, nTPCtracksInFuture, int); //! Number of TPC tracks in the future events (configurable, but e.g. one drift time) +// Columns declared to guarantee the backward compatibility of the tables +DECLARE_SOA_COLUMN(QvecBPosRe, qvecBPosRe, float); +DECLARE_SOA_COLUMN(QvecBPosIm, qvecBPosIm, float); +DECLARE_SOA_COLUMN(QvecBNegRe, qvecBNegRe, float); +DECLARE_SOA_COLUMN(QvecBNegIm, qvecBNegIm, float); +DECLARE_SOA_COLUMN(QvecBAllRe, qvecBAllRe, float); +DECLARE_SOA_COLUMN(QvecBAllIm, qvecBAllIm, float); +DECLARE_SOA_COLUMN(NTrkBPos, nTrkBPos, int); +DECLARE_SOA_COLUMN(NTrkBNeg, nTrkBNeg, int); +DECLARE_SOA_COLUMN(NTrkBAll, nTrkBAll, int); + DECLARE_SOA_COLUMN(Q1ZNAX, q1znax, float); //! Q-vector x component, evaluated with ZNA (harmonic 1 and power 1) DECLARE_SOA_COLUMN(Q1ZNAY, q1znay, float); //! Q-vector y component, evaluated with ZNA (harmonic 1 and power 1) DECLARE_SOA_COLUMN(Q1ZNCX, q1zncx, float); //! Q-vector x component, evaluated with ZNC (harmonic 1 and power 1) @@ -102,6 +114,13 @@ DECLARE_SOA_TABLE(ReducedEvents, "AOD", "REDUCEDEVENT", //! Main event informa collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, collision::CollisionTime, collision::CollisionTimeRes); +DECLARE_SOA_TABLE(StoredReducedEvents, "AOD1", "REDUCEDEVENT", //! Main event information table + o2::soa::Index<>, + reducedevent::Tag, bc::RunNumber, + collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, + collision::CollisionTime, collision::CollisionTimeRes, + o2::soa::Marker<1>); + DECLARE_SOA_TABLE(ReducedEventsExtended, "AOD", "REEXTENDED", //! Extended event information bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, cent::CentRun2V0M, mult::MultTPC, mult::MultFV0A, mult::MultFV0C, mult::MultFT0A, mult::MultFT0C, @@ -134,8 +153,11 @@ DECLARE_SOA_TABLE(ReducedEventsQvectorExtra, "AOD", "REQVECTOREXTRA", //! Eve reducedevent::S11A, reducedevent::S12A, reducedevent::S13A, reducedevent::S31A); DECLARE_SOA_TABLE(ReducedEventsQvectorCentr, "AOD", "REQVECTORCTR", //! Event Q-vector information from central framework - qvec::QvecFT0ARe, qvec::QvecFT0AIm, qvec::QvecFT0CRe, qvec::QvecFT0CIm, qvec::QvecFT0MRe, qvec::QvecFT0MIm, qvec::QvecFV0ARe, qvec::QvecFV0AIm, qvec::QvecBPosRe, qvec::QvecBPosIm, qvec::QvecBNegRe, qvec::QvecBNegIm, - qvec::SumAmplFT0A, qvec::SumAmplFT0C, qvec::SumAmplFT0M, qvec::SumAmplFV0A, qvec::NTrkBPos, qvec::NTrkBNeg); + qvec::QvecFT0ARe, qvec::QvecFT0AIm, qvec::QvecFT0CRe, qvec::QvecFT0CIm, qvec::QvecFT0MRe, qvec::QvecFT0MIm, qvec::QvecFV0ARe, qvec::QvecFV0AIm, reducedevent::QvecBPosRe, reducedevent::QvecBPosIm, reducedevent::QvecBNegRe, reducedevent::QvecBNegIm, + qvec::SumAmplFT0A, qvec::SumAmplFT0C, qvec::SumAmplFT0M, qvec::SumAmplFV0A, reducedevent::NTrkBPos, reducedevent::NTrkBNeg); + +DECLARE_SOA_TABLE(ReducedEventsQvectorCentrExtra, "AOD", "REQVECCTREXTA", //! Event Q-vector information from central framework with TPC all + reducedevent::QvecBAllRe, reducedevent::QvecBAllIm, reducedevent::NTrkBAll); DECLARE_SOA_TABLE(ReducedEventsRefFlow, "AOD", "REREFFLOW", //! Event Ref Flow information reducedevent::M11REF, reducedevent::M1111REF, reducedevent::CORR2REF, reducedevent::CORR4REF, cent::CentFT0C); @@ -143,6 +165,9 @@ DECLARE_SOA_TABLE(ReducedEventsRefFlow, "AOD", "REREFFLOW", //! Event Ref Flo DECLARE_SOA_TABLE(ReducedEventsQvectorZN, "AOD", "REQVECTORZN", //! Event Q-vector information from ZNs detectors reducedevent::Q1ZNAX, reducedevent::Q1ZNAY, reducedevent::Q1ZNCX, reducedevent::Q1ZNCY); +DECLARE_SOA_TABLE(ReducedEventsInfo, "AOD", "REDUCEVENTINFO", //! Main event index table + reducedevent::CollisionId); + // TODO and NOTE: This table is just an extension of the ReducedEvents table // There is no explicit accounting for MC events which were not reconstructed!!! // However, for analysis which will require these events, a special skimming process function @@ -153,6 +178,7 @@ DECLARE_SOA_TABLE(ReducedMCEvents, "AOD", "REDUCEDMCEVENT", //! Event level MC mccollision::T, mccollision::Weight, mccollision::ImpactParameter); using ReducedEvent = ReducedEvents::iterator; +using StoredReducedEvent = StoredReducedEvents::iterator; using ReducedEventExtended = ReducedEventsExtended::iterator; using ReducedEventVtxCov = ReducedEventsVtxCov::iterator; using ReducedEventMultPV = ReducedEventsMultPV::iterator; @@ -160,6 +186,7 @@ using ReducedEventMultAll = ReducedEventsMultAll::iterator; using ReducedEventQvector = ReducedEventsQvector::iterator; using ReducedEventQvectorExtra = ReducedEventsQvectorExtra::iterator; using ReducedEventQvectorCentr = ReducedEventsQvectorCentr::iterator; +using ReducedEventQvectorCentrExtra = ReducedEventsQvectorCentrExtra::iterator; using ReducedEventRefFlow = ReducedEventsRefFlow::iterator; using ReducedEventQvectorZN = ReducedEventsQvectorZN::iterator; using ReducedMCEvent = ReducedMCEvents::iterator; @@ -180,6 +207,14 @@ DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); //! DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); //! DECLARE_SOA_COLUMN(EnergyCommonZPA, energyCommonZPA, float); //! DECLARE_SOA_COLUMN(EnergyCommonZPC, energyCommonZPC, float); //! +DECLARE_SOA_COLUMN(EnergyZNA1, energyZNA1, float); //! +DECLARE_SOA_COLUMN(EnergyZNA2, energyZNA2, float); //! +DECLARE_SOA_COLUMN(EnergyZNA3, energyZNA3, float); //! +DECLARE_SOA_COLUMN(EnergyZNA4, energyZNA4, float); //! +DECLARE_SOA_COLUMN(EnergyZNC1, energyZNC1, float); //! +DECLARE_SOA_COLUMN(EnergyZNC2, energyZNC2, float); //! +DECLARE_SOA_COLUMN(EnergyZNC3, energyZNC3, float); //! +DECLARE_SOA_COLUMN(EnergyZNC4, energyZNC4, float); //! DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); //! DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); //! DECLARE_SOA_COLUMN(TimeZPA, timeZPA, float); //! @@ -192,12 +227,18 @@ DECLARE_SOA_TABLE(ReducedZdcs, "AOD", "REDUCEDZDC", //! Event ZDC information reducedzdc::TimeZNA, reducedzdc::TimeZNC, reducedzdc::TimeZPA, reducedzdc::TimeZPC); +DECLARE_SOA_TABLE(ReducedZdcsExtra, "AOD", "REDUCEDZDCEXTRA", //! Event ZDC extra information + reducedzdc::EnergyZNA1, reducedzdc::EnergyZNA2, reducedzdc::EnergyZNA3, reducedzdc::EnergyZNA4, + reducedzdc::EnergyZNC1, reducedzdc::EnergyZNC2, reducedzdc::EnergyZNC3, reducedzdc::EnergyZNC4); + using ReducedZdc = ReducedZdcs::iterator; +using ReducedZdcExtra = ReducedZdcsExtra::iterator; namespace reducedtrack { // basic track information DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); //! +DECLARE_SOA_INDEX_COLUMN(Track, track); //! // ---- flags reserved for storing various information during filtering DECLARE_SOA_BITMAP_COLUMN(FilteringFlags, filteringFlags, 64); //! // ----------------------------------------------------- @@ -272,7 +313,7 @@ DECLARE_SOA_TABLE(ReducedTracksBarrelPID, "AOD", "RTBARRELPID", //! // barrel collision information (joined with ReducedTracks) allowing to connect different tables (cross PWGs) DECLARE_SOA_TABLE(ReducedTracksBarrelInfo, "AOD", "RTBARRELINFO", - reducedtrack::CollisionId, collision::PosX, collision::PosY, collision::PosZ); + reducedtrack::CollisionId, collision::PosX, collision::PosY, collision::PosZ, reducedtrack::TrackId); using ReducedTrack = ReducedTracks::iterator; using ReducedTrackBarrel = ReducedTracksBarrel::iterator; @@ -314,24 +355,24 @@ DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! Particle rapidity } // namespace reducedtrackMC // NOTE: This table is nearly identical to the one from Framework (except that it points to the event ID, not the BC id) // This table contains all MC truth tracks (both barrel and muon) -DECLARE_SOA_TABLE_FULL(ReducedMCTracks, "ReducedMCTracks", "AOD", "REDUCEDMCTRACK", //! MC track information (on disk) - o2::soa::Index<>, reducedtrackMC::ReducedMCEventId, - mcparticle::PdgCode, mcparticle::StatusCode, mcparticle::Flags, - reducedtrackMC::MothersIds, reducedtrackMC::DaughtersIdSlice, - mcparticle::Weight, - reducedtrackMC::Pt, reducedtrackMC::Eta, reducedtrackMC::Phi, reducedtrackMC::E, - mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, - reducedtrackMC::McReducedFlags, - reducedtrackMC::Px, - reducedtrackMC::Py, - reducedtrackMC::Pz, - reducedtrackMC::P, - reducedtrackMC::Y, - mcparticle::ProducedByGenerator, - mcparticle::FromBackgroundEvent, - mcparticle::GetGenStatusCode, - mcparticle::GetProcess, - mcparticle::IsPhysicalPrimary); +DECLARE_SOA_TABLE(ReducedMCTracks, "AOD", "REDUCEDMCTRACK", //! MC track information (on disk) + o2::soa::Index<>, reducedtrackMC::ReducedMCEventId, + mcparticle::PdgCode, mcparticle::StatusCode, mcparticle::Flags, + reducedtrackMC::MothersIds, reducedtrackMC::DaughtersIdSlice, + mcparticle::Weight, + reducedtrackMC::Pt, reducedtrackMC::Eta, reducedtrackMC::Phi, reducedtrackMC::E, + mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, + reducedtrackMC::McReducedFlags, + reducedtrackMC::Px, + reducedtrackMC::Py, + reducedtrackMC::Pz, + reducedtrackMC::P, + reducedtrackMC::Y, + mcparticle::ProducedByGenerator, + mcparticle::FromBackgroundEvent, + mcparticle::GetGenStatusCode, + mcparticle::GetProcess, + mcparticle::IsPhysicalPrimary); using ReducedMCTrack = ReducedMCTracks::iterator; @@ -365,9 +406,9 @@ DECLARE_SOA_COLUMN(MftNClusters, mftNClusters, int); } // namespace reducedmft // MFT track kinematics -DECLARE_SOA_TABLE_FULL(ReducedMFTs, "ReducedMFTs", "AOD", "REDUCEDMFT", //! - o2::soa::Index<>, reducedmft::ReducedEventId, reducedmft::FilteringFlags, - reducedmft::Pt, reducedmft::Eta, reducedmft::Phi); +DECLARE_SOA_TABLE(ReducedMFTs, "AOD", "REDUCEDMFT", //! + o2::soa::Index<>, reducedmft::ReducedEventId, reducedmft::FilteringFlags, + reducedmft::Pt, reducedmft::Eta, reducedmft::Phi); // MFT tracks extra info (cluster size, sign) DECLARE_SOA_TABLE(ReducedMFTsExtra, "AOD", "RMFTEXTRA", //! @@ -413,15 +454,15 @@ DECLARE_SOA_INDEX_COLUMN(ReducedMFT, matchMFTTrack); //! matching index pointin } // namespace reducedmuon // Muon track kinematics -DECLARE_SOA_TABLE_FULL(ReducedMuons, "ReducedMuons", "AOD", "REDUCEDMUON", //! - o2::soa::Index<>, reducedmuon::ReducedEventId, - reducedmuon::MatchMCHTrackId, reducedmuon::ReducedMFTId, - reducedmuon::FilteringFlags, - reducedmuon::Pt, reducedmuon::Eta, reducedmuon::Phi, reducedmuon::Sign, reducedmuon::IsAmbiguous, - reducedmuon::Px, - reducedmuon::Py, - reducedmuon::Pz, - reducedmuon::P); +DECLARE_SOA_TABLE(ReducedMuons, "AOD", "REDUCEDMUON", //! + o2::soa::Index<>, reducedmuon::ReducedEventId, + reducedmuon::MatchMCHTrackId, reducedmuon::ReducedMFTId, + reducedmuon::FilteringFlags, + reducedmuon::Pt, reducedmuon::Eta, reducedmuon::Phi, reducedmuon::Sign, reducedmuon::IsAmbiguous, + reducedmuon::Px, + reducedmuon::Py, + reducedmuon::Pz, + reducedmuon::P); // Muon track quality details DECLARE_SOA_TABLE(ReducedMuonsExtra, "AOD", "RTMUONEXTRA", //! @@ -480,18 +521,6 @@ DECLARE_SOA_TABLE(ReducedMFTAssoc, "AOD", "RMFTASSOC", //! Table for reducemft-t reducedtrack_association::ReducedEventId, reducedtrack_association::ReducedMFTId); -namespace smearedtrack -{ -DECLARE_SOA_COLUMN(PtSmeared, ptSmeared, float); -DECLARE_SOA_COLUMN(EtaSmeared, etaSmeared, float); -DECLARE_SOA_COLUMN(PhiSmeared, phiSmeared, float); -DECLARE_SOA_COLUMN(Efficiency, efficiency, float); -} // namespace smearedtrack - -DECLARE_SOA_TABLE(SmearedTracks, "AOD", "SMEAREDTRACK", // use like this Join - smearedtrack::PtSmeared, smearedtrack::EtaSmeared, smearedtrack::PhiSmeared, smearedtrack::Efficiency); -using SmearedTrack = SmearedTracks::iterator; - namespace dilepton_track_index { DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, ReducedMuons, "_0"); //! Index to first prong @@ -590,6 +619,8 @@ namespace reducedpair DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, ReducedTracks, "_0"); //! Index to first prong DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, ReducedTracks, "_1"); //! Index to second prong +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, Tracks, "_0"); //! Index of first prong in Tracks table +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! Index of second prong in Tracks table DECLARE_SOA_COLUMN(Mass, mass, float); //! DECLARE_SOA_COLUMN(Pt, pt, float); //! DECLARE_SOA_COLUMN(Eta, eta, float); //! @@ -597,6 +628,7 @@ DECLARE_SOA_COLUMN(Phi, phi, float); //! DECLARE_SOA_COLUMN(Sign, sign, int); //! DECLARE_SOA_BITMAP_COLUMN(FilterMap, filterMap, 32); //! DECLARE_SOA_BITMAP_COLUMN(PairFilterMap, pairFilterMap, 32); //! +DECLARE_SOA_BITMAP_COLUMN(CommonFilterMap, commonFilterMap, 32); //! DECLARE_SOA_COLUMN(McDecision, mcDecision, uint32_t); //! DECLARE_SOA_COLUMN(Tauz, tauz, float); //! Longitudinal pseudo-proper time of lepton pair (in ns) DECLARE_SOA_COLUMN(TauzErr, tauzErr, float); //! Error on longitudinal pseudo-proper time of lepton pair (in ns) @@ -657,27 +689,43 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(Rap, rap, //! [](float pt, float eta, float m) -> float { return std::log((std::sqrt(m * m + pt * pt * std::cosh(eta) * std::cosh(eta)) + pt * std::sinh(eta)) / std::sqrt(m * m + pt * pt)); }); +DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! + [](float pt, float eta, float m) -> float { return std::log((std::sqrt(m * m + pt * pt * std::cosh(eta) * std::cosh(eta)) + pt * std::sinh(eta)) / std::sqrt(m * m + pt * pt)); }); } // namespace reducedpair -DECLARE_SOA_TABLE_FULL(Dielectrons, "Dielectrons", "AOD", "RTDIELECTRON", //! - o2::soa::Index<>, reducedpair::ReducedEventId, - reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, - reducedpair::FilterMap, reducedpair::McDecision, - reducedpair::Rap, - reducedpair::Px, - reducedpair::Py, - reducedpair::Pz, - reducedpair::P); - -DECLARE_SOA_TABLE_FULL(Dimuons, "Dimuons", "AOD", "RTDIMUON", //! - o2::soa::Index<>, reducedpair::ReducedEventId, - reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, - reducedpair::FilterMap, reducedpair::McDecision, - reducedpair::Px, - reducedpair::Py, - reducedpair::Pz, - reducedpair::P, - reducedpair::Rap); +DECLARE_SOA_TABLE(Dielectrons, "AOD", "RTDIELECTRON", //! + o2::soa::Index<>, reducedpair::ReducedEventId, + reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, + reducedpair::FilterMap, reducedpair::McDecision, + reducedpair::Rap, + reducedpair::Y, + reducedpair::Px, + reducedpair::Py, + reducedpair::Pz, + reducedpair::P); + +DECLARE_SOA_TABLE(StoredDielectrons, "AOD1", "RTDIELECTRON", //! + o2::soa::Index<>, reducedpair::ReducedEventId, + reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, + reducedpair::FilterMap, reducedpair::McDecision, + reducedpair::Rap, + reducedpair::Y, + reducedpair::Px, + reducedpair::Py, + reducedpair::Pz, + reducedpair::P, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Dimuons, "AOD", "RTDIMUON", //! + o2::soa::Index<>, reducedpair::ReducedEventId, + reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, + reducedpair::FilterMap, reducedpair::McDecision, + reducedpair::Px, + reducedpair::Py, + reducedpair::Pz, + reducedpair::P, + reducedpair::Rap, + reducedpair::Y); DECLARE_SOA_TABLE(DielectronsExtra, "AOD", "RTDIELEEXTRA", //! reducedpair::Index0Id, reducedpair::Index1Id, @@ -685,6 +733,9 @@ DECLARE_SOA_TABLE(DielectronsExtra, "AOD", "RTDIELEEXTRA", //! reducedpair::Lz, reducedpair::Lxy); +DECLARE_SOA_TABLE(DielectronsInfo, "AOD", "RTDIELINFO", + reducedpair::CollisionId, reducedpair::Prong0Id, reducedpair::Prong1Id); + DECLARE_SOA_TABLE(DimuonsExtra, "AOD", "RTDIMUEXTRA", //! dilepton_track_index::Index0Id, dilepton_track_index::Index1Id, reducedpair::Tauz, @@ -758,25 +809,32 @@ DECLARE_SOA_TABLE(DimuonsAll, "AOD", "RTDIMUONALL", //! reducedpair::VertexPz, reducedpair::SVertex); +DECLARE_SOA_TABLE(DileptonsMiniTree, "AOD", "RTDILEPTMTREE", //! + reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::CentFT0C, reducedpair::Cos2DeltaPhi); + using Dielectron = Dielectrons::iterator; +using StoredDielectron = StoredDielectrons::iterator; using Dimuon = Dimuons::iterator; using DielectronExtra = DielectronsExtra::iterator; +using DielectronInfo = DielectronsInfo::iterator; using DimuonExtra = DimuonsExtra::iterator; using DileptonFlow = DileptonsFlow::iterator; using DileptonInfo = DileptonsInfo::iterator; using DielectronAll = DielectronsAll::iterator; using DimuonAll = DimuonsAll::iterator; +using DileptonMiniTree = DileptonsMiniTree::iterator; // Tables for using analysis-dilepton-track with analysis-asymmetric-pairing -DECLARE_SOA_TABLE_FULL(Ditracks, "Ditracks", "AOD", "RTDITRACK", //! - o2::soa::Index<>, reducedpair::ReducedEventId, - reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, - reducedpair::FilterMap, reducedpair::PairFilterMap, - reducedpair::Rap, - reducedpair::Px, - reducedpair::Py, - reducedpair::Pz, - reducedpair::P); +DECLARE_SOA_TABLE(Ditracks, "AOD", "RTDITRACK", //! + o2::soa::Index<>, reducedpair::ReducedEventId, + reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, + reducedpair::FilterMap, reducedpair::PairFilterMap, reducedpair::CommonFilterMap, + reducedpair::Rap, + reducedpair::Y, + reducedpair::Px, + reducedpair::Py, + reducedpair::Pz, + reducedpair::P); DECLARE_SOA_TABLE(DitracksExtra, "AOD", "RTDITRKEXTRA", //! reducedpair::Index0Id, reducedpair::Index1Id, @@ -940,6 +998,33 @@ DECLARE_SOA_TABLE(RedDleptDmesAll, "AOD", "RTDILPTDMESALL", //! jpsidmescorr::BdtBkg, jpsidmescorr::BdtPrompt, jpsidmescorr::BdtNonprompt); + +namespace muondca +{ +DECLARE_SOA_COLUMN(pDCA, pdca, float); //! +DECLARE_SOA_COLUMN(DCA, dca, float); //! +DECLARE_SOA_COLUMN(DCAx, dcax, float); //! +DECLARE_SOA_COLUMN(DCAy, dcay, float); //! +DECLARE_SOA_COLUMN(Rabs, rabs, float); //! +DECLARE_SOA_COLUMN(Px, px, float); //! +DECLARE_SOA_COLUMN(Py, py, float); //! +DECLARE_SOA_COLUMN(Pz, pz, float); //! +} // namespace muondca + +DECLARE_SOA_TABLE(ReducedMuonsDca, "AOD", "RTMUONDCA", + muondca::pDCA, + muondca::DCA, + muondca::DCAx, + muondca::DCAy, + muondca::Rabs, + reducedmuon::Pt, + reducedmuon::Eta, reducedmuon::Phi, + reducedmuon::Sign, reducedmuon::IsAmbiguous, + muondca::Px, + muondca::Py, + muondca::Pz); + +using ReducedMuonDca = ReducedMuonsDca::iterator; } // namespace o2::aod #endif // PWGDQ_DATAMODEL_REDUCEDINFOTABLES_H_ diff --git a/PWGDQ/TableProducer/CMakeLists.txt b/PWGDQ/TableProducer/CMakeLists.txt index 7663568572f..81c2976b2e7 100644 --- a/PWGDQ/TableProducer/CMakeLists.txt +++ b/PWGDQ/TableProducer/CMakeLists.txt @@ -31,7 +31,7 @@ o2physics_add_dpl_workflow(table-maker-mc-with-assoc o2physics_add_dpl_workflow(table-maker-jpsi-hf SOURCES tableMakerJpsiHf.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore KFParticle::KFParticle + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-maker-muon-mch-trk-eff diff --git a/PWGDQ/TableProducer/tableMaker.cxx b/PWGDQ/TableProducer/tableMaker.cxx index 5e2c42b00a8..6eb031eb38e 100644 --- a/PWGDQ/TableProducer/tableMaker.cxx +++ b/PWGDQ/TableProducer/tableMaker.cxx @@ -56,6 +56,7 @@ #include "DetectorsBase/Propagator.h" #include "DetectorsBase/GeometryManager.h" #include "EventFiltering/Zorro.h" +#include "Framework/HistogramRegistry.h" using std::cout; using std::endl; @@ -65,20 +66,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; -// DQ triggers -enum DQTriggers { - kSingleE = 1 << 0, // 0000001 - kLMeeIMR = 1 << 1, // 0000010 - kLMeeHMR = 1 << 2, // 0000100 - kDiElectron = 1 << 3, // 0001000 - kSingleMuLow = 1 << 4, // 0010000 - kSingleMuHigh = 1 << 5, // 0100000 - kDiMuon = 1 << 6, // 1000000 - kNTriggersDQ -}; - Zorro zorro; -std::string zorroTriggerMask[7] = {"fSingleE", "fLMeeIMR", "fLMeeHMR", "fDiElectron", "fSingleMuLow", "fSingleMuHigh", "fDiMuon"}; using MyBarrelTracks = soa::Join; +using MyBarrelTracksForElectronMuon = soa::Join; using MyEvents = soa::Join; using MyEventsWithMults = soa::Join; using MyEventsWithFilter = soa::Join; @@ -140,6 +130,7 @@ constexpr static uint32_t gkTrackFillMapWithV0Bits = gkTrackFillMap | VarManager constexpr static uint32_t gkTrackFillMapWithV0BitsForMaps = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackV0Bits | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackTPCPID; constexpr static uint32_t gkTrackFillMapWithDalitzBits = gkTrackFillMap | VarManager::ObjTypes::DalitzBits; constexpr static uint32_t gkTrackFillMapWithV0AndDalitzBits = gkTrackFillMap | VarManager::ObjTypes::TrackV0Bits | VarManager::ObjTypes::DalitzBits; +constexpr static uint32_t gkTrackFillMapForElectronMuon = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackTPCPID; constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::Muon; constexpr static uint32_t gkMuonFillMapWithCov = VarManager::ObjTypes::Muon | VarManager::ObjTypes::MuonCov; constexpr static uint32_t gkMuonFillMapWithCovAmbi = VarManager::ObjTypes::Muon | VarManager::ObjTypes::MuonCov | VarManager::ObjTypes::AmbiMuon; @@ -151,13 +142,14 @@ struct TableMaker { Produces event; Produces eventExtended; Produces eventVtxCov; + Produces eventInfo; Produces multPV; Produces multAll; + Produces trackBarrelInfo; Produces trackBasic; Produces trackBarrel; Produces trackBarrelCov; Produces trackBarrelPID; - Produces trackBarrelInfo; Produces muonBasic; Produces muonExtra; Produces muonCov; @@ -172,9 +164,11 @@ struct TableMaker { Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigTrackCuts{"cfgBarrelTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable fConfigMuonCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; - Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; - Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; - Configurable fConfigAddMuonHistogram{"cfgAddMuonHistogram", "", "Comma separated list of histograms"}; + struct : ConfigurableGroup { + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddMuonHistogram{"cfgAddMuonHistogram", "", "Comma separated list of histograms"}; + } addHistoConfigurations; Configurable fConfigBarrelTrackPtLow{"cfgBarrelLowPt", 1.0f, "Low pt cut for tracks in the barrel"}; Configurable fConfigBarrelTrackMaxAbsEta{"cfgBarrelMaxAbsEta", 0.9f, "Eta absolute value cut for tracks in the barrel"}; Configurable fConfigMuonPtLow{"cfgMuonLowPt", 1.0f, "Low pt cut for muons"}; @@ -184,9 +178,18 @@ struct TableMaker { Configurable fConfigDetailedQA{"cfgDetailedQA", false, "If true, include more QA histograms (BeforeCuts classes)"}; Configurable fIsRun2{"cfgIsRun2", false, "Whether we analyze Run-2 or Run-3 data"}; Configurable fIsAmbiguous{"cfgIsAmbiguous", false, "Whether we enable QA plots for ambiguous tracks"}; - Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + + struct : ConfigurableGroup { + Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; + Configurable fConfigZorroTrigMask{"cfgZorroTriggerMask", "fDiMuon", "DQ Trigger masks: fSingleE,fLMeeIMR,fLMeeHMR,fDiElectron,fSingleMuLow,fSingleMuHigh,fDiMuon"}; + } useZorro; + + struct : ConfigurableGroup { + Configurable fConfigCcdbUrl{"useCCDBConfigurations.ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"useCCDBConfigurations.ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbPathZorro{"useCCDBConfigurations.ccdb-path-zorro", "Users/r/rlietava/EventFiltering/OTS/", "base path to the ccdb object for zorro"}; + } useCCDBConfigurations; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas(electrons, pions, protons)"}; Configurable fConfigComputeTPCpostCalibKaon{"cfgTPCpostCalibKaon", false, "If true, compute TPC post-calibrated n-sigmas for kaons"}; @@ -197,11 +200,16 @@ struct TableMaker { Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable grpmagPathRun2{"grpmagPathRun2", "GLO/GRP/GRP", "CCDB path of the GRPObject (Usage for Run 2)"}; + struct : ConfigurableGroup { + Configurable useMatCorrType{"useMatConfigurations.useMatCorrType", 1, "materialCorrType: 0: none, 1: TGeo, 2: LUT"}; + Configurable lutPath{"useMatConfigurations.lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + } useMatConfigurations; Service fCCDB; o2::parameters::GRPObject* grpmagrun2 = nullptr; // for run 2, we access the GRPObject from GLO/GRP/GRP o2::parameters::GRPMagField* grpmag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField + o2::base::MatLayerCylSet* lut = nullptr; AnalysisCompositeCut* fEventCut; //! Event selection cut std::vector fTrackCuts; //! Barrel track cuts @@ -215,6 +223,8 @@ struct TableMaker { bool fDoDetailedQA = false; // Bool to set detailed QA true, if QA is set true int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + HistogramRegistry registry{"registry"}; + // TODO: filter on TPC dedx used temporarily until electron PID will be improved Filter barrelSelectedTracks = ifnode(fIsRun2.node() == true, aod::track::trackType == uint8_t(aod::track::Run2Track), aod::track::trackType == uint8_t(aod::track::Track)) && o2::aod::track::pt >= fConfigBarrelTrackPtLow && nabs(o2::aod::track::eta) <= fConfigBarrelTrackMaxAbsEta && o2::aod::track::tpcSignal >= fConfigMinTpcSignal && o2::aod::track::tpcSignal <= fConfigMaxTpcSignal && o2::aod::track::tpcChi2NCl < 4.0f && o2::aod::track::itsChi2NCl < 36.0f; @@ -223,11 +233,19 @@ struct TableMaker { void init(o2::framework::InitContext& context) { DefineCuts(); - fCCDB->setURL(fConfigCcdbUrl); + fCCDB->setURL(useCCDBConfigurations.fConfigCcdbUrl); fCCDB->setCaching(true); fCCDB->setLocalObjectValidityChecking(); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - fCCDB->get(geoPath); + if (useMatConfigurations.useMatCorrType == 1) { + LOGF(info, "TGeo correction requested, loading geometry"); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + fCCDB->get(geoPath); + } + } + if (useMatConfigurations.useMatCorrType == 2) { + LOGF(info, "LUT correction requested, loading LUT"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(fCCDB->get(useMatConfigurations.lutPath)); + LOGF(info, "LUT load done!"); } VarManager::SetDefaultVarNames(); fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); @@ -314,7 +332,7 @@ struct TableMaker { fOutputList.setObject(fHistMan->GetMainHistogramList()); // CCDB configuration if (fConfigComputeTPCpostCalib) { - fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setURL(useCCDBConfigurations.fConfigCcdbUrl.value); fCCDB->setCaching(true); fCCDB->setLocalObjectValidityChecking(); // Not later than now objects @@ -357,7 +375,7 @@ struct TableMaker { auto bc = collision.template bc_as(); if (fCurrentRun != bc.runNumber()) { if (fConfigComputeTPCpostCalib) { - auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bc.timestamp()); + auto calibList = fCCDB->getForTimeStamp(useCCDBConfigurations.fConfigCcdbPathTPC.value, bc.timestamp()); VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); @@ -382,6 +400,11 @@ struct TableMaker { if (fPropMuon) { VarManager::SetupMuonMagField(); } + if (useMatConfigurations.useMatCorrType == 2) { + // setMatLUT only after magfield has been initalized + // (setMatLUT has implicit and problematic init field call if not) + o2::base::Propagator::Instance()->setMatLUT(lut); + } } fCurrentRun = bc.runNumber(); } @@ -396,7 +419,9 @@ struct TableMaker { } // Put the 8 first bits of the event filter in the last 8 bits of the tag if constexpr ((TEventFillMap & VarManager::ObjTypes::EventFilter) > 0) { - tag |= (collision.eventFilter() << 56); + if (!useZorro.fConfigRunZorro) { + tag |= (collision.eventFilter() << 56); + } } VarManager::ResetValues(0, VarManager::kNEventWiseVariables); @@ -415,17 +440,19 @@ struct TableMaker { // fill stats information, before selections for (int i = 0; i < kNaliases; i++) { if (triggerAliases & (uint32_t(1) << i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(kNaliases)); - if (fConfigRunZorro) { - for (int i = 0; i < kNTriggersDQ; ++i) { - zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), zorroTriggerMask[i]); - if (!zorro.isSelected(bc.globalBC())) { - tag |= static_cast(1 << i); - } + if (useZorro.fConfigRunZorro) { + zorro.setBaseCCDBPath(useCCDBConfigurations.fConfigCcdbPathZorro.value); + zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), useZorro.fConfigZorroTrigMask.value); + + zorro.populateHistRegistry(registry, fCurrentRun); + + if (zorro.isSelected(bc.globalBC())) { + tag |= (static_cast(true) << 56); // the same bit is used for this zorro selections from ccdb } } else { if (!fEventCut->IsSelected(VarManager::fgValues)) { @@ -436,10 +463,10 @@ struct TableMaker { // fill stats information, after selections for (int i = 0; i < kNaliases; i++) { if (triggerAliases & (uint32_t(1) << i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(kNaliases)); fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); @@ -462,6 +489,7 @@ struct TableMaker { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMultExtra) > 0) { multPV(collision.multNTracksHasITS(), collision.multNTracksHasTPC(), collision.multNTracksHasTOF(), collision.multNTracksHasTRD(), collision.multNTracksITSOnly(), collision.multNTracksTPCOnly(), collision.multNTracksITSTPC(), collision.trackOccupancyInTimeRange()); @@ -474,9 +502,9 @@ struct TableMaker { uint8_t trackTempFilterMap = 0; int isAmbiguous = 0; if constexpr (static_cast(TTrackFillMap)) { + trackBarrelInfo.reserve(tracksBarrel.size()); trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); - trackBarrelInfo.reserve(tracksBarrel.size()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov.reserve(tracksBarrel.size()); } @@ -517,7 +545,7 @@ struct TableMaker { fHistMan->FillHistClass(Form("Ambiguous_TrackBarrel_%s", (*cut).GetName()), VarManager::fgValues); } } - (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); + (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); } } if (!trackTempFilterMap) { @@ -535,7 +563,7 @@ struct TableMaker { trackFilteringTag = uint64_t(track.pidbit()); for (int iv0 = 0; iv0 < 5; iv0++) { if (track.pidbit() & (uint8_t(1) << iv0)) { - (reinterpret_cast(fStatsList->At(1)))->Fill(fTrackCuts.size() + static_cast(iv0)); + (reinterpret_cast(fStatsList->At(1)))->Fill(fTrackCuts.size() + static_cast(iv0)); } } if (fConfigIsOnlyforMaps) { @@ -565,6 +593,7 @@ struct TableMaker { } // create the track tables + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ(), track.globalIndex()); trackBasic(event.lastIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), isAmbiguous); trackBarrel(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), @@ -574,7 +603,6 @@ struct TableMaker { track.length(), track.dcaXY(), track.dcaZ(), track.trackTime(), track.trackTimeRes(), track.tofExpMom(), track.detectorMap()); - trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov(track.cYY(), track.cZY(), track.cZZ(), track.cSnpY(), track.cSnpZ(), track.cSnpSnp(), track.cTglY(), track.cTglZ(), track.cTglSnp(), track.cTglTgl(), @@ -592,6 +620,10 @@ struct TableMaker { track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), track.trdSignal()); } + if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackTPCPID)) { + trackBarrelPID(track.tpcSignal(), track.tpcNSigmaEl(), -1, track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + -1, -1, -1, -1, -1, -1, -1); + } } } // end if constexpr (TTrackFillMap) @@ -717,7 +749,7 @@ struct TableMaker { fHistMan->FillHistClass(Form("Ambiguous_Muons_%s", (*cut).GetName()), VarManager::fgValues); } } - (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(i)); + (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(i)); } } if (!trackTempFilterMap) { @@ -803,7 +835,7 @@ struct TableMaker { auto bc = collision.template bc_as(); if (fCurrentRun != bc.runNumber()) { if (fConfigComputeTPCpostCalib) { - auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bc.timestamp()); + auto calibList = fCCDB->getForTimeStamp(useCCDBConfigurations.fConfigCcdbPathTPC.value, bc.timestamp()); VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); @@ -828,6 +860,11 @@ struct TableMaker { if constexpr (static_cast(TMuonFillMap)) { VarManager::SetupMuonMagField(); } + if (useMatConfigurations.useMatCorrType == 2) { + // setMatLUT only after magfield has been initalized + // (setMatLUT has implicit and problematic init field call if not) + o2::base::Propagator::Instance()->setMatLUT(lut); + } } fCurrentRun = bc.runNumber(); } @@ -844,7 +881,9 @@ struct TableMaker { } // Put the 8 first bits of the event filter in the last 8 bits of the tag if constexpr ((TEventFillMap & VarManager::ObjTypes::EventFilter) > 0) { - tag |= (collision.eventFilter() << 56); + if (!useZorro.fConfigRunZorro) { + tag |= (collision.eventFilter() << 56); + } } VarManager::ResetValues(0, VarManager::kNEventWiseVariables); @@ -862,17 +901,19 @@ struct TableMaker { // fill stats information, before selections for (int i = 0; i < kNaliases; i++) { if (triggerAliases & (uint32_t(1) << i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(kNaliases)); - if (fConfigRunZorro) { - for (int i = 0; i < kNTriggersDQ; ++i) { - zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), zorroTriggerMask[i]); - if (!zorro.isSelected(bc.globalBC())) { - tag |= static_cast(1 << i); - } + if (useZorro.fConfigRunZorro) { + zorro.setBaseCCDBPath(useCCDBConfigurations.fConfigCcdbPathZorro.value); + zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), useZorro.fConfigZorroTrigMask.value); + + zorro.populateHistRegistry(registry, fCurrentRun); + + if (zorro.isSelected(bc.globalBC())) { + tag |= (static_cast(true) << 56); // the same bit is used for this zorro selections from ccdb } } else { if (!fEventCut->IsSelected(VarManager::fgValues)) { @@ -883,10 +924,10 @@ struct TableMaker { // fill stats information, after selections for (int i = 0; i < kNaliases; i++) { if (triggerAliases & (uint32_t(1) << i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(kNaliases)); fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); @@ -914,9 +955,9 @@ struct TableMaker { uint8_t trackTempFilterMap = 0; int isAmbiguous = 0; if constexpr (static_cast(TTrackFillMap)) { + trackBarrelInfo.reserve(tracksBarrel.size()); trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); - trackBarrelInfo.reserve(tracksBarrel.size()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov.reserve(tracksBarrel.size()); } @@ -951,7 +992,7 @@ struct TableMaker { fHistMan->FillHistClass(Form("Ambiguous_TrackBarrel_%s", (*cut).GetName()), VarManager::fgValues); } } - (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); + (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); } } if (!trackTempFilterMap) { @@ -969,7 +1010,7 @@ struct TableMaker { trackFilteringTag |= (uint64_t(track.pidbit()) << 2); for (int iv0 = 0; iv0 < 5; iv0++) { if (track.pidbit() & (uint8_t(1) << iv0)) { - (reinterpret_cast(fStatsList->At(1)))->Fill(fTrackCuts.size() + static_cast(iv0)); + (reinterpret_cast(fStatsList->At(1)))->Fill(fTrackCuts.size() + static_cast(iv0)); } } if (fConfigIsOnlyforMaps) { @@ -993,6 +1034,7 @@ struct TableMaker { trackFilteringTag |= (uint64_t(trackTempFilterMap) << 15); // BIT15-...: user track filters // create the track tables + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ(), track.globalIndex()); trackBasic(event.lastIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), isAmbiguous); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), @@ -1001,7 +1043,6 @@ struct TableMaker { track.length(), track.dcaXY(), track.dcaZ(), track.trackTime(), track.trackTimeRes(), track.tofExpMom(), track.detectorMap()); - trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.cYY(), track.cZY(), track.cZZ(), track.cSnpY(), track.cSnpZ(), @@ -1019,6 +1060,10 @@ struct TableMaker { track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), track.trdSignal()); } + if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackTPCPID)) { + trackBarrelPID(track.tpcSignal(), track.tpcNSigmaEl(), -1, track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + -1, -1, -1, -1, -1, -1, -1); + } } } // end if constexpr (TTrackFillMap) @@ -1099,7 +1144,7 @@ struct TableMaker { fHistMan->FillHistClass(Form("Ambiguous_Muons_%s", (*cut).GetName()), VarManager::fgValues); } } - (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(i)); + (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(i)); } } if (!trackTempFilterMap) { @@ -1181,28 +1226,28 @@ struct TableMaker { } } - TString histEventName = fConfigAddEventHistogram.value; + TString histEventName = addHistoConfigurations.fConfigAddEventHistogram.value; if (classStr.Contains("Event")) { if (fConfigQA) { dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "event", histEventName); } } - TString histTrackName = fConfigAddTrackHistogram.value; + TString histTrackName = addHistoConfigurations.fConfigAddTrackHistogram.value; if (classStr.Contains("Track")) { if (fConfigQA) { dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "track", histTrackName); } } - TString histMuonName = fConfigAddMuonHistogram.value; + TString histMuonName = addHistoConfigurations.fConfigAddMuonHistogram.value; if (classStr.Contains("Muons")) { if (fConfigQA) { dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "track", histMuonName); } } - TString histMftName = fConfigAddMuonHistogram.value; + TString histMftName = addHistoConfigurations.fConfigAddMuonHistogram.value; if (classStr.Contains("Mft")) { if (fConfigDetailedQA) { dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "track", histMftName); @@ -1214,7 +1259,7 @@ struct TableMaker { fStatsList.setObject(new TList()); fStatsList->SetOwner(kTRUE); std::vector eventLabels{"BCs", "Collisions before filtering", "Before cuts", "After cuts"}; - TH2I* histEvents = new TH2I("EventStats", "Event statistics", eventLabels.size(), -0.5, eventLabels.size() - 0.5, kNaliases + 1, -0.5, +kNaliases + 0.5); + TH2F* histEvents = new TH2F("EventStats", "Event statistics", eventLabels.size(), -0.5, eventLabels.size() - 0.5, kNaliases + 1, -0.5, +kNaliases + 0.5); int ib = 1; for (auto label = eventLabels.begin(); label != eventLabels.end(); label++, ib++) { histEvents->GetXaxis()->SetBinLabel(ib, (*label).Data()); @@ -1226,7 +1271,7 @@ struct TableMaker { fStatsList->Add(histEvents); // Track statistics: one bin for each track selection and 5 bins for V0 tags (gamma, K0s, Lambda, anti-Lambda, Omega) - TH1I* histTracks = new TH1I("TrackStats", "Track statistics", fTrackCuts.size() + 5.0, -0.5, fTrackCuts.size() - 0.5 + 5.0); + TH1D* histTracks = new TH1D("TrackStats", "Track statistics", fTrackCuts.size() + 5.0, -0.5, fTrackCuts.size() - 0.5 + 5.0); ib = 1; for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, ib++) { histTracks->GetXaxis()->SetBinLabel(ib, (*cut).GetName()); @@ -1236,7 +1281,7 @@ struct TableMaker { histTracks->GetXaxis()->SetBinLabel(fTrackCuts.size() + 1 + ib, v0TagNames[ib]); } fStatsList->Add(histTracks); - TH1I* histMuons = new TH1I("MuonStats", "Muon statistics", fMuonCuts.size(), -0.5, fMuonCuts.size() - 0.5); + TH1D* histMuons = new TH1D("MuonStats", "Muon statistics", fMuonCuts.size(), -0.5, fMuonCuts.size() - 0.5); ib = 1; for (auto cut = fMuonCuts.begin(); cut != fMuonCuts.end(); cut++, ib++) { histMuons->GetXaxis()->SetBinLabel(ib, (*cut).GetName()); @@ -1284,10 +1329,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, tracksBarrel, tracksMuon, nullptr, nullptr); } @@ -1299,15 +1344,22 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, tracksBarrel, tracksMuon, nullptr, nullptr); } } + // Produce barrel + muon tables for the eletron-muon analysis, without PIDTOF---------------------------------------------------------------------- + void processFullForElectronMuon(MyEvents::iterator const& collision, aod::BCsWithTimestamps const& bcs, + soa::Filtered const& tracksBarrel, soa::Filtered const& tracksMuon) + { + fullSkimming(collision, bcs, tracksBarrel, tracksMuon, nullptr, nullptr); + } + // Produce barrel only tables, with V0Bits ------------------------------------------------------------------------------------------------ void processBarrelOnlyWithV0Bits(MyEvents::iterator const& collision, aod::BCsWithTimestamps const& bcs, soa::Filtered const& tracksBarrel) @@ -1365,10 +1417,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, tracksBarrel, nullptr, nullptr, nullptr); } @@ -1387,10 +1439,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, tracksBarrel, nullptr, nullptr, nullptr); } @@ -1402,10 +1454,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, tracksBarrel, nullptr, nullptr, nullptr); } @@ -1473,10 +1525,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, nullptr, tracksMuon, nullptr, nullptr); } @@ -1581,10 +1633,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (bc.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(kNaliases)); } // List of process functions removed because they are not using cov matrix @@ -1623,10 +1675,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, nullptr, tracksMuon, nullptr, nullptr); } @@ -1638,10 +1690,10 @@ struct TableMaker { { for (int i = 0; i < kNaliases; i++) { if (collision.alias_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); if (collision.eventFilter()) { fullSkimming(collision, bcs, nullptr, tracksMuon, nullptr, nullptr); } @@ -1665,6 +1717,7 @@ struct TableMaker { PROCESS_SWITCH(TableMaker, processFullWithCent, "Build full DQ skimmed data model, w/ centrality", false); PROCESS_SWITCH(TableMaker, processFullWithCentAndMults, "Build full DQ skimmed data model, w/ centrality and multiplicities", false); PROCESS_SWITCH(TableMaker, processFullWithCovCentAndMults, "Build full DQ skimmed data model, w/ centrality, multiplicities and track covariances", false); + PROCESS_SWITCH(TableMaker, processFullForElectronMuon, "Build full DQ skimmed data model for electron-muon correlation analysis, w/o centrality", false); PROCESS_SWITCH(TableMaker, processBarrelOnlyWithV0Bits, "Build full DQ skimmed data model, w/o centrality, w/ V0Bits", false); PROCESS_SWITCH(TableMaker, processBarrelOnlyWithV0BitsAndMaps, "Build full DQ skimmed data model, w/o multiplicity, w/ V0Bits", false); PROCESS_SWITCH(TableMaker, processBarrelOnlyWithDalitzBits, "Build barrel-only DQ skimmed data model, w/o centrality, w/ DalitzBits", false); diff --git a/PWGDQ/TableProducer/tableMakerJpsiHf.cxx b/PWGDQ/TableProducer/tableMakerJpsiHf.cxx index 9c18f0b9fc4..6bc27a63029 100644 --- a/PWGDQ/TableProducer/tableMakerJpsiHf.cxx +++ b/PWGDQ/TableProducer/tableMakerJpsiHf.cxx @@ -22,12 +22,15 @@ #include "Framework/runDataProcessing.h" #include "PWGHF/Core/HfHelper.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/VarManager.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/HistogramsLibrary.h" using namespace o2; using namespace o2::analysis; @@ -36,15 +39,48 @@ using namespace o2::framework::expressions; using namespace o2::aod; using namespace o2::aod::hf_cand_2prong; +// bit maps used for the Fill functions of the VarManager +constexpr static uint32_t gkTrackFillMapWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; +constexpr static uint32_t gkMuonFillMapWithColl = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra | VarManager::ObjTypes::ReducedMuonCollInfo; + +namespace +{ +struct CandidateDilepton { + float fMass; + float fPt; + float fPhi; + float fEta; + float fTauz; + float fLz; + float fLxy; + int fSign; + uint32_t fMcDecision; + + float pt() const { return fPt; } + float mass() const { return fMass; } + float phi() const { return fPhi; } + float eta() const { return fEta; } + int sign() const { return fSign; } + uint32_t mcDecision() const { return fMcDecision; } + float tauz() const { return fTauz; } + float lz() const { return fLz; } + float lxy() const { return fLxy; } + float px() const { return fPt * std::cos(fPhi); } + float py() const { return fPt * std::sin(fPhi); } + float pz() const { return fPt * std::sinh(fEta); } + float p() const { return fPt * std::cosh(fEta); } + float rap() const { return std::log((std::sqrt(fMass * fMass + fPt * fPt * std::cosh(fEta) * std::cosh(fEta)) + fPt * std::sinh(fEta)) / std::sqrt(fMass * fMass + fPt * fPt)); } +}; +} // namespace + // Declarations of various short names using MyEvents = soa::Join; -using MyDimuonCandidatesSelected = soa::Join; -using MyDimuonCandidatesSelectedWithDca = soa::Join; -using MyDielectronCandidatesSelected = soa::Join; -using MyDielectronCandidatesSelectedWithDca = soa::Join; using MyD0CandidatesSelected = soa::Join; using MyD0CandidatesSelectedWithBdt = soa::Join; +using MyBarrelTracksSelectedWithColl = soa::Join; +using MyMuonTracksSelectedWithColl = soa::Join; + HfHelper hfHelper; struct tableMakerJpsiHf { @@ -64,32 +100,38 @@ struct tableMakerJpsiHf { // cuts on BDT output scores to be applied only for the histograms Configurable yCandDmesonMax{"yCandDmesonMax", -1., "max. cand. rapidity"}; // DQ configurables - Configurable dileptonDecayChannel{"dileptonDecayChannel", "JPsiToMuMu", "Dilepton decay channel (JPsiToMuMu/JPsiToEE)"}; + Configurable fConfigTrackCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + // Configurable fConfigPairCuts{"cfgPairCuts", "", "Comma separated list of pair cuts"}; It seems to me that they are not used + Configurable fConfigMuonCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; Configurable massDileptonCandMin{"massDileptonCandMin", 1, "minimum dilepton mass"}; Configurable massDileptonCandMax{"massDileptonCandMax", 5, "maximum dilepton mass"}; // General configurables Configurable configDebug{"configDebug", true, "If true, fill D0 - J/psi histograms separately"}; Configurable storeTableForNorm{"storeTableForNorm", true, "If true, store a table with number of processed collisions for normalisation"}; - SliceCache cache; - Partition selectedDimuonCandidates = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; - Partition selectedDimuonCandidatesWithDca = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; - Partition selectedDielectronCandidates = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; - Partition selectedDielectronCandidatesWithDca = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; - Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Partition selectedD0CandidatesWithBdt = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Preslice perCollisionDmeson = aod::hf_cand::collisionId; - Preslice perCollisionDimuon = aod::reducedpair::collisionId; - Preslice perCollisionDielectron = aod::reducedpair::collisionId; + Preslice perCollisionDmesonWithBdt = aod::hf_cand::collisionId; + PresliceUnsorted perCollisionMuons = aod::reducedmuon::collisionId; + PresliceUnsorted perCollisionElectrons = aod::reducedtrack::collisionId; + + SliceCache cache; + Filter filterD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; // Define histograms manager float* fValuesDileptonCharmHadron{}; HistogramManager* fHistMan{}; OutputObj fOutputList{"output"}; + std::vector fTrackCuts; + std::vector fMuonCuts; + void init(o2::framework::InitContext&) { + std::array doprocess{doprocessJspiToMuMuD0, doprocessJspiToMuMuD0WithBdt, doprocessJspiToEED0, doprocessJspiToEED0WithBdt}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function should be enabled! Please check your configuration!"); + } + fValuesDileptonCharmHadron = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); @@ -99,28 +141,116 @@ struct tableMakerJpsiHf { fHistMan->AddHistClass("JPsi"); fHistMan->AddHistClass("JPsiDmeson"); dqhistograms::DefineHistograms(fHistMan, "Dmeson", "dilepton-charmhadron", "dmeson"); - if (dileptonDecayChannel.value == "JPsiToMuMu") { + if (doprocessJspiToMuMuD0 || doprocessJspiToMuMuD0WithBdt) { dqhistograms::DefineHistograms(fHistMan, "JPsi", "dilepton-charmhadron", "jpsitomumu"); dqhistograms::DefineHistograms(fHistMan, "JPsiDmeson", "dilepton-charmhadron", "jpsitomumudmeson"); } - if (dileptonDecayChannel.value == "JPsiToEE") { + if (doprocessJspiToEED0 || doprocessJspiToEED0WithBdt) { dqhistograms::DefineHistograms(fHistMan, "JPsi", "dilepton-charmhadron", "jpsitoee"); dqhistograms::DefineHistograms(fHistMan, "JPsiDmeson", "dilepton-charmhadron", "jpsitoeedmeson"); } VarManager::SetUseVars(fHistMan->GetUsedVars()); fOutputList.setObject(fHistMan->GetMainHistogramList()); + + // cut strings + if (doprocessJspiToMuMuD0 || doprocessJspiToMuMuD0WithBdt) { + TString cutNamesMuon = fConfigMuonCuts.value; + if (!cutNamesMuon.IsNull()) { + std::unique_ptr objArray(cutNamesMuon.Tokenize(",")); + for (int iCut{0}; iCut < objArray->GetEntries(); ++iCut) { + fMuonCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(iCut)->GetName())); + } + } + } + if (doprocessJspiToEED0 || doprocessJspiToEED0WithBdt) { + TString cutNamesElectron = fConfigTrackCuts.value; + if (!cutNamesElectron.IsNull()) { // if track cuts + std::unique_ptr objArray(cutNamesElectron.Tokenize(",")); + for (int iCut{0}; iCut < objArray->GetEntries(); ++iCut) { + fTrackCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(iCut)->GetName())); + } + } + } + + // It seems they are not applied when filling the table + // TString cutNamesPair = fConfigPairCuts.value; + // if (!cutNamesPair.IsNull()) { + // std::unique_ptr objArray(cutNamesPair.Tokenize(",")); + // for (int iCut{0}; iCut < objArray->GetEntries(); ++iCut) { + // fPairCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(iCut)->GetName())); + // } + // } + } + + // template function for lepton selection + template + bool isLeptonSelected(TTrack const& lepton) + { + + if constexpr (TPairType == VarManager::kDecayToEE) { + VarManager::FillTrack(lepton); + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++) { + if (!(*cut).IsSelected(VarManager::fgValues)) { + return false; + } + } + } else if constexpr (TPairType == VarManager::kDecayToMuMu) { + VarManager::FillTrack(lepton); + for (auto cut = fMuonCuts.begin(); cut != fMuonCuts.end(); cut++) { + if (!(*cut).IsSelected(VarManager::fgValues)) { + return false; + } + } + } + + return true; + } + + // template function to compute the dilepton combinatorial + template + std::vector computeDileptonCombinatorial(TTracks const& tracks) + { + std::vector dileptons{}; + uint32_t dileptonMcDecision{0u}; // placeholder, copy of the dqEfficiency.cxx one + + for (auto& [trackFirst, trackSecond] : combinations(tracks, tracks)) { + bool isFirstSelected = isLeptonSelected(trackFirst); + bool isSecondSelected = isLeptonSelected(trackSecond); + + if (!isFirstSelected || !isSecondSelected || (trackFirst.sign() + trackSecond.sign()) != 0) { + continue; + } + + // we fill a struct for the dileptons, which has the same signatures of the DQ tables to be used in the VarManager + VarManager::FillPair(trackFirst, trackSecond); + + if (VarManager::fgValues[VarManager::kMass] < massDileptonCandMin || VarManager::fgValues[VarManager::kMass] > massDileptonCandMax) { + continue; + } + + CandidateDilepton dilepton{}; + dilepton.fMass = VarManager::fgValues[VarManager::kMass]; + dilepton.fPt = VarManager::fgValues[VarManager::kPt]; + dilepton.fEta = VarManager::fgValues[VarManager::kEta]; + dilepton.fPhi = VarManager::fgValues[VarManager::kPhi]; + dilepton.fSign = trackFirst.sign() + trackSecond.sign(); + dilepton.fMcDecision = dileptonMcDecision; + dileptons.push_back(dilepton); + } + + return dileptons; } // Template function to run pair - hadron combinations // TODO: generalise to all charm-hadron species - template - void runDileptonDmeson(TDqTrack const& dileptons, THfTrack const& dmesons, MyEvents::iterator const& collision) + template + void runDileptonDmeson(TDqTrack const& leptons, THfTrack const& dmesons, MyEvents::iterator const& collision) { VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); bool isCollSel{false}; if (configDebug) { - for (auto& dmeson : dmesons) { + for (auto const& dmeson : dmesons) { if (!TESTBIT(dmeson.hfflag(), DecayType::D0ToPiK)) { continue; } @@ -158,7 +288,11 @@ struct tableMakerJpsiHf { } } + // we compute the dileptons on the fly + auto dileptons = computeDileptonCombinatorial(leptons); + // loop over dileptons + std::vector filledDmesonIds{}; // keep track of the D-mesons filled in the table to avoid repetitions for (auto dilepton : dileptons) { auto massJPsi = dilepton.mass(); bool isJPsiFilled{false}; @@ -175,11 +309,17 @@ struct tableMakerJpsiHf { } // loop over D mesons - for (auto& dmeson : dmesons) { + for (auto const& dmeson : dmesons) { if (!TESTBIT(dmeson.hfflag(), DecayType::D0ToPiK)) { continue; } + int dmesonIdx = dmeson.globalIndex(); + bool isDmesonFilled{false}; + if (std::find(filledDmesonIds.begin(), filledDmesonIds.end(), dmesonIdx) != filledDmesonIds.end()) { // we already included this D meson in the table, skip it + isDmesonFilled = true; + } + auto rapD0 = hfHelper.yD0(dmeson); if (yCandDmesonMax >= 0. && std::abs(rapD0) > yCandDmesonMax) { @@ -203,20 +343,25 @@ struct tableMakerJpsiHf { } isJPsiFilled = true; } - redDmesons(indexRed, dmeson.px(), dmeson.py(), dmeson.pz(), dmeson.xSecondaryVertex(), dmeson.ySecondaryVertex(), dmeson.zSecondaryVertex(), 0, 0); + if (!isDmesonFilled) { + redDmesons(indexRed, dmeson.px(), dmeson.py(), dmeson.pz(), dmeson.xSecondaryVertex(), dmeson.ySecondaryVertex(), dmeson.zSecondaryVertex(), 0, 0); + filledDmesonIds.push_back(dmesonIdx); + } std::array scores = {999., -999., -999., 999., -999., -999.}; // D0 + D0bar if constexpr (withBdt) { - if (dmeson.mlProbD0().size() == 3) { - for (auto iScore{0u}; iScore < dmeson.mlProbD0().size(); ++iScore) { - scores[iScore] = dmeson.mlProbD0()[iScore]; + if (!isDmesonFilled) { + if (dmeson.mlProbD0().size() == 3) { + for (auto iScore{0u}; iScore < dmeson.mlProbD0().size(); ++iScore) { + scores[iScore] = dmeson.mlProbD0()[iScore]; + } } - } - if (dmeson.mlProbD0bar().size() == 3) { - for (auto iScore{0u}; iScore < dmeson.mlProbD0bar().size(); ++iScore) { - scores[iScore + 3] = dmeson.mlProbD0bar()[iScore]; + if (dmeson.mlProbD0bar().size() == 3) { + for (auto iScore{0u}; iScore < dmeson.mlProbD0bar().size(); ++iScore) { + scores[iScore + 3] = dmeson.mlProbD0bar()[iScore]; + } } + redDmesBdts(scores[0], scores[1], scores[2], scores[3], scores[4], scores[5]); } - redDmesBdts(scores[0], scores[1], scores[2], scores[3], scores[4], scores[5]); } if (dmeson.isSelD0() >= 1) { @@ -231,61 +376,63 @@ struct tableMakerJpsiHf { fHistMan->FillHistClass("JPsiDmeson", fValuesDileptonCharmHadron); VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); } - redD0Masses(massD0, massD0bar); + if (!isDmesonFilled) { + redD0Masses(massD0, massD0bar); + } } } } } // process J/psi(->mumu) - D0 - void processJspiToMuMuD0(MyEvents const& collisions, MyDimuonCandidatesSelected const&, MyD0CandidatesSelected const&) + void processJspiToMuMuD0(MyEvents const& collisions, MyMuonTracksSelectedWithColl const& muonCandidates, soa::Filtered const& selectedD0Candidates) { if (storeTableForNorm) { redCollCounter(collisions.size()); } - for (auto& collision : collisions) { - auto groupedDmesonCandidates = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - auto groupedDileptonCandidates = selectedDimuonCandidates->sliceByCached(aod::reducedpair::collisionId, collision.globalIndex(), cache); - runDileptonDmeson(groupedDileptonCandidates, groupedDmesonCandidates, collision); + for (auto const& collision : collisions) { + auto groupedDmesonCandidates = selectedD0Candidates.sliceBy(perCollisionDmeson, collision.globalIndex()); + auto groupedLeptonCandidates = muonCandidates.sliceBy(perCollisionMuons, collision.globalIndex()); + runDileptonDmeson(groupedLeptonCandidates, groupedDmesonCandidates, collision); } } // process J/psi(->ee) - D0 - void processJspiToEED0(MyEvents const& collisions, MyDielectronCandidatesSelected const&, MyD0CandidatesSelected const&) + void processJspiToEED0(MyEvents const& collisions, MyBarrelTracksSelectedWithColl const& electronCandidates, soa::Filtered const& selectedD0Candidates) { if (storeTableForNorm) { redCollCounter(collisions.size()); } - for (auto& collision : collisions) { - auto groupedDmesonCandidates = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - auto groupedDileptonCandidates = selectedDielectronCandidates->sliceByCached(aod::reducedpair::collisionId, collision.globalIndex(), cache); - runDileptonDmeson(groupedDileptonCandidates, groupedDmesonCandidates, collision); + for (auto const& collision : collisions) { + auto groupedDmesonCandidates = selectedD0Candidates.sliceBy(perCollisionDmeson, collision.globalIndex()); + auto groupedLeptonCandidates = electronCandidates.sliceBy(perCollisionElectrons, collision.globalIndex()); + runDileptonDmeson(groupedLeptonCandidates, groupedDmesonCandidates, collision); } } // process J/psi(->mumu) - D0 adding the BDT output scores to the D0 table - void processJspiToMuMuD0WithBdt(MyEvents const& collisions, MyDimuonCandidatesSelected const&, MyD0CandidatesSelectedWithBdt const&) + void processJspiToMuMuD0WithBdt(MyEvents const& collisions, MyMuonTracksSelectedWithColl const& muonCandidates, soa::Filtered const& selectedD0CandidatesWithBdt) { if (storeTableForNorm) { redCollCounter(collisions.size()); } - for (auto& collision : collisions) { - auto groupedDmesonCandidates = selectedD0CandidatesWithBdt->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - auto groupedDileptonCandidates = selectedDimuonCandidates->sliceByCached(aod::reducedpair::collisionId, collision.globalIndex(), cache); - runDileptonDmeson(groupedDileptonCandidates, groupedDmesonCandidates, collision); + for (auto const& collision : collisions) { + auto groupedDmesonCandidates = selectedD0CandidatesWithBdt.sliceBy(perCollisionDmesonWithBdt, collision.globalIndex()); + auto groupedLeptonCandidates = muonCandidates.sliceBy(perCollisionMuons, collision.globalIndex()); + runDileptonDmeson(groupedLeptonCandidates, groupedDmesonCandidates, collision); } } // process J/psi(->ee) - D0 adding the BDT output scores to the D0 table - void processJspiToEED0WithBdt(MyEvents const& collisions, MyDielectronCandidatesSelected const&, MyD0CandidatesSelectedWithBdt const&) + void processJspiToEED0WithBdt(MyEvents const& collisions, MyBarrelTracksSelectedWithColl const& electronCandidates, soa::Filtered const& selectedD0CandidatesWithBdt) { if (storeTableForNorm) { redCollCounter(collisions.size()); } - for (auto& collision : collisions) { - auto groupedDmesonCandidates = selectedD0CandidatesWithBdt->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - auto groupedDileptonCandidates = selectedDielectronCandidates->sliceByCached(aod::reducedpair::collisionId, collision.globalIndex(), cache); - runDileptonDmeson(groupedDileptonCandidates, groupedDmesonCandidates, collision); + for (auto const& collision : collisions) { + auto groupedDmesonCandidates = selectedD0CandidatesWithBdt.sliceBy(perCollisionDmesonWithBdt, collision.globalIndex()); + auto groupedLeptonCandidates = electronCandidates.sliceBy(perCollisionElectrons, collision.globalIndex()); + runDileptonDmeson(groupedLeptonCandidates, groupedDmesonCandidates, collision); } } diff --git a/PWGDQ/TableProducer/tableMakerMC.cxx b/PWGDQ/TableProducer/tableMakerMC.cxx index 287cb047284..40d3c346b58 100644 --- a/PWGDQ/TableProducer/tableMakerMC.cxx +++ b/PWGDQ/TableProducer/tableMakerMC.cxx @@ -111,10 +111,12 @@ struct TableMakerMC { Produces event; Produces eventExtended; Produces eventVtxCov; + Produces eventInfo; Produces multPV; Produces multAll; Produces eventMClabels; Produces eventMC; + Produces trackBarrelInfo; Produces trackBasic; Produces trackBarrel; Produces trackBarrelCov; @@ -453,6 +455,7 @@ struct TableMakerMC { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + eventInfo(collision.globalIndex()); // make an entry for this MC event only if it was not already added to the table if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { eventMC(mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), @@ -515,6 +518,7 @@ struct TableMakerMC { int isAmbiguous = 0; // loop over reconstructed tracks if constexpr (static_cast(TTrackFillMap)) { + trackBarrelInfo.reserve(tracksBarrel.size()); trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); trackBarrelPID.reserve(tracksBarrel.size()); @@ -622,6 +626,7 @@ struct TableMakerMC { fCounters[0]++; } + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ(), track.globalIndex()); trackBasic(event.lastIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), isAmbiguous); trackBarrel(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), @@ -1010,6 +1015,7 @@ struct TableMakerMC { eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + eventInfo(collision.globalIndex()); // make an entry for this MC event only if it was not already added to the table if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { eventMC(mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), @@ -1066,6 +1072,7 @@ struct TableMakerMC { int isAmbiguous = 0; // loop over reconstructed tracks if constexpr (static_cast(TTrackFillMap)) { + trackBarrelInfo.reserve(tracksBarrel.size()); trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); trackBarrelPID.reserve(tracksBarrel.size()); @@ -1168,6 +1175,7 @@ struct TableMakerMC { fCounters[0]++; } + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ(), track.globalIndex()); trackBasic(event.lastIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), isAmbiguous); trackBarrel(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), diff --git a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx index e89b601d139..bcb465d13fb 100644 --- a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx @@ -105,10 +105,12 @@ struct TableMakerMC { Produces event; Produces eventExtended; Produces eventVtxCov; + Produces eventInfo; Produces multPV; Produces multAll; Produces eventMClabels; + Produces trackBarrelInfo; Produces trackBasic; Produces trackBarrel; Produces trackBarrelCov; @@ -150,21 +152,28 @@ struct TableMakerMC { Configurable fIsRun2{"cfgIsRun2", false, "Whether we analyze Run-2 or Run-3 data"}; Configurable fConfigBarrelTrackMaxAbsEta{"cfgBarrelMaxAbsEta", 0.9f, "Eta absolute value cut for tracks in the barrel"}; Configurable fConfigBarrelTrackMinPt{"cfgBarrelMinPt", 0.5f, "Minimum pt for tracks in the barrel"}; - Configurable fConfigBarrelRequireTPC{"cfgBarrelRequireTPC", true, "Require TPC for tracks in the barrel"}; Configurable fConfigBarrelMinTPCncls{"cfgBarrelMinTPCncls", 50.0f, "Minimum TPC cls for tracks in the barrel"}; Configurable fConfigBarrelMaxTPCchi2{"cfgBarrelMaxTPCchi2", 10.0f, "Maximum TPC chi2/ndf for tracks in the barrel"}; - Configurable fConfigBarrelRequireITS{"cfgBarrelRequireITS", true, "Require ITS for tracks in the barrel"}; Configurable fConfigBarrelMaxITSchi2{"cfgBarrelMaxITSchi2", 36.0f, "Maximum ITS chi2/ndf for tracks in the barrel"}; Configurable fConfigMuonPtLow{"cfgMuonLowPt", 1.0f, "Low pt cut for muons"}; // CCDB connection configurables Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fPropMuon{"cfgPropMuon", false, "Propgate muon tracks through absorber"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable grpmagPathRun2{"grpmagPathRun2", "GLO/GRP/GRP", "CCDB path of the GRPObject (Usage for Run 2)"}; + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propagate tracks to primary vertex"}; + + // Muon related options + Configurable fPropMuon{"cfgPropMuon", true, "Propagate muon tracks through absorber (do not use if applying pairing)"}; + Configurable fRefitGlobalMuon{"cfgRefitGlobalMuon", true, "Correct global muon parameters"}; + Configurable fMuonMatchEtaMin{"cfgMuonMatchEtaMin", -4.0f, "Definition of the acceptance of muon tracks to be matched with MFT"}; + Configurable fMuonMatchEtaMax{"cfgMuonMatchEtaMax", -2.5f, "Definition of the acceptance of muon tracks to be matched with MFT"}; + Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; o2::parameters::GRPObject* grpmagrun2 = nullptr; // for run 2, we access the GRPObject from GLO/GRP/GRP o2::parameters::GRPMagField* grpmag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField @@ -190,7 +199,6 @@ struct TableMakerMC { void init(o2::framework::InitContext& context) { - LOG(info) << "init IN"; DefineCuts(); VarManager::SetDefaultVarNames(); @@ -279,6 +287,7 @@ struct TableMakerMC { if (!o2::base::GeometryManager::isGeometryLoaded()) { fCCDB->get(geoPath); } + fCCDBApi.init(fConfigCcdbUrl.value); } void DefineCuts() @@ -318,7 +327,6 @@ struct TableMakerMC { // skim MC collisions // NOTE: So far, all MC collisions are skimmed. In case there will be filtering based on MC collisions, // one has to do a mapping of the old vs new indices so that the skimmed labels are properly updated. - LOG(info) << "skimMCCollisions IN"; VarManager::ResetValues(0, VarManager::kNVars); for (auto& mcCollision : mcCollisions) { @@ -328,7 +336,6 @@ struct TableMakerMC { eventMC(mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.t(), mcCollision.weight(), mcCollision.impactParameter()); } - LOG(info) << "skimMCCollisions lastIndex :: " << eventMC.lastIndex(); } void skimMCParticles(aod::McParticles const& mcTracks, aod::McCollisions const&) @@ -338,8 +345,6 @@ struct TableMakerMC { fLabelsMapReversed.clear(); fMCFlags.clear(); - LOG(info) << "skimMCParticles IN"; - uint16_t mcflags = 0; int trackCounter = 0; @@ -351,9 +356,9 @@ struct TableMakerMC { bool checked = false; if constexpr (soa::is_soa_filtered_v) { auto mctrack_raw = mcTracks.rawIteratorAt(mctrack.globalIndex()); - checked = sig.CheckSignal(false, mctrack_raw); + checked = sig.CheckSignal(true, mctrack_raw); } else { - checked = sig.CheckSignal(false, mctrack); + checked = sig.CheckSignal(true, mctrack); } if (checked) { mcflags |= (uint16_t(1) << i); @@ -384,11 +389,10 @@ struct TableMakerMC { } } } // end loop over mc stack - LOG(info) << "skimMCParticles added particles :: " << fLabelsMap.size(); } template - void skimCollisions(TEvents const& collisions, BCsWithTimestamps const& bcs) + void skimCollisions(TEvents const& collisions, BCsWithTimestamps const& /*bcs*/) { // Skim collisions fCollIndexMap.clear(); @@ -405,8 +409,6 @@ struct TableMakerMC { int multTracksPV = -1.0; float centFT0C = -1.0; - LOG(info) << "skimCollisions IN"; - for (const auto& collision : collisions) { for (int i = 0; i < o2::aod::evsel::kNsel; i++) { @@ -478,6 +480,7 @@ struct TableMakerMC { multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventMClabels(collision.mcCollisionId(), collision.mcMask()); + eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMultExtra) > 0) { multPV(collision.multNTracksHasITS(), collision.multNTracksHasTPC(), collision.multNTracksHasTOF(), collision.multNTracksHasTRD(), collision.multNTracksITSOnly(), collision.multNTracksTPCOnly(), collision.multNTracksITSTPC(), collision.trackOccupancyInTimeRange()); @@ -487,12 +490,10 @@ struct TableMakerMC { fCollIndexMap[collision.globalIndex()] = event.lastIndex(); } - - LOG(info) << "skimCollisions event.lastIndex() :: " << event.lastIndex(); } template - void skimTracks(TEvent const& collision, TTracks const& tracks, TrackAssoc const& assocs, aod::McParticles const& mcTracks) + void skimTracks(TEvent const& collision, TTracks const& /*tracks*/, TrackAssoc const& assocs, aod::McParticles const& mcTracks) { // Skim the barrel tracks // Loop over the collision-track associations, retrieve the track, and apply track cuts for selection @@ -504,8 +505,6 @@ struct TableMakerMC { uint16_t mcflags = 0; int trackCounter = fLabelsMap.size(); - LOG(info) << "skimTracks IN"; - for (const auto& assoc : assocs) { auto track = assoc.template track_as(); @@ -521,6 +520,9 @@ struct TableMakerMC { trackFilteringTag = uint64_t(0); trackTempFilterMap = uint8_t(0); VarManager::FillTrack(track); + if (fPropTrack && (track.collisionId() != collision.globalIndex())) { + VarManager::FillTrackCollision(track, collision); + } if (fDoDetailedQA) { fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); } @@ -564,6 +566,7 @@ struct TableMakerMC { fCollIndexMap.find(track.collisionId()) != fCollIndexMap.end()) { // if the original track collisionId is from a not skimmed collision, keep -1 as coll index reducedEventIdx = fCollIndexMap[track.collisionId()]; } + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ(), track.globalIndex()); trackBasic(reducedEventIdx, trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), 0); trackBarrel(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), @@ -627,17 +630,13 @@ struct TableMakerMC { // write the skimmed collision - track association trackBarrelAssoc(fCollIndexMap[collision.globalIndex()], fTrackIndexMap[track.globalIndex()]); } // end loop over associations - - LOG(info) << "skimTracks track.lastIndex() / trackAssoc.lastIndex() :: " << trackBasic.lastIndex() << " / " << trackBarrelAssoc.lastIndex(); } // end skimTracks template - void skimMFT(TEvent const& collision, MFTTracks const& mfts, MFTTrackAssoc const& mftAssocs) + void skimMFT(TEvent const& collision, MFTTracks const& /*mfts*/, MFTTrackAssoc const& mftAssocs) { // Skim MFT tracks // So far no cuts are applied here - LOG(info) << "skimMFT IN"; - for (const auto& assoc : mftAssocs) { auto track = assoc.template mfttrack_as(); @@ -657,19 +656,15 @@ struct TableMakerMC { } mftAssoc(fCollIndexMap[collision.globalIndex()], fMftIndexMap[track.globalIndex()]); } - - LOG(info) << "skimMFT mftTrack.lastIndex()/mftAssoc.lastIndex() :: " << mftTrack.lastIndex() << " / " << mftAssoc.lastIndex(); } - template - void skimMuons(TEvent const& collision, TMuons const& muons, FwdTrackAssoc const& muonAssocs, aod::McParticles const& mcTracks) + template + void skimMuons(TEvent const& collision, TMuons const& muons, FwdTrackAssoc const& muonAssocs, aod::McParticles const& mcTracks, TMFTTracks const& /*mftTracks*/) { // Skim the fwd-tracks (muons) // Loop over the collision-track associations, recompute track properties depending on the collision assigned, and apply track cuts for selection // Muons are written only once, even if they constribute to more than one association, // which means that in the case of multiple associations, the track parameters are wrong and should be computed again at analysis time. - LOG(info) << "skimMuons IN"; - uint8_t trackFilteringTag = uint8_t(0); uint8_t trackTempFilterMap = uint8_t(0); fFwdTrackIndexMapReversed.clear(); @@ -683,10 +678,25 @@ struct TableMakerMC { auto muon = assoc.template fwdtrack_as(); trackFilteringTag = uint8_t(0); + trackTempFilterMap = uint8_t(0); VarManager::FillTrack(muon); // NOTE: If a muon is associated to multiple collisions, depending on the selections, // it may be accepted for some associations and rejected for other - VarManager::FillPropagateMuon(muon, collision); + if (fPropMuon) { + VarManager::FillPropagateMuon(muon, collision); + } + // recalculte pDca and global muon kinematics + if (static_cast(muon.trackType()) < 2 && fRefitGlobalMuon) { + auto muontrack = muon.template matchMCHTrack_as(); + if (muontrack.eta() < fMuonMatchEtaMin || muontrack.eta() > fMuonMatchEtaMax) { + continue; + } + auto mfttrack = muon.template matchMFTTrack_as(); + VarManager::FillTrackCollision(muontrack, collision); + VarManager::FillGlobalMuonRefit(muontrack, mfttrack, collision); + } else { + VarManager::FillTrackCollision(muon, collision); + } if (fDoDetailedQA) { fHistMan->FillHistClass("Muons_BeforeCuts", VarManager::fgValues); @@ -786,18 +796,31 @@ struct TableMakerMC { mftIdx = fMftIndexMap[muon.matchMFTTrackId()]; } } - muonBasic(reducedEventIdx, mchIdx, mftIdx, fFwdTrackFilterMap[muon.globalIndex()], muon.pt(), muon.eta(), muon.phi(), muon.sign(), 0); - muonExtra(muon.nClusters(), muon.pDca(), muon.rAtAbsorberEnd(), + VarManager::FillTrack(muon); + if (fPropMuon) { + VarManager::FillPropagateMuon(muon, collision); + } + // recalculte pDca and global muon kinematics + if (static_cast(muon.trackType()) < 2 && fRefitGlobalMuon) { + auto muontrack = muon.template matchMCHTrack_as(); + auto mfttrack = muon.template matchMFTTrack_as(); + VarManager::FillTrackCollision(muontrack, collision); + VarManager::FillGlobalMuonRefit(muontrack, mfttrack, collision); + } else { + VarManager::FillTrackCollision(muon, collision); + } + muonBasic(reducedEventIdx, mchIdx, mftIdx, fFwdTrackFilterMap[muon.globalIndex()], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], muon.sign(), 0); + muonExtra(muon.nClusters(), VarManager::fgValues[VarManager::kMuonPDca], VarManager::fgValues[VarManager::kMuonRAtAbsorberEnd], muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), muon.matchScoreMCHMFT(), muon.mchBitMap(), muon.midBitMap(), - muon.midBoards(), muon.trackType(), muon.fwdDcaX(), muon.fwdDcaY(), + muon.midBoards(), muon.trackType(), VarManager::fgValues[VarManager::kMuonDCAx], VarManager::fgValues[VarManager::kMuonDCAy], muon.trackTime(), muon.trackTimeRes()); if constexpr (static_cast(TMuonFillMap & VarManager::ObjTypes::MuonCov)) { - muonCov(muon.x(), muon.y(), muon.z(), muon.phi(), muon.tgl(), muon.sign() / muon.pt(), - muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), muon.cPhiPhi(), - muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), muon.c1PtX(), muon.c1PtY(), - muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()); + muonCov(VarManager::fgValues[VarManager::kX], VarManager::fgValues[VarManager::kY], VarManager::fgValues[VarManager::kZ], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kTgl], muon.sign() / VarManager::fgValues[VarManager::kPt], + VarManager::fgValues[VarManager::kMuonCXX], VarManager::fgValues[VarManager::kMuonCXY], VarManager::fgValues[VarManager::kMuonCYY], VarManager::fgValues[VarManager::kMuonCPhiX], VarManager::fgValues[VarManager::kMuonCPhiY], VarManager::fgValues[VarManager::kMuonCPhiPhi], + VarManager::fgValues[VarManager::kMuonCTglX], VarManager::fgValues[VarManager::kMuonCTglY], VarManager::fgValues[VarManager::kMuonCTglPhi], VarManager::fgValues[VarManager::kMuonCTglTgl], VarManager::fgValues[VarManager::kMuonC1Pt2X], VarManager::fgValues[VarManager::kMuonC1Pt2Y], + VarManager::fgValues[VarManager::kMuonC1Pt2Phi], VarManager::fgValues[VarManager::kMuonC1Pt2Tgl], VarManager::fgValues[VarManager::kMuonC1Pt21Pt2]); } if (muon.has_mcParticle()) { auto mctrack = muon.template mcParticle_as(); @@ -806,7 +829,6 @@ struct TableMakerMC { muonLabels(-1, 0, 0); } } // end loop over selected muons - LOG(info) << "skimMuons muonBasic.lastIndex()/muonAssoc.lastIndex() :: " << muonBasic.lastIndex() << " / " << muonAssoc.lastIndex(); } // end skimMuons template 0 && fCurrentRun != bcs.begin().runNumber()) { if (fIsRun2 == true) { grpmagrun2 = fCCDB->getForTimeStamp(grpmagPathRun2, bcs.begin().timestamp()); @@ -830,8 +850,13 @@ struct TableMakerMC { o2::base::Propagator::initFieldFromGRP(grpmag); } } + std::map metadataRCT, header; + header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", bcs.begin().runNumber()), metadataRCT, -1); + uint64_t sor = std::atol(header["SOR"].c_str()); + uint64_t eor = std::atol(header["EOR"].c_str()); + VarManager::SetSORandEOR(sor, eor); + fCurrentRun = bcs.begin().runNumber(); - LOG(info) << "fullSkimming CCDB read"; } // skim MC Collisions @@ -847,6 +872,7 @@ struct TableMakerMC { eventExtended.reserve(collisions.size()); eventVtxCov.reserve(collisions.size()); eventMClabels.reserve(collisions.size()); + eventInfo.reserve(collisions.size()); skimCollisions(collisions, bcs); if (fCollIndexMap.size() == 0) { return; @@ -854,6 +880,7 @@ struct TableMakerMC { if constexpr (static_cast(TTrackFillMap)) { fTrackIndexMap.clear(); + trackBarrelInfo.reserve(tracksBarrel.size()); trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); trackBarrelCov.reserve(tracksBarrel.size()); @@ -893,8 +920,13 @@ struct TableMakerMC { skimMFT(collision, mftTracks, groupedMFTIndices); } if constexpr (static_cast(TMuonFillMap)) { - auto groupedMuonIndices = fwdTrackAssocs.sliceBy(fwdtrackIndicesPerCollision, origIdx); - skimMuons(collision, muons, groupedMuonIndices, mcParticles); + if constexpr (static_cast(TMFTFillMap)) { + auto groupedMuonIndices = fwdTrackAssocs.sliceBy(fwdtrackIndicesPerCollision, origIdx); + skimMuons(collision, muons, groupedMuonIndices, mcParticles, mftTracks); + } else { + auto groupedMuonIndices = fwdTrackAssocs.sliceBy(fwdtrackIndicesPerCollision, origIdx); + skimMuons(collision, muons, groupedMuonIndices, mcParticles, nullptr); + } } } // end loop over skimmed collisions } @@ -1042,7 +1074,6 @@ struct TableMakerMC { aod::TrackAssoc const& trackAssocs, aod::FwdTrackAssoc const& fwdTrackAssocs, aod::MFTTrackAssoc const& mftAssocs, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { - LOG(info) << "processPP IN"; fullSkimming(collisions, bcs, tracksBarrel, tracksMuon, mftTracks, trackAssocs, fwdTrackAssocs, mftAssocs, mcCollisions, mcParticles); } diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index f1dc2ca933b..f7df4a672bc 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -61,20 +61,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; -// DQ triggers -enum DQTriggers { - kSingleE = 1 << 0, // 0000001 - kLMeeIMR = 1 << 1, // 0000010 - kLMeeHMR = 1 << 2, // 0000100 - kDiElectron = 1 << 3, // 0001000 - kSingleMuLow = 1 << 4, // 0010000 - kSingleMuHigh = 1 << 5, // 0100000 - kDiMuon = 1 << 6, // 1000000 - kNTriggersDQ -}; - Zorro zorro; -std::string zorroTriggerMask[7] = {"fSingleE", "fLMeeIMR", "fLMeeHMR", "fDiElectron", "fSingleMuLow", "fSingleMuHigh", "fDiMuon"}; // TODO: Since DCA depends on which collision the track is associated to, we should remove writing and subscribing to DCA tables, to optimize on CPU / memory using MyBarrelTracks = soa::Join; using MyEventsWithFilter = soa::Join; using MyEventsWithMultsAndFilter = soa::Join; using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MyMuons = soa::Join; using MyMuonsWithCov = soa::Join; using MyMuonsColl = soa::Join; @@ -124,15 +111,16 @@ DECLARE_SOA_TABLE(AmbiguousTracksFwd, "AOD", "AMBIGUOUSFWDTR", //! Table for Fwd // constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; // constexpr static uint32_t gkEventFillMapWithFilter = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::EventFilter; -// constexpr static uint32_t gkEventFillMapWithMult = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult; +constexpr static uint32_t gkEventFillMapWithMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult; +constexpr static uint32_t gkEventFillMapWithMultsZdc = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult | VarManager::ObjTypes::Zdc; constexpr static uint32_t gkEventFillMapWithMultsAndEventFilter = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult | VarManager::ObjTypes::CollisionMultExtra | VarManager::ObjTypes::EventFilter; constexpr static uint32_t gkEventFillMapWithMultsEventFilterZdc = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult | VarManager::ObjTypes::EventFilter | VarManager::ObjTypes::Zdc; // constexpr static uint32_t gkEventFillMapWithCent = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent; -constexpr static uint32_t gkEventFillMapWithCentAndMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent | VarManager::CollisionMult; +constexpr static uint32_t gkEventFillMapWithCentAndMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent | VarManager::CollisionMult | VarManager::ObjTypes::CollisionMultExtra; // constexpr static uint32_t gkEventFillMapWithCentRun2 = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCentRun2; // Unused variable // constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackPID | VarManager::ObjTypes::TrackPIDExtra; constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID | VarManager::ObjTypes::TrackPIDExtra; -// constexpr static uint32_t gkTrackFillMapWithV0Bits = gkTrackFillMapWithCov | VarManager::ObjTypes::TrackV0Bits; +constexpr static uint32_t gkTrackFillMapWithV0Bits = gkTrackFillMapWithCov | VarManager::ObjTypes::TrackV0Bits; // constexpr static uint32_t gkTrackFillMapWithV0BitsForMaps = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackV0Bits | VarManager::ObjTypes::TrackTPCPID; // constexpr static uint32_t gkTrackFillMapWithDalitzBits = gkTrackFillMap | VarManager::ObjTypes::DalitzBits; // constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::Muon; @@ -147,14 +135,15 @@ struct TableMaker { Produces event; Produces eventExtended; Produces eventVtxCov; + Produces eventInfo; Produces zdc; Produces multPV; Produces multAll; + Produces trackBarrelInfo; Produces trackBasic; Produces trackBarrel; Produces trackBarrelCov; Produces trackBarrelPID; - Produces trackBarrelInfo; Produces trackBarrelAssoc; Produces muonBasic; Produces muonExtra; @@ -175,6 +164,7 @@ struct TableMaker { Configurable fConfigTrackCuts{"cfgBarrelTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable fConfigMuonCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; + Configurable fConfigZorroTrigMask{"cfgZorroTriggerMask", "fDiMuon", "DQ Trigger masks: fSingleE,fLMeeIMR,fLMeeHMR,fDiElectron,fSingleMuLow,fSingleMuHigh,fDiMuon"}; // Steer QA output Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; @@ -197,6 +187,7 @@ struct TableMaker { // CCDB connection configurables Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbPathZorro{"ccdb-path-zorro", "Users/r/rlietava/EventFiltering/OTS/", "base path to the ccdb object for zorro"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; @@ -210,8 +201,14 @@ struct TableMaker { Configurable fConfigDummyRunlist{"cfgDummyRunlist", false, "If true, use dummy runlist"}; Configurable fConfigInitRunNumber{"cfgInitRunNumber", 543215, "Initial run number used in run by run checks"}; + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propagate tracks to associated collision to recalculate DCA and momentum vector"}; + // Muon related options - Configurable fPropMuon{"cfgPropMuon", true, "Propgate muon tracks through absorber (do not use if applying pairing)"}; + Configurable fPropMuon{"cfgPropMuon", true, "Propagate muon tracks through absorber (do not use if applying pairing)"}; + Configurable fRefitGlobalMuon{"cfgRefitGlobalMuon", true, "Correct global muon parameters"}; + Configurable fMuonMatchEtaMin{"cfgMuonMatchEtaMin", -4.0f, "Definition of the acceptance of muon tracks to be matched with MFT"}; + Configurable fMuonMatchEtaMax{"cfgMuonMatchEtaMax", -2.5f, "Definition of the acceptance of muon tracks to be matched with MFT"}; Service fCCDB; @@ -223,6 +220,7 @@ struct TableMaker { std::vector fMuonCuts; //! Muon track cuts Service ccdb; + o2::ccdb::CcdbApi fCCDBApi; bool fDoDetailedQA = false; // Bool to set detailed QA true, if QA is set true int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. @@ -278,9 +276,9 @@ struct TableMaker { histClasses += "Event_AfterCuts;"; } - bool enableBarrelHistos = (context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterBarrelOnly") || - context.mOptions.get("processPbPb") || context.mOptions.get("processPbPbBarrelOnly")); - bool enableMuonHistos = (context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterMuonOnly") || context.mOptions.get("processPPWithFilterMuonMFT") || + bool enableBarrelHistos = (context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnly") || + context.mOptions.get("processPbPb") || context.mOptions.get("processPbPbBarrelOnly") || context.mOptions.get("processPbPbBarrelOnlyWithV0Bits")); + bool enableMuonHistos = (context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterMuonOnly") || context.mOptions.get("processPPWithFilterMuonMFT") || context.mOptions.get("processPPMuonOnly") || context.mOptions.get("processPPMuonMFT") || context.mOptions.get("processPbPb") || context.mOptions.get("processPbPbMuonOnly") || context.mOptions.get("processPbPbMuonMFT")); if (enableBarrelHistos) { @@ -326,6 +324,7 @@ struct TableMaker { // Not later than now objects fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); } + fCCDBApi.init(fConfigCcdbUrl.value); } void DefineCuts() @@ -411,7 +410,7 @@ struct TableMaker { fStatsList.setObject(new TList()); fStatsList->SetOwner(kTRUE); std::vector eventLabels{"BCs", "Collisions before filtering", "Before cuts", "After cuts"}; - TH2I* histEvents = new TH2I("EventStats", "Event statistics", eventLabels.size(), -0.5, eventLabels.size() - 0.5, o2::aod::evsel::kNsel + 1, -0.5, static_cast(o2::aod::evsel::kNsel) + 0.5); + TH2D* histEvents = new TH2D("EventStats", "Event statistics", eventLabels.size(), -0.5, eventLabels.size() - 0.5, o2::aod::evsel::kNsel + 1, -0.5, static_cast(o2::aod::evsel::kNsel) + 0.5); int ib = 1; for (auto label = eventLabels.begin(); label != eventLabels.end(); label++, ib++) { histEvents->GetXaxis()->SetBinLabel(ib, (*label).Data()); @@ -423,7 +422,7 @@ struct TableMaker { fStatsList->Add(histEvents); // Track statistics: one bin for each track selection and 5 bins for V0 tags (gamma, K0s, Lambda, anti-Lambda, Omega) - TH1I* histTracks = new TH1I("TrackStats", "Track statistics", fTrackCuts.size() + 5.0, -0.5, fTrackCuts.size() - 0.5 + 5.0); + TH1D* histTracks = new TH1D("TrackStats", "Track statistics", fTrackCuts.size() + 5.0, -0.5, fTrackCuts.size() - 0.5 + 5.0); ib = 1; for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, ib++) { histTracks->GetXaxis()->SetBinLabel(ib, (*cut).GetName()); @@ -433,7 +432,7 @@ struct TableMaker { histTracks->GetXaxis()->SetBinLabel(fTrackCuts.size() + 1 + ib, v0TagNames[ib]); } fStatsList->Add(histTracks); - TH1I* histMuons = new TH1I("MuonStats", "Muon statistics", fMuonCuts.size(), -0.5, fMuonCuts.size() - 0.5); + TH1D* histMuons = new TH1D("MuonStats", "Muon statistics", fMuonCuts.size(), -0.5, fMuonCuts.size() - 0.5); ib = 1; for (auto cut = fMuonCuts.begin(); cut != fMuonCuts.end(); cut++, ib++) { histMuons->GetXaxis()->SetBinLabel(ib, (*cut).GetName()); @@ -441,8 +440,9 @@ struct TableMaker { fStatsList->Add(histMuons); } - template - void skimCollisions(TEvents const& collisions, TBCs const& /*bcs*/, TZdcs const& /*zdcs*/) + template + void skimCollisions(TEvents const& collisions, TBCs const& /*bcs*/, TZdcs const& /*zdcs*/, + TTrackAssoc const& trackAssocs, TTracks const& tracks) { // Skim collisions // NOTE: So far, collisions are filtered based on the user specified analysis cuts and the filterPP event filter. @@ -461,23 +461,15 @@ struct TableMaker { int multTracklets = -1.0; int multTracksPV = -1.0; float centFT0C = -1.0; - /*float energyCommonZNA = -1.0; - float energyCommonZNC = -1.0; - float energyCommonZPA = -1.0; - float energyCommonZPC = -1.0; - float timeZNA = -1.0; - float timeZNC = -1.0; - float timeZPA = -1.0; - float timeZPC = -1.0;*/ for (const auto& collision : collisions) { for (int i = 0; i < o2::aod::evsel::kNsel; i++) { if (collision.selection_bit(i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(o2::aod::evsel::kNsel)); + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(o2::aod::evsel::kNsel)); // apply the event filter computed by filter-PP if constexpr ((TEventFillMap & VarManager::ObjTypes::EventFilter) > 0) { @@ -507,24 +499,11 @@ struct TableMaker { if (bcEvSel.has_zdc()) { auto bc_zdc = bcEvSel.zdc(); VarManager::FillZDC(bc_zdc); - /*energyCommonZNA = bc_zdc.energyCommonZNA(); - energyCommonZNC = bc_zdc.energyCommonZNC(); - energyCommonZPA = bc_zdc.energyCommonZPA(); - energyCommonZPC = bc_zdc.energyCommonZPC(); - timeZNA = bc_zdc.timeZNA(); - timeZNC = bc_zdc.timeZNC(); - timeZPA = bc_zdc.timeZPA(); - timeZPC = bc_zdc.timeZPC();*/ - } /*else { - energyCommonZNA = -1.0; - energyCommonZNC = -1.0; - energyCommonZPA = -1.0; - energyCommonZPC = -1.0; - timeZNA = -1.0; - timeZNC = -1.0; - timeZPA = -1.0; - timeZPC = -1.0; - }*/ + } + } + if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMultExtra) > 0 && (TTrackFillMap & VarManager::ObjTypes::Track) > 0 && (TTrackFillMap & VarManager::ObjTypes::TrackDCA) > 0) { + auto groupedTrackIndices = trackAssocs.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + VarManager::FillEventTrackEstimators(collision, groupedTrackIndices, tracks); } if (fDoDetailedQA) { fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); @@ -533,31 +512,30 @@ struct TableMaker { // fill stats information, before selections for (int i = 0; i < o2::aod::evsel::kNsel; i++) { if (collision.selection_bit(i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(o2::aod::evsel::kNsel)); + (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(o2::aod::evsel::kNsel)); if (fConfigRunZorro) { - for (int i = 0; i < kNTriggersDQ; ++i) { - zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), zorroTriggerMask[i]); - if (!zorro.isSelected(bc.globalBC())) { - tag |= static_cast(1 << i); - } + zorro.setBaseCCDBPath(fConfigCcdbPathZorro.value); + zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), fConfigZorroTrigMask.value); + if (zorro.isSelected(bc.globalBC())) { + tag |= (static_cast(true) << 56); // the same bit is used for this zorro selections from ccdb } } else { if (!fEventCut->IsSelected(VarManager::fgValues)) { - return; + continue; } } // fill stats information, after selections for (int i = 0; i < o2::aod::evsel::kNsel; i++) { if (collision.selection_bit(i)) { - (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(o2::aod::evsel::kNsel)); + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(o2::aod::evsel::kNsel)); fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); @@ -582,18 +560,23 @@ struct TableMaker { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::Zdc) > 0) { if (bcEvSel.has_zdc()) { auto bc_zdc = bcEvSel.zdc(); zdc(bc_zdc.energyCommonZNA(), bc_zdc.energyCommonZNC(), bc_zdc.energyCommonZPA(), bc_zdc.energyCommonZPC(), bc_zdc.timeZNA(), bc_zdc.timeZNC(), bc_zdc.timeZPA(), bc_zdc.timeZPC()); + } else { + zdc(-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0); } } if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMultExtra) > 0) { multPV(collision.multNTracksHasITS(), collision.multNTracksHasTPC(), collision.multNTracksHasTOF(), collision.multNTracksHasTRD(), collision.multNTracksITSOnly(), collision.multNTracksTPCOnly(), collision.multNTracksITSTPC(), collision.trackOccupancyInTimeRange()); + multAll(collision.multAllTracksTPCOnly(), collision.multAllTracksITSTPC(), - 0, 0, 0.0, 0.0, 0, 0); + VarManager::fgValues[VarManager::kNTPCpileupContribA], VarManager::fgValues[VarManager::kNTPCpileupContribC], + VarManager::fgValues[VarManager::kNTPCpileupZA], VarManager::fgValues[VarManager::kNTPCpileupZC], 0, 0); } fCollIndexMap[collision.globalIndex()] = event.lastIndex(); @@ -611,12 +594,23 @@ struct TableMaker { uint64_t trackFilteringTag = uint64_t(0); uint64_t trackTempFilterMap = uint8_t(0); + // material correction for track propagation + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + for (const auto& assoc : assocs) { + // get track auto track = assoc.template track_as(); trackFilteringTag = uint64_t(0); trackTempFilterMap = uint8_t(0); VarManager::FillTrack(track); + + // compute quantities which depend on the associated collision, such as DCA + if (fPropTrack && (track.collisionId() != collision.globalIndex())) { + VarManager::FillTrackCollisionMatCorr(track, collision, noMatCorr, o2::base::Propagator::Instance()); + } + if (fDoDetailedQA) { fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); } @@ -631,7 +625,7 @@ struct TableMaker { if (fConfigQA) { fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), VarManager::fgValues); } - (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); + (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); } } if (!trackTempFilterMap) { @@ -643,7 +637,7 @@ struct TableMaker { trackFilteringTag |= uint64_t(track.pidbit()); for (int iv0 = 0; iv0 < 5; iv0++) { if (track.pidbit() & (uint8_t(1) << iv0)) { - (reinterpret_cast(fStatsList->At(1)))->Fill(fTrackCuts.size() + static_cast(iv0)); + (reinterpret_cast(fStatsList->At(1)))->Fill(fTrackCuts.size() + static_cast(iv0)); } } if (fConfigIsOnlyforMaps) { @@ -685,7 +679,7 @@ struct TableMaker { uint32_t reducedEventIdx = fCollIndexMap[collision.globalIndex()]; // NOTE: trackBarrelInfo stores the index of the collision as in AO2D (for use in some cases where the analysis on skims is done // in workflows where the original AO2Ds are also present) - trackBarrelInfo(collision.globalIndex(), collision.posX(), collision.posY(), collision.posZ()); + trackBarrelInfo(collision.globalIndex(), collision.posX(), collision.posY(), collision.posZ(), track.globalIndex()); trackBasic(reducedEventIdx, trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), 0); trackBarrel(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), @@ -744,8 +738,8 @@ struct TableMaker { } } - template - void skimMuons(TEvent const& collision, TBCs const& /*bcs*/, TMuons const& muons, FwdTrackAssoc const& muonAssocs, MFTTracks const& mftTracks) + template + void skimMuons(TEvent const& collision, TBCs const& /*bcs*/, TMuons const& muons, FwdTrackAssoc const& muonAssocs, TMFTTracks const& /*mftTracks*/) { // Skim the fwd-tracks (muons) // Loop over the collision-track associations, recompute track properties depending on the collision assigned, and apply track cuts for selection @@ -763,6 +757,7 @@ struct TableMaker { auto muon = assoc.template fwdtrack_as(); trackFilteringTag = uint8_t(0); + trackTempFilterMap = uint8_t(0); VarManager::FillTrack(muon); // NOTE: If a muon is associated to multiple collisions, depending on the selections, // it may be accepted for some associations and rejected for other @@ -770,8 +765,11 @@ struct TableMaker { VarManager::FillPropagateMuon(muon, collision); } // recalculte pDca and global muon kinematics - if (static_cast(muon.trackType()) < 2) { + if (static_cast(muon.trackType()) < 2 && fRefitGlobalMuon) { auto muontrack = muon.template matchMCHTrack_as(); + if (muontrack.eta() < fMuonMatchEtaMin || muontrack.eta() > fMuonMatchEtaMax) { + continue; + } auto mfttrack = muon.template matchMFTTrack_as(); VarManager::FillTrackCollision(muontrack, collision); VarManager::FillGlobalMuonRefit(muontrack, mfttrack, collision); @@ -790,7 +788,7 @@ struct TableMaker { if (fConfigQA) { fHistMan->FillHistClass(Form("Muons_%s", (*cut).GetName()), VarManager::fgValues); } - (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(i)); + (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(i)); } } @@ -839,6 +837,19 @@ struct TableMaker { mftIdx = fMftIndexMap[muon.matchMFTTrackId()]; } } + VarManager::FillTrack(muon); + if (fPropMuon) { + VarManager::FillPropagateMuon(muon, collision); + } + // recalculte pDca and global muon kinematics + if (static_cast(muon.trackType()) < 2 && fRefitGlobalMuon) { + auto muontrack = muon.template matchMCHTrack_as(); + auto mfttrack = muon.template matchMFTTrack_as(); + VarManager::FillTrackCollision(muontrack, collision); + VarManager::FillGlobalMuonRefit(muontrack, mfttrack, collision); + } else { + VarManager::FillTrackCollision(muon, collision); + } muonBasic(reducedEventIdx, mchIdx, mftIdx, fFwdTrackFilterMap[muon.globalIndex()], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], muon.sign(), 0); muonExtra(muon.nClusters(), VarManager::fgValues[VarManager::kMuonPDca], VarManager::fgValues[VarManager::kMuonRAtAbsorberEnd], muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), @@ -865,7 +876,7 @@ struct TableMaker { TTrackAssoc const& trackAssocs, TFwdTrackAssoc const& fwdTrackAssocs, TMFTTrackAssoc const& mftAssocs) { - if (fCurrentRun != bcs.begin().runNumber()) { + if (bcs.size() > 0 && fCurrentRun != bcs.begin().runNumber()) { if (fConfigComputeTPCpostCalib) { auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bcs.begin().timestamp()); VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); @@ -890,20 +901,30 @@ struct TableMaker { o2::base::Propagator::initFieldFromGRP(grpmag); } } + std::map metadataRCT, header; + header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", bcs.begin().runNumber()), metadataRCT, -1); + uint64_t sor = std::atol(header["SOR"].c_str()); + uint64_t eor = std::atol(header["EOR"].c_str()); + VarManager::SetSORandEOR(sor, eor); + fCurrentRun = bcs.begin().runNumber(); } // skim collisions - skimCollisions(collisions, bcs, zdcs); + event.reserve(collisions.size()); + eventExtended.reserve(collisions.size()); + eventVtxCov.reserve(collisions.size()); + + skimCollisions(collisions, bcs, zdcs, trackAssocs, tracksBarrel); if (fCollIndexMap.size() == 0) { return; } if constexpr (static_cast(TTrackFillMap)) { fTrackIndexMap.clear(); + trackBarrelInfo.reserve(tracksBarrel.size()); trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); - trackBarrelInfo.reserve(tracksBarrel.size()); trackBarrelCov.reserve(tracksBarrel.size()); trackBarrelPID.reserve(tracksBarrel.size()); trackBarrelAssoc.reserve(tracksBarrel.size()); @@ -938,9 +959,14 @@ struct TableMaker { auto groupedMFTIndices = mftAssocs.sliceBy(mfttrackIndicesPerCollision, origIdx); skimMFT(collision, bcs, mftTracks, groupedMFTIndices); } - if constexpr (static_cast(TMuonFillMap) && static_cast(TMFTFillMap)) { - auto groupedMuonIndices = fwdTrackAssocs.sliceBy(fwdtrackIndicesPerCollision, origIdx); - skimMuons(collision, bcs, muons, groupedMuonIndices, mftTracks); + if constexpr (static_cast(TMuonFillMap)) { + if constexpr (static_cast(TMFTFillMap)) { + auto groupedMuonIndices = fwdTrackAssocs.sliceBy(fwdtrackIndicesPerCollision, origIdx); + skimMuons(collision, bcs, muons, groupedMuonIndices, mftTracks); + } else { + auto groupedMuonIndices = fwdTrackAssocs.sliceBy(fwdtrackIndicesPerCollision, origIdx); + skimMuons(collision, bcs, muons, groupedMuonIndices, nullptr); + } } } // end loop over skimmed collisions } @@ -982,6 +1008,29 @@ struct TableMaker { fullSkimming(collisions, bcs, nullptr, nullptr, muons, mftTracks, nullptr, fwdTrackAssocs, mftAssocs); } + // produce the barrel-only DQ skimmed data model typically for pp/p-Pb or UPC Pb-Pb (no centrality), meant to run on skimmed data + void processPPBarrelOnly(MyEventsWithMults const& collisions, MyBCs const& bcs, aod::Zdcs& zdcs, + MyBarrelTracksWithCov const& tracksBarrel, + TrackAssoc const& trackAssocs) + { + fullSkimming(collisions, bcs, zdcs, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr); + } + + // produce the muon-only DQ skimmed data model typically for pp/p-Pb or UPC Pb-Pb (no centrality), meant to run on skimmed data + void processPPMuonOnly(MyEventsWithMults const& collisions, BCsWithTimestamps const& bcs, + MyMuonsWithCov const& muons, FwdTrackAssoc const& fwdTrackAssocs, MFTTracks const& mftTracks) + { + fullSkimming(collisions, bcs, nullptr, nullptr, muons, nullptr, nullptr, fwdTrackAssocs, nullptr); + } + + // produce the muon+mft DQ skimmed data model typically for pp/p-Pb or UPC Pb-Pb (no centrality), meant to run on skimmed data + void processPPMuonMFT(MyEventsWithMults const& collisions, BCsWithTimestamps const& bcs, + MyMuonsWithCov const& muons, MFTTracks const& mftTracks, + FwdTrackAssoc const& fwdTrackAssocs, MFTTrackAssoc const& mftAssocs) + { + fullSkimming(collisions, bcs, nullptr, nullptr, muons, mftTracks, nullptr, fwdTrackAssocs, mftAssocs); + } + // produce the full DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter void processPbPb(MyEventsWithCentAndMults const& collisions, BCsWithTimestamps const& bcs, MyBarrelTracksWithCov const& tracksBarrel, @@ -1000,6 +1049,14 @@ struct TableMaker { fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr); } + // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter + void processPbPbBarrelOnlyWithV0Bits(MyEventsWithCentAndMults const& collisions, BCsWithTimestamps const& bcs, + MyBarrelTracksWithV0Bits const& tracksBarrel, + TrackAssoc const& trackAssocs) + { + fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr); + } + // produce the muon only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter void processPbPbMuonOnly(MyEventsWithCentAndMults const& collisions, BCsWithTimestamps const& bcs, MyMuonsWithCov const& muons, FwdTrackAssoc const& fwdTrackAssocs) @@ -1020,18 +1077,22 @@ struct TableMaker { { for (int i = 0; i < o2::aod::evsel::kNsel; i++) { if (bc.selection_bit(i) > 0) { - (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(i)); + (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(i)); } } - (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(o2::aod::evsel::kNsel)); + (reinterpret_cast(fStatsList->At(0)))->Fill(0.0, static_cast(o2::aod::evsel::kNsel)); } PROCESS_SWITCH(TableMaker, processPPWithFilter, "Build full DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb, w/ event filtering", false); PROCESS_SWITCH(TableMaker, processPPWithFilterBarrelOnly, "Build barrel only DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb, w/ event filtering", false); PROCESS_SWITCH(TableMaker, processPPWithFilterMuonOnly, "Build muon only DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb, w/ event filtering", false); PROCESS_SWITCH(TableMaker, processPPWithFilterMuonMFT, "Build muon + mft DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb, w/ event filtering", false); + PROCESS_SWITCH(TableMaker, processPPBarrelOnly, "Build barrel only DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb", false); + PROCESS_SWITCH(TableMaker, processPPMuonOnly, "Build muon only DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb", false); + PROCESS_SWITCH(TableMaker, processPPMuonMFT, "Build muon + mft DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb", false); PROCESS_SWITCH(TableMaker, processPbPb, "Build full DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnly, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); + PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyWithV0Bits, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/ V0 bits, w/o event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbMuonOnly, "Build muon only DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbMuonMFT, "Build muon + mft DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); PROCESS_SWITCH(TableMaker, processOnlyBCs, "Analyze the BCs to store sampled lumi", false); diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index f8fccece684..7ba233973ab 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -69,6 +69,11 @@ o2physics_add_dpl_workflow(task-j-psi-hf PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-muon-dca + SOURCES muonDCA.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(correlation SOURCES dqCorrelation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2Physics::GFWCore diff --git a/PWGDQ/Tasks/dqEfficiency.cxx b/PWGDQ/Tasks/dqEfficiency.cxx index 4e2fb04b2c3..2704cbc36a1 100644 --- a/PWGDQ/Tasks/dqEfficiency.cxx +++ b/PWGDQ/Tasks/dqEfficiency.cxx @@ -482,6 +482,7 @@ struct AnalysisSameEventPairing { Produces dielectronList; Produces dimuonList; Produces dielectronExtraList; + Produces dielectronInfoList; Produces dimuonExtraList; Produces dielectronAllList; Produces dimuonAllList; @@ -499,6 +500,7 @@ struct AnalysisSameEventPairing { Configurable fConfigMuonCuts{"cfgMuonCuts", "", "Comma separated list of barrel track cuts"}; Configurable fConfigMCRecSignals{"cfgMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; Configurable fConfigMCGenSignals{"cfgMCGenSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable fConfigSkimSignalOnly{"fConfigSkimSignalOnly", false, "Configurable to select only matched candidates"}; Configurable fConfigFlatTables{"cfgFlatTables", false, "Produce a single flat tables with all relevant information of the pairs and single tracks"}; Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; Configurable fUseRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; @@ -738,6 +740,7 @@ struct AnalysisSameEventPairing { uint32_t dileptonFilterMap = 0; uint32_t dileptonMcDecision = 0; dielectronList.reserve(1); + dielectronInfoList.reserve(1); dimuonList.reserve(1); dielectronExtraList.reserve(1); dimuonExtraList.reserve(1); @@ -783,21 +786,25 @@ struct AnalysisSameEventPairing { dileptonFilterMap = twoTrackFilter; dileptonMcDecision = mcDecision; - - if constexpr (TPairType == VarManager::kDecayToEE) { - dielectronList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision); - dielectronExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingLz], VarManager::fgValues[VarManager::kVertexingLxy]); - } - if constexpr ((TPairType == VarManager::kDecayToEE) && (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { - if (fConfigFlatTables.value) { - dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision, - t1.pt(), t1.eta(), t1.phi(), t1.tpcNClsCrossedRows(), t1.tpcNClsFound(), t1.tpcChi2NCl(), t1.dcaXY(), t1.dcaZ(), t1.tpcSignal(), t1.tpcNSigmaEl(), t1.tpcNSigmaPi(), t1.tpcNSigmaPr(), t1.beta(), t1.tofNSigmaEl(), t1.tofNSigmaPi(), t1.tofNSigmaPr(), - t2.pt(), t2.eta(), t2.phi(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), - VarManager::fgValues[VarManager::kKFTrack0DCAxyz], VarManager::fgValues[VarManager::kKFTrack1DCAxyz], VarManager::fgValues[VarManager::kKFDCAxyzBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DCAxy], VarManager::fgValues[VarManager::kKFTrack1DCAxy], VarManager::fgValues[VarManager::kKFDCAxyBetweenProngs], - VarManager::fgValues[VarManager::kKFTrack0DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack0DeviationxyFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationxyFromPV], - VarManager::fgValues[VarManager::kKFMass], VarManager::fgValues[VarManager::kKFChi2OverNDFGeo], VarManager::fgValues[VarManager::kVertexingLxyz], VarManager::fgValues[VarManager::kVertexingLxyzOverErr], VarManager::fgValues[VarManager::kVertexingLxy], VarManager::fgValues[VarManager::kVertexingLxyOverErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], VarManager::fgValues[VarManager::kKFCosPA], VarManager::fgValues[VarManager::kKFJpsiDCAxyz], VarManager::fgValues[VarManager::kKFJpsiDCAxy], - VarManager::fgValues[VarManager::kKFPairDeviationFromPV], VarManager::fgValues[VarManager::kKFPairDeviationxyFromPV], - VarManager::fgValues[VarManager::kKFMassGeoTop], VarManager::fgValues[VarManager::kKFChi2OverNDFGeoTop]); + if (!fConfigSkimSignalOnly || (fConfigSkimSignalOnly && mcDecision > 0)) { + if constexpr (TPairType == VarManager::kDecayToEE) { + dielectronList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision); + if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackCollInfo) > 0) { + dielectronInfoList(t1.collisionId(), t1.trackId(), t2.trackId()); + } + dielectronExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingLz], VarManager::fgValues[VarManager::kVertexingLxy]); + } + if constexpr ((TPairType == VarManager::kDecayToEE) && (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { + if (fConfigFlatTables.value) { + dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision, + t1.pt(), t1.eta(), t1.phi(), t1.tpcNClsCrossedRows(), t1.tpcNClsFound(), t1.tpcChi2NCl(), t1.dcaXY(), t1.dcaZ(), t1.tpcSignal(), t1.tpcNSigmaEl(), t1.tpcNSigmaPi(), t1.tpcNSigmaPr(), t1.beta(), t1.tofNSigmaEl(), t1.tofNSigmaPi(), t1.tofNSigmaPr(), + t2.pt(), t2.eta(), t2.phi(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), + VarManager::fgValues[VarManager::kKFTrack0DCAxyz], VarManager::fgValues[VarManager::kKFTrack1DCAxyz], VarManager::fgValues[VarManager::kKFDCAxyzBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DCAxy], VarManager::fgValues[VarManager::kKFTrack1DCAxy], VarManager::fgValues[VarManager::kKFDCAxyBetweenProngs], + VarManager::fgValues[VarManager::kKFTrack0DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack0DeviationxyFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationxyFromPV], + VarManager::fgValues[VarManager::kKFMass], VarManager::fgValues[VarManager::kKFChi2OverNDFGeo], VarManager::fgValues[VarManager::kVertexingLxyz], VarManager::fgValues[VarManager::kVertexingLxyzOverErr], VarManager::fgValues[VarManager::kVertexingLxy], VarManager::fgValues[VarManager::kVertexingLxyOverErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], VarManager::fgValues[VarManager::kKFCosPA], VarManager::fgValues[VarManager::kKFJpsiDCAxyz], VarManager::fgValues[VarManager::kKFJpsiDCAxy], + VarManager::fgValues[VarManager::kKFPairDeviationFromPV], VarManager::fgValues[VarManager::kKFPairDeviationxyFromPV], + VarManager::fgValues[VarManager::kKFMassGeoTop], VarManager::fgValues[VarManager::kKFChi2OverNDFGeoTop]); + } } } if constexpr (TPairType == VarManager::kDecayToMuMu) { diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 7681772d0ff..9624b322309 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -96,6 +96,7 @@ using MyBarrelTracks = soa::Join; using MyBarrelTracksWithCov = soa::Join; using MyBarrelTracksWithCovWithAmbiguities = soa::Join; +using MyBarrelTracksWithCovWithAmbiguitiesWithColl = soa::Join; using MyDielectronCandidates = soa::Join; using MyDimuonCandidates = soa::Join; using MyMuonTracks = soa::Join; @@ -109,6 +110,7 @@ constexpr static uint32_t gkEventFillMapWithCov = VarManager::ObjTypes::ReducedE // constexpr static uint32_t gkEventFillMapWithCovQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector; constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t gkTrackFillMapWithCovWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; // constexpr static uint32_t gkTrackFillMapWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra; @@ -425,7 +427,7 @@ struct AnalysisTrackSelection { } template - void runTrackSelection(ReducedTracksAssoc const& assocs, TEvents const& events, TTracks const& tracks, TEventsMC const& eventsMC, TTracksMC const& tracksMC) + void runTrackSelection(ReducedTracksAssoc const& assocs, TEvents const& events, TTracks const& tracks, TEventsMC const& /*eventsMC*/, TTracksMC const& tracksMC) { fNAssocsInBunch.clear(); fNAssocsOutOfBunch.clear(); @@ -503,8 +505,10 @@ struct AnalysisTrackSelection { int isig = 0; if (filterMap > 0) { for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(false, track.reducedMCTrack())) { - mcDecision |= (uint32_t(1) << isig); + if (track.has_reducedMCTrack()) { + if ((*sig).CheckSignal(true, track.reducedMCTrack())) { + mcDecision |= (uint32_t(1) << isig); + } } } @@ -697,7 +701,7 @@ struct AnalysisMuonSelection { } template - void runMuonSelection(ReducedMuonsAssoc const& assocs, TEvents const& events, TMuons const& muons, ReducedMCEvents const& eventsMC, ReducedMCTracks const& muonsMC) + void runMuonSelection(ReducedMuonsAssoc const& assocs, TEvents const& events, TMuons const& muons, ReducedMCEvents const& /*eventsMC*/, ReducedMCTracks const& muonsMC) { if (events.size() > 0 && fCurrentRun != events.begin().runNumber()) { o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(grpmagPath, events.begin().timestamp()); @@ -769,8 +773,10 @@ struct AnalysisMuonSelection { int isig = 0; for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { if constexpr ((TMuonFillMap & VarManager::ObjTypes::ReducedMuon) > 0) { - if ((*sig).CheckSignal(false, track.reducedMCTrack())) { - mcDecision |= (uint32_t(1) << isig); + if (track.has_reducedMCTrack()) { + if ((*sig).CheckSignal(true, track.reducedMCTrack())) { + mcDecision |= (uint32_t(1) << isig); + } } } } @@ -868,6 +874,8 @@ struct AnalysisPrefilterSelection { Configurable fConfigPrefilterTrackCut{"cfgPrefilterTrackCut", "", "Prefilter track cut"}; Configurable fConfigPrefilterPairCut{"cfgPrefilterPairCut", "", "Prefilter pair cut"}; Configurable fConfigTrackCuts{"cfgTrackCuts", "", "Track cuts for which to run the prefilter"}; + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; std::map fPrefilterMap; AnalysisCompositeCut* fPairCut; @@ -932,8 +940,8 @@ struct AnalysisPrefilterSelection { VarManager::SetupTwoProngFwdDCAFitter(5.0f, true, 200.0f, 1.0e-3f, 0.9f, true); } - template - void runPrefilter(soa::Join const& assocs, TTracks const& tracks) + template + void runPrefilter(TEvent const& event, soa::Join const& assocs, TTracks const& /*tracks*/) { for (auto& [assoc1, assoc2] : o2::soa::combinations(assocs, assocs)) { @@ -958,6 +966,9 @@ struct AnalysisPrefilterSelection { // compute pair quantities VarManager::FillPair(track1, track2); + if (fPropTrack) { + VarManager::FillPairCollision(event, track1, track2); + } // if the pair fullfils the criteria, add an entry into the prefilter map for the two tracks if (fPairCut->IsSelected(VarManager::fgValues)) { if (fPrefilterMap.find(track1.globalIndex()) == fPrefilterMap.end() && track1Candidate > 0) { @@ -978,7 +989,7 @@ struct AnalysisPrefilterSelection { for (auto& event : events) { auto groupedAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); if (groupedAssocs.size() > 1) { - runPrefilter(groupedAssocs, tracks); + runPrefilter(event, groupedAssocs, tracks); } } uint32_t mymap = -1; @@ -1012,6 +1023,7 @@ struct AnalysisSameEventPairing { Produces dielectronList; Produces dimuonList; Produces dielectronsExtraList; + Produces dielectronInfoList; Produces dimuonsExtraList; Produces dimuonAllList; Produces dileptonFlowList; @@ -1033,6 +1045,7 @@ struct AnalysisSameEventPairing { Configurable fConfigUseRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; Configurable fConfigFlatTables{"cfgFlatTables", false, "Produce a single flat tables with all relevant information of the pairs and single tracks"}; Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; @@ -1045,8 +1058,13 @@ struct AnalysisSameEventPairing { Configurable fConfigCollisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; Configurable fConfigCenterMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; - Configurable fConfigMCRecSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigRunMCGenPair{"cfgRunMCGenPair", false, "Do pairing of true MC particles"}; Configurable fConfigMCGenSignals{"cfgBarrelMCGenSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable fConfigMCRecSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigSkimSignalOnly{"fConfigSkimSignalOnly", false, "Configurable to select only matched candidates"}; + + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; Service fCCDB; @@ -1079,7 +1097,7 @@ struct AnalysisSameEventPairing { void init(o2::framework::InitContext& context) { - fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed"); + fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed"); fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed"); bool isDummy = context.mOptions.get("processDummy"); if (isDummy) { @@ -1151,13 +1169,15 @@ struct AnalysisSameEventPairing { Form("PairsBarrelSEPM_%s", objArray->At(icut)->GetName()), Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), Form("PairsBarrelSEMM_%s", objArray->At(icut)->GetName())}; - // assign separate hist directories for ambiguous tracks - names.push_back(Form("PairsBarrelSEPM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); - names.push_back(Form("PairsBarrelSEPP_ambiguousInBunch_%s", objArray->At(icut)->GetName())); - names.push_back(Form("PairsBarrelSEMM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); - names.push_back(Form("PairsBarrelSEPM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); - names.push_back(Form("PairsBarrelSEPP_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); - names.push_back(Form("PairsBarrelSEMM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + if (fConfigQA) { + // assign separate hist directories for ambiguous tracks + names.push_back(Form("PairsBarrelSEPM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsBarrelSEPP_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsBarrelSEMM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsBarrelSEPP_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsBarrelSEMM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + } for (auto& n : names) { histNames += Form("%s;", n.Data()); } @@ -1183,21 +1203,28 @@ struct AnalysisSameEventPairing { // assign hist directories for the MC matched pairs for each (track cut,MCsignal) combination if (!sigNamesStr.IsNull()) { - for (auto& sig : fRecMCSignals) { + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); names = { Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPMCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPMIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPM_ambiguousInBunch_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPM_ambiguousInBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPM_ambiguousInBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPM_ambiguousOutOfBunch_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPM_ambiguousOutOfBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsBarrelSEPM_ambiguousOutOfBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())}; - histNames += Form("%s;%s;%s;%s;%s;%s;%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data(), names[3].Data(), names[4].Data(), names[5].Data(), names[6].Data(), names[7].Data(), names[8].Data()); + Form("PairsBarrelSEPP_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), + Form("PairsBarrelSEMM_%s_%s", objArray->At(icut)->GetName(), sig.GetName())}; + if (fConfigQA) { + names.push_back(Form("PairsBarrelSEPMCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPMIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousInBunch_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousInBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousInBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousOutOfBunch_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousOutOfBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsBarrelSEPM_ambiguousOutOfBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + } + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fBarrelHistNamesMCmatched.try_emplace(icut * fRecMCSignals.size() + isig, names); } // end loop over MC signals } - fBarrelHistNamesMCmatched[icut] = names; } // end if enableBarrelHistos } } @@ -1341,7 +1368,7 @@ struct AnalysisSameEventPairing { // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) template - void runSameEventPairing(TEvents const& events, Preslice& preslice, TTrackAssocs const& assocs, TTracks const& tracks, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) + void runSameEventPairing(TEvents const& events, Preslice& preslice, TTrackAssocs const& assocs, TTracks const& /*tracks*/, ReducedMCEvents const& /*mcEvents*/, ReducedMCTracks const& /*mcTracks*/) { if (fCurrentRun != events.begin().runNumber()) { initParamsFromCCDB(events.begin().timestamp(), TTwoProngFitter); @@ -1369,6 +1396,7 @@ struct AnalysisSameEventPairing { dimuonList.reserve(1); dielectronsExtraList.reserve(1); dimuonsExtraList.reserve(1); + dielectronInfoList.reserve(1); dileptonInfoList.reserve(1); if (fConfigFlatTables.value) { dimuonAllList.reserve(1); @@ -1392,7 +1420,7 @@ struct AnalysisSameEventPairing { for (auto& [a1, a2] : o2::soa::combinations(groupedAssocs, groupedAssocs)) { - if constexpr (TPairType == VarManager::kDecayToEE || TPairType == VarManager::kDecayToPiPi) { + if constexpr (TPairType == VarManager::kDecayToEE) { twoTrackFilter = a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & a2.isBarrelSelectedPrefilter_raw() & fTrackFilterMask; if (!twoTrackFilter) { // the tracks must have at least one filter bit in common to continue @@ -1421,30 +1449,39 @@ struct AnalysisSameEventPairing { int isig = 0; mcDecision = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(false, t1.reducedMCTrack(), t2.reducedMCTrack())) { - mcDecision |= (uint32_t(1) << isig); + if (t1.has_reducedMCTrack() && t2.has_reducedMCTrack()) { + if ((*sig).CheckSignal(true, t1.reducedMCTrack(), t2.reducedMCTrack())) { + mcDecision |= (uint32_t(1) << isig); + } } } // end loop over MC signals - isCorrectAssoc_leg1 = (t1.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); - isCorrectAssoc_leg2 = (t2.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + if (t1.has_reducedMCTrack() && t2.has_reducedMCTrack()) { + isCorrectAssoc_leg1 = (t1.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + isCorrectAssoc_leg2 = (t2.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + } VarManager::FillPair(t1, t2); + if (fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } if constexpr (TTwoProngFitter) { VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); } if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); } - - dielectronList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], - VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], - t1.sign() + t2.sign(), twoTrackFilter, mcDecision); - - if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackCollInfo) > 0) { - dileptonInfoList(t1.collisionId(), event.posX(), event.posY(), event.posZ()); - } - if constexpr (trackHasCov && TTwoProngFitter) { - dielectronsExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); + if (!fConfigSkimSignalOnly || (fConfigSkimSignalOnly && mcDecision > 0)) { + dielectronList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], + t1.sign() + t2.sign(), twoTrackFilter, mcDecision); + + if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackCollInfo) > 0) { + dielectronInfoList(t1.collisionId(), t1.trackId(), t2.trackId()); + dileptonInfoList(t1.collisionId(), event.posX(), event.posY(), event.posZ()); + } + if constexpr (trackHasCov && TTwoProngFitter) { + dielectronsExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); + } } } @@ -1462,14 +1499,22 @@ struct AnalysisSameEventPairing { int isig = 0; mcDecision = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(false, t1.reducedMCTrack(), t2.reducedMCTrack())) { - mcDecision |= (uint32_t(1) << isig); + if (t1.has_reducedMCTrack() && t2.has_reducedMCTrack()) { + if ((*sig).CheckSignal(true, t1.reducedMCTrack(), t2.reducedMCTrack())) { + mcDecision |= (uint32_t(1) << isig); + } } } // end loop over MC signals - isCorrectAssoc_leg1 = (t1.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); - isCorrectAssoc_leg2 = (t2.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + + if (t1.has_reducedMCTrack() && t2.has_reducedMCTrack()) { + isCorrectAssoc_leg1 = (t1.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + isCorrectAssoc_leg2 = (t2.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + } VarManager::FillPair(t1, t2); + if (fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } if constexpr (TTwoProngFitter) { VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); } @@ -1534,26 +1579,28 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); // reconstructed, unmatched for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals if (mcDecision & (uint32_t(1) << isig)) { - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size()].Data(), VarManager::fgValues); // matched signal - if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { // correct track-collision association - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size() + 1].Data(), VarManager::fgValues); - } else { // incorrect track-collision association - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size() + 2].Data(), VarManager::fgValues); - } - if (isAmbiInBunch) { // ambiguous in bunch - fHistMan->FillHistClass(histNames[icut][isig * fRecMCSignals.size() + 3].Data(), VarManager::fgValues); - if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size() + 4].Data(), VarManager::fgValues); - } else { - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size() + 5].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][0].Data(), VarManager::fgValues); // matched signal + if (fConfigQA) { + if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { // correct track-collision association + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][3].Data(), VarManager::fgValues); + } else { // incorrect track-collision association + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][4].Data(), VarManager::fgValues); } - } - if (isAmbiOutOfBunch) { // ambiguous out of bunch - fHistMan->FillHistClass(histNames[icut][isig * fRecMCSignals.size() + 6].Data(), VarManager::fgValues); - if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size() + 7].Data(), VarManager::fgValues); - } else { - fHistMan->FillHistClass(histNamesMC[icut][isig * fRecMCSignals.size() + 8].Data(), VarManager::fgValues); + if (isAmbiInBunch) { // ambiguous in bunch + fHistMan->FillHistClass(histNames[icut * fRecMCSignals.size() + isig][5].Data(), VarManager::fgValues); + if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][6].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][7].Data(), VarManager::fgValues); + } + } + if (isAmbiOutOfBunch) { // ambiguous out of bunch + fHistMan->FillHistClass(histNames[icut * fRecMCSignals.size() + isig][8].Data(), VarManager::fgValues); + if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][9].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][10].Data(), VarManager::fgValues); + } } } } @@ -1561,19 +1608,33 @@ struct AnalysisSameEventPairing { } else { if (sign1 > 0) { // ++ pairs fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); - if (isAmbiInBunch) { - fHistMan->FillHistClass(histNames[icut][4].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (uint32_t(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][1].Data(), VarManager::fgValues); + } } - if (isAmbiOutOfBunch) { - fHistMan->FillHistClass(histNames[icut][4 + 3].Data(), VarManager::fgValues); + if (fConfigQA) { + if (isAmbiInBunch) { + fHistMan->FillHistClass(histNames[icut][4].Data(), VarManager::fgValues); + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(histNames[icut][4 + 3].Data(), VarManager::fgValues); + } } } else { // -- pairs fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); - if (isAmbiInBunch) { - fHistMan->FillHistClass(histNames[icut][5].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (uint32_t(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][2].Data(), VarManager::fgValues); + } } - if (isAmbiOutOfBunch) { - fHistMan->FillHistClass(histNames[icut][5 + 3].Data(), VarManager::fgValues); + if (fConfigQA) { + if (isAmbiInBunch) { + fHistMan->FillHistClass(histNames[icut][5].Data(), VarManager::fgValues); + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(histNames[icut][5 + 3].Data(), VarManager::fgValues); + } } } } @@ -1617,9 +1678,9 @@ struct AnalysisSameEventPairing { bool checked = false; /*if constexpr (soa::is_soa_filtered_v) { auto mctrack_raw = groupedMCTracks.rawIteratorAt(mctrack.globalIndex()); - checked = sig.CheckSignal(false, mctrack_raw); + checked = sig.CheckSignal(true, mctrack_raw); } else {*/ - checked = sig.CheckSignal(false, mctrack); + checked = sig.CheckSignal(true, mctrack); //} if (checked) { fHistMan->FillHistClass(Form("MCTruthGen_%s", sig.GetName()), VarManager::fgValues); @@ -1638,7 +1699,7 @@ struct AnalysisSameEventPairing { if (sig.GetNProngs() != 2) { // NOTE: 2-prong signals required here continue; } - if (sig.CheckSignal(false, t1_raw, t2_raw)) { + if (sig.CheckSignal(true, t1_raw, t2_raw)) { VarManager::FillPairMC(t1, t2); fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig.GetName()), VarManager::fgValues); } @@ -1655,7 +1716,8 @@ struct AnalysisSameEventPairing { { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons, mcEvents, mcTracks); - runMCGen(mcEvents, mcTracks); + if (fConfigRunMCGenPair) + runMCGen(mcEvents, mcTracks); // runSameEventPairing(event, tracks, muons); } @@ -1664,14 +1726,25 @@ struct AnalysisSameEventPairing { MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); - runMCGen(mcEvents, mcTracks); + if (fConfigRunMCGenPair) + runMCGen(mcEvents, mcTracks); + } + + void processBarrelOnlyWithCollSkimmed(MyEventsVtxCovSelected const& events, + soa::Join const& barrelAssocs, + MyBarrelTracksWithCovWithAmbiguitiesWithColl const& barrelTracks, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); + if (fConfigRunMCGenPair) + runMCGen(mcEvents, mcTracks); } void processMuonOnlySkimmed(MyEventsVtxCovSelected const& events, soa::Join const& muonAssocs, MyMuonTracksWithCov const& muons, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons, mcEvents, mcTracks); - runMCGen(mcEvents, mcTracks); + if (fConfigRunMCGenPair) + runMCGen(mcEvents, mcTracks); } void processDummy(MyEvents&) @@ -1681,6 +1754,7 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processAllSkimmed, "Run all types of pairing, with skimmed tracks/muons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmed, "Run barrel only pairing, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithCollSkimmed, "Run barrel only pairing, with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmed, "Run muon only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", false); }; @@ -1871,7 +1945,7 @@ struct AnalysisDileptonTrack { // Template function to run pair - hadron combinations template - void runDileptonHadron(TEvent const& event, TTrackAssocs const& assocs, TTracks const& tracks, TDileptons const& dileptons, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) + void runDileptonHadron(TEvent const& event, TTrackAssocs const& assocs, TTracks const& tracks, TDileptons const& dileptons, ReducedMCEvents const& /*mcEvents*/, ReducedMCTracks const& /*mcTracks*/) { VarManager::ResetValues(0, VarManager::kNVars, fValuesHadron); VarManager::ResetValues(0, VarManager::kNVars, fValuesDilepton); @@ -1918,7 +1992,7 @@ struct AnalysisDileptonTrack { mcDecision = 0; isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(false, lepton1MC, lepton2MC, trackMC)) { + if ((*sig).CheckSignal(true, lepton1MC, lepton2MC, trackMC)) { mcDecision |= (uint32_t(1) << isig); } } @@ -1939,7 +2013,7 @@ struct AnalysisDileptonTrack { mcDecision = 0; isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(false, lepton1MC, lepton2MC, trackMC)) { + if ((*sig).CheckSignal(true, lepton1MC, lepton2MC, trackMC)) { mcDecision |= (uint32_t(1) << isig); } } @@ -2027,7 +2101,7 @@ struct AnalysisDileptonTrack { // TODO: Use the mcReducedFlags to select signals isig = 0; for (auto& sig : fGenMCSignals) { - if (sig.CheckSignal(false, track)) { + if (sig.CheckSignal(true, track)) { fHistMan->FillHistClass(fHistNamesMCgen[isig++], VarManager::fgValues); } } diff --git a/PWGDQ/Tasks/dqFlow.cxx b/PWGDQ/Tasks/dqFlow.cxx index 67bce2f8b8c..d8f8b6c417e 100644 --- a/PWGDQ/Tasks/dqFlow.cxx +++ b/PWGDQ/Tasks/dqFlow.cxx @@ -65,7 +65,9 @@ using MyBcs = soa::Join; using MyEvents = soa::Join; using MyEventsWithCent = soa::Join; using MyEventsWithCentRun3 = soa::Join; -using MyEventsWithCentQvectRun3 = soa::Join; +// using MyEventsWithCentQvectRun3 = soa::Join; +// using MyEventsWithCentQvectRun3 = soa::Join; +using MyEventsWithCentQvectRun3 = soa::Join; using MyBarrelTracks = soa::Join; constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCentRun2; constexpr static uint32_t gkEventFillMapRun3 = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent; -constexpr static uint32_t gkEventFillMapRun3Qvect = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent | VarManager::ObjTypes::CollisionQvect; +constexpr static uint32_t gkEventFillMapRun3Qvect = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent | VarManager::ObjTypes::CollisionQvectCentr; constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackPID; void DefineHistograms(HistogramManager* histMan, TString histClasses); @@ -99,8 +101,11 @@ struct DQEventQvector { Produces eventQvector; Produces eventQvectorExtra; Produces eventQvectorCentr; + Produces eventQvectorCentrExtra; Produces eventRefFlow; Produces eventQvectorZN; + Produces eventReducedZdc; + Produces eventReducedZdcExtra; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigQA{"cfgQA", true, "If true, fill QA histograms"}; @@ -291,8 +296,9 @@ struct DQEventQvector { // Fill the tree for the reduced event table with Q vector quantities if (fEventCut->IsSelected(VarManager::fgValues)) { - eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecBPosRe(), collision.qvecBPosIm(), collision.qvecBNegRe(), collision.qvecBNegIm(), - collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkBPos(), collision.nTrkBNeg()); + eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), + collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); + eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); } } @@ -460,7 +466,7 @@ struct DQEventQvector { eventRefFlow(VarManager::fgValues[VarManager::kM11REF], VarManager::fgValues[VarManager::kM1111REF], VarManager::fgValues[VarManager::kCORR2REF], VarManager::fgValues[VarManager::kCORR4REF], centrality); } - if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0) { + if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { VarManager::FillQVectorFromCentralFW(collision); if (bc.has_zdc()) { @@ -477,12 +483,19 @@ struct DQEventQvector { } } if (fEventCut->IsSelected(VarManager::fgValues)) { - eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecBPosRe(), collision.qvecBPosIm(), collision.qvecBNegRe(), collision.qvecBNegIm(), - collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkBPos(), collision.nTrkBNeg()); + eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), + collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); + eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); if (bc.has_zdc()) { eventQvectorZN(VarManager::fgValues[VarManager::kQ1ZNAX], VarManager::fgValues[VarManager::kQ1ZNAY], VarManager::fgValues[VarManager::kQ1ZNCX], VarManager::fgValues[VarManager::kQ1ZNCY]); + eventReducedZdc(VarManager::fgValues[VarManager::kEnergyCommonZNA], VarManager::fgValues[VarManager::kEnergyCommonZNC], VarManager::fgValues[VarManager::kEnergyCommonZPA], VarManager::fgValues[VarManager::kEnergyCommonZPC], + VarManager::fgValues[VarManager::kTimeZNA], VarManager::fgValues[VarManager::kTimeZNC], VarManager::fgValues[VarManager::kTimeZPA], VarManager::fgValues[VarManager::kTimeZPC]); + eventReducedZdcExtra(VarManager::fgValues[VarManager::kEnergyZNA1], VarManager::fgValues[VarManager::kEnergyZNA2], VarManager::fgValues[VarManager::kEnergyZNA3], VarManager::fgValues[VarManager::kEnergyZNA4], + VarManager::fgValues[VarManager::kEnergyZNC1], VarManager::fgValues[VarManager::kEnergyZNC2], VarManager::fgValues[VarManager::kEnergyZNC3], VarManager::fgValues[VarManager::kEnergyZNC4]); } else { eventQvectorZN(-999, -999, -999, -999); + eventReducedZdc(-999, -999, -999, -999, -999, -999, -999, -999); + eventReducedZdcExtra(-999, -999, -999, -999, -999, -999, -999, -999); } } } diff --git a/PWGDQ/Tasks/filterPP.cxx b/PWGDQ/Tasks/filterPP.cxx index f13392d197f..6cd9fad6d7e 100644 --- a/PWGDQ/Tasks/filterPP.cxx +++ b/PWGDQ/Tasks/filterPP.cxx @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include #include #include #include "Framework/AnalysisTask.h" @@ -378,7 +377,7 @@ struct DQFilterPPTask { Produces eventFilter; Produces dqtable; OutputObj fOutputList{"output"}; - OutputObj fStats{"Statistics"}; + OutputObj fStats{"Statistics"}; HistogramManager* fHistMan; Configurable fConfigBarrelSelections{"cfgBarrelSels", "jpsiPID1:pairMassLow:1", ":[]:,[:[]:],..."}; @@ -450,7 +449,7 @@ struct DQFilterPPTask { VarManager::SetUseVars(AnalysisCut::fgUsedVars); // setup the Stats histogram - fStats.setObject(new TH1I("Statistics", "Stats for DQ triggers", fNBarrelCuts + fNMuonCuts + 2, -2.5, -0.5 + fNBarrelCuts + fNMuonCuts)); + fStats.setObject(new TH1D("Statistics", "Stats for DQ triggers", fNBarrelCuts + fNMuonCuts + 2, -2.5, -0.5 + fNBarrelCuts + fNMuonCuts)); fStats->GetXaxis()->SetBinLabel(1, "Events inspected"); fStats->GetXaxis()->SetBinLabel(2, "Events selected"); if (fNBarrelCuts) { diff --git a/PWGDQ/Tasks/filterPPwithAssociation.cxx b/PWGDQ/Tasks/filterPPwithAssociation.cxx index a245c2dac0a..4f92cf7cc90 100644 --- a/PWGDQ/Tasks/filterPPwithAssociation.cxx +++ b/PWGDQ/Tasks/filterPPwithAssociation.cxx @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include #include #include #include "Framework/AnalysisTask.h" @@ -506,7 +505,7 @@ struct DQFilterPPTask { Produces eventFilter; Produces dqtable; OutputObj fOutputList{"output"}; - OutputObj fStats{"Statistics"}; + OutputObj fStats{"Statistics"}; HistogramManager* fHistMan; Configurable fConfigBarrelSelections{"cfgBarrelSels", "jpsiPID1:pairMassLow:1", ":[]:,[:[]:],..."}; @@ -588,7 +587,7 @@ struct DQFilterPPTask { VarManager::SetUseVars(AnalysisCut::fgUsedVars); // setup the Stats histogram - fStats.setObject(new TH1F("Statistics", "Stats for DQ triggers", fNBarrelCuts + fNMuonCuts + 2, -2.5, -0.5 + fNBarrelCuts + fNMuonCuts)); + fStats.setObject(new TH1D("Statistics", "Stats for DQ triggers", fNBarrelCuts + fNMuonCuts + 2, -2.5, -0.5 + fNBarrelCuts + fNMuonCuts)); fStats->GetXaxis()->SetBinLabel(1, "Events inspected"); fStats->GetXaxis()->SetBinLabel(2, "Events selected"); if (fNBarrelCuts) { diff --git a/PWGDQ/Tasks/filterPbPb.cxx b/PWGDQ/Tasks/filterPbPb.cxx index a9671f0711e..a562b34d4df 100644 --- a/PWGDQ/Tasks/filterPbPb.cxx +++ b/PWGDQ/Tasks/filterPbPb.cxx @@ -30,8 +30,8 @@ using MyBCs = soa::Join eventFilter; - OutputObj fStats{"Statistics"}; - OutputObj fFilterOutcome{"Filter outcome"}; + OutputObj fStats{"Statistics"}; + OutputObj fFilterOutcome{"Filter outcome"}; Configurable fConfigEventTypes{"cfgEventTypes", "doublegap,singlegap", "Which event types to select. doublegap, singlegap or both, comma separated"}; Configurable fConfigNDtColl{"cfgNDtColl", 4, "Number of standard deviations to consider in BC range"}; @@ -54,16 +54,19 @@ struct DQFilterPbPbTask { void init(o2::framework::InitContext&) { // setup the Stats histogram - fStats.setObject(new TH1I("Statistics", "Stats for DQ triggers", 2, -2.5, -0.5)); + fStats.setObject(new TH1D("Statistics", "Stats for DQ triggers", 2, -2.5, -0.5)); fStats->GetXaxis()->SetBinLabel(1, "Events inspected"); fStats->GetXaxis()->SetBinLabel(2, "Events selected"); // setup the FilterOutcome histogram - fFilterOutcome.setObject(new TH1I("Filter outcome", "Filter outcome", 5, -0.5, 4.5)); + fFilterOutcome.setObject(new TH1D("Filter outcome", "Filter outcome", 8, 0.5, 8.5)); fFilterOutcome->GetXaxis()->SetBinLabel(1, "Events inspected"); fFilterOutcome->GetXaxis()->SetBinLabel(2, "Events selected"); - fFilterOutcome->GetXaxis()->SetBinLabel(3, "Failed FIT veto"); - fFilterOutcome->GetXaxis()->SetBinLabel(4, Form("numContrib not in [%d, %d]", fConfigMinNPVCs.value, fConfigMaxNPVCs.value)); - fFilterOutcome->GetXaxis()->SetBinLabel(5, "BC not found"); + fFilterOutcome->GetXaxis()->SetBinLabel(3, "!A && !C"); + fFilterOutcome->GetXaxis()->SetBinLabel(4, "!A && C"); + fFilterOutcome->GetXaxis()->SetBinLabel(5, "A && !C"); + fFilterOutcome->GetXaxis()->SetBinLabel(6, "A && C"); + fFilterOutcome->GetXaxis()->SetBinLabel(7, Form("numContrib not in [%d, %d]", fConfigMinNPVCs.value, fConfigMaxNPVCs.value)); + fFilterOutcome->GetXaxis()->SetBinLabel(8, "BC not found"); TString eventTypesString = fConfigEventTypes.value; for (std::vector::size_type i = 0; i < eventTypeOptions.size(); i++) { @@ -84,10 +87,10 @@ struct DQFilterPbPbTask { int eventTypes, std::vector FITAmpLimits, int nDtColl, int minNBCs, int minNPVCs, int maxNPVCs, float maxFITTime, bool useFV0, bool useFT0, bool useFDD) { - fFilterOutcome->Fill(0., 1.); + fFilterOutcome->Fill(1., 1.); // Find BC associated with collision if (!collision.has_foundBC()) { - fFilterOutcome->Fill(4., 1); + fFilterOutcome->Fill(8., 1); return 0; } // foundBCId is stored in EvSels @@ -212,31 +215,38 @@ struct DQFilterPbPbTask { // Compute FIT decision uint64_t FITDecision = 0; - if (eventTypes & (uint32_t(1) << 0)) { - if (isSideAClean && isSideCClean) { + if (isSideAClean && isSideCClean) { + fFilterOutcome->Fill(3, 1); + if (eventTypes & (uint32_t(1) << 0)) { FITDecision |= (uint64_t(1) << VarManager::kDoubleGap); } } - if (eventTypes & (uint32_t(1) << 1)) { - if (isSideAClean && !isSideCClean) { + if (isSideAClean && !isSideCClean) { + fFilterOutcome->Fill(4, 1); + if (eventTypes & (uint32_t(1) << 1)) { FITDecision |= (uint64_t(1) << VarManager::kSingleGapA); - } else if (!isSideAClean && isSideCClean) { + } + } else if (!isSideAClean && isSideCClean) { + fFilterOutcome->Fill(5, 1); + if (eventTypes & (uint32_t(1) << 1)) { FITDecision |= (uint64_t(1) << VarManager::kSingleGapC); } + } else if (!isSideAClean && !isSideCClean) { + fFilterOutcome->Fill(6, 1); } + if (!FITDecision) { - fFilterOutcome->Fill(2, 1); return 0; } // Number of primary vertex contributors if (collision.numContrib() < minNPVCs || collision.numContrib() > maxNPVCs) { - fFilterOutcome->Fill(3, 1); + fFilterOutcome->Fill(7, 1); return 0; } // If we made it here, the event passed - fFilterOutcome->Fill(1, 1); + fFilterOutcome->Fill(2, 1); // Return filter bitmap corresponding to FIT decision return FITDecision; } diff --git a/PWGDQ/Tasks/muonDCA.cxx b/PWGDQ/Tasks/muonDCA.cxx new file mode 100644 index 00000000000..b2031418d5c --- /dev/null +++ b/PWGDQ/Tasks/muonDCA.cxx @@ -0,0 +1,196 @@ +// Copyright 2019-2020 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. +// +/// \file muonDCA.cxx +/// \brief Task to compute and evaluate DCA quantities +/// \author Nicolas Bizé , SUBATECH +// +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGDQ/Core/VarManager.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod; + +using MyMuons = soa::Join; +using MyEvents = soa::Join; +using MyEventsVtxCov = soa::Join; + +// constexpr static uint32_t gkMuonDCAFillMapWithCov = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra | VarManager::ObjTypes::ReducedMuonCov | VarManager::ObjTypes::MuonDCA; + +constexpr static int toVertex = VarManager::kToVertex; +constexpr static int toDCA = VarManager::kToDCA; +constexpr static int toRabs = VarManager::kToRabs; + +static o2::globaltracking::MatchGlobalFwd mExtrap; +template +bool isSelected(const T& muon); + +struct muonExtrap { + Produces dcaTable; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + Service fCCDB; + o2::parameters::GRPMagField* grpmag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField + int fCurrentRun; // needed to detect if the run changed and trigger update of magnetic field + + HistogramRegistry registry{ + "registry", + {}}; + + void init(o2::framework::InitContext&) + { + // Load geometry + fCCDB->setURL(fConfigCcdbUrl); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + LOGF(info, "Load geometry from CCDB"); + fCCDB->get(geoPath); + } + + AxisSpec pdcaAxis = {5000, 0.0, 5000.0, "p #times DCA"}; + AxisSpec dcaAxis = {200, 0.0, 200.0, "DCA"}; + AxisSpec dcaxAxis = {200, -100.0, 100.0, "DCA_x"}; + AxisSpec dcayAxis = {200, -100.0, 100.0, "DCA_y"}; + AxisSpec rabsAxis = {100, 0., 100.0, "R_{abs}"}; + AxisSpec xAxis = {200, -100., 100.0, "x (cm)"}; + AxisSpec yAxis = {200, -100., 100.0, "y (cm)"}; + AxisSpec zAxis = {200, -100., 100.0, "z (cm)"}; + + HistogramConfigSpec pdcaSpec({HistType::kTH1F, {pdcaAxis}}); + HistogramConfigSpec dcaSpec({HistType::kTH1F, {dcaAxis}}); + HistogramConfigSpec dcaxSpec({HistType::kTH1F, {dcaxAxis}}); + HistogramConfigSpec dcaySpec({HistType::kTH1F, {dcayAxis}}); + HistogramConfigSpec rabsSpec({HistType::kTH1F, {rabsAxis}}); + HistogramConfigSpec xSpec({HistType::kTH1F, {xAxis}}); + HistogramConfigSpec ySpec({HistType::kTH1F, {yAxis}}); + HistogramConfigSpec zSpec({HistType::kTH1F, {zAxis}}); + + registry.add("pdca", "pDCA", pdcaSpec); + registry.add("dca", "DCA", dcaSpec); + registry.add("dcax", "DCA_x", dcaxSpec); + registry.add("dcay", "DCA_y", dcaySpec); + registry.add("rabs", "R_{abs}", rabsSpec); + registry.add("xAtVtx", "x at vertex", xSpec); + registry.add("xAtDCA", "x at DCA", xSpec); + registry.add("xAtRabs", "x at end abs", xSpec); + registry.add("yAtVtx", "y at vertex", ySpec); + registry.add("yAtDCA", "y at DCA", ySpec); + registry.add("yAtRabs", "y at end abs", ySpec); + registry.add("zAtVtx", "z at vertex", zSpec); + registry.add("zAtDCA", "z at DCA", zSpec); + registry.add("zAtRabs", "z at end abs", zSpec); + } + + void processExtrapolation(MyEventsVtxCov::iterator const& collision, MyMuons const& muons) + { + if (fCurrentRun != collision.runNumber()) { + grpmag = fCCDB->getForTimeStamp(grpmagPath, collision.timestamp()); + if (grpmag != nullptr) { + LOGF(info, "Init field from GRP"); + o2::base::Propagator::initFieldFromGRP(grpmag); + } + LOGF(info, "Set field for muons"); + VarManager::SetupMuonMagField(); + fCurrentRun = collision.runNumber(); + } + + for (auto& muon : muons) { + if (static_cast(muon.trackType()) < 2) { + continue; // Make sure to remove global muon tracks + } + // propagate muon track to vertex + o2::dataformats::GlobalFwdTrack muonTrackAtVertex = VarManager::PropagateMuon(muon, collision, toVertex); + + // propagate muon track to DCA + o2::dataformats::GlobalFwdTrack muonTrackAtDCA = VarManager::PropagateMuon(muon, collision, toDCA); + + // propagate to Rabs + o2::dataformats::GlobalFwdTrack muonTrackAtRabs = VarManager::PropagateMuon(muon, collision, toRabs); + + // Calculate DCA quantities (preferable to do it with VarManager) + double dcax = muonTrackAtDCA.getX() - collision.posX(); + double dcay = muonTrackAtDCA.getY() - collision.posY(); + double dca = std::sqrt(dcax * dcax + dcay * dcay); + double pdca = muonTrackAtVertex.getP() * dca; + double xAtVtx = muonTrackAtVertex.getX(); + double yAtVtx = muonTrackAtVertex.getY(); + double zAtVtx = muonTrackAtVertex.getZ(); + double xAtDCA = muonTrackAtDCA.getX(); + double yAtDCA = muonTrackAtDCA.getY(); + double zAtDCA = muonTrackAtDCA.getZ(); + double xAbs = muonTrackAtRabs.getX(); + double yAbs = muonTrackAtRabs.getY(); + double zAbs = muonTrackAtRabs.getZ(); + + double rabs = std::sqrt(xAbs * xAbs + yAbs * yAbs); + + // QA histograms + registry.get(HIST("pdca"))->Fill(pdca); + registry.get(HIST("dca"))->Fill(dca); + registry.get(HIST("dcax"))->Fill(dcax); + registry.get(HIST("dcay"))->Fill(dcay); + registry.get(HIST("rabs"))->Fill(rabs); + + registry.get(HIST("xAtDCA"))->Fill(xAtDCA); + registry.get(HIST("xAtRabs"))->Fill(xAbs); + registry.get(HIST("xAtVtx"))->Fill(xAtVtx); + + registry.get(HIST("yAtDCA"))->Fill(yAtDCA); + registry.get(HIST("yAtRabs"))->Fill(yAbs); + registry.get(HIST("yAtVtx"))->Fill(yAtVtx); + + registry.get(HIST("zAtDCA"))->Fill(zAtDCA); + registry.get(HIST("zAtRabs"))->Fill(zAbs); + registry.get(HIST("zAtVtx"))->Fill(zAtVtx); + + // Fill DCA table + dcaTable(pdca, + dca, + dcax, + dcay, + rabs, + muonTrackAtVertex.getPt(), + muonTrackAtVertex.getEta(), + muonTrackAtVertex.getPhi(), + muon.sign(), + muon.isAmbiguous(), + muonTrackAtVertex.getPx(), + muonTrackAtVertex.getPy(), + muonTrackAtVertex.getPz()); + } + } + + PROCESS_SWITCH(muonExtrap, processExtrapolation, "process extrapolation", false); + + void processDummy(MyEventsVtxCov&) + { + // do nothing + } + + PROCESS_SWITCH(muonExtrap, processDummy, "do nothing", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index 5643d311b05..34435873ff6 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -76,6 +76,29 @@ DECLARE_SOA_COLUMN(TauxyBcandidate, tauxyBcandidate, float); DECLARE_SOA_COLUMN(TauzBcandidate, tauzBcandidate, float); DECLARE_SOA_COLUMN(CosPBcandidate, cosPBcandidate, float); DECLARE_SOA_COLUMN(Chi2Bcandidate, chi2Bcandidate, float); + +// Xcandidate columns +DECLARE_SOA_COLUMN(massXcandidate, MXcandidate, float); +DECLARE_SOA_COLUMN(pTXcandidate, PtXcandidate, float); +DECLARE_SOA_COLUMN(rapidityXcandidate, YXcandidate, float); +DECLARE_SOA_COLUMN(etaXcandidate, EtaXcandidate, float); +DECLARE_SOA_COLUMN(massJpsicandidate, MJpsicandidate, float); +DECLARE_SOA_COLUMN(massDipioncandidate, MDipioncandidate, float); +DECLARE_SOA_COLUMN(pTJpsicandidate, PtJpsicandidate, float); +DECLARE_SOA_COLUMN(pTDipioncandidate, PtDipioncandidate, float); +DECLARE_SOA_COLUMN(massDiff, Q, float); +DECLARE_SOA_COLUMN(angDistPion1, DeltaR1, float); +DECLARE_SOA_COLUMN(angDistPion2, DeltaR2, float); +DECLARE_SOA_COLUMN(cosDileptonDipion, CosDileptonDipion, float); +DECLARE_SOA_COLUMN(dcaxyPion1, DcaXYPion1, float); +DECLARE_SOA_COLUMN(dcazPion1, DcaZPion1, float); +DECLARE_SOA_COLUMN(dcaxyPion2, DcaXYPion2, float); +DECLARE_SOA_COLUMN(dcazPion2, DcaZPion2, float); +DECLARE_SOA_COLUMN(pTPion1, PtPion1, float); +DECLARE_SOA_COLUMN(pTPion2, PtPion2, float); +DECLARE_SOA_COLUMN(dileptonSign, DileptonSign, int); +DECLARE_SOA_COLUMN(ditrackSign, DitrackSign, int); + } // namespace dqanalysisflags DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); @@ -84,6 +107,7 @@ DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBar DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTS", dqanalysisflags::IsMuonSelected); DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsPrefilterVetoed); DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", dqanalysisflags::massBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate); +DECLARE_SOA_TABLE(XCandidates, "AOD", "DQX3872", dqanalysisflags::massXcandidate, dqanalysisflags::pTXcandidate, dqanalysisflags::rapidityXcandidate, dqanalysisflags::etaXcandidate, dqanalysisflags::massJpsicandidate, dqanalysisflags::massDipioncandidate, dqanalysisflags::pTJpsicandidate, dqanalysisflags::pTDipioncandidate, dqanalysisflags::massDiff, dqanalysisflags::angDistPion1, dqanalysisflags::angDistPion2, dqanalysisflags::cosDileptonDipion, dqanalysisflags::dcaxyPion1, dqanalysisflags::dcazPion1, dqanalysisflags::dcaxyPion2, dqanalysisflags::dcazPion2, dqanalysisflags::pTPion1, dqanalysisflags::pTPion2, dqanalysisflags::dileptonSign, dqanalysisflags::ditrackSign); } // namespace o2::aod // Declarations of various short names @@ -93,7 +117,6 @@ using MyEventsHashSelected = soa::Join; using MyEventsVtxCovSelected = soa::Join; using MyEventsVtxCovSelectedQvector = soa::Join; -using MyEventsVtxCovSelectedQvectorExtra = soa::Join; using MyEventsVtxCovSelectedQvectorExtraWithRefFlow = soa::Join; using MyEventsVtxCovSelectedQvectorCentr = soa::Join; using MyEventsQvector = soa::Join; @@ -127,7 +150,6 @@ constexpr static uint32_t gkEventFillMapWithQvectorMultExtra = VarManager::ObjTy constexpr static uint32_t gkEventFillMapWithQvectorCentr = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::CollisionQvect; constexpr static uint32_t gkEventFillMapWithQvectorCentrMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::CollisionQvect | VarManager::ObjTypes::ReducedEventMultExtra; constexpr static uint32_t gkEventFillMapWithCovQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector; -constexpr static uint32_t gkEventFillMapWithCovQvectorExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector | VarManager::ObjTypes::ReducedEventQvectorExtra; constexpr static uint32_t gkEventFillMapWithCovQvectorExtraWithRefFlow = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector | VarManager::ObjTypes::ReducedEventQvectorExtra | VarManager::ObjTypes::ReducedEventRefFlow; constexpr static uint32_t gkEventFillMapWithCovQvectorCentr = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::CollisionQvect; constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; @@ -153,6 +175,7 @@ struct AnalysisEventSelection { Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; Configurable fConfigITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; Configurable fConfigITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; @@ -222,13 +245,25 @@ struct AnalysisEventSelection { if (fConfigQA) { fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event } - if (fEventCut->IsSelected(VarManager::fgValues)) { - if (fConfigQA) { - fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + + if (!fConfigRunZorro) { + if (fEventCut->IsSelected(VarManager::fgValues)) { + if (fConfigQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + } + eventSel(1); + } else { + eventSel(0); } - eventSel(1); } else { - eventSel(0); + if (fEventCut->IsSelected(VarManager::fgValues) && event.tag_bit(56)) { // This is the bit used for the software trigger event selections [TO BE DONE: find a more clear way to use it] + if (fConfigQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + } + eventSel(1); + } else { + eventSel(0); + } } if (fMixHandler != nullptr) { @@ -877,11 +912,13 @@ struct AnalysisSameEventPairing { Produces dielectronList; Produces dimuonList; Produces dielectronExtraList; + Produces dielectronInfoList; Produces dimuonExtraList; Produces dielectronAllList; Produces dimuonAllList; Produces dileptonFlowList; Produces dileptonInfoList; + Produces dileptonMiniTree; float mMagField = 0.0; o2::parameters::GRPMagField* grpmag = nullptr; o2::base::MatLayerCylSet* lut = nullptr; @@ -912,6 +949,13 @@ struct AnalysisSameEventPairing { Configurable fCollisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; Configurable fCenterMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; + // Configurables to create output tree (flat tables or minitree) + struct : ConfigurableGroup { + Configurable fConfigMiniTree{"useMiniTree.cfgMiniTree", false, "Produce a single flat table with minimal information for analysis"}; + Configurable fConfigMiniTreeMinMass{"useMiniTree.cfgMiniTreeMinMass", 2, "Min. mass cut for minitree"}; + Configurable fConfigMiniTreeMaxMass{"useMiniTree.cfgMiniTreeMaxMass", 5, "Max. mass cut for minitree"}; + } useMiniTree; + Service ccdb; Filter filterEventSelected = aod::dqanalysisflags::isEventSelected == 1; // NOTE: the barrel filter map contains decisions for both electrons and hadrons used in the correlation task @@ -1136,6 +1180,7 @@ struct AnalysisSameEventPairing { dielectronList.reserve(1); dimuonList.reserve(1); dielectronExtraList.reserve(1); + dielectronInfoList.reserve(1); dimuonExtraList.reserve(1); dileptonInfoList.reserve(1); dileptonFlowList.reserve(1); @@ -1143,6 +1188,9 @@ struct AnalysisSameEventPairing { dielectronAllList.reserve(1); dimuonAllList.reserve(1); } + if (useMiniTree.fConfigMiniTree) { + dileptonMiniTree.reserve(1); + } if (fConfigMultDimuons.value) { @@ -1196,6 +1244,9 @@ struct AnalysisSameEventPairing { if constexpr (TPairType == pairTypeEE) { dielectronList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision); + if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackCollInfo) > 0) { + dielectronInfoList(t1.collisionId(), t1.trackId(), t2.trackId()); + } } if constexpr ((TPairType == pairTypeEE) && (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { if (fConfigFlatTables.value) { @@ -1247,21 +1298,23 @@ struct AnalysisSameEventPairing { VarManager::fgValues[VarManager::kU2Q2], VarManager::fgValues[VarManager::kU3Q3], VarManager::fgValues[VarManager::kR2EP_AB], VarManager::fgValues[VarManager::kR2SP_AB], VarManager::fgValues[VarManager::kCentFT0C], VarManager::fgValues[VarManager::kCos2DeltaPhi], VarManager::fgValues[VarManager::kCos3DeltaPhi], - VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], VarManager::fgValues[VarManager::kMultDimuons], + VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], VarManager::fgValues[VarManager::kMultDimuons], VarManager::fgValues[VarManager::kVertexingPz], VarManager::fgValues[VarManager::kVertexingSV]); } + auto collId = 0; if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedMuonCollInfo) > 0) { - if constexpr (eventHasQvector == true || eventHasQvectorCentr == true) { - dileptonFlowList(t1.collisionId(), VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kCentFT0C], - VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), isFirst, - VarManager::fgValues[VarManager::kU2Q2], VarManager::fgValues[VarManager::kR2SP_AB], VarManager::fgValues[VarManager::kR2SP_AC], VarManager::fgValues[VarManager::kR2SP_BC], - VarManager::fgValues[VarManager::kU3Q3], VarManager::fgValues[VarManager::kR3SP], - VarManager::fgValues[VarManager::kCos2DeltaPhi], VarManager::fgValues[VarManager::kR2EP_AB], VarManager::fgValues[VarManager::kR2EP_AC], VarManager::fgValues[VarManager::kR2EP_BC], - VarManager::fgValues[VarManager::kCos3DeltaPhi], VarManager::fgValues[VarManager::kR3EP], - VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], - VarManager::fgValues[VarManager::kCORR2REF], VarManager::fgValues[VarManager::kCORR4REF], VarManager::fgValues[VarManager::kM11REF], VarManager::fgValues[VarManager::kM1111REF], - VarManager::fgValues[VarManager::kMultDimuons], VarManager::fgValues[VarManager::kMultA]); - } + collId = t1.collisionId(); + } + if constexpr (eventHasQvector == true || eventHasQvectorCentr == true) { + dileptonFlowList(collId, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kCentFT0C], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), isFirst, + VarManager::fgValues[VarManager::kU2Q2], VarManager::fgValues[VarManager::kR2SP_AB], VarManager::fgValues[VarManager::kR2SP_AC], VarManager::fgValues[VarManager::kR2SP_BC], + VarManager::fgValues[VarManager::kU3Q3], VarManager::fgValues[VarManager::kR3SP], + VarManager::fgValues[VarManager::kCos2DeltaPhi], VarManager::fgValues[VarManager::kR2EP_AB], VarManager::fgValues[VarManager::kR2EP_AC], VarManager::fgValues[VarManager::kR2EP_BC], + VarManager::fgValues[VarManager::kCos3DeltaPhi], VarManager::fgValues[VarManager::kR3EP], + VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], + VarManager::fgValues[VarManager::kCORR2REF], VarManager::fgValues[VarManager::kCORR4REF], VarManager::fgValues[VarManager::kM11REF], VarManager::fgValues[VarManager::kM1111REF], + VarManager::fgValues[VarManager::kMultDimuons], VarManager::fgValues[VarManager::kMultA]); } if (t1.sign() != t2.sign()) { isFirst = false; @@ -1276,6 +1329,16 @@ struct AnalysisSameEventPairing { if (fConfigAmbiguousHist && !(t1.isAmbiguous() || t2.isAmbiguous())) { fHistMan->FillHistClass(Form("%s_unambiguous", histNames[iCut][0].Data()), VarManager::fgValues); } + if (useMiniTree.fConfigMiniTree) { + float dileptonMass = VarManager::fgValues[VarManager::kMass]; + if (dileptonMass > useMiniTree.fConfigMiniTreeMinMass && dileptonMass < useMiniTree.fConfigMiniTreeMaxMass) { + dileptonMiniTree(VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], + VarManager::fgValues[VarManager::kRap], + VarManager::fgValues[VarManager::kCentFT0C], + VarManager::fgValues[VarManager::kCos2DeltaPhi]); + } + } } else { if (t1.sign() > 0) { fHistMan->FillHistClass(histNames[iCut][1].Data(), VarManager::fgValues); @@ -1418,12 +1481,12 @@ struct AnalysisSameEventPairing { VarManager::FillEvent(event, VarManager::fgValues); runSameEventPairing(event, muons, muons); } - void processVnDecayToMuMuSkimmedWithWeights(soa::Filtered::iterator const& event, soa::Filtered const& muons) + void processVnDecayToMuMuSkimmedWithWeights(soa::Filtered::iterator const& event, soa::Filtered const& muons) { // Reset the fValues array VarManager::ResetValues(0, VarManager::kNVars); - VarManager::FillEvent(event, VarManager::fgValues); - runSameEventPairing(event, muons, muons); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, muons, muons); } void processVnDecayToMuMuSkimmedWithWeightsAndColl(soa::Filtered::iterator const& event, soa::Filtered const& muons) @@ -1776,13 +1839,15 @@ struct AnalysisDileptonHadron { struct AnalysisDileptonTrackTrack { OutputObj fOutputList{"output"}; - Configurable fConfigTrackCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; // used for select the tracks from SelectedTracks - Configurable fConfigDileptonCut{"cfgDiLeptonCut", "pairJpsi", "Dilepton cut"}; - Configurable fConfigDitrackCut{"cfgDiTrackCut", "pairNoCut", "Track-Track cut"}; - Configurable fConfigQuadrupletCut{"cfgQuadrupletCut", "pairNoCut", "Dilepton-Track-Track cut"}; - Configurable fConfigAddDileptonHistogram{"cfgAddDileptonHistogram", "berral", "Comma separated list of histograms"}; - Configurable fConfigAddDitrackHistogram{"cfgAddDitrackHistogram", "berral", "Comma separated list of histograms"}; - Configurable fConfigAddQuadrupletHistogram{"cfgAddQuadrupletHistogram", "XtoJpsipipi", "Comma separated list of histograms"}; + Configurable fConfigTrackCuts{"cfgTrackCuts", "pionPIDCut1", "Comma separated list of barrel track cuts"}; // used for select the tracks from SelectedTracks + Configurable fConfigDileptonCut{"cfgDiLeptonCut", "pairJpsi2", "Dilepton cut"}; + Configurable fConfigDitrackCut{"cfgDiTrackCut", "DipionPairCut1", "Track-Track cut"}; + Configurable fConfigQuadrupletCut{"cfgQuadrupletCut", "pairX3872Cut1", "Dilepton-Track-Track cut"}; + Configurable fConfigAddDileptonHistogram{"cfgAddDileptonHistogram", "barrel", "Comma separated list of histograms"}; + Configurable fConfigAddDitrackHistogram{"cfgAddDitrackHistogram", "barrel", "Comma separated list of histograms"}; + Configurable fConfigAddQuadrupletHistogram{"cfgAddQuadrupletHistogram", "xtojpsipipi", "Comma separated list of histograms"}; + + Produces XTable; Filter eventFilter = aod::dqanalysisflags::isEventSelected == 1; Filter dileptonFilter = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 4.0f; @@ -1912,6 +1977,7 @@ struct AnalysisDileptonTrackTrack { if (t1.isBarrelSelected() & (uint32_t(1) << (iTrackCut + 1)) && t2.isBarrelSelected() & (uint32_t(1) << (iTrackCut + 1))) { fHistMan->FillHistClass(Form("DitrackSelected_%s_%s", fDitrackCut.GetName(), (*cutname).Data()), fValuesDitrack); if (fQuadrupletCut.IsSelected(fValuesQuadruplet)) { + XTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kRap], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kPairMass], fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kPairPt], fValuesQuadruplet[VarManager::kDitrackPt], fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kCosthetaDileptonDitrack], fValuesQuadruplet[VarManager::kTrackDCAxyProng1], fValuesQuadruplet[VarManager::kTrackDCAzProng1], fValuesQuadruplet[VarManager::kTrackDCAxyProng2], fValuesQuadruplet[VarManager::kTrackDCAzProng2], fValuesQuadruplet[VarManager::kPt1], fValuesQuadruplet[VarManager::kPt2], dilepton.sign(), t1.sign() + t2.sign()); if (fIsUnlikeSignDilepton) { if (fIsUnlikeSignDitrack) { fHistMan->FillHistClass(Form("QuadrupletSEUSUS_%s_%s_%s", fDileptonCut.GetName(), fDitrackCut.GetName(), (*cutname).Data()), fValuesQuadruplet); @@ -1927,7 +1993,7 @@ struct AnalysisDileptonTrackTrack { } } } - } // check if the diTrack cut is selected + } // check if the Ditrack cut is selected } // loop over hadron cuts } } diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 27ba5262394..9e92e0d36db 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -70,6 +71,8 @@ DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelected, isBarrelSelected, 32); DECLARE_SOA_COLUMN(BarrelAmbiguityInBunch, barrelAmbiguityInBunch, int8_t); //! Barrel track in-bunch ambiguity DECLARE_SOA_COLUMN(BarrelAmbiguityOutOfBunch, barrelAmbiguityOutOfBunch, int8_t); //! Barrel track out of bunch ambiguity DECLARE_SOA_BITMAP_COLUMN(IsMuonSelected, isMuonSelected, 32); //! Muon track decisions (joinable to ReducedMuonsAssoc) +DECLARE_SOA_COLUMN(MuonAmbiguityInBunch, muonAmbiguityInBunch, int8_t); //! Muon track in-bunch ambiguity +DECLARE_SOA_COLUMN(MuonAmbiguityOutOfBunch, muonAmbiguityOutOfBunch, int8_t); //! Muon track out of bunch ambiguity DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelectedPrefilter, isBarrelSelectedPrefilter, 32); //! Barrel prefilter decisions (joinable to ReducedTracksAssoc) // Bcandidate columns for ML analysis of B->Jpsi+K DECLARE_SOA_COLUMN(massBcandidate, MBcandidate, float); @@ -88,14 +91,17 @@ DECLARE_SOA_TABLE(MixingHashes, "AOD", "DQANAMIXHASH", dqanalysisflags::MixingHa DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected); //! joinable to ReducedTracksAssoc DECLARE_SOA_TABLE(BarrelAmbiguities, "AOD", "DQBARRELAMB", dqanalysisflags::BarrelAmbiguityInBunch, dqanalysisflags::BarrelAmbiguityOutOfBunch); //! joinable to ReducedBarrelTracks DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTS", dqanalysisflags::IsMuonSelected); //! joinable to ReducedMuonsAssoc +DECLARE_SOA_TABLE(MuonAmbiguities, "AOD", "DQMUONAMB", dqanalysisflags::MuonAmbiguityInBunch, dqanalysisflags::MuonAmbiguityOutOfBunch); //! joinable to ReducedMuonTracks DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); //! joinable to ReducedTracksAssoc DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", dqanalysisflags::massBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate); } // namespace o2::aod // Declarations of various short names using MyEvents = soa::Join; +using MyEventsMultExtra = soa::Join; using MyEventsZdc = soa::Join; using MyEventsSelected = soa::Join; +using MyEventsMultExtraSelected = soa::Join; using MyEventsHashSelected = soa::Join; using MyEventsVtxCov = soa::Join; using MyEventsVtxCovSelected = soa::Join; @@ -108,11 +114,13 @@ using MyBarrelTracks = soa::Join; using MyBarrelTracksWithCov = soa::Join; using MyBarrelTracksWithCovWithAmbiguities = soa::Join; +using MyBarrelTracksWithCovWithAmbiguitiesWithColl = soa::Join; using MyDielectronCandidates = soa::Join; using MyDitrackCandidates = soa::Join; using MyDimuonCandidates = soa::Join; using MyMuonTracks = soa::Join; using MyMuonTracksWithCov = soa::Join; +using MyMuonTracksWithCovWithAmbiguities = soa::Join; using MyMuonTracksSelectedWithColl = soa::Join; // bit maps used for the Fill functions of the VarManager @@ -120,11 +128,12 @@ constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::ReducedEvent | constexpr static uint32_t gkEventFillMapWithZdc = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedZdc; constexpr static uint32_t gkEventFillMapWithCov = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov; constexpr static uint32_t gkEventFillMapWithCovZdc = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ReducedZdc; +constexpr static uint32_t gkEventFillMapWithMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra; // constexpr static uint32_t gkEventFillMapWithQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventQvector; // constexpr static uint32_t gkEventFillMapWithCovQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector; constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; -// constexpr static uint32_t gkTrackFillMapWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; +constexpr static uint32_t gkTrackFillMapWithCovWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; // constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra; constexpr static uint32_t gkMuonFillMapWithCov = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra | VarManager::ObjTypes::ReducedMuonCov; @@ -168,7 +177,6 @@ struct AnalysisEventSelection { std::map fSelMap; // key: reduced event global index, value: event selection decision std::map> fBCCollMap; // key: global BC, value: vector of reduced event global indices - std::map fMetadataRCT, fHeader; int fCurrentRun; void init(o2::framework::InitContext&) @@ -208,18 +216,20 @@ struct AnalysisEventSelection { void runEventSelection(TEvents const& events) { if (events.size() > 0 && events.begin().runNumber() != fCurrentRun) { - fHeader = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", events.begin().runNumber()), fMetadataRCT, -1); - uint64_t sor = std::atol(fHeader["SOR"].c_str()); - uint64_t eor = std::atol(fHeader["EOR"].c_str()); - LOGP(debug, "=========================== SOR / EOR is {} / {}", sor, eor); - // cout << "=========================== SOR / EOR is " << sor << " / " << eor << endl; + std::map metadataRCT, header; + header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", events.begin().runNumber()), metadataRCT, -1); + uint64_t sor = std::atol(header["SOR"].c_str()); + uint64_t eor = std::atol(header["EOR"].c_str()); + VarManager::SetSORandEOR(sor, eor); + LOG(info) << "============================= SOR / EOR :: " << sor << " / " << eor; + auto alppar = fCCDB->getForTimeStamp>("ITS/Config/AlpideParam", events.begin().timestamp()); EventSelectionParams* par = fCCDB->getForTimeStamp("EventSelection/EventSelectionParams", events.begin().timestamp()); int itsROFrameStartBorderMargin = fConfigITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : fConfigITSROFrameStartBorderMargin; int itsROFrameEndBorderMargin = fConfigITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : fConfigITSROFrameEndBorderMargin; VarManager::SetITSROFBorderselection(alppar->roFrameBiasInBC, alppar->roFrameLengthInBC, itsROFrameStartBorderMargin, itsROFrameEndBorderMargin); LOGP(debug, "==============++++++++++++========== roBias / roLength / start / end :: {} / {} / {} / {}", alppar->roFrameBiasInBC, alppar->roFrameLengthInBC, itsROFrameStartBorderMargin, itsROFrameEndBorderMargin); - // cout << "==============++++++++++++========== roBias / roLength / start / end :: " << alppar->roFrameBiasInBC << " / " << alppar->roFrameLengthInBC << " / " << itsROFrameStartBorderMargin << " / " << itsROFrameEndBorderMargin << endl; + fCurrentRun = events.begin().runNumber(); } @@ -314,6 +324,11 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processSkimmedWithMultExtra(MyEventsMultExtra const& events) + { + runEventSelection(events); + publishSelections(events); + } void processDummy(MyEvents&) { // do nothing @@ -321,6 +336,7 @@ struct AnalysisEventSelection { PROCESS_SWITCH(AnalysisEventSelection, processSkimmed, "Run event selection on DQ skimmed events", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithZdc, "Run event selection on DQ skimmed events, with ZDC", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtra, "Run event selection on DQ skimmed events, with mult extra", false); PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", false); }; @@ -341,13 +357,16 @@ struct AnalysisTrackSelection { Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fConfigDummyRunlist{"cfgDummyRunlist", false, "If true, use dummy runlist"}; Configurable fConfigInitRunNumber{"cfgInitRunNumber", 543215, "Initial run number used in run by run checks"}; + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; HistogramManager* fHistMan; std::vector fTrackCuts; - int fCurrentRun; // current run (needed to detect run changes for loading CCDB parameters) + int fCurrentRun; // current run kept to detect run changes and trigger loading params from CCDB std::map> fNAssocsInBunch; // key: track global index, value: vector of global index for events associated in-bunch (events that have in-bunch pileup or splitting) std::map> fNAssocsOutOfBunch; // key: track global index, value: vector of global index for events associated out-of-bunch (events that have no in-bunch pileup) @@ -392,6 +411,7 @@ struct AnalysisTrackSelection { fCCDB->setLocalObjectValidityChecking(); fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); } + fCCDBApi.init(fConfigCcdbUrl.value); } template @@ -400,14 +420,16 @@ struct AnalysisTrackSelection { fNAssocsInBunch.clear(); fNAssocsOutOfBunch.clear(); - if (fConfigComputeTPCpostCalib && events.size() > 0 && fCurrentRun != events.begin().runNumber()) { - auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, events.begin().timestamp()); - VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + if (events.size() > 0 && fCurrentRun != events.begin().runNumber()) { + if (fConfigComputeTPCpostCalib) { + auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, events.begin().timestamp()); + VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + } o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(grpmagPath, events.begin().timestamp()); if (grpmag != nullptr) { @@ -416,6 +438,12 @@ struct AnalysisTrackSelection { LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", events.begin().timestamp()); } + std::map metadataRCT, header; + header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", events.begin().runNumber()), metadataRCT, -1); + uint64_t sor = std::atol(header["SOR"].c_str()); + uint64_t eor = std::atol(header["EOR"].c_str()); + VarManager::SetSORandEOR(sor, eor); + fCurrentRun = events.begin().runNumber(); } @@ -438,7 +466,9 @@ struct AnalysisTrackSelection { filterMap = 0; VarManager::FillTrack(track); // compute quantities which depend on the associated collision, such as DCA - VarManager::FillTrackCollision(track, event); + if (fPropTrack) { + VarManager::FillTrackCollision(track, event); + } if (fConfigQA) { fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); } @@ -518,6 +548,10 @@ struct AnalysisTrackSelection { { runTrackSelection(assocs, events, tracks); } + void processSkimmedWithMultExtra(ReducedTracksAssoc const& assocs, MyEventsMultExtraSelected const& events, MyBarrelTracks const& tracks) + { + runTrackSelection(assocs, events, tracks); + } void processSkimmedWithCov(ReducedTracksAssoc const& assocs, MyEventsVtxCovSelected const& events, MyBarrelTracksWithCov const& tracks) { runTrackSelection(assocs, events, tracks); @@ -528,6 +562,7 @@ struct AnalysisTrackSelection { } PROCESS_SWITCH(AnalysisTrackSelection, processSkimmed, "Run barrel track selection on DQ skimmed track associations", false); + PROCESS_SWITCH(AnalysisTrackSelection, processSkimmedWithMultExtra, "Run barrel track selection on DQ skimmed track associations, with extra multiplicity tables", false); PROCESS_SWITCH(AnalysisTrackSelection, processSkimmedWithCov, "Run barrel track selection on DQ skimmed tracks w/ cov matrix associations", false); PROCESS_SWITCH(AnalysisTrackSelection, processDummy, "Dummy function", false); }; @@ -536,6 +571,7 @@ struct AnalysisTrackSelection { // Here one should add all the track cuts needed through the workflow (e.g. cuts for same-event pairing, track for dilepton-track correlations) struct AnalysisMuonSelection { Produces muonSel; + Produces muonAmbiguities; OutputObj fOutputList{"output"}; Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; @@ -553,6 +589,9 @@ struct AnalysisMuonSelection { int fCurrentRun; // current run kept to detect run changes and trigger loading params from CCDB + std::map> fNAssocsInBunch; // key: muon global index, value: vector of global index for events associated in-bunch (events that have in-bunch pileup or splitting) + std::map> fNAssocsOutOfBunch; // key: muon global index, value: vector of global index for events associated out-of-bunch (events that have no in-bunch pileup) + void init(o2::framework::InitContext&) { fCurrentRun = 0; @@ -576,6 +615,7 @@ struct AnalysisMuonSelection { for (auto& cut : fMuonCuts) { histDirNames += Form("TrackMuon_%s;", cut.GetName()); } + histDirNames += "TrackMuon_AmbiguityInBunch;TrackMuon_AmbiguityOutOfBunch;"; DefineHistograms(fHistMan, histDirNames.Data(), fConfigAddMuonHistogram.value.data()); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill @@ -592,8 +632,11 @@ struct AnalysisMuonSelection { } template - void runMuonSelection(ReducedMuonsAssoc const& assocs, TEvents const& events, TMuons const& /*muons*/) + void runMuonSelection(ReducedMuonsAssoc const& assocs, TEvents const& events, TMuons const& muons) { + fNAssocsInBunch.clear(); + fNAssocsOutOfBunch.clear(); + if (events.size() > 0 && fCurrentRun != events.begin().runNumber()) { o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(grpmagPath, events.begin().timestamp()); if (grpmag != nullptr) { @@ -606,6 +649,7 @@ struct AnalysisMuonSelection { } muonSel.reserve(assocs.size()); + muonAmbiguities.reserve(muons.size()); uint32_t filterMap = 0; int iCut = 0; @@ -615,7 +659,7 @@ struct AnalysisMuonSelection { muonSel(0); continue; } - VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + VarManager::ResetValues(0, VarManager::kNMuonTrackVariables); // fill event information which might be needed in histograms/cuts that combine track and event properties VarManager::FillEvent(event); @@ -637,7 +681,66 @@ struct AnalysisMuonSelection { } } // end loop over cuts muonSel(filterMap); + + // count the number of associations per track + if (filterMap > 0) { + if (event.isEventSelected_bit(1)) { + if (fNAssocsInBunch.find(track.globalIndex()) == fNAssocsInBunch.end()) { + std::vector evVector = {event.globalIndex()}; + fNAssocsInBunch[track.globalIndex()] = evVector; + } else { + auto& evVector = fNAssocsInBunch[track.globalIndex()]; + evVector.push_back(event.globalIndex()); + } + } else { + if (fNAssocsOutOfBunch.find(track.globalIndex()) == fNAssocsOutOfBunch.end()) { + std::vector evVector = {event.globalIndex()}; + fNAssocsOutOfBunch[track.globalIndex()] = evVector; + } else { + auto& evVector = fNAssocsOutOfBunch[track.globalIndex()]; + evVector.push_back(event.globalIndex()); + } + } + } } // end loop over assocs + + // QA the collision-track associations + if (fConfigQA) { + for (auto& [trackIdx, evIndices] : fNAssocsInBunch) { + if (evIndices.size() == 1) { + continue; + } + auto track = muons.rawIteratorAt(trackIdx); + VarManager::ResetValues(0, VarManager::kNMuonTrackVariables); + VarManager::FillTrack(track); + VarManager::fgValues[VarManager::kMuonNAssocsInBunch] = static_cast(evIndices.size()); + fHistMan->FillHistClass("TrackMuon_AmbiguityInBunch", VarManager::fgValues); + } // end loop over in-bunch ambiguous tracks + + for (auto& [trackIdx, evIndices] : fNAssocsOutOfBunch) { + if (evIndices.size() == 1) { + continue; + } + auto track = muons.rawIteratorAt(trackIdx); + VarManager::ResetValues(0, VarManager::kNMuonTrackVariables); + VarManager::FillTrack(track); + VarManager::fgValues[VarManager::kMuonNAssocsOutOfBunch] = static_cast(evIndices.size()); + fHistMan->FillHistClass("TrackMuon_AmbiguityOutOfBunch", VarManager::fgValues); + } // end loop over out-of-bunch ambiguous tracks + } + + // publish the ambiguity table + for (auto& track : muons) { + int8_t nInBunch = 0; + if (fNAssocsInBunch.find(track.globalIndex()) != fNAssocsInBunch.end()) { + nInBunch = fNAssocsInBunch[track.globalIndex()].size(); + } + int8_t nOutOfBunch = 0; + if (fNAssocsOutOfBunch.find(track.globalIndex()) != fNAssocsOutOfBunch.end()) { + nOutOfBunch = fNAssocsOutOfBunch[track.globalIndex()].size(); + } + muonAmbiguities(nInBunch, nOutOfBunch); + } } void processSkimmed(ReducedMuonsAssoc const& assocs, MyEventsVtxCovSelected const& events, MyMuonTracksWithCov const& muons) @@ -812,6 +915,7 @@ struct AnalysisSameEventPairing { Produces dielectronList; Produces dimuonList; Produces dielectronsExtraList; + Produces dielectronInfoList; Produces dimuonsExtraList; Produces dielectronAllList; Produces dimuonAllList; @@ -828,7 +932,7 @@ struct AnalysisSameEventPairing { Configurable fConfigPairCuts{"cfgPairCuts", "", "Comma separated list of pair cuts"}; Configurable fConfigMixingDepth{"cfgMixingDepth", 100, "Number of Events stored for event mixing"}; - Configurable fConfigAddEventMixingHistogram{"cfgAddEventMixingHistogram", "", "Comma separated list of histograms"}; + // Configurable fConfigAddEventMixingHistogram{"cfgAddEventMixingHistogram", "", "Comma separated list of histograms"}; Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigCcdbPath{"ccdb-path", "Users/lm", "base path to the ccdb object"}; @@ -848,8 +952,11 @@ struct AnalysisSameEventPairing { Configurable fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable fConfigCollisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; Configurable fConfigCenterMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; Filter filterEventSelected = aod::dqanalysisflags::isEventSelected == uint32_t(1); @@ -879,8 +986,8 @@ struct AnalysisSameEventPairing { void init(o2::framework::InitContext& context) { - fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed"); - fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed"); + fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov"); + fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed"); fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed"); fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed"); bool isDummy = context.mOptions.get("processDummy"); @@ -993,6 +1100,14 @@ struct AnalysisSameEventPairing { names.push_back(Form("PairsMuonMEMM_%s", objArray->At(icut)->GetName())); histNames += Form("%s;%s;%s;", names[3].Data(), names[4].Data(), names[5].Data()); } + names.push_back(Form("PairsMuonSEPM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEPP_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEMM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEPP_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEMM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + histNames += Form("%s;%s;%s;", names[(fEnableMuonMixingHistos ? 6 : 3)].Data(), names[(fEnableMuonMixingHistos ? 7 : 4)].Data(), names[(fEnableMuonMixingHistos ? 8 : 5)].Data()); + histNames += Form("%s;%s;%s;", names[(fEnableMuonMixingHistos ? 9 : 6)].Data(), names[(fEnableMuonMixingHistos ? 10 : 7)].Data(), names[(fEnableMuonMixingHistos ? 11 : 8)].Data()); fMuonHistNames[icut] = names; TString cutNamesStr = fConfigPairCuts.value; @@ -1018,6 +1133,7 @@ struct AnalysisSameEventPairing { fCCDB->setURL(fConfigCcdbUrl.value); fCCDB->setCaching(true); fCCDB->setLocalObjectValidityChecking(); + fCCDBApi.init(fConfigCcdbUrl.value); if (fConfigNoCorr) { VarManager::SetupFwdDCAFitterNoCorr(); @@ -1075,7 +1191,7 @@ struct AnalysisSameEventPairing { fOutputList.setObject(fHistMan->GetMainHistogramList()); } - void initParamsFromCCDB(uint64_t timestamp, bool withTwoProngFitter = true) + void initParamsFromCCDB(uint64_t timestamp, int runNumber, bool withTwoProngFitter = true) { if (fConfigUseRemoteField.value) { @@ -1108,6 +1224,12 @@ struct AnalysisSameEventPairing { VarManager::SetupTwoProngDCAFitter(fConfigMagField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, fConfigUseAbsDCA.value); // needed because take in varmanager Bz from fgFitterTwoProngBarrel for PhiV calculations } } + + std::map metadataRCT, header; + header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", runNumber), metadataRCT, -1); + uint64_t sor = std::atol(header["SOR"].c_str()); + uint64_t eor = std::atol(header["EOR"].c_str()); + VarManager::SetSORandEOR(sor, eor); } // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) @@ -1116,7 +1238,7 @@ struct AnalysisSameEventPairing { { if (events.size() > 0) { // Additional protection to avoid crashing of events.begin().runNumber() if (fCurrentRun != events.begin().runNumber()) { - initParamsFromCCDB(events.begin().timestamp(), TTwoProngFitter); + initParamsFromCCDB(events.begin().timestamp(), events.begin().runNumber(), TTwoProngFitter); fCurrentRun = events.begin().runNumber(); } } @@ -1124,12 +1246,15 @@ struct AnalysisSameEventPairing { TString cutNames = fConfigTrackCuts.value; std::map> histNames = fTrackHistNames; int ncuts = fNCutsBarrel; + int histIdxOffset = 0; if constexpr (TPairType == pairTypeMuMu) { cutNames = fConfigMuonCuts.value; histNames = fMuonHistNames; ncuts = fNCutsMuon; + if (fEnableMuonMixingHistos) { + histIdxOffset = 3; + } } - int histIdxOffset = 0; if constexpr (TPairType == pairTypeEE) { if (fEnableBarrelMixingHistos) { histIdxOffset = 3; @@ -1147,6 +1272,7 @@ struct AnalysisSameEventPairing { dielectronList.reserve(1); dimuonList.reserve(1); dielectronsExtraList.reserve(1); + dielectronInfoList.reserve(1); dimuonsExtraList.reserve(1); dileptonInfoList.reserve(1); dileptonFlowList.reserve(1); @@ -1173,8 +1299,7 @@ struct AnalysisSameEventPairing { bool isFirst = true; for (auto& [a1, a2] : o2::soa::combinations(groupedAssocs, groupedAssocs)) { - - if constexpr (TPairType == VarManager::kDecayToEE || TPairType == VarManager::kDecayToPiPi) { + if constexpr (TPairType == VarManager::kDecayToEE) { twoTrackFilter = a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & a2.isBarrelSelectedPrefilter_raw() & fTrackFilterMask; if (!twoTrackFilter) { // the tracks must have at least one filter bit in common to continue @@ -1200,6 +1325,10 @@ struct AnalysisSameEventPairing { } VarManager::FillPair(t1, t2); + // compute quantities which depend on the associated collision, such as DCA + if (fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } if constexpr (TTwoProngFitter) { VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); } @@ -1212,6 +1341,7 @@ struct AnalysisSameEventPairing { t1.sign() + t2.sign(), twoTrackFilter, 0); if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackCollInfo) > 0) { + dielectronInfoList(t1.collisionId(), t1.trackId(), t2.trackId()); dileptonInfoList(t1.collisionId(), event.posX(), event.posY(), event.posZ()); } if constexpr (trackHasCov && TTwoProngFitter) { @@ -1239,10 +1369,31 @@ struct AnalysisSameEventPairing { auto t1 = a1.template reducedmuon_as(); auto t2 = a2.template reducedmuon_as(); + if (t1.matchMCHTrackId() == t2.matchMCHTrackId()) + continue; + if (t1.matchMFTTrackId() == t2.matchMFTTrackId()) + continue; sign1 = t1.sign(); sign2 = t2.sign(); + // store the ambiguity number of the two dilepton legs in the last 4 digits of the two-track filter + if (t1.muonAmbiguityInBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 28); + } + if (t2.muonAmbiguityInBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 29); + } + if (t1.muonAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 30); + } + if (t2.muonAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 31); + } VarManager::FillPair(t1, t2); + // compute quantities which depend on the associated collision, such as DCA + if (fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } if constexpr (TTwoProngFitter) { VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); } @@ -1279,11 +1430,11 @@ struct AnalysisSameEventPairing { -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., - t1.isAmbiguous(), t2.isAmbiguous(), + (twoTrackFilter & (uint32_t(1) << 28)) || (twoTrackFilter & (uint32_t(1) << 30)), (twoTrackFilter & (uint32_t(1) << 29)) || (twoTrackFilter & (uint32_t(1) << 31)), VarManager::fgValues[VarManager::kU2Q2], VarManager::fgValues[VarManager::kU3Q3], VarManager::fgValues[VarManager::kR2EP_AB], VarManager::fgValues[VarManager::kR2SP_AB], VarManager::fgValues[VarManager::kCentFT0C], VarManager::fgValues[VarManager::kCos2DeltaPhi], VarManager::fgValues[VarManager::kCos3DeltaPhi], - VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], VarManager::fgValues[VarManager::kMultDimuons], + VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], VarManager::fgValues[VarManager::kMultDimuons], VarManager::fgValues[VarManager::kVertexingPz], VarManager::fgValues[VarManager::kVertexingSV]); } if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedMuonCollInfo) > 0) { @@ -1294,7 +1445,7 @@ struct AnalysisSameEventPairing { VarManager::fgValues[VarManager::kU3Q3], VarManager::fgValues[VarManager::kR3SP], VarManager::fgValues[VarManager::kCos2DeltaPhi], VarManager::fgValues[VarManager::kR2EP_AB], VarManager::fgValues[VarManager::kR2EP_AC], VarManager::fgValues[VarManager::kR2EP_BC], VarManager::fgValues[VarManager::kCos3DeltaPhi], VarManager::fgValues[VarManager::kR3EP], - VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], + VarManager::fgValues[VarManager::kCORR2POI], VarManager::fgValues[VarManager::kCORR4POI], VarManager::fgValues[VarManager::kM01POI], VarManager::fgValues[VarManager::kM0111POI], VarManager::fgValues[VarManager::kCORR2REF], VarManager::fgValues[VarManager::kCORR4REF], VarManager::fgValues[VarManager::kM11REF], VarManager::fgValues[VarManager::kM1111REF], VarManager::fgValues[VarManager::kMultDimuons], VarManager::fgValues[VarManager::kMultA]); } @@ -1378,7 +1529,7 @@ struct AnalysisSameEventPairing { continue; } auto t1 = a1.template reducedtrack_as(); - auto t2 = a1.template reducedtrack_as(); + auto t2 = a2.template reducedtrack_as(); VarManager::FillPairME(t1, t2); if constexpr ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0) { VarManager::FillPairVn(t1, t2); @@ -1392,11 +1543,16 @@ struct AnalysisSameEventPairing { continue; } auto t1 = a1.template reducedmuon_as(); - auto t2 = a1.template reducedmuon_as(); + auto t2 = a2.template reducedmuon_as(); + if (t1.matchMCHTrackId() == t2.matchMCHTrackId()) + continue; + if (t1.matchMFTTrackId() == t2.matchMFTTrackId()) + continue; VarManager::FillPairME(t1, t2); if constexpr ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0) { VarManager::FillPairVn(t1, t2); } + pairSign = t1.sign() + t2.sign(); ncuts = fNCutsMuon; histNames = fMuonHistNames; } @@ -1444,7 +1600,7 @@ struct AnalysisSameEventPairing { void processAllSkimmed(MyEventsVtxCovSelected const& events, soa::Join const& barrelAssocs, MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, - soa::Join const& muonAssocs, MyMuonTracksWithCov const& muons) + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons); @@ -1458,8 +1614,22 @@ struct AnalysisSameEventPairing { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); } + void processBarrelOnlySkimmedNoCov(MyEventsSelected const& events, + soa::Join const& barrelAssocs, + MyBarrelTracksWithAmbiguities const& barrelTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); + } + + void processBarrelOnlyWithCollSkimmed(MyEventsVtxCovSelected const& events, + soa::Join const& barrelAssocs, + MyBarrelTracksWithCovWithAmbiguitiesWithColl const& barrelTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); + } + void processMuonOnlySkimmed(MyEventsVtxCovSelected const& events, - soa::Join const& muonAssocs, MyMuonTracksWithCov const& muons) + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) { runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons); } @@ -1472,6 +1642,12 @@ struct AnalysisSameEventPairing { runSameSideMixing(events, muonAssocs, muons, muonAssocsPerCollision); } + void processMixingBarrelSkimmed(soa::Filtered& events, + soa::Join const& trackAssocs, MyBarrelTracksWithCov const& tracks) + { + runSameSideMixing(events, trackAssocs, tracks, trackAssocsPerCollision); + } + void processDummy(MyEvents&) { // do nothing @@ -1479,8 +1655,11 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processAllSkimmed, "Run all types of pairing, with skimmed tracks/muons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmed, "Run barrel only pairing, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithCollSkimmed, "Run barrel only pairing, with skimmed tracks and with collision information", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmedNoCov, "Run barrel only pairing (no covariances), with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmed, "Run muon only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMixingAllSkimmed, "Run all types of mixed pairing, with skimmed tracks/muons", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processMixingBarrelSkimmed, "Run barrel type mixing pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", false); }; @@ -1498,8 +1677,12 @@ struct AnalysisAsymmetricPairing { // Configurables Configurable fConfigLegCuts{"cfgLegCuts", "", ":[:],[:[:],...]"}; + Configurable fConfigLegAFilterMask{"cfgLegAFilterMask", 0, "Filter mask corresponding to cuts in event-selection"}; + Configurable fConfigLegBFilterMask{"cfgLegBFilterMask", 0, "Filter mask corresponding to cuts in event-selection"}; + Configurable fConfigLegCFilterMask{"cfgLegCFilterMask", 0, "Filter mask corresponding to cuts in event-selection"}; Configurable fConfigCommonTrackCuts{"cfgCommonTrackCuts", "", "Comma separated list of cuts to be applied to all legs"}; Configurable fConfigPairCuts{"cfgPairCuts", "", "Comma separated list of pair cuts"}; + Configurable fConfigSkipAmbiguousIdCombinations{"cfgSkipAmbiguousIdCombinations", true, "Choose whether to skip pairs/triples which pass a stricter combination of cuts, e.g. KKPi triplets for D+ -> KPiPi"}; Configurable fConfigHistogramSubgroups{"cfgAsymmetricPairingHistogramsSubgroups", "barrel,vertexing", "Comma separated list of asymmetric-pairing histogram subgroups"}; Configurable fConfigSameSignHistograms{"cfgSameSignHistograms", false, "Include same sign pair histograms for 2-prong decays"}; @@ -1539,6 +1722,11 @@ struct AnalysisAsymmetricPairing { Preslice> trackAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + // Partitions for triplets and asymmetric pairs + Partition> legACandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fConfigLegAFilterMask) > uint32_t(0); + Partition> legBCandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fConfigLegBFilterMask) > uint32_t(0); + Partition> legCCandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fConfigLegCFilterMask) > uint32_t(0); + void init(o2::framework::InitContext& context) { bool isDummy = context.mOptions.get("processDummy"); @@ -1550,6 +1738,10 @@ struct AnalysisAsymmetricPairing { TString histNames = ""; std::vector names; + // Get the leg cut filter maps + fLegAFilterMask = fConfigLegAFilterMask.value; + fLegBFilterMask = fConfigLegBFilterMask.value; + fLegCFilterMask = fConfigLegCFilterMask.value; // Get the pair cuts TString cutNamesStr = fConfigPairCuts.value; if (!cutNamesStr.IsNull()) { @@ -1579,7 +1771,21 @@ struct AnalysisAsymmetricPairing { } } } + // Check that the leg cut masks make sense + if (static_cast(std::floor(TMath::Log2(fLegAFilterMask))) + 1 > objArray->GetEntries()) { + LOGF(fatal, "fConfigLegAFilterMask has highest bit at position %d, but track-selection only has %d cuts!", static_cast(std::floor(TMath::Log2(fLegAFilterMask))) + 1, objArray->GetEntries()); + } + if (static_cast(std::floor(TMath::Log2(fLegBFilterMask))) + 1 > objArray->GetEntries()) { + LOGF(fatal, "fConfigLegBFilterMask has highest bit at position %d, but track-selection only has %d cuts!", static_cast(std::floor(TMath::Log2(fLegBFilterMask))) + 1, objArray->GetEntries()); + } + if (static_cast(std::floor(TMath::Log2(fLegCFilterMask))) + 1 > objArray->GetEntries()) { + LOGF(fatal, "fConfigLegCFilterMask has highest bit at position %d, but track-selection only has %d cuts!", static_cast(std::floor(TMath::Log2(fLegCFilterMask))) + 1, objArray->GetEntries()); + } + // Get the cuts defining the legs + uint32_t fConstructedLegAFilterMask = 0; + uint32_t fConstructedLegBFilterMask = 0; + uint32_t fConstructedLegCFilterMask = 0; TString legCutsStr = fConfigLegCuts.value; std::unique_ptr objArrayLegs(legCutsStr.Tokenize(",")); if (objArrayLegs->GetEntries() == 0) { @@ -1605,7 +1811,7 @@ struct AnalysisAsymmetricPairing { // Find leg cuts in the track selection cuts legAIdx = objArray->IndexOf(legs->At(0)); if (legAIdx >= 0) { - fLegAFilterMask |= (uint32_t(1) << legAIdx); + fConstructedLegAFilterMask |= (uint32_t(1) << legAIdx); fTrackCutFilterMasks[icut] |= uint32_t(1) << legAIdx; } else { LOGF(fatal, "Leg A cut %s was not calculated upstream. Check the config!", legs->At(0)->GetName()); @@ -1613,7 +1819,7 @@ struct AnalysisAsymmetricPairing { } legBIdx = objArray->IndexOf(legs->At(1)); if (legBIdx >= 0) { - fLegBFilterMask |= (uint32_t(1) << legBIdx); + fConstructedLegBFilterMask |= (uint32_t(1) << legBIdx); fTrackCutFilterMasks[icut] |= uint32_t(1) << legBIdx; } else { LOGF(fatal, "Leg B cut %s was not calculated upstream. Check the config!", legs->At(1)->GetName()); @@ -1622,7 +1828,7 @@ struct AnalysisAsymmetricPairing { if (isThreeProng[icut]) { legCIdx = objArray->IndexOf(legs->At(2)); if (legCIdx >= 0) { - fLegCFilterMask |= (uint32_t(1) << legCIdx); + fConstructedLegCFilterMask |= (uint32_t(1) << legCIdx); fTrackCutFilterMasks[icut] |= uint32_t(1) << legCIdx; } else { LOGF(fatal, "Leg C cut %s was not calculated upstream. Check the config!", legs->At(2)->GetName()); @@ -1717,6 +1923,16 @@ struct AnalysisAsymmetricPairing { } // end if (pair cuts) } } + // Make sure the leg cuts are covered by the configured filter masks + if (fLegAFilterMask != fConstructedLegAFilterMask) { + LOGF(fatal, "cfgLegAFilterMask (%d) is not equal to the mask constructed by the cuts specified in cfgLegCuts (%d)!", fLegAFilterMask, fConstructedLegAFilterMask); + } + if (fLegBFilterMask != fConstructedLegBFilterMask) { + LOGF(fatal, "cfgLegBFilterMask (%d) is not equal to the mask constructed by the cuts specified in cfgLegCuts (%d)!", fLegBFilterMask, fConstructedLegBFilterMask); + } + if (fLegCFilterMask != fConstructedLegCFilterMask) { + LOGF(fatal, "cfgLegCFilterMask (%d) is not equal to the mask constructed by the cuts specified in cfgLegCuts (%d)!", fLegCFilterMask, fConstructedLegCFilterMask); + } // Make sure only pairs or only triplets of leg cuts were given int tripletCheckSum = std::count(isThreeProng.begin(), isThreeProng.end(), true); if (tripletCheckSum != 0 && tripletCheckSum != fNLegCuts) { @@ -1738,7 +1954,7 @@ struct AnalysisAsymmetricPairing { fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); DefineHistograms(fHistMan, histNames.Data(), fConfigHistogramSubgroups.value.data()); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } @@ -1784,7 +2000,7 @@ struct AnalysisAsymmetricPairing { // Template function to run same event pairing with asymmetric pairs (e.g. kaon-pion) template - void runAsymmetricPairing(TEvents const& events, Preslice& preslice, TTrackAssocs const& assocs, TTracks const& /*tracks*/) + void runAsymmetricPairing(TEvents const& events, Preslice& preslice, TTrackAssocs const& /*assocs*/, TTracks const& /*tracks*/) { if (events.size() > 0) { // Additional protection to avoid crashing of events.begin().runNumber() if (fCurrentRun != events.begin().runNumber()) { @@ -1810,145 +2026,147 @@ struct AnalysisAsymmetricPairing { VarManager::ResetValues(0, VarManager::kNVars); VarManager::FillEvent(event, VarManager::fgValues); - auto groupedAssocs = assocs.sliceBy(preslice, event.globalIndex()); - if (groupedAssocs.size() == 0) { + auto groupedLegAAssocs = legACandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegAAssocs.size() == 0) { + continue; + } + auto groupedLegBAssocs = legBCandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegBAssocs.size() == 0) { continue; } // TODO: Think about double counting - for (auto& a1 : groupedAssocs) { - // Check if a1 is a leg A candidate - uint32_t a1AFilter = a1.isBarrelSelected_raw() & fLegAFilterMask; - if (!a1AFilter) { - continue; - } - for (auto& a2 : groupedAssocs) { - // Check if a2 is a leg B candidate - uint32_t a2BFilter = a2.isBarrelSelected_raw() & fLegBFilterMask; - if (!a2BFilter) { - continue; - } - - uint32_t twoTrackFilter = 0; - uint32_t pairFilter = 0; + std::set> globIdxPairs; + for (auto& [a1, a2] : combinations(soa::CombinationsFullIndexPolicy(groupedLegAAssocs, groupedLegBAssocs))) { + + uint32_t twoTrackFilter = 0; + uint32_t twoTrackCommonFilter = 0; + uint32_t pairFilter = 0; + bool isPairIdWrong = false; + for (int icut = 0; icut < fNLegCuts; ++icut) { // Find leg pair definitions both candidates participate in - for (int icut = 0; icut < fNLegCuts; ++icut) { - if (((a1AFilter | a2BFilter) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) { - twoTrackFilter |= (uint32_t(1) << icut); + if ((((a1.isBarrelSelected_raw() & fLegAFilterMask) | (a2.isBarrelSelected_raw() & fLegBFilterMask)) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) { + twoTrackFilter |= (uint32_t(1) << icut); + // If the supposed pion passes a kaon cut, this is a K+K-. Skip it. + if (TPairType == VarManager::kDecayToKPi && fConfigSkipAmbiguousIdCombinations.value) { + if (a2.isBarrelSelected_raw() & fLegAFilterMask) { + isPairIdWrong = true; + } } } - // Find common track cuts both candidates pass - twoTrackFilter |= a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & fCommonTrackCutMask; + } - if (!twoTrackFilter) { - continue; - } + if (!twoTrackFilter || isPairIdWrong) { + continue; + } - auto t1 = a1.template reducedtrack_as(); - auto t2 = a2.template reducedtrack_as(); + // Find common track cuts both candidates pass + twoTrackCommonFilter |= a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & fCommonTrackCutMask; - // Avoid self-pairs - if (t1.globalIndex() == t2.globalIndex()) { - continue; - } + auto t1 = a1.template reducedtrack_as(); + auto t2 = a2.template reducedtrack_as(); - sign1 = t1.sign(); - sign2 = t2.sign(); - // store the ambiguity number of the two dilepton legs in the last 4 digits of the two-track filter - if (t1.barrelAmbiguityInBunch() > 1 || t1.barrelAmbiguityOutOfBunch() > 1) { - twoTrackFilter |= (uint32_t(1) << 30); - } - if (t2.barrelAmbiguityInBunch() > 1 || t2.barrelAmbiguityOutOfBunch() > 1) { - twoTrackFilter |= (uint32_t(1) << 31); - } + // Avoid self-pairs + if (t1.globalIndex() == t2.globalIndex()) { + continue; + } - VarManager::FillPair(t1, t2); - if constexpr (TTwoProngFitter) { - VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); - } + sign1 = t1.sign(); + sign2 = t2.sign(); + // store the ambiguity number of the two dilepton legs in the last 4 digits of the two-track filter + if (t1.barrelAmbiguityInBunch() > 1 || t1.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 30); + } + if (t2.barrelAmbiguityInBunch() > 1 || t2.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 31); + } - // Fill histograms - bool isAmbi = false; - for (int icut = 0; icut < fNLegCuts; icut++) { - if (twoTrackFilter & (uint32_t(1) << icut)) { - isAmbi = (twoTrackFilter & (uint32_t(1) << 30)) || (twoTrackFilter & (uint32_t(1) << 31)); - if (sign1 * sign2 < 0) { - fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); + VarManager::FillPair(t1, t2); + if constexpr (TTwoProngFitter) { + VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); + } + + // Fill histograms + bool isAmbi = false; + for (int icut = 0; icut < fNLegCuts; icut++) { + if (twoTrackFilter & (uint32_t(1) << icut)) { + isAmbi = (twoTrackFilter & (uint32_t(1) << 30)) || (twoTrackFilter & (uint32_t(1) << 31)); + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); + if (isAmbi && fConfigAmbiguousHistograms.value) { + fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); + } + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); if (isAmbi && fConfigAmbiguousHistograms.value) { - fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][4].Data(), VarManager::fgValues); } + } else { + fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); + if (isAmbi && fConfigAmbiguousHistograms.value) { + fHistMan->FillHistClass(histNames[icut][5].Data(), VarManager::fgValues); + } + } + } + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (twoTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][0].Data(), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][2].Data(), VarManager::fgValues); + } + } + } + } // end loop (common cuts) + for (unsigned int iPairCut = 0; iPairCut < fPairCuts.size(); iPairCut++) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!(cut.IsSelected(VarManager::fgValues))) // apply pair cuts + continue; + pairFilter |= (uint32_t(1) << iPairCut); + // Histograms with pair cuts + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][0].Data(), VarManager::fgValues); } else if (fConfigSameSignHistograms.value) { if (sign1 > 0) { - fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); - if (isAmbi && fConfigAmbiguousHistograms.value) { - fHistMan->FillHistClass(histNames[icut][4].Data(), VarManager::fgValues); - } + fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][1].Data(), VarManager::fgValues); } else { - fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); - if (isAmbi && fConfigAmbiguousHistograms.value) { - fHistMan->FillHistClass(histNames[icut][5].Data(), VarManager::fgValues); - } + fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][2].Data(), VarManager::fgValues); } } - for (unsigned int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { - if (twoTrackFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + // Histograms with pair cuts and common track cuts + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + if (twoTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { if (sign1 * sign2 < 0) { - fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][0].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][0].Data(), VarManager::fgValues); } else if (fConfigSameSignHistograms.value) { if (sign1 > 0) { - fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][1].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][1].Data(), VarManager::fgValues); } else { - fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][2].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][2].Data(), VarManager::fgValues); } } } - } // end loop (common cuts) - for (unsigned int iPairCut = 0; iPairCut < fPairCuts.size(); iPairCut++) { - AnalysisCompositeCut cut = fPairCuts.at(iPairCut); - if (!(cut.IsSelected(VarManager::fgValues))) // apply pair cuts - continue; - pairFilter |= (uint32_t(1) << iPairCut); - // Histograms with pair cuts - if (sign1 * sign2 < 0) { - fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][0].Data(), VarManager::fgValues); - } else if (fConfigSameSignHistograms.value) { - if (sign1 > 0) { - fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][1].Data(), VarManager::fgValues); - } else { - fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][2].Data(), VarManager::fgValues); - } - } - // Histograms with pair cuts and common track cuts - for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { - if (twoTrackFilter & fCommonTrackCutFilterMasks[iCommonCut]) { - if (sign1 * sign2 < 0) { - fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][0].Data(), VarManager::fgValues); - } else if (fConfigSameSignHistograms.value) { - if (sign1 > 0) { - fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][1].Data(), VarManager::fgValues); - } else { - fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][2].Data(), VarManager::fgValues); - } - } - } - } - } // end loop (pair cuts) - } - } // end loop (cuts) - ditrackList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], - VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], - t1.sign() + t2.sign(), twoTrackFilter, pairFilter); - if constexpr (trackHasCov && TTwoProngFitter) { - ditrackExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); + } + } // end loop (pair cuts) } - } // end inner assoc loop (leg A) - } // end outer assoc loop (leg B) - } // end event loop + } // end loop (cuts) + ditrackList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], + t1.sign() + t2.sign(), twoTrackFilter, pairFilter, twoTrackCommonFilter); + if constexpr (trackHasCov && TTwoProngFitter) { + ditrackExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); + } + } // end inner assoc loop (leg A) + } // end event loop } // Template function to run same event triplets (e.g. D+->K-pi+pi+) template - void runThreeProng(TEvents const& events, Preslice& preslice, TTrackAssocs const& assocs, TTracks const& tracks, VarManager::PairCandidateType tripletType) + void runThreeProng(TEvents const& events, Preslice& preslice, TTrackAssocs const& /*assocs*/, TTracks const& tracks, VarManager::PairCandidateType tripletType) { if (events.size() > 0) { // Additional protection to avoid crashing of events.begin().runNumber() if (fCurrentRun != events.begin().runNumber()) { @@ -1967,30 +2185,28 @@ struct AnalysisAsymmetricPairing { VarManager::ResetValues(0, VarManager::kNVars); VarManager::FillEvent(event, VarManager::fgValues); - auto groupedAssocs = assocs.sliceBy(preslice, event.globalIndex()); - if (groupedAssocs.size() == 0) { + auto groupedLegAAssocs = legACandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegAAssocs.size() == 0) { + continue; + } + auto groupedLegBAssocs = legBCandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegBAssocs.size() == 0) { + continue; + } + auto groupedLegCAssocs = legCCandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegCAssocs.size() == 0) { continue; } - // Partitions based on leg selections - Partition legACandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fLegAFilterMask) > uint32_t(0); - legACandidateAssocs.bindTable(groupedAssocs); - legACandidateAssocs.bindExternalIndices(&tracks); - Partition legBCandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fLegBFilterMask) > uint32_t(0); - legBCandidateAssocs.bindTable(groupedAssocs); - legBCandidateAssocs.bindExternalIndices(&tracks); - Partition legCCandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fLegCFilterMask) > uint32_t(0); - legCCandidateAssocs.bindTable(groupedAssocs); - legCCandidateAssocs.bindExternalIndices(&tracks); - + std::set> globIdxTriplets; // Based on triplet type, make suitable combinations of the partitions if (tripletType == VarManager::kTripleCandidateToPKPi) { - for (auto& [a1, a2, a3] : combinations(soa::CombinationsFullIndexPolicy(legACandidateAssocs, legBCandidateAssocs, legCCandidateAssocs))) { + for (auto& [a1, a2, a3] : combinations(soa::CombinationsFullIndexPolicy(groupedLegAAssocs, groupedLegBAssocs, groupedLegCAssocs))) { readTriplet(a1, a2, a3, tracks, event, tripletType, histNames); } } else if (tripletType == VarManager::kTripleCandidateToKPiPi) { - for (auto& a1 : legACandidateAssocs) { - for (auto& [a2, a3] : combinations(legBCandidateAssocs, legCCandidateAssocs)) { + for (auto& a1 : groupedLegAAssocs) { + for (auto& [a2, a3] : combinations(groupedLegBAssocs, groupedLegCAssocs)) { readTriplet(a1, a2, a3, tracks, event, tripletType, histNames); } } @@ -2005,19 +2221,36 @@ struct AnalysisAsymmetricPairing { void readTriplet(TTrackAssoc const& a1, TTrackAssoc const& a2, TTrackAssoc const& a3, TTracks const& /*tracks*/, TEvent const& event, VarManager::PairCandidateType tripletType, std::map> histNames) { uint32_t threeTrackFilter = 0; - // Find out which leg cut combination the triplet passes + uint32_t threeTrackCommonFilter = 0; for (int icut = 0; icut < fNLegCuts; ++icut) { + // Find out which leg cut combination the triplet passes if ((((a1.isBarrelSelected_raw() & fLegAFilterMask) | (a2.isBarrelSelected_raw() & fLegBFilterMask) | (a3.isBarrelSelected_raw() & fLegCFilterMask)) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) { threeTrackFilter |= (uint32_t(1) << icut); + if (tripletType == VarManager::kTripleCandidateToPKPi && fConfigSkipAmbiguousIdCombinations.value) { + // Check if the supposed pion passes as a proton or kaon, if so, skip this triplet. It is pKp or pKK. + if ((a3.isBarrelSelected_raw() & fLegAFilterMask) || (a3.isBarrelSelected_raw() & fLegBFilterMask)) { + return; + } + // Check if the supposed kaon passes as a proton, if so, skip this triplet. It is ppPi. + if (a2.isBarrelSelected_raw() & fLegAFilterMask) { + return; + } + } + if (tripletType == VarManager::kTripleCandidateToKPiPi && fConfigSkipAmbiguousIdCombinations.value) { + // Check if one of the supposed pions pass as a kaon, if so, skip this triplet. It is KKPi. + if ((a2.isBarrelSelected_raw() & fLegAFilterMask) || (a3.isBarrelSelected_raw() & fLegAFilterMask)) { + return; + } + } } } - // Find common track cuts both candidates pass - threeTrackFilter |= a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & a3.isBarrelSelected_raw() & fCommonTrackCutMask; - if (!threeTrackFilter) { return; } + // Find common track cuts all candidates pass + threeTrackCommonFilter |= a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & a3.isBarrelSelected_raw() & fCommonTrackCutMask; + auto t1 = a1.template reducedtrack_as(); auto t2 = a2.template reducedtrack_as(); auto t3 = a3.template reducedtrack_as(); @@ -2050,8 +2283,8 @@ struct AnalysisAsymmetricPairing { if (fConfigAmbiguousHistograms.value && ((threeTrackFilter & (uint32_t(1) << 29)) || (threeTrackFilter & (uint32_t(1) << 30)) || (threeTrackFilter & (uint32_t(1) << 31)))) { fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); } - for (unsigned int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { - if (threeTrackFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (threeTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { fHistMan->FillHistClass(histNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut][0].Data(), VarManager::fgValues); } } // end loop (common cuts) @@ -2064,7 +2297,7 @@ struct AnalysisAsymmetricPairing { fHistMan->FillHistClass(histNames[fNLegCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut][0].Data(), VarManager::fgValues); // Histograms with pair cuts and common track cuts for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { - if (threeTrackFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + if (threeTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { fHistMan->FillHistClass(histNames[(fNLegCuts * (fNCommonTrackCuts + 1) + fNLegCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut][0].Data(), VarManager::fgValues); } } @@ -2129,6 +2362,8 @@ struct AnalysisDileptonTrack { int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. int fNCuts; int fNPairCuts; + int fNCommonTrackCuts; + std::map fCommonTrackCutMap; int fTrackCutBit; std::map fHistNamesDileptonTrack; std::map fHistNamesDileptons; @@ -2201,6 +2436,8 @@ struct AnalysisDileptonTrack { // get the cuts employed for same-event pairing string tempCutsSinglePair; string pairCuts; + string pairCommonCuts; + string tempCutsTrack; if (isBarrel) { getTaskOptionValue(context, "analysis-same-event-pairing", "cfgTrackCuts", tempCutsSinglePair, false); getTaskOptionValue(context, "analysis-same-event-pairing", "cfgPairCuts", pairCuts, false); @@ -2208,8 +2445,27 @@ struct AnalysisDileptonTrack { getTaskOptionValue(context, "analysis-same-event-pairing", "cfgMuonCuts", tempCutsSinglePair, false); getTaskOptionValue(context, "analysis-same-event-pairing", "cfgPairCuts", pairCuts, false); } else if (isBarrelAsymmetric) { + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempCutsTrack, false); getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgLegCuts", tempCutsSinglePair, false); getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgPairCuts", pairCuts, false); + getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgCommonTrackCuts", pairCommonCuts, false); + } + + // If asymmetric pair is used, it may have common track cuts + TString pairCommonCutsStr = pairCommonCuts; + if (!pairCommonCutsStr.IsNull()) { // if common track cuts + TString tempCutsTrackStr = tempCutsTrack; + std::unique_ptr objArrayTempTrack(tempCutsTrackStr.Tokenize(",")); + int fNTempTrackCuts = objArrayTempTrack->GetEntries(); + std::unique_ptr objArrayCommon(pairCommonCutsStr.Tokenize(",")); + fNCommonTrackCuts = objArrayCommon->GetEntries(); + for (int icut = 0; icut < fNCommonTrackCuts; ++icut) { + for (int iicut = 0; iicut < fNTempTrackCuts; ++iicut) { + if (std::strcmp(objArrayCommon->At(icut)->GetName(), objArrayTempTrack->At(iicut)->GetName()) == 0) { + fCommonTrackCutMap[icut] = iicut; + } + } + } } TString tempCutsSinglePairStr = tempCutsSinglePair; @@ -2237,14 +2493,33 @@ struct AnalysisDileptonTrack { TString pairCutsStr = pairCuts; DefineHistograms(fHistMan, fHistNamesDileptonTrack[icut], fConfigHistogramSubgroups.value.data()); // define dilepton-track histograms DefineHistograms(fHistMan, fHistNamesDileptons[icut], "barrel,vertexing"); // define dilepton histograms + if (!pairCommonCutsStr.IsNull()) { + std::unique_ptr objArrayCommon(pairCommonCutsStr.Tokenize(",")); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + // fTrackHistNames[fNLegCuts + icut * fNCommonTrackCuts + iCommonCut] = names; + fHistNamesDileptonTrack[fNCuts + icut * fNCommonTrackCuts + iCommonCut] = Form("DileptonTrack_%s_%s_%s", tempStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), fConfigTrackCut.value.data()); + fHistNamesDileptons[fNCuts + icut * fNCommonTrackCuts + iCommonCut] = Form("DileptonsSelected_%s_%s", tempStr.Data(), objArrayCommon->At(iCommonCut)->GetName()); + DefineHistograms(fHistMan, fHistNamesDileptonTrack[fNCuts + icut * fNCommonTrackCuts + iCommonCut], fConfigHistogramSubgroups.value.data()); // define dilepton-track histograms + DefineHistograms(fHistMan, fHistNamesDileptons[fNCuts + icut * fNCommonTrackCuts + iCommonCut], "barrel,vertexing"); // define dilepton histograms + } + } if (!pairCutsStr.IsNull()) { std::unique_ptr objArrayPairCuts(pairCutsStr.Tokenize(",")); fNPairCuts = objArrayPairCuts->GetEntries(); for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { - fHistNamesDileptonTrack[fNCuts + icut * fNPairCuts + iPairCut] = Form("DileptonTrack_%s_%s_%s", tempStr.Data(), objArrayPairCuts->At(iPairCut)->GetName(), fConfigTrackCut.value.data()); - fHistNamesDileptons[fNCuts + icut * fNPairCuts + iPairCut] = Form("DileptonsSelected_%s_%s", tempStr.Data(), objArrayPairCuts->At(iPairCut)->GetName()); - DefineHistograms(fHistMan, fHistNamesDileptonTrack[fNCuts + icut * fNPairCuts + iPairCut], fConfigHistogramSubgroups.value.data()); // define dilepton-track histograms - DefineHistograms(fHistMan, fHistNamesDileptons[fNCuts + icut * fNPairCuts + iPairCut], "barrel,vertexing"); // define dilepton histograms + fHistNamesDileptonTrack[fNCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut] = Form("DileptonTrack_%s_%s_%s", tempStr.Data(), objArrayPairCuts->At(iPairCut)->GetName(), fConfigTrackCut.value.data()); + fHistNamesDileptons[fNCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut] = Form("DileptonsSelected_%s_%s", tempStr.Data(), objArrayPairCuts->At(iPairCut)->GetName()); + DefineHistograms(fHistMan, fHistNamesDileptonTrack[fNCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut], fConfigHistogramSubgroups.value.data()); // define dilepton-track histograms + DefineHistograms(fHistMan, fHistNamesDileptons[fNCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut], "barrel,vertexing"); // define dilepton histograms + if (!pairCommonCutsStr.IsNull()) { + std::unique_ptr objArrayCommon(pairCommonCutsStr.Tokenize(",")); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + fHistNamesDileptonTrack[(fNCuts * (fNCommonTrackCuts + 1) + fNCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut] = Form("DileptonTrack_%s_%s_%s_%s", tempStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), objArrayPairCuts->At(iPairCut)->GetName(), fConfigTrackCut.value.data()); + fHistNamesDileptons[(fNCuts * (fNCommonTrackCuts + 1) + fNCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut] = Form("DileptonsSelected_%s_%s_%s", tempStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), objArrayPairCuts->At(iPairCut)->GetName()); + DefineHistograms(fHistMan, fHistNamesDileptonTrack[(fNCuts * (fNCommonTrackCuts + 1) + fNCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut], fConfigHistogramSubgroups.value.data()); // define dilepton-track histograms + DefineHistograms(fHistMan, fHistNamesDileptons[(fNCuts * (fNCommonTrackCuts + 1) + fNCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut], "barrel,vertexing"); // define dilepton histograms + } + } } } if (isBarrelME || isMuonME) { @@ -2321,9 +2596,19 @@ struct AnalysisDileptonTrack { if (dilepton.filterMap_bit(icut)) { fHistMan->FillHistClass(fHistNamesDileptons[icut].Data(), fValuesDilepton); if constexpr (TCandidateType == VarManager::kDstarToD0KPiPi) { // Dielectrons and Dimuons don't have the PairFilterMap column + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (dilepton.commonFilterMap_bit(fCommonTrackCutMap[iCommonCut])) { + fHistMan->FillHistClass(fHistNamesDileptons[fNCuts + icut * fNCommonTrackCuts + iCommonCut].Data(), fValuesDilepton); + } + } for (int iPairCut = 0; iPairCut < fNPairCuts; iPairCut++) { if (dilepton.pairFilterMap_bit(iPairCut)) { - fHistMan->FillHistClass(fHistNamesDileptons[fNCuts + icut * fNPairCuts + iPairCut].Data(), fValuesDilepton); + fHistMan->FillHistClass(fHistNamesDileptons[fNCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut].Data(), fValuesDilepton); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (dilepton.commonFilterMap_bit(fCommonTrackCutMap[iCommonCut])) { + fHistMan->FillHistClass(fHistNamesDileptons[(fNCuts * (fNCommonTrackCuts + 1) + fNCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut].Data(), fValuesDilepton); + } + } } } } @@ -2360,9 +2645,19 @@ struct AnalysisDileptonTrack { if (dilepton.filterMap_bit(icut)) { fHistMan->FillHistClass(fHistNamesDileptonTrack[icut].Data(), fValuesHadron); if constexpr (TCandidateType == VarManager::kDstarToD0KPiPi) { // Dielectrons and Dimuons don't have the PairFilterMap column + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (dilepton.commonFilterMap_bit(fCommonTrackCutMap[iCommonCut])) { + fHistMan->FillHistClass(fHistNamesDileptonTrack[fNCuts + icut * fNCommonTrackCuts + iCommonCut].Data(), fValuesHadron); + } + } for (int iPairCut = 0; iPairCut < fNPairCuts; iPairCut++) { if (dilepton.pairFilterMap_bit(iPairCut)) { - fHistMan->FillHistClass(fHistNamesDileptonTrack[fNCuts + icut * fNPairCuts + iPairCut].Data(), fValuesHadron); + fHistMan->FillHistClass(fHistNamesDileptonTrack[fNCuts * (fNCommonTrackCuts + 1) + icut * fNPairCuts + iPairCut].Data(), fValuesHadron); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (dilepton.commonFilterMap_bit(fCommonTrackCutMap[iCommonCut])) { + fHistMan->FillHistClass(fHistNamesDileptonTrack[(fNCuts * (fNCommonTrackCuts + 1) + fNCuts * fNPairCuts) + icut * (fNPairCuts * fNCommonTrackCuts + 1) + iCommonCut * (1 + fNPairCuts) + iPairCut].Data(), fValuesHadron); + } + } } } } diff --git a/PWGDQ/Tasks/taskJpsiHf.cxx b/PWGDQ/Tasks/taskJpsiHf.cxx index 0b00497c3d8..b8ee0b7e34e 100644 --- a/PWGDQ/Tasks/taskJpsiHf.cxx +++ b/PWGDQ/Tasks/taskJpsiHf.cxx @@ -68,6 +68,10 @@ struct taskJPsiHf { Configurable massDileptonCandMin{"massDileptonCandMin", 1.f, "minimum dilepton mass"}; Configurable massDileptonCandMax{"massDileptonCandMax", 5.f, "maximum dilepton mass"}; + // Preslices for unsorted indexes + PresliceUnsorted perCollisionDilepton = aod::jpsidmescorr::redJpDmCollId; + PresliceUnsorted perCollisionDmeson = aod::jpsidmescorr::redJpDmCollId; + // histogram for normalisation std::shared_ptr hCollisions; HistogramRegistry registry{"registry"}; @@ -95,7 +99,7 @@ struct taskJPsiHf { for (auto& dilepton : dileptons) { ptDilepton = RecoDecay::pt(dilepton.px(), dilepton.py()); - rapDilepton = RecoDecay::y(std::array{dilepton.px(), dilepton.py(), dilepton.pz()}, dilepton.mass()); + rapDilepton = RecoDecay::y(std::array{dilepton.px(), dilepton.py(), dilepton.pz()}, constants::physics::MassJPsi); phiDilepton = RecoDecay::phi(dilepton.px(), dilepton.py()); for (auto& dmeson : dmesons) { @@ -109,7 +113,7 @@ struct taskJPsiHf { } if (dmeson.massD0() > 0) { - rapDmeson = RecoDecay::y(std::array{dmeson.px(), dmeson.py(), dmeson.pz()}, dmeson.massD0()); + rapDmeson = RecoDecay::y(std::array{dmeson.px(), dmeson.py(), dmeson.pz()}, constants::physics::MassD0); deltaRap = rapDilepton - rapDmeson; auto bdtBkg = dmeson.bdtBkgMassHypo0(); auto bdtPrompt = dmeson.bdtPromptMassHypo0(); @@ -119,12 +123,12 @@ struct taskJPsiHf { } } if (dmeson.massD0bar() > 0) { - rapDmeson = RecoDecay::y(std::array{dmeson.px(), dmeson.py(), dmeson.pz()}, dmeson.massD0bar()); + rapDmeson = RecoDecay::y(std::array{dmeson.px(), dmeson.py(), dmeson.pz()}, constants::physics::MassD0); deltaRap = rapDilepton - rapDmeson; auto bdtBkg = dmeson.bdtBkgMassHypo1(); auto bdtPrompt = dmeson.bdtPromptMassHypo1(); auto bdtNonPrompt = dmeson.bdtNonpromptMassHypo1(); - if ((dilepton.mass() > massDileptonCandMin && dilepton.mass() < massDileptonCandMax) && (dmeson.massD0() > massHfCandMin && dmeson.massD0() < massHfCandMax && bdtBkg < cutsDmesBdt->get(ptBinDmesForBdt, "BDT background") && bdtPrompt > cutsDmesBdt->get(ptBinDmesForBdt, "BDT prompt") && bdtNonPrompt > cutsDmesBdt->get(ptBinDmesForBdt, "BDT nonprompt"))) { + if ((dilepton.mass() > massDileptonCandMin && dilepton.mass() < massDileptonCandMax) && (dmeson.massD0bar() > massHfCandMin && dmeson.massD0bar() < massHfCandMax && bdtBkg < cutsDmesBdt->get(ptBinDmesForBdt, "BDT background") && bdtPrompt > cutsDmesBdt->get(ptBinDmesForBdt, "BDT prompt") && bdtNonPrompt > cutsDmesBdt->get(ptBinDmesForBdt, "BDT nonprompt"))) { redDileptDimesAll(dilepton.mass(), dmeson.massD0bar(), ptDilepton, ptDmeson, rapDilepton, rapDmeson, phiDilepton, phiDmeson, deltaRap, deltaPhi, bdtBkg, bdtPrompt, bdtNonPrompt); } } @@ -132,11 +136,15 @@ struct taskJPsiHf { } } - void processRedJspiD0(MyRedEvents::iterator const& event, MyRedPairCandidatesSelected const& dileptons, MyRedD0CandidatesSelected const& dmesons) + void processRedJspiD0(MyRedEvents const& events, MyRedPairCandidatesSelected const& dileptons, MyRedD0CandidatesSelected const& dmesons) { // Fill the column of collisions with pairs - hCollisions->Fill(1.f); - runDileptonDmeson(event, dileptons, dmesons); + for (auto& event : events) { + hCollisions->Fill(1.f); + auto groupedDileptonCandidates = dileptons.sliceBy(perCollisionDilepton, event.index()); + auto groupedDmesonCandidates = dmesons.sliceBy(perCollisionDmeson, event.index()); + runDileptonDmeson(event, groupedDileptonCandidates, groupedDmesonCandidates); + } } void processNormCounter(RedJpDmColCounts const& normCounters) diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 8b98d574c72..cdb61eee77c 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -165,6 +165,9 @@ struct v0selector { registry.add("hMassGamma", "hMassGamma", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 0.0f, 0.1f}}); registry.add("hGammaRxy", "hGammaRxy", HistType::kTH2F, {{1800, -90.0f, 90.0f}, {1800, -90.0f, 90.0f}}); registry.add("hMassK0S", "hMassK0S", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 0.45, 0.55}}); + registry.add("hMassK0SPt", "hMassK0SPt", HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.45, 0.55}}); + registry.add("hMassK0SEta", "hMassK0SEta", HistType::kTH2F, {{20, -1, 1}, {100, 0.45, 0.55}}); + registry.add("hMassK0SPhi", "hMassK0SPhi", HistType::kTH2F, {{63, 0, 6.3}, {100, 0.45, 0.55}}); registry.add("hMassLambda", "hMassLambda", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.05, 1.15f}}); registry.add("hMassAntiLambda", "hAntiMassLambda", HistType::kTH2F, {{900, 0.0f, 90.0f}, {100, 1.05, 1.15f}}); registry.add("hV0Pt", "pT", HistType::kTH1F, {{100, 0.0f, 10}}); @@ -308,6 +311,9 @@ struct v0selector { } else if (v0id == kK0S) { // K0S-> pi pi if (fillhisto) { registry.fill(HIST("hMassK0S"), V0radius, mK0S); + registry.fill(HIST("hMassK0SPt"), V0.pt(), mK0S); + registry.fill(HIST("hMassK0SEta"), V0.eta(), mK0S); + registry.fill(HIST("hMassK0SPhi"), V0.phi(), mK0S); } if ((0.48 < mK0S && mK0S < 0.51) && TMath::Abs(V0.posTrack_as().tpcNSigmaPi()) < 5 && TMath::Abs(V0.negTrack_as().tpcNSigmaPi()) < 5) { pidmap[V0.posTrackId()] |= (uint8_t(1) << kK0S); diff --git a/PWGEM/Dilepton/CMakeLists.txt b/PWGEM/Dilepton/CMakeLists.txt index 9d96b0b8d33..7ff980baa4f 100644 --- a/PWGEM/Dilepton/CMakeLists.txt +++ b/PWGEM/Dilepton/CMakeLists.txt @@ -9,7 +9,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -# add_subdirectory(Core) +add_subdirectory(Core) # add_subdirectory(DataModel) add_subdirectory(Tasks) add_subdirectory(TableProducer) diff --git a/PWGEM/Dilepton/Core/CMakeLists.txt b/PWGEM/Dilepton/Core/CMakeLists.txt new file mode 100644 index 00000000000..92d06924294 --- /dev/null +++ b/PWGEM/Dilepton/Core/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2019-2020 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. + +o2physics_add_library(PWGEMDileptonCore + SOURCES EMEventCut.cxx + DielectronCut.cxx + DimuonCut.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore) + +o2physics_target_root_dictionary(PWGEMDileptonCore + HEADERS EMEventCut.h + DielectronCut.h + DimuonCut.h + LINKDEF PWGEMDileptonCoreLinkDef.h) diff --git a/PWGEM/Dilepton/Core/DielectronCut.cxx b/PWGEM/Dilepton/Core/DielectronCut.cxx new file mode 100644 index 00000000000..6d549e0457f --- /dev/null +++ b/PWGEM/Dilepton/Core/DielectronCut.cxx @@ -0,0 +1,260 @@ +// Copyright 2019-2020 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. + +// +// Class for dilepton Cut +// + +#include "Framework/Logger.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" + +ClassImp(DielectronCut); + +const std::pair> DielectronCut::its_ib_any_Requirement = {1, {0, 1, 2}}; // hits on any ITS ib layers. +const std::pair> DielectronCut::its_ib_1st_Requirement = {1, {0}}; // hit on 1st ITS ib layers. + +void DielectronCut::SetPairPtRange(float minPt, float maxPt) +{ + mMinPairPt = minPt; + mMaxPairPt = maxPt; + LOG(info) << "Dielectron Cut, set pair pt range: " << mMinPairPt << " - " << mMaxPairPt; +} +void DielectronCut::SetPairYRange(float minY, float maxY) +{ + mMinPairY = minY; + mMaxPairY = maxY; + LOG(info) << "Dielectron Cut, set pair eta range: " << mMinPairY << " - " << mMaxPairY; +} +void DielectronCut::SetPairDCARange(float min, float max) +{ + mMinPairDCA3D = min; + mMaxPairDCA3D = max; + LOG(info) << "Dielectron Cut, set pair 3d dca range: " << mMinPairDCA3D << " - " << mMaxPairDCA3D; +} +void DielectronCut::SetMeeRange(float min, float max) +{ + mMinMee = min; + mMaxMee = max; + LOG(info) << "Dielectron Cut, set mee range: " << mMinMee << " - " << mMaxMee; +} +void DielectronCut::SetMaxPhivPairMeeDep(std::function meeDepCut) +{ + mMaxPhivPairMeeDep = meeDepCut; + LOG(info) << "Dielectron Cut, set max phiv pair mee dep: " << mMaxPhivPairMeeDep(0.02); +} +void DielectronCut::SetPhivPairRange(float min, float max) +{ + mMinPhivPair = min; + mMaxPhivPair = max; + LOG(info) << "Dielectron Cut, set phiv range: " << mMinPhivPair << " - " << mMaxPhivPair; +} +void DielectronCut::SelectPhotonConversion(bool flag) +{ + mSelectPC = flag; + LOG(info) << "Dielectron Cut, select photon conversion: " << mSelectPC; +} +void DielectronCut::SetTrackPtRange(float minPt, float maxPt) +{ + mMinTrackPt = minPt; + mMaxTrackPt = maxPt; + LOG(info) << "Dielectron Cut, set track pt range: " << mMinTrackPt << " - " << mMaxTrackPt; +} +void DielectronCut::SetTrackEtaRange(float minEta, float maxEta) +{ + mMinTrackEta = minEta; + mMaxTrackEta = maxEta; + LOG(info) << "Dielectron Cut, set track eta range: " << mMinTrackEta << " - " << mMaxTrackEta; +} +void DielectronCut::SetTrackPhiRange(float minPhi, float maxPhi) +{ + mMinTrackPhi = minPhi; + mMaxTrackPhi = maxPhi; + LOG(info) << "Dielectron Cut, set track phi range (rad.): " << mMinTrackPhi << " - " << mMaxTrackPhi; +} +void DielectronCut::SetMinNClustersTPC(int minNClustersTPC) +{ + mMinNClustersTPC = minNClustersTPC; + LOG(info) << "Dielectron Cut, set min N clusters TPC: " << mMinNClustersTPC; +} +void DielectronCut::SetMinNCrossedRowsTPC(int minNCrossedRowsTPC) +{ + mMinNCrossedRowsTPC = minNCrossedRowsTPC; + LOG(info) << "Dielectron Cut, set min N crossed rows TPC: " << mMinNCrossedRowsTPC; +} +void DielectronCut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC) +{ + mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; + LOG(info) << "Dielectron Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; +} +void DielectronCut::SetChi2PerClusterTPC(float min, float max) +{ + mMinChi2PerClusterTPC = min; + mMaxChi2PerClusterTPC = max; + LOG(info) << "Dielectron Cut, set chi2 per cluster TPC range: " << mMinChi2PerClusterTPC << " - " << mMaxChi2PerClusterTPC; +} + +void DielectronCut::SetNClustersITS(int min, int max) +{ + mMinNClustersITS = min; + mMaxNClustersITS = max; + LOG(info) << "Dielectron Cut, set N clusters ITS range: " << mMinNClustersITS << " - " << mMaxNClustersITS; +} +void DielectronCut::SetChi2PerClusterITS(float min, float max) +{ + mMinChi2PerClusterITS = min; + mMaxChi2PerClusterITS = max; + LOG(info) << "Dielectron Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; +} +void DielectronCut::SetMeanClusterSizeITS(float min, float max, float maxP) +{ + mMinMeanClusterSizeITS = min; + mMaxMeanClusterSizeITS = max; + mMaxP_ITSClusterSize = maxP; + LOG(info) << "Dielectron Cut, set mean cluster size ITS range: " << mMinMeanClusterSizeITS << " - " << mMaxMeanClusterSizeITS; +} +void DielectronCut::SetTrackDca3DRange(float min, float max) +{ + mMinDca3D = min; + mMaxDca3D = max; + LOG(info) << "Dielectron Cut, set DCA 3D range in sigma: " << mMinDca3D << " - " << mMaxDca3D; +} +void DielectronCut::SetTrackMaxDcaXY(float maxDcaXY) +{ + mMaxDcaXY = maxDcaXY; + LOG(info) << "Dielectron Cut, set max DCA xy: " << mMaxDcaXY; +} +void DielectronCut::SetTrackMaxDcaZ(float maxDcaZ) +{ + mMaxDcaZ = maxDcaZ; + LOG(info) << "Dielectron Cut, set max DCA z: " << mMaxDcaZ; +} + +void DielectronCut::SetTrackMaxDcaXYPtDep(std::function ptDepCut) +{ + mMaxDcaXYPtDep = ptDepCut; + LOG(info) << "Dielectron Cut, set max DCA xy pt dep: " << mMaxDcaXYPtDep(1.0); +} +void DielectronCut::ApplyPhiV(bool flag) +{ + mApplyPhiV = flag; + LOG(info) << "Dielectron Cut, apply phiv cut: " << mApplyPhiV; +} +void DielectronCut::ApplyPrefilter(bool flag) +{ + mApplyPF = flag; + LOG(info) << "Dielectron Cut, apply prefilter: " << mApplyPF; +} + +void DielectronCut::SetPIDScheme(int scheme) +{ + mPIDScheme = scheme; + LOG(info) << "Dielectron Cut, PID scheme: " << static_cast(mPIDScheme); +} +void DielectronCut::SetMinPinTOF(float min) +{ + mMinPinTOF = min; + LOG(info) << "Dielectron Cut, set min pin for TOF: " << mMinPinTOF; +} + +void DielectronCut::SetMuonExclusionTPC(bool flag) +{ + mMuonExclusionTPC = flag; + LOG(info) << "Dielectron Cut, set flag for muon exclusion in TPC: " << mMuonExclusionTPC; +} + +void DielectronCut::SetTOFbetaRange(float min, float max) +{ + mMinTOFbeta = min; + mMaxTOFbeta = max; + LOG(info) << "Dielectron Cut, set TOF beta range (TOFif): " << mMinTOFbeta << " - " << mMaxTOFbeta; +} + +void DielectronCut::SetTPCNsigmaElRange(float min, float max) +{ + mMinTPCNsigmaEl = min; + mMaxTPCNsigmaEl = max; + LOG(info) << "Dielectron Cut, set TPC n sigma El range: " << mMinTPCNsigmaEl << " - " << mMaxTPCNsigmaEl; +} +void DielectronCut::SetTPCNsigmaMuRange(float min, float max) +{ + mMinTPCNsigmaMu = min; + mMaxTPCNsigmaMu = max; + LOG(info) << "Dielectron Cut, set TPC n sigma Mu range: " << mMinTPCNsigmaMu << " - " << mMaxTPCNsigmaMu; +} +void DielectronCut::SetTPCNsigmaPiRange(float min, float max) +{ + mMinTPCNsigmaPi = min; + mMaxTPCNsigmaPi = max; + LOG(info) << "Dielectron Cut, set TPC n sigma Pi range: " << mMinTPCNsigmaPi << " - " << mMaxTPCNsigmaPi; +} +void DielectronCut::SetTPCNsigmaKaRange(float min, float max) +{ + mMinTPCNsigmaKa = min; + mMaxTPCNsigmaKa = max; + LOG(info) << "Dielectron Cut, set TPC n sigma Ka range: " << mMinTPCNsigmaKa << " - " << mMaxTPCNsigmaKa; +} +void DielectronCut::SetTPCNsigmaPrRange(float min, float max) +{ + mMinTPCNsigmaPr = min; + mMaxTPCNsigmaPr = max; + LOG(info) << "Dielectron Cut, set TPC n sigma Pr range: " << mMinTPCNsigmaPr << " - " << mMaxTPCNsigmaPr; +} + +void DielectronCut::SetTOFNsigmaElRange(float min, float max) +{ + mMinTOFNsigmaEl = min; + mMaxTOFNsigmaEl = max; + LOG(info) << "Dielectron Cut, set TOF n sigma El range: " << mMinTOFNsigmaEl << " - " << mMaxTOFNsigmaEl; +} +void DielectronCut::SetTOFNsigmaMuRange(float min, float max) +{ + mMinTOFNsigmaMu = min; + mMaxTOFNsigmaMu = max; + LOG(info) << "Dielectron Cut, set TOF n sigma Mu range: " << mMinTOFNsigmaMu << " - " << mMaxTOFNsigmaMu; +} +void DielectronCut::SetTOFNsigmaPiRange(float min, float max) +{ + mMinTOFNsigmaPi = min; + mMaxTOFNsigmaPi = max; + LOG(info) << "Dielectron Cut, set TOF n sigma Pi range: " << mMinTOFNsigmaPi << " - " << mMaxTOFNsigmaPi; +} +void DielectronCut::SetTOFNsigmaKaRange(float min, float max) +{ + mMinTOFNsigmaKa = min; + mMaxTOFNsigmaKa = max; + LOG(info) << "Dielectron Cut, set TOF n sigma Ka range: " << mMinTOFNsigmaKa << " - " << mMaxTOFNsigmaKa; +} +void DielectronCut::SetTOFNsigmaPrRange(float min, float max) +{ + mMinTOFNsigmaPr = min; + mMaxTOFNsigmaPr = max; + LOG(info) << "Dielectron Cut, set TOF n sigma Pr range: " << mMinTOFNsigmaPr << " - " << mMaxTOFNsigmaPr; +} +void DielectronCut::SetMaxPinMuonTPConly(float max) +{ + mMaxPinMuonTPConly = max; + LOG(info) << "Dielectron Cut, set max pin for Muon ID with TPC only: " << mMaxPinMuonTPConly; +} +void DielectronCut::SetMaxPinForPionRejectionTPC(float max) +{ + mMaxPinForPionRejectionTPC = max; + LOG(info) << "Dielectron Cut, set max pin for pion rejection in TPC: " << mMaxPinForPionRejectionTPC; +} +void DielectronCut::RequireITSibAny(bool flag) +{ + mRequireITSibAny = flag; + LOG(info) << "Dielectron Cut, require ITS ib any: " << mRequireITSibAny; +} +void DielectronCut::RequireITSib1st(bool flag) +{ + mRequireITSib1st = flag; + LOG(info) << "Dielectron Cut, require ITS ib 1st: " << mRequireITSib1st; +} diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h new file mode 100644 index 00000000000..eb6afd4ccc7 --- /dev/null +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -0,0 +1,475 @@ +// Copyright 2019-2020 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. + +// +// Class for dielectron selection +// + +#ifndef PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ +#define PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ + +#include +#include +#include +#include +#include +#include "TNamed.h" +#include "Math/Vector4D.h" + +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +#include "Framework/Logger.h" +#include "Framework/DataTypes.h" +#include "CommonConstants/PhysicsConstants.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +class DielectronCut : public TNamed +{ + public: + DielectronCut() = default; + DielectronCut(const char* name, const char* title) : TNamed(name, title) {} + ~DielectronCut() {} + + enum class DielectronCuts : int { + // pair cut + kMee = 0, + kPairPtRange, + kPairYRange, + kPairDCARange, + kPhiV, + // track cut + kTrackPtRange, + kTrackEtaRange, + kTrackPhiRange, + kTPCNCls, + kTPCCrossedRows, + kTPCCrossedRowsOverNCls, + kTPCChi2NDF, + kTPCNsigmaEl, + kTPCNsigmaMu, + kTPCNsigmaPi, + kTPCNsigmaKa, + kTPCNsigmaPr, + kTOFNsigmaEl, + kTOFNsigmaMu, + kTOFNsigmaPi, + kTOFNsigmaKa, + kTOFNsigmaPr, + kDCA3Dsigma, + kDCAxy, + kDCAz, + kITSNCls, + kITSChi2NDF, + kITSCluserSize, + kPrefilter, + kNCuts + }; + + enum class PIDSchemes : int { + kUnDef = -1, + kTOFreq = 0, + kTPChadrej = 1, + kTPChadrejORTOFreq = 2, + kTPConly = 3, + kTOFif = 4, + kPIDML = 5 + }; + + template + bool IsSelected(TPair const& pair) const + { + auto t1 = std::get<0>(pair); + auto t2 = std::get<1>(pair); + float bz = std::get<2>(pair); + + if (!IsSelectedTrack(t1) || !IsSelectedTrack(t2)) { + return false; + } + + if (!IsSelectedPair(t1, t2, bz)) { + return false; + } + + return true; + } + + template + bool IsSelectedPair(TTrack1 const& t1, TTrack2 const& t2, const float bz) const + { + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + float dca_t1_3d = dca3DinSigma(t1); + float dca_t2_3d = dca3DinSigma(t2); + float dca_ee_3d = std::sqrt((dca_t1_3d * dca_t1_3d + dca_t2_3d * dca_t2_3d) / 2.); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), bz); + + if (v12.M() < mMinMee || mMaxMee < v12.M()) { + return false; + } + + if (v12.Rapidity() < mMinPairY || mMaxPairY < v12.Rapidity()) { + return false; + } + + if (mApplyPhiV && ((phiv < mMinPhivPair || (mMaxPhivPairMeeDep ? mMaxPhivPairMeeDep(v12.M()) : mMaxPhivPair) < phiv) ^ mSelectPC)) { + return false; + } + if (dca_ee_3d < mMinPairDCA3D || mMaxPairDCA3D < dca_ee_3d) { // in sigma for pair + return false; + } + return true; + } + + template + bool IsSelectedTrack(TTrack const& track, TCollision const& collision = 0) const + { + if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track + return false; + } + + if (!IsSelectedTrack(track, DielectronCuts::kTrackPtRange)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTrackEtaRange)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTrackPhiRange)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kDCA3Dsigma)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kDCAxy)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kDCAz)) { + return false; + } + + // ITS cuts + if (!IsSelectedTrack(track, DielectronCuts::kITSNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kITSChi2NDF)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kITSCluserSize)) { + return false; + } + + if (mRequireITSibAny) { + auto hits_ib = std::count_if(its_ib_any_Requirement.second.begin(), its_ib_any_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits_ib < its_ib_any_Requirement.first) { + return false; + } + } + + if (mRequireITSib1st) { + auto hits_ib = std::count_if(its_ib_1st_Requirement.second.begin(), its_ib_1st_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits_ib < its_ib_1st_Requirement.first) { + return false; + } + } + + // TPC cuts + if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { + return false; + } + + if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { + return false; + } + + // // TOF beta cut + // if (track.hasTOF() && (track.beta() < mMinTOFbeta || mMaxTOFbeta < track.beta())) { + // return false; + // } + + // PID cuts + if constexpr (isML) { + if (!PassPIDML(track, collision)) { + return false; + } + } else { + if (!PassPID(track)) { + return false; + } + } + + return true; + } + + template + bool PassPIDML(TTrack const& track, TCollision const& collision) const + { + std::vector inputFeatures{static_cast(collision.numContrib()), track.p(), track.tgl(), + track.tpcNSigmaEl(), /*track.tpcNSigmaMu(),*/ track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tofNSigmaEl(), /*track.tofNSigmaMu(),*/ track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))}; + + // calculate classifier + float prob_ele = mPIDModel->evalModel(inputFeatures)[0]; + // LOGF(info, "prob_ele = %f", prob_ele); + if (prob_ele < 0.95) { + return false; + } else { + return true; + } + } + + template + bool PassPID(T const& track) const + { + switch (mPIDScheme) { + case static_cast(PIDSchemes::kTOFreq): + return PassTOFreq(track); + + case static_cast(PIDSchemes::kTPChadrej): + return PassTPChadrej(track); + + case static_cast(PIDSchemes::kTPChadrejORTOFreq): + return PassTPChadrej(track) || PassTOFreq(track); + + case static_cast(PIDSchemes::kTPConly): + return PassTPConly(track); + + case static_cast(PIDSchemes::kTOFif): + return PassTOFif(track); + + case static_cast(PIDSchemes::kPIDML): + return true; // don't use kPIDML here. + + case static_cast(PIDSchemes::kUnDef): + return true; + + default: + return true; + } + } + + template + bool PassTOFreq(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; + bool is_el_included_TOF = mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; + } + + template + bool PassTPChadrej(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; + bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; + bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); + bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); + bool is_el_included_TOF = track.hasTOF() ? (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) : true; + return is_el_included_TPC && is_mu_excluded_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC && is_el_included_TOF; + } + + template + bool PassTPConly(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + return is_el_included_TPC; + } + + template + bool PassTOFif(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; + bool is_el_included_TOF = track.hasTOF() ? (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) : true; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; + } + + template + bool IsSelectedTrack(T const& track, const DielectronCuts& cut) const + { + switch (cut) { + case DielectronCuts::kTrackPtRange: + return track.pt() >= mMinTrackPt && track.pt() <= mMaxTrackPt; + + case DielectronCuts::kTrackEtaRange: + return track.eta() >= mMinTrackEta && track.eta() <= mMaxTrackEta; + + case DielectronCuts::kTrackPhiRange: + return track.phi() >= mMinTrackPhi && track.phi() <= mMaxTrackPhi; + + case DielectronCuts::kTPCNCls: + return track.tpcNClsFound() >= mMinNClustersTPC; + + case DielectronCuts::kTPCCrossedRows: + return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; + + case DielectronCuts::kTPCCrossedRowsOverNCls: + return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + + case DielectronCuts::kTPCChi2NDF: + return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; + + case DielectronCuts::kDCA3Dsigma: + return mMinDca3D <= dca3DinSigma(track) && dca3DinSigma(track) <= mMaxDca3D; // in sigma for single leg + + case DielectronCuts::kDCAxy: + return abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + + case DielectronCuts::kDCAz: + return abs(track.dcaZ()) <= mMaxDcaZ; + + case DielectronCuts::kITSNCls: + return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; + + case DielectronCuts::kITSChi2NDF: + return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; + + case DielectronCuts::kITSCluserSize: + return track.p() < mMaxP_ITSClusterSize ? mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS : true; + + case DielectronCuts::kPrefilter: + return track.pfb() <= 0; + + default: + return false; + } + } + + // Setters + void SetPairPtRange(float minPt = 0.f, float maxPt = 1e10f); + void SetPairYRange(float minY = -1e10f, float maxY = 1e10f); + void SetPairDCARange(float min = 0.f, float max = 1e10f); // 3D DCA in sigma + void SetMeeRange(float min = 0.f, float max = 0.5); + void SetMaxPhivPairMeeDep(std::function meeDepCut); + void SetPhivPairRange(float min, float max); + void SelectPhotonConversion(bool flag); + + void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); + void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); + void SetTrackPhiRange(float minPhi = 0.f, float maxPhi = 2.f * M_PI); + void SetMinNClustersTPC(int minNClustersTPC); + void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC); + void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC); + void SetChi2PerClusterTPC(float min, float max); + void SetNClustersITS(int min, int max); + void SetChi2PerClusterITS(float min, float max); + void SetMeanClusterSizeITS(float min, float max, float maxP = 0.f); + + void SetPIDScheme(int scheme); + void SetMinPinTOF(float min); + void SetMuonExclusionTPC(bool flag); + void SetTOFbetaRange(float min, float max); + void SetTPCNsigmaElRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaMuRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaPiRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaKaRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaPrRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaElRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaMuRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaPiRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaKaRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaPrRange(float min = -1e+10, float max = 1e+10); + void SetMaxPinMuonTPConly(float max); + void SetMaxPinForPionRejectionTPC(float max); + void RequireITSibAny(bool flag); + void RequireITSib1st(bool flag); + + void SetTrackDca3DRange(float min, float max); // in sigma + void SetTrackMaxDcaXY(float maxDcaXY); // in cm + void SetTrackMaxDcaZ(float maxDcaZ); // in cm + void SetTrackMaxDcaXYPtDep(std::function ptDepCut); + void ApplyPrefilter(bool flag); + void ApplyPhiV(bool flag); + + void SetPIDModel(o2::ml::OnnxModel* model) + { + mPIDModel = model; + } + + // Getters + bool IsPhotonConversionSelected() const { return mSelectPC; } + + private: + static const std::pair> its_ib_any_Requirement; + static const std::pair> its_ib_1st_Requirement; + // pair cuts + float mMinMee{0.f}, mMaxMee{1e10f}; + float mMinPairPt{0.f}, mMaxPairPt{1e10f}; // range in pT + float mMinPairY{-1e10f}, mMaxPairY{1e10f}; // range in rapidity + float mMinPairDCA3D{0.f}, mMaxPairDCA3D{1e10f}; // range in 3D DCA in sigma + float mMinPhivPair{0.f}, mMaxPhivPair{+3.2}; + std::function mMaxPhivPairMeeDep{}; // max phiv as a function of mee + bool mSelectPC{false}; // flag to select photon conversion used in mMaxPhivPairMeeDep + + // kinematic cuts + float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT + float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta + float mMinTrackPhi{0.f}, mMaxTrackPhi{2.f * M_PI}; // range in phi + + // track quality cuts + int mMinNClustersTPC{0}; // min number of TPC clusters + int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC + float mMinChi2PerClusterTPC{-1e10f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster + float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters + float mMinChi2PerClusterITS{-1e10f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster + float mMaxPinMuonTPConly{0.2f}; // max pin cut for muon ID with TPConly + float mMaxPinForPionRejectionTPC{1e10f}; // max pin cut for muon ID with TPConly + bool mRequireITSibAny{true}; + bool mRequireITSib1st{false}; + + float mMinDca3D{0.0f}; // min dca in 3D in units of sigma + float mMaxDca3D{1e+10}; // max dca in 3D in units of sigma + float mMaxDcaXY{1.0f}; // max dca in xy plane + float mMaxDcaZ{1.0f}; // max dca in z direction + std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT + bool mApplyPhiV{true}; + bool mApplyPF{false}; + float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) + float mMaxP_ITSClusterSize{0.0}; + + // pid cuts + int mPIDScheme{-1}; + float mMinPinTOF{0.0f}; // min pin cut for TOF. + bool mMuonExclusionTPC{false}; // flag to reject muon in TPC for low B + float mMinTOFbeta{-999}, mMaxTOFbeta{999}; + float mMinTPCNsigmaEl{-1e+10}, mMaxTPCNsigmaEl{+1e+10}; + float mMinTPCNsigmaMu{-1e+10}, mMaxTPCNsigmaMu{+1e+10}; + float mMinTPCNsigmaPi{-1e+10}, mMaxTPCNsigmaPi{+1e+10}; + float mMinTPCNsigmaKa{-1e+10}, mMaxTPCNsigmaKa{+1e+10}; + float mMinTPCNsigmaPr{-1e+10}, mMaxTPCNsigmaPr{+1e+10}; + + float mMinTOFNsigmaEl{-1e+10}, mMaxTOFNsigmaEl{+1e+10}; + float mMinTOFNsigmaMu{-1e+10}, mMaxTOFNsigmaMu{+1e+10}; + float mMinTOFNsigmaPi{-1e+10}, mMaxTOFNsigmaPi{+1e+10}; + float mMinTOFNsigmaKa{-1e+10}, mMaxTOFNsigmaKa{+1e+10}; + float mMinTOFNsigmaPr{-1e+10}, mMaxTOFNsigmaPr{+1e+10}; + o2::ml::OnnxModel* mPIDModel{nullptr}; + + ClassDef(DielectronCut, 1); +}; + +#endif // PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h new file mode 100644 index 00000000000..b84a8a03356 --- /dev/null +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -0,0 +1,1549 @@ +// Copyright 2019-2020 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 leptons. +// Please write to: daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_CORE_DILEPTON_H_ +#define PWGEM_DILEPTON_CORE_DILEPTON_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "TH1D.h" +#include "TString.h" +#include "Math/Vector4D.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "DCAFitter/DCAFitterN.h" +#include "DCAFitter/FwdDCAFitterN.h" +#include "CommonConstants/LHCConstants.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMFwdTrack.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyCollisionsWithSWT = soa::Join; +using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; + +using MyElectrons = soa::Join; +using MyElectron = MyElectrons::iterator; +using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectron = FilteredMyElectrons::iterator; + +using MyMuons = soa::Join; +using MyMuon = MyMuons::iterator; +using FilteredMyMuons = soa::Filtered; +using FilteredMyMuon = FilteredMyMuons::iterator; + +using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrackWithCov>; +using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMFwdTrackWithCov>; + +template +struct Dilepton { + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable cfgApplySPresolution{"cfgApplySPresolution", false, "flag to apply resolution correction for flow analysis"}; + Configurable spresoPath{"spresoPath", "Users/d/dsekihat/PWGEM/dilepton/Qvector/resolution/LHC23zzh/pass3/test", "Path to SP resolution file"}; + Configurable spresoHistName{"spresoHistName", "h1_R2_FT0M_BPos_BNeg", "histogram name of SP resolution file"}; + + Configurable cfgAnalysisType{"cfgAnalysisType", static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC), "kQC:0, kUPC:1, kFlowV2:2, kFlowV3:3, kPolarization:4, kVM:5, kHFll:6"}; + Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; + Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; + Configurable ndepth{"ndepth", 100, "depth for event mixing"}; + Configurable ndiff_bc_mix{"ndiff_bc_mix", 5, "difference in global BC required in mixed events"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; + ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -M_PI / 2, +M_PI / 2}, "Mixing bins - event plane angle"}; + ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult + Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + Configurable cfgUseDCAxy{"cfgUseDCAxy", false, "flag to use DCAxy, instead of DCA3D"}; + + ConfigurableAxis ConfMllBins{"ConfMllBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.25, 3.30, 3.35, 3.40, 3.45, 3.50, 3.55, 3.60, 3.65, 3.70, 3.75, 3.80, 3.85, 3.90, 3.95, 4.00}, "mll bins for output histograms"}; + ConfigurableAxis ConfPtllBins{"ConfPtllBins", {VARIABLE_WIDTH, 0.00, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTll bins for output histograms"}; + ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAll bins for output histograms"}; + + // ConfigurableAxis ConfMmumuBins{"ConfMmumuBins", {VARIABLE_WIDTH, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.11,1.12,1.13,1.14,1.15,1.16,1.17,1.18,1.19, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.25, 3.30, 3.35, 3.40, 3.45, 3.50, 3.55, 3.60, 3.65, 3.70, 3.75, 3.80, 3.85, 3.90, 3.95, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.10, 5.20, 5.30, 5.40, 5.50, 5.60, 5.70, 5.80, 5.90, 6.00, 6.10, 6.20, 6.30, 6.40, 6.50, 6.60, 6.70, 6.80, 6.90, 7.00, 7.10, 7.20, 7.30, 7.40, 7.50, 7.60, 7.70, 7.80, 7.90, 8.00, 8.10, 8.20, 8.30, 8.40, 8.50, 8.60, 8.70, 8.80, 8.90, 9.00, 9.10, 9.20, 9.30, 9.40, 9.50, 9.60, 9.70, 9.80, 9.90, 10.00, 10.10, 10.20, 10.30, 10.40, 10.50, 10.60, 10.70, 10.80, 10.90, 11.00, 11.50, 12.00}, "mmumu bins for output histograms"}; // for dimuon. one can copy bins here to hyperloop page. + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "dimuoncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -4.0, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", -2.5, "max pair rapidity"}; + Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + } dimuoncuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber; + float d_bz; + // o2::vertexing::DCAFitterN<2> fitter; + // o2::vertexing::FwdDCAFitterN<2> fwdfitter; + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; + + std::vector cent_bin_edges; + std::vector zvtx_bin_edges; + std::vector ep_bin_edges; + std::vector occ_bin_edges; + int nmod = -1; // this is for flow analysis + int subdet2 = -1; // this is for flow analysis + int subdet3 = -1; // this is for flow analysis + float leptonM1 = 0.f; + float leptonM2 = 0.f; + + float beamM1 = o2::constants::physics::MassProton; // mass of beam + float beamM2 = o2::constants::physics::MassProton; // mass of beam + float beamE1 = 0.f; // beam energy + float beamE2 = 0.f; // beam energy + float beamP1 = 0.f; // beam momentum + float beamP2 = 0.f; // beam momentum + TH2D* h2sp_resolution = nullptr; + + void init(InitContext& /*context*/) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + if (ConfVtxBins.value[0] == VARIABLE_WIDTH) { + zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); + zvtx_bin_edges.erase(zvtx_bin_edges.begin()); + for (auto& edge : zvtx_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfVtxBins.value[0]); + float xmin = static_cast(ConfVtxBins.value[1]); + float xmax = static_cast(ConfVtxBins.value[2]); + zvtx_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + zvtx_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: zvtx_bin_edges[%d] = %f", i, zvtx_bin_edges[i]); + } + } + + if (ConfCentBins.value[0] == VARIABLE_WIDTH) { + cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); + cent_bin_edges.erase(cent_bin_edges.begin()); + for (auto& edge : cent_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: cent_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfCentBins.value[0]); + float xmin = static_cast(ConfCentBins.value[1]); + float xmax = static_cast(ConfCentBins.value[2]); + cent_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + cent_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: cent_bin_edges[%d] = %f", i, cent_bin_edges[i]); + } + } + + if (ConfEPBins.value[0] == VARIABLE_WIDTH) { + ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); + ep_bin_edges.erase(ep_bin_edges.begin()); + for (auto& edge : ep_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: ep_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfEPBins.value[0]); + float xmin = static_cast(ConfEPBins.value[1]); + float xmax = static_cast(ConfEPBins.value[2]); + ep_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + ep_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: ep_bin_edges[%d] = %f", i, ep_bin_edges[i]); + } + } + + if (ConfOccupancyBins.value[0] == VARIABLE_WIDTH) { + occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); + occ_bin_edges.erase(occ_bin_edges.begin()); + for (auto& edge : occ_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: occ_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfOccupancyBins.value[0]); + float xmin = static_cast(ConfOccupancyBins.value[1]); + float xmax = static_cast(ConfOccupancyBins.value[2]); + occ_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + occ_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: occ_bin_edges[%d] = %f", i, occ_bin_edges[i]); + } + } + + emh_pos = new TEMH(ndepth); + emh_neg = new TEMH(ndepth); + + DefineEMEventCut(); + addhistograms(); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + DefineDielectronCut(); + leptonM1 = o2::constants::physics::MassElectron; + leptonM2 = o2::constants::physics::MassElectron; + // fitter.setPropagateToPCA(true); + // fitter.setMaxR(5.f); + // fitter.setMinParamChange(1e-3); + // fitter.setMinRelChi2Change(0.9); + // fitter.setMaxDZIni(1e9); + // fitter.setMaxChi2(1e9); + // fitter.setUseAbsDCA(true); + // fitter.setWeightedFinalPCA(false); + // fitter.setMatCorrType(matCorr); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + DefineDimuonCut(); + leptonM1 = o2::constants::physics::MassMuon; + leptonM2 = o2::constants::physics::MassMuon; + // fwdfitter.setPropagateToPCA(true); + // fwdfitter.setMaxR(90.f); + // fwdfitter.setMinParamChange(1e-3); + // fwdfitter.setMinRelChi2Change(0.9); + // fwdfitter.setMaxChi2(1e9); + // fwdfitter.setUseAbsDCA(true); + // fwdfitter.setTGeoMat(false); + } + + fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{1001, -0.5, 1000.5}}, true); + if (doprocessTriggerAnalysis) { + fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + // fitter.setBz(d_bz); + // fwdfitter.setBz(d_bz); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = collision.runNumber(); + // fitter.setBz(d_bz); + // fwdfitter.setBz(d_bz); + + auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", collision.timestamp()); + int beamZ1 = grplhcif->getBeamZ(o2::constants::lhc::BeamC); + int beamZ2 = grplhcif->getBeamZ(o2::constants::lhc::BeamA); + int beamA1 = grplhcif->getBeamA(o2::constants::lhc::BeamC); + int beamA2 = grplhcif->getBeamA(o2::constants::lhc::BeamA); + beamE1 = grplhcif->getBeamEnergyPerNucleonInGeV(o2::constants::lhc::BeamC); + beamE2 = grplhcif->getBeamEnergyPerNucleonInGeV(o2::constants::lhc::BeamA); + beamM1 = o2::constants::physics::MassProton * beamA1; + beamM2 = o2::constants::physics::MassProton * beamA2; + beamP1 = std::sqrt(std::pow(beamE1, 2) - std::pow(beamM1, 2)); + beamP2 = std::sqrt(std::pow(beamE2, 2) - std::pow(beamM2, 2)); + LOGF(info, "beamZ1 = %d, beamZ2 = %d, beamA1 = %d, beamA2 = %d, beamE1 = %f (GeV), beamE2 = %f (GeV), beamM1 = %f (GeV), beamM2 = %f (GeV), beamP1 = %f (GeV), beamP2 = %f (GeV)", beamZ1, beamZ2, beamA1, beamA2, beamE1, beamE2, beamM1, beamM2, beamP1, beamP2); + + if constexpr (isTriggerAnalysis) { + LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", cfg_swt_name.value); + LOGF(info, "total inspected TVX events = %d in run number %d", collision.nInspectedTVX(), collision.runNumber()); + fRegistry.fill(HIST("Event/hNInspectedTVX"), collision.runNumber(), collision.nInspectedTVX()); + } + + if (cfgApplySPresolution) { + auto list = ccdb->getForTimeStamp(spresoPath, collision.timestamp()); + h2sp_resolution = reinterpret_cast(list->FindObject(spresoHistName.value.data())); + LOGF(info, "h2sp_resolution.GetBinContent(40, 1) = %f", h2sp_resolution->GetBinContent(40, 1)); + } + } + + ~Dilepton() + { + delete emh_pos; + emh_pos = 0x0; + delete emh_neg; + emh_neg = 0x0; + + map_mixed_eventId_to_centrality.clear(); + map_mixed_eventId_to_occupancy.clear(); + map_mixed_eventId_to_qvector.clear(); + map_mixed_eventId_to_globalBC.clear(); + + used_trackIds.clear(); + used_trackIds.shrink_to_fit(); + + if (eid_bdt) { + delete eid_bdt; + } + delete h2sp_resolution; + } + + void addhistograms() + { + const std::string qvec_det_names[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; + + std::string mass_axis_title = "m_{ll} (GeV/c^{2})"; + std::string pair_pt_axis_title = "p_{T,ll} (GeV/c)"; + std::string pair_dca_axis_title = "DCA_{ll} (#sigma)"; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + mass_axis_title = "m_{ee} (GeV/c^{2})"; + pair_pt_axis_title = "p_{T,ee} (GeV/c)"; + pair_dca_axis_title = "DCA_{ee}^{3D} (#sigma)"; + if (cfgUseDCAxy) { + pair_dca_axis_title = "DCA_{ee}^{XY} (#sigma)"; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + mass_axis_title = "m_{#mu#mu} (GeV/c^{2})"; + pair_pt_axis_title = "p_{T,#mu#mu} (GeV/c)"; + pair_dca_axis_title = "DCA_{#mu#mu}^{XY} (#sigma)"; + } + + // pair info + const AxisSpec axis_mass{ConfMllBins, mass_axis_title}; + const AxisSpec axis_pt{ConfPtllBins, pair_pt_axis_title}; + const AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; + + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC)) { + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.add("Pair/same/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, true); // phiv is only for dielectron + } + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kUPC)) { + const AxisSpec axis_aco{10, 0, 1.f, "#alpha = 1 - #frac{|#varphi_{l^{+}} - #varphi_{l^{-}}|}{#pi}"}; + const AxisSpec axis_asym_pt{10, 0, 1.f, "A = #frac{|p_{T,l^{+}} - p_{T,l^{-}}|}{|p_{T,l^{+}} + p_{T,l^{-}}|}"}; + const AxisSpec axis_dphi_e_ee{18, 0, M_PI, "#Delta#varphi = #varphi_{l} - #varphi_{ll} (rad.)"}; + const AxisSpec axis_cos_theta_cs{10, 0.f, 1.f, "|cos(#theta_{CS})|"}; + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_cos_theta_cs}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV2) || cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV3)) { + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV2)) { + nmod = 2; + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV3)) { + nmod = 3; + } + + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.add("Pair/same/uls/hPrfUQ", Form("dilepton <#vec{u}_{%d,ll} #upoint #vec{Q}_{%d}^{%s}>", nmod, nmod, qvec_det_names[cfgQvecEstimator].data()), kTProfile3D, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + + fRegistry.add("Pair/mix/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.add("Pair/mix/uls/hs_woEPmix", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.add("Pair/mix/uls/hPrfUQCosDPhi", Form("dilepton <#vec{u}_{%d,l1} #upoint #vec{Q}_{%d,ev1}^{%s} cos(%d(#varphi_{l1} - #varphi_{ll}))> + <#vec{u}_{%d,l2} #upoint #vec{Q}_{%d,ev2}^{%s} cos(%d(#varphi_{l2} - #varphi_{ll}))>", nmod, nmod, qvec_det_names[cfgQvecEstimator].data(), nmod, nmod, nmod, qvec_det_names[cfgQvecEstimator].data(), nmod), kTProfile3D, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.add("Pair/mix/uls/hPrf2UQ1UQ2CosDPhi12", Form("dilepton <2 #vec{u}_{%d,l1} #upoint #vec{Q}_{%d,ev1}^{%s} #vec{u}_{%d,l2} #upoint #vec{Q}_{%d,ev2}^{%s} cos(%d(#varphi_{l1} - #varphi_{l2}))>", nmod, nmod, qvec_det_names[cfgQvecEstimator].data(), nmod, nmod, qvec_det_names[cfgQvecEstimator].data(), nmod), kTProfile3D, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.addClone("Pair/mix/uls/", "Pair/mix/lspp/"); + fRegistry.addClone("Pair/mix/uls/", "Pair/mix/lsmm/"); + + // std::string detname1 = qvec_det_names[cfgQvecEstimator]; + // std::string detname2 = ""; + // std::string detname3 = ""; + // if (detname1.find("FT0") != std::string::npos) { // for dielectrons + // detname2 = qvec_det_names[4]; + // detname3 = qvec_det_names[5]; + // subdet2 = 4; + // subdet3 = 5; + // } else if (detname1.find("B") != std::string::npos) { // for dimuon + // detname2 = qvec_det_names[1]; + // detname3 = qvec_det_names[2]; + // subdet2 = 1; + // subdet3 = 2; + // } + + // fRegistry.add("Pair/mix/ev1/hPrf_SP12_CentFT0C", Form("Q_{%d}^{%s} #upoint Q_{%d}^{%s};centrality FT0C (%%);Q_{%d}^{%s} #upoint Q_{%d}^{%s}", nmod, detname1.data(), nmod, detname2.data(), nmod, detname1.data(), nmod, detname2.data()), kTProfile, {{110, 0, 110}}, true); + // fRegistry.add("Pair/mix/ev1/hPrf_SP13_CentFT0C", Form("Q_{%d}^{%s} #upoint Q_{%d}^{%s};centrality FT0C (%%);Q_{%d}^{%s} #upoint Q_{%d}^{%s}", nmod, detname1.data(), nmod, detname3.data(), nmod, detname1.data(), nmod, detname3.data()), kTProfile, {{110, 0, 110}}, true); + // fRegistry.add("Pair/mix/ev1/hPrf_SP23_CentFT0C", Form("Q_{%d}^{%s} #upoint Q_{%d}^{%s};centrality FT0C (%%);Q_{%d}^{%s} #upoint Q_{%d}^{%s}", nmod, detname2.data(), nmod, detname3.data(), nmod, detname2.data(), nmod, detname3.data()), kTProfile, {{110, 0, 110}}, true); + // fRegistry.addClone("Pair/mix/ev1/", "Pair/mix/ev2/"); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kPolarization)) { + const AxisSpec axis_cos_theta_cs{10, 0.f, 1.f, "|cos(#theta_{CS})|"}; + const AxisSpec axis_phi_cs{18, 0.f, M_PI, "|#varphi_{CS}| (rad.)"}; + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_cos_theta_cs, axis_phi_cs}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kVM)) { + std::string pair_y_axis_title = "y_{ll}"; + int nbin_y = 20; + float min_y = -1.0; + float max_y = +1.0; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pair_y_axis_title = "y_{ee}"; + nbin_y = 20; + min_y = -1.0; + max_y = +1.0; + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + pair_y_axis_title = "y_{#mu#mu}"; + nbin_y = 25; + min_y = -4.5; + max_y = -2.0; + } + const AxisSpec axis_y{nbin_y, min_y, max_y, pair_y_axis_title}; + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kHFll)) { + const AxisSpec axis_dphi_ee{18, 0, M_PI, "#Delta#varphi = #varphi_{e1} - #varphi_{e2} (rad.)"}; + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_dphi_ee}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } else { // same as kQC to avoid seg. fault + fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } + + // event info + if (nmod == 2) { + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<2>(&fRegistry); + } else if (nmod == 3) { + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<3>(&fRegistry); + } else { + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); + } + fRegistry.add("Event/before/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); + fRegistry.add("Event/after/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for pair + fDielectronCut.SetMeeRange(dielectroncuts.cfg_min_mass, dielectroncuts.cfg_max_mass); + fDielectronCut.SetPairPtRange(dielectroncuts.cfg_min_pair_pt, dielectroncuts.cfg_max_pair_pt); + fDielectronCut.SetPairYRange(dielectroncuts.cfg_min_pair_y, dielectroncuts.cfg_max_pair_y); + fDielectronCut.SetPairDCARange(dielectroncuts.cfg_min_pair_dca3d, dielectroncuts.cfg_max_pair_dca3d); // in sigma + fDielectronCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dielectroncuts.cfg_phiv_intercept) / dielectroncuts.cfg_phiv_slope; }); + fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); + fDielectronCut.ApplyPrefilter(dielectroncuts.cfg_apply_pf); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(dielectroncuts.cfg_min_phi_track, dielectroncuts.cfg_max_phi_track); + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(0, 16); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // for pair + fDimuonCut.SetMassRange(dimuoncuts.cfg_min_mass, dimuoncuts.cfg_max_mass); + fDimuonCut.SetPairPtRange(dimuoncuts.cfg_min_pair_pt, dimuoncuts.cfg_max_pair_pt); + fDimuonCut.SetPairYRange(dimuoncuts.cfg_min_pair_y, dimuoncuts.cfg_max_pair_y); + fDimuonCut.SetPairDCAxyRange(dimuoncuts.cfg_min_pair_dcaxy, dimuoncuts.cfg_max_pair_dcaxy); // DCAxy in cm + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, 1e10f); + fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_eta_track, dimuoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_phi_track, dimuoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(dimuoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 16); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + } + + template + bool isGoodQvector(TQvectors const& qvectors) + { + bool is_good = true; + for (auto& qn : qvectors[nmod]) { + if (fabs(qn[0]) > 20.f || fabs(qn[1]) > 20.f) { + is_good = false; + break; + } + } + return is_good; + } + + float getSPresolution(const float centrality, const int occupancy) + { + if (h2sp_resolution == nullptr) { + return 1.f; + } else { + int binId_cen = h2sp_resolution->GetXaxis()->FindBin(centrality); + int binId_occ = h2sp_resolution->GetYaxis()->FindBin(occupancy); + + if (centrality < h2sp_resolution->GetXaxis()->GetXmin()) { + binId_cen = 1; + } + if (h2sp_resolution->GetXaxis()->GetXmax() < centrality) { + binId_cen = h2sp_resolution->GetXaxis()->GetNbins(); + } + + if (occupancy < h2sp_resolution->GetYaxis()->GetXmin()) { + binId_occ = 1; + } + if (h2sp_resolution->GetYaxis()->GetXmax() < occupancy) { + binId_occ = h2sp_resolution->GetYaxis()->GetNbins(); + } + return h2sp_resolution->GetBinContent(binId_cen, binId_occ); + } + } + + template + bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut) + { + if constexpr (ev_id == 1) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + // bool is_found1 = std::find(t2.ambiguousElectronsIds.begin(), t2.ambiguousElectronsIds.end(), t1.globalIndex()) != t2.ambiguousElectronsIds.end(); //this does not work. + // bool is_found2 = std::find(t1.ambiguousElectronsIds.begin(), t1.ambiguousElectronsIds.end(), t2.globalIndex()) != t1.ambiguousElectronsIds.end(); //this does not work. + auto v1ambIds = t1.ambiguousElectronsIds(); + auto v2ambIds = t2.ambiguousElectronsIds(); + + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + // LOGF(info, "event id = %d: same track is found. t1.globalIndex() = %d, t1.sign() = %d, t1.pt() = %f, t1.eta() = %f, t1.phi() = %f, t2.globalIndex() = %d, t2.sign() = %d, t2.pt() = %f, t2.eta() = %f, t2.phi() = %f, deta = %f, dphi = %f (rad.)", ev_id, t1.globalIndex(), t1.sign(), t1.pt(), t1.eta(), t1.phi(), t2.globalIndex(), t2.sign(), t2.pt(), t2.eta(), t2.phi(), t1.eta() - t2.eta(), t1.phi() - t2.phi()); + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + // bool is_found1 = std::find(t2.ambiguousMuonsIds.begin(), t2.ambiguousMuonsIds.end(), t1.globalIndex()) != t2.ambiguousMuonsIds.end(); //this does not work. + // bool is_found2 = std::find(t1.ambiguousMuonsIds.begin(), t1.ambiguousMuonsIds.end(), t2.globalIndex()) != t1.ambiguousMuonsIds.end(); //this does not work. + auto v1ambIds = t1.ambiguousMuonsIds(); + auto v2ambIds = t2.ambiguousMuonsIds(); + + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + // LOGF(info, "event id = %d: same track is found. t1.globalIndex() = %d, t1.sign() = %d, t1.pt() = %f, t1.eta() = %f, t1.phi() = %f, t2.globalIndex() = %d, t2.sign() = %d, t2.pt() = %f, t2.eta() = %f, t2.phi() = %f, deta = %f, dphi = %f (rad.)", ev_id, t1.globalIndex(), t1.sign(), t1.pt(), t1.eta(), t1.phi(), t2.globalIndex(), t2.sign(), t2.pt(), t2.eta(), t2.phi(), t1.eta() - t2.eta(), t1.phi() - t2.phi()); + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } + } + + if constexpr (ev_id == 0) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(t1, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.template IsSelectedPair(t1, t2, d_bz)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedPair(t1, t2)) { + return false; + } + } + + // float pca = 999.f, lxy = 999.f; // in unit of cm + // o2::aod::pwgem::dilepton::utils::pairutil::isSVFound(fitter, collision, t1, t2, pca, lxy); + // o2::aod::pwgem::dilepton::utils::pairutil::isSVFoundFwd(fwdfitter, collision, t1, t2, pca, lxy); + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; + } + if (ev_id == 1) { + weight = 1.f; + } + + // LOGF(info, "ev_id = %d, t1.sign() = %d, t2.sign() = %d, map_weight[std::make_pair(%d, %d)] = %f", ev_id, t1.sign(), t2.sign(), t1.globalIndex(), t2.globalIndex(), weight); + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), leptonM1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + float dca_t1 = 999.f, dca_t2 = 999.f, pair_dca = 999.f; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + dca_t1 = dca3DinSigma(t1); + dca_t2 = dca3DinSigma(t2); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + if (cfgUseDCAxy) { + dca_t1 = t1.dcaXY() / std::sqrt(t1.cYY()); + dca_t2 = t2.dcaXY() / std::sqrt(t2.cYY()); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + dca_t1 = fwdDcaXYinSigma(t1); + dca_t2 = fwdDcaXYinSigma(t2); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + } + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC)) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsPhiV"), phiv, v12.M(), weight); + } + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsPhiV"), phiv, v12.M(), weight); + } + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsPhiV"), phiv, v12.M(), weight); + } + } + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kUPC)) { + float dphi = v1.Phi() - v2.Phi(); + o2::math_utils::bringToPMPi(dphi); + float aco = 1.f - abs(dphi) / M_PI; + float asym = abs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + float dphi_e_ee = v1.Phi() - v12.Phi(); + o2::math_utils::bringToPMPi(dphi_e_ee); + + float cos_thetaCS = 999, phiCS = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(t1, t2, leptonM1, leptonM2, beamE1, beamE2, beamP1, beamP2, cos_thetaCS, phiCS); + + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, aco, asym, abs(dphi_e_ee), abs(cos_thetaCS), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, aco, asym, abs(dphi_e_ee), abs(cos_thetaCS), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, aco, asym, abs(dphi_e_ee), abs(cos_thetaCS), weight); + } + + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV2) || cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV3)) { + std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; + std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; + std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; + std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; + std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; + std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q3ft0m = {collision.q3xft0m(), collision.q3yft0m()}; + std::array q3ft0a = {collision.q3xft0a(), collision.q3yft0a()}; + std::array q3ft0c = {collision.q3xft0c(), collision.q3yft0c()}; + std::array q3btot = {collision.q3xbtot(), collision.q3ybtot()}; + std::array q3bpos = {collision.q3xbpos(), collision.q3ybpos()}; + std::array q3bneg = {collision.q3xbneg(), collision.q3ybneg()}; + + std::vector>> qvectors = { + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 0th harmonics + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg}, // 3rd harmonics + }; + + if constexpr (ev_id == 0) { + // LOGF(info, "collision.centFT0C() = %f, collision.trackOccupancyInTimeRange() = %d, getSPresolution = %f", collision.centFT0C(), collision.trackOccupancyInTimeRange(), getSPresolution(collision.centFT0C(), collision.trackOccupancyInTimeRange())); + + float sp = RecoDecay::dotProd(std::array{static_cast(std::cos(nmod * v12.Phi())), static_cast(std::sin(nmod * v12.Phi()))}, qvectors[nmod][cfgQvecEstimator]) / getSPresolution(collision.centFT0C(), collision.trackOccupancyInTimeRange()); + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hPrfUQ"), v12.M(), v12.Pt(), pair_dca, sp, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hPrfUQ"), v12.M(), v12.Pt(), pair_dca, sp, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hPrfUQ"), v12.M(), v12.Pt(), pair_dca, sp, weight); + } + } else if constexpr (ev_id == 1) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } + } + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kPolarization)) { + float cos_thetaCS = 999, phiCS = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(t1, t2, leptonM1, leptonM2, beamE1, beamE2, beamP1, beamP2, cos_thetaCS, phiCS); + o2::math_utils::bringToPMPi(phiCS); + + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, abs(cos_thetaCS), abs(phiCS), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, abs(cos_thetaCS), abs(phiCS), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, abs(cos_thetaCS), abs(phiCS), weight); + } + + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kVM)) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), weight); + } + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kHFll)) { + float dphi = v1.Phi() - v2.Phi(); + o2::math_utils::bringToPMPi(dphi); + + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, abs(dphi), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, abs(dphi), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, abs(dphi), weight); + } + + } else { // same as kQC to avoid seg. fault + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } + } + + // store tracks for event mixing without double counting + if constexpr (ev_id == 0) { + std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); + std::pair pair_tmp_id1 = std::make_pair(ndf, t1.globalIndex()); + std::pair pair_tmp_id2 = std::make_pair(ndf, t2.globalIndex()); + + std::vector possibleIds1; + std::vector possibleIds2; + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + std::copy(t1.ambiguousElectronsIds().begin(), t1.ambiguousElectronsIds().end(), std::back_inserter(possibleIds1)); + std::copy(t2.ambiguousElectronsIds().begin(), t2.ambiguousElectronsIds().end(), std::back_inserter(possibleIds2)); + + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id1) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id1); + if (cfgDoMix) { + if (t1.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, + t1.x(), t1.y(), t1.z(), t1.alpha(), t1.snp(), t1.tgl(), t1.cYY(), t1.cZY(), t1.cZZ(), + t1.cSnpY(), t1.cSnpZ(), t1.cSnpSnp(), t1.cTglY(), t1.cTglZ(), t1.cTglSnp(), t1.cTglTgl(), t1.c1PtY(), t1.c1PtZ(), t1.c1PtSnp(), t1.c1PtTgl(), t1.c1Pt21Pt2())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, + t1.x(), t1.y(), t1.z(), t1.alpha(), t1.snp(), t1.tgl(), t1.cYY(), t1.cZY(), t1.cZZ(), + t1.cSnpY(), t1.cSnpZ(), t1.cSnpSnp(), t1.cTglY(), t1.cTglZ(), t1.cTglSnp(), t1.cTglTgl(), t1.c1PtY(), t1.c1PtZ(), t1.c1PtSnp(), t1.c1PtTgl(), t1.c1Pt21Pt2())); + } + } + } + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id2) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id2); + if (cfgDoMix) { + if (t2.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, + t2.x(), t2.y(), t2.z(), t2.alpha(), t2.snp(), t2.tgl(), t2.cYY(), t2.cZY(), t2.cZZ(), + t2.cSnpY(), t2.cSnpZ(), t2.cSnpSnp(), t2.cTglY(), t2.cTglZ(), t2.cTglSnp(), t2.cTglTgl(), t2.c1PtY(), t2.c1PtZ(), t2.c1PtSnp(), t2.c1PtTgl(), t2.c1Pt21Pt2())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, + t2.x(), t2.y(), t2.z(), t2.alpha(), t2.snp(), t2.tgl(), t2.cYY(), t2.cZY(), t2.cZZ(), + t2.cSnpY(), t2.cSnpZ(), t2.cSnpSnp(), t2.cTglY(), t2.cTglZ(), t2.cTglSnp(), t2.cTglTgl(), t2.c1PtY(), t2.c1PtZ(), t2.c1PtSnp(), t2.c1PtTgl(), t2.c1Pt21Pt2())); + } + } + } + } else if (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + std::copy(t1.ambiguousMuonsIds().begin(), t1.ambiguousMuonsIds().end(), std::back_inserter(possibleIds1)); + std::copy(t2.ambiguousMuonsIds().begin(), t2.ambiguousMuonsIds().end(), std::back_inserter(possibleIds2)); + + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id1) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id1); + if (cfgDoMix) { + if (t1.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, + t1.x(), t1.y(), t1.z(), t1.tgl(), t1.cXX(), t1.cXY(), t1.cYY(), + t1.cPhiX(), t1.cPhiY(), t1.cPhiPhi(), t1.cTglX(), t1.cTglY(), t1.cTglPhi(), t1.cTglTgl(), t1.c1PtX(), t1.c1PtY(), t1.c1PtPhi(), t1.c1PtTgl(), t1.c1Pt21Pt2(), t1.chi2())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, + t1.x(), t1.y(), t1.z(), t1.tgl(), t1.cXX(), t1.cXY(), t1.cYY(), + t1.cPhiX(), t1.cPhiY(), t1.cPhiPhi(), t1.cTglX(), t1.cTglY(), t1.cTglPhi(), t1.cTglTgl(), t1.c1PtX(), t1.c1PtY(), t1.c1PtPhi(), t1.c1PtTgl(), t1.c1Pt21Pt2(), t1.chi2())); + } + } + } + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id2) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id2); + if (cfgDoMix) { + if (t2.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, + t2.x(), t2.y(), t2.z(), t2.tgl(), t2.cXX(), t2.cXY(), t2.cYY(), + t2.cPhiX(), t2.cPhiY(), t2.cPhiPhi(), t2.cTglX(), t2.cTglY(), t2.cTglPhi(), t2.cTglTgl(), t2.c1PtX(), t2.c1PtY(), t2.c1PtPhi(), t2.c1PtTgl(), t2.c1Pt21Pt2(), t2.chi2())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, + t2.x(), t2.y(), t2.z(), t2.tgl(), t2.cXX(), t2.cXY(), t2.cYY(), + t2.cPhiX(), t2.cPhiY(), t2.cPhiPhi(), t2.cTglX(), t2.cTglY(), t2.cTglPhi(), t2.cTglTgl(), t2.c1PtX(), t2.c1PtY(), t2.c1PtPhi(), t2.c1PtTgl(), t2.c1Pt21Pt2(), t2.chi2())); + } + } + } + } + } + return true; + } + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_multiplicity = cfgNtracksPV08Min <= o2::aod::mult::multNTracksPV && o2::aod::mult::multNTracksPV < cfgNtracksPV08Max; + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + SliceCache cache; + Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter_electron = (dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < dielectroncuts.cfg_min_TPCNsigmaPi || dielectroncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); + Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + + Preslice perCollision_muon = aod::emprimarymuon::emeventId; + Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); + Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); + + TEMH* emh_pos = nullptr; + TEMH* emh_neg = nullptr; + std::map, std::vector>>> map_mixed_eventId_to_qvector; + std::map, float> map_mixed_eventId_to_centrality; + std::map, int> map_mixed_eventId_to_occupancy; + std::map, uint64_t> map_mixed_eventId_to_globalBC; + + std::vector> used_trackIds; + int ndf = 0; + + template + void runPairing(TCollisions const& collisions, TLeptons const& posTracks, TLeptons const& negTracks, TPresilce const& perCollision, TCut const& cut) + { + for (auto& collision : collisions) { + initCCDB(collision); + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + float centrality = centralities[cfgCentEstimator]; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + } + + std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; + std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; + std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; + std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; + std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; + std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q3ft0m = {collision.q3xft0m(), collision.q3yft0m()}; + std::array q3ft0a = {collision.q3xft0a(), collision.q3yft0a()}; + std::array q3ft0c = {collision.q3xft0c(), collision.q3yft0c()}; + std::array q3btot = {collision.q3xbtot(), collision.q3ybtot()}; + std::array q3bpos = {collision.q3xbpos(), collision.q3ybpos()}; + std::array q3bneg = {collision.q3xbneg(), collision.q3ybneg()}; + const float eventplanes_2_for_mix[6] = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg()}; + float ep2 = eventplanes_2_for_mix[cfgEP2Estimator_for_Mix]; + + std::vector>> qvectors = { + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 0th harmonics + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg}, // 3rd harmonics + }; + + if (nmod == 2) { + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, 2>(&fRegistry, collision); + } else if (nmod == 3) { + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, 3>(&fRegistry, collision); + } else { + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + } + if (nmod < 0 || isGoodQvector(qvectors)) { + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev - 1); // is qvector calibarated + } + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + if (nmod > 0 && !isGoodQvector(qvectors)) { + continue; + } + + if (nmod == 2) { + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, 2>(&fRegistry, collision); + } else if (nmod == 3) { + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, 3>(&fRegistry, collision); + } else { + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); + } + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev - 1); // is qvector calibarated + + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + + auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + // LOGF(info, "collision.globalIndex() = %d , collision.posZ() = %f , collision.numContrib() = %d, centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", collision.globalIndex(), collision.posZ(), collision.numContrib(), centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); + + int nuls = 0, nlspp = 0, nlsmm = 0; + for (auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + bool is_pair_ok = fillPairInfo<0>(collision, pos, neg, cut); + if (is_pair_ok) { + nuls++; + } + } + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + bool is_pair_ok = fillPairInfo<0>(collision, pos1, pos2, cut); + if (is_pair_ok) { + nlspp++; + } + } + for (auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + bool is_pair_ok = fillPairInfo<0>(collision, neg1, neg2, cut); + if (is_pair_ok) { + nlsmm++; + } + } + + if (!cfgDoMix || !(nuls > 0 || nlspp > 0 || nlsmm > 0)) { + continue; + } + + // event mixing + int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; + if (zbin < 0) { + zbin = 0; + } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { + zbin = static_cast(zvtx_bin_edges.size()) - 2; + } + + int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; + if (centbin < 0) { + centbin = 0; + } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { + centbin = static_cast(cent_bin_edges.size()) - 2; + } + + int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; + if (epbin < 0) { + epbin = 0; + } else if (static_cast(ep_bin_edges.size()) - 2 < epbin) { + epbin = static_cast(ep_bin_edges.size()) - 2; + } + + int occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; + if (occbin < 0) { + occbin = 0; + } else if (static_cast(occ_bin_edges.size()) - 2 < occbin) { + occbin = static_cast(occ_bin_edges.size()) - 2; + } + + // LOGF(info, "collision.globalIndex() = %d, collision.posZ() = %f, centrality = %f, ep2 = %f, collision.trackOccupancyInTimeRange() = %d, zbin = %d, centbin = %d, epbin = %d, occbin = %d", collision.globalIndex(), collision.posZ(), centrality, ep2, collision.trackOccupancyInTimeRange(), zbin, centbin, epbin, occbin); + + std::tuple key_bin = std::make_tuple(zbin, centbin, epbin, occbin); + std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); + + // make a vector of selected photons in this collision. + auto selected_posTracks_in_this_event = emh_pos->GetTracksPerCollision(key_df_collision); + auto selected_negTracks_in_this_event = emh_neg->GetTracksPerCollision(key_df_collision); + // LOGF(info, "N selected tracks in current event (%d, %d), zvtx = %f, centrality = %f , npos = %d , nneg = %d, nuls = %d , nlspp = %d, nlsmm = %d", ndf, collision.globalIndex(), collision.posZ(), centralities[cfgCentEstimator], selected_posTracks_in_this_event.size(), selected_negTracks_in_this_event.size(), nuls, nlspp, nlsmm); + + auto collisionIds_in_mixing_pool = emh_pos->GetCollisionIdsFromEventPool(key_bin); // pos/neg does not matter. + // LOGF(info, "collisionIds_in_mixing_pool.size() = %d", collisionIds_in_mixing_pool.size()); + + for (auto& mix_dfId_collisionId : collisionIds_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int mix_collisionId = mix_dfId_collisionId.second; + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto posTracks_from_event_pool = emh_pos->GetTracksPerCollision(mix_dfId_collisionId); + auto negTracks_from_event_pool = emh_neg->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "Do event mixing: current event (%d, %d) | event pool (%d, %d), npos = %d , nneg = %d", ndf, collision.globalIndex(), mix_dfId, mix_collisionId, posTracks_from_event_pool.size(), negTracks_from_event_pool.size()); + + for (auto& pos : selected_posTracks_in_this_event) { // ULS mix + for (auto& neg : negTracks_from_event_pool) { + fillPairInfo<1>(collision, pos, neg, cut); + } + } + + for (auto& neg : selected_negTracks_in_this_event) { // ULS mix + for (auto& pos : posTracks_from_event_pool) { + fillPairInfo<1>(collision, neg, pos, cut); + } + } + + for (auto& pos1 : selected_posTracks_in_this_event) { // LS++ mix + for (auto& pos2 : posTracks_from_event_pool) { + fillPairInfo<1>(collision, pos1, pos2, cut); + } + } + + for (auto& neg1 : selected_negTracks_in_this_event) { // LS-- mix + for (auto& neg2 : negTracks_from_event_pool) { + fillPairInfo<1>(collision, neg1, neg2, cut); + } + } + } // end of loop over mixed event pool + + // run mixed event loop for flow measurement. Don't divide mixed-event categories by event planes, if you do flow measurement. + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV2) || cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kFlowV3)) { + for (int epbin_tmp = 0; epbin_tmp < static_cast(ep_bin_edges.size()) - 1; epbin_tmp++) { + std::tuple key_bin = std::make_tuple(zbin, centbin, epbin_tmp, occbin); + auto collisionIds_in_mixing_pool = emh_pos->GetCollisionIdsFromEventPool(key_bin); // pos/neg does not matter. + // LOGF(info, "collisionIds_in_mixing_pool.size() = %d", collisionIds_in_mixing_pool.size()); + + for (auto& mix_dfId_collisionId : collisionIds_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int mix_collisionId = mix_dfId_collisionId.second; + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + + auto centrality_mix = map_mixed_eventId_to_centrality[mix_dfId_collisionId]; + auto occupancy_mix = map_mixed_eventId_to_occupancy[mix_dfId_collisionId]; + auto qvectors_mix = map_mixed_eventId_to_qvector[mix_dfId_collisionId]; + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto posTracks_from_event_pool = emh_pos->GetTracksPerCollision(mix_dfId_collisionId); + auto negTracks_from_event_pool = emh_neg->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "Do event mixing: current event (%d, %d) | event pool (%d, %d), npos = %d , nneg = %d", ndf, collision.globalIndex(), mix_dfId, mix_collisionId, posTracks_from_event_pool.size(), negTracks_from_event_pool.size()); + + for (auto& pos : selected_posTracks_in_this_event) { // ULS mix + for (auto& neg : negTracks_from_event_pool) { + fillMixedPairInfoForFlow(pos, neg, cut, qvectors, qvectors_mix, collision.centFT0C(), centrality_mix, collision.trackOccupancyInTimeRange(), occupancy_mix); + } + } + + for (auto& neg : selected_negTracks_in_this_event) { // ULS mix + for (auto& pos : posTracks_from_event_pool) { + fillMixedPairInfoForFlow(neg, pos, cut, qvectors, qvectors_mix, collision.centFT0C(), centrality_mix, collision.trackOccupancyInTimeRange(), occupancy_mix); + } + } + + for (auto& pos1 : selected_posTracks_in_this_event) { // LS++ mix + for (auto& pos2 : posTracks_from_event_pool) { + fillMixedPairInfoForFlow(pos1, pos2, cut, qvectors, qvectors_mix, collision.centFT0C(), centrality_mix, collision.trackOccupancyInTimeRange(), occupancy_mix); + } + } + + for (auto& neg1 : selected_negTracks_in_this_event) { // LS-- mix + for (auto& neg2 : negTracks_from_event_pool) { + fillMixedPairInfoForFlow(neg1, neg2, cut, qvectors, qvectors_mix, collision.centFT0C(), centrality_mix, collision.trackOccupancyInTimeRange(), occupancy_mix); + } + } + } // end of loop over mixed event pool + + } // end of ep bin loop + + } // end of mixing loop for flow + + if (nuls > 0 || nlspp > 0 || nlsmm > 0) { + if (nmod > 0) { + map_mixed_eventId_to_qvector[key_df_collision] = qvectors; + map_mixed_eventId_to_centrality[key_df_collision] = collision.centFT0C(); + map_mixed_eventId_to_occupancy[key_df_collision] = collision.trackOccupancyInTimeRange(); + } + map_mixed_eventId_to_globalBC[key_df_collision] = collision.globalBC(); + emh_pos->AddCollisionIdAtLast(key_bin, key_df_collision); + emh_neg->AddCollisionIdAtLast(key_bin, key_df_collision); + } + + } // end of collision loop + + ndf++; + } // end of DF + + template + bool fillMixedPairInfoForFlow(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TQvectors const& qvectors, TMixedQvectors const& qvectors_mix, const float centrality, const float centrality_mix, const int occupancy, const int occupancy_mix) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto v1ambIds = t1.ambiguousElectronsIds(); + auto v2ambIds = t2.ambiguousElectronsIds(); + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto v1ambIds = t1.ambiguousMuonsIds(); + auto v2ambIds = t2.ambiguousMuonsIds(); + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.template IsSelectedPair(t1, t2, d_bz)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedPair(t1, t2)) { + return false; + } + } + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), leptonM1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + float dca_t1 = 999.f, dca_t2 = 999.f, pair_dca = 999.f; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + dca_t1 = dca3DinSigma(t1); + dca_t2 = dca3DinSigma(t2); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + dca_t1 = fwdDcaXYinSigma(t1); + dca_t2 = fwdDcaXYinSigma(t2); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + } + + float sp1 = RecoDecay::dotProd(std::array{static_cast(std::cos(nmod * v1.Phi())), static_cast(std::sin(nmod * v1.Phi()))}, qvectors[nmod][cfgQvecEstimator]) / getSPresolution(centrality, occupancy); + float sp2 = RecoDecay::dotProd(std::array{static_cast(std::cos(nmod * v2.Phi())), static_cast(std::sin(nmod * v2.Phi()))}, qvectors_mix[nmod][cfgQvecEstimator]) / getSPresolution(centrality_mix, occupancy_mix); + float cos_dphi1 = std::cos(nmod * (v1.Phi() - v12.Phi())); + float cos_dphi2 = std::cos(nmod * (v2.Phi() - v12.Phi())); + float cos_dphi12 = std::cos(nmod * (v1.Phi() - v2.Phi())); + const float weight = 1.f; + + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/mix/uls/hs_woEPmix"), v12.M(), v12.Pt(), pair_dca, weight); + fRegistry.fill(HIST("Pair/mix/uls/hPrfUQCosDPhi"), v12.M(), v12.Pt(), pair_dca, sp1 * cos_dphi1 + sp2 * cos_dphi2, weight); + fRegistry.fill(HIST("Pair/mix/uls/hPrf2UQ1UQ2CosDPhi12"), v12.M(), v12.Pt(), pair_dca, 2.f * sp1 * sp2 * cos_dphi12, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/mix/lspp/hs_woEPmix"), v12.M(), v12.Pt(), pair_dca, weight); + fRegistry.fill(HIST("Pair/mix/lspp/hPrfUQCosDPhi"), v12.M(), v12.Pt(), pair_dca, sp1 * cos_dphi1 + sp2 * cos_dphi2, weight); + fRegistry.fill(HIST("Pair/mix/lspp/hPrf2UQ1UQ2CosDPhi12"), v12.M(), v12.Pt(), pair_dca, 2.f * sp1 * sp2 * cos_dphi12, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/mix/lsmm/hs_woEPmix"), v12.M(), v12.Pt(), pair_dca, weight); + fRegistry.fill(HIST("Pair/mix/lsmm/hPrfUQCosDPhi"), v12.M(), v12.Pt(), pair_dca, sp1 * cos_dphi1 + sp2 * cos_dphi2, weight); + fRegistry.fill(HIST("Pair/mix/lsmm/hPrf2UQ1UQ2CosDPhi12"), v12.M(), v12.Pt(), pair_dca, 2.f * sp1 * sp2 * cos_dphi12, weight); + } + return true; + } + + template + bool isPairOK(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(t1, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.template IsSelectedPair(t1, t2, d_bz)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedPair(t1, t2)) { + return false; + } + } + return true; + } + + std::map, float> map_weight; // -> float + template + void fillPairWeightMap(TCollisions const& collisions, TLeptons const& posTracks, TLeptons const& negTracks, TPresilce const& perCollision, TCut const& cut, TAllTracks const& tracks) + { + std::vector> passed_pairIds; + passed_pairIds.reserve(posTracks.size() * negTracks.size()); + + for (auto& collision : collisions) { + initCCDB(collision); + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + } + + std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; + std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; + std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; + std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; + std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; + std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q3ft0m = {collision.q3xft0m(), collision.q3yft0m()}; + std::array q3ft0a = {collision.q3xft0a(), collision.q3yft0a()}; + std::array q3ft0c = {collision.q3xft0c(), collision.q3yft0c()}; + std::array q3btot = {collision.q3xbtot(), collision.q3ybtot()}; + std::array q3bpos = {collision.q3xbpos(), collision.q3ybpos()}; + std::array q3bneg = {collision.q3xbneg(), collision.q3ybneg()}; + + std::vector>> qvectors = { + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 0th harmonics + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg}, // 3rd harmonics + {{999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}, {999.f, 999.f}}, // 4th harmonics + }; + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + if (nmod > 0 && !isGoodQvector(qvectors)) { + continue; + } + + auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + + for (auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (isPairOK(collision, pos, neg, cut)) { + passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); + } + } + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + if (isPairOK(collision, pos1, pos2, cut)) { + passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); + } + } + for (auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + if (isPairOK(collision, neg1, neg2, cut)) { + passed_pairIds.emplace_back(std::make_pair(neg1.globalIndex(), neg2.globalIndex())); + } + } + } // end of collision loop + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& pairId : passed_pairIds) { + auto t1 = tracks.rawIteratorAt(std::get<0>(pairId)); + auto t2 = tracks.rawIteratorAt(std::get<1>(pairId)); + // LOGF(info, "std::get<0>(pairId) = %d, std::get<1>(pairId) = %d, t1.globalIndex() = %d, t2.globalIndex() = %d", std::get<0>(pairId), std::get<1>(pairId), t1.globalIndex(), t2.globalIndex()); + + float n = 1.f; // include myself. + for (auto& ambId1 : t1.ambiguousElectronsIds()) { + for (auto& ambId2 : t2.ambiguousElectronsIds()) { + if (std::find(passed_pairIds.begin(), passed_pairIds.end(), std::make_pair(ambId1, ambId2)) != passed_pairIds.end()) { + n += 1.f; + } + } + } + map_weight[pairId] = 1.f / n; + } // end of passed_pairIds loop + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& pairId : passed_pairIds) { + auto t1 = tracks.rawIteratorAt(std::get<0>(pairId)); + auto t2 = tracks.rawIteratorAt(std::get<1>(pairId)); + + float n = 1.f; // include myself. + for (auto& ambId1 : t1.ambiguousMuonsIds()) { + for (auto& ambId2 : t2.ambiguousMuonsIds()) { + if (std::find(passed_pairIds.begin(), passed_pairIds.end(), std::make_pair(ambId1, ambId2)) != passed_pairIds.end()) { + n += 1.f; + } + } + } + map_weight[pairId] = 1.f / n; + } // end of passed_pairIds loop + } + passed_pairIds.clear(); + passed_pairIds.shrink_to_fit(); + } + + void processAnalysis(FilteredMyCollisions const& collisions, Types const&... args) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto electrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); + } + runPairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto muons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); + } + runPairing(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut); + } + map_weight.clear(); + } + PROCESS_SWITCH(Dilepton, processAnalysis, "run dilepton analysis", true); + + using FilteredMyCollisionsWithSWT = soa::Filtered; + void processTriggerAnalysis(FilteredMyCollisionsWithSWT const& collisions, Types const&... args) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto electrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); + } + runPairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto muons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); + } + runPairing(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut); + } + map_weight.clear(); + } + PROCESS_SWITCH(Dilepton, processTriggerAnalysis, "run dilepton analysis on triggered data", false); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(Dilepton, processDummy, "Dummy function", false); +}; + +#endif // PWGEM_DILEPTON_CORE_DILEPTON_H_ diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h new file mode 100644 index 00000000000..f8a82e5109b --- /dev/null +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -0,0 +1,1680 @@ +// Copyright 2019-2020 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 leptons in MC +// Please write to: daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_CORE_DILEPTONMC_H_ +#define PWGEM_DILEPTON_CORE_DILEPTONMC_H_ + +#include +#include +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "CommonConstants/LHCConstants.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "DCAFitter/DCAFitterN.h" +#include "DCAFitter/FwdDCAFitterN.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCElectrons = soa::Join; +using MyMCElectron = MyMCElectrons::iterator; +using FilteredMyMCElectrons = soa::Filtered; +using FilteredMyMCElectron = FilteredMyMCElectrons::iterator; + +using MyMCMuons = soa::Join; +using MyMCMuon = MyMCMuons::iterator; +using FilteredMyMCMuons = soa::Filtered; +using FilteredMyMCMuon = FilteredMyMCMuons::iterator; + +using MySmearedElectrons = soa::Join; +using MySmearedElectron = MySmearedElectrons::iterator; + +using MySmearedMuons = soa::Join; +using MySmearedMuon = MySmearedMuons::iterator; + +// template +template +struct DileptonMC { + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + Configurable cfgUseDCAxy{"cfgUseDCAxy", false, "flag to use DCAxy, instead of DCA3D"}; + + ConfigurableAxis ConfMllBins{"ConfMllBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.25, 3.30, 3.35, 3.40, 3.45, 3.50, 3.55, 3.60, 3.65, 3.70, 3.75, 3.80, 3.85, 3.90, 3.95, 4.00}, "mll bins for output histograms"}; + ConfigurableAxis ConfPtllBins{"ConfPtllBins", {VARIABLE_WIDTH, 0.00, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTll bins for output histograms"}; + ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAll bins for output histograms"}; + + // ConfigurableAxis ConfMmumuBins{"ConfMmumuBins", {VARIABLE_WIDTH, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.11,1.12,1.13,1.14,1.15,1.16,1.17,1.18,1.19, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.25, 3.30, 3.35, 3.40, 3.45, 3.50, 3.55, 3.60, 3.65, 3.70, 3.75, 3.80, 3.85, 3.90, 3.95, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.10, 5.20, 5.30, 5.40, 5.50, 5.60, 5.70, 5.80, 5.90, 6.00, 6.10, 6.20, 6.30, 6.40, 6.50, 6.60, 6.70, 6.80, 6.90, 7.00, 7.10, 7.20, 7.30, 7.40, 7.50, 7.60, 7.70, 7.80, 7.90, 8.00, 8.10, 8.20, 8.30, 8.40, 8.50, 8.60, 8.70, 8.80, 8.90, 9.00, 9.10, 9.20, 9.30, 9.40, 9.50, 9.60, 9.70, 9.80, 9.90, 10.00, 10.10, 10.20, 10.30, 10.40, 10.50, 10.60, 10.70, 10.80, 10.90, 11.00, 11.50, 12.00}, "mmumu bins for output histograms"}; // for dimuon. one can copy bins here to hyperloop page. + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + + Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "max eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "dimuoncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -4.0, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", -2.5, "max pair rapidity"}; + Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + } dimuoncuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + // o2::vertexing::DCAFitterN<2> fitter; + // o2::vertexing::FwdDCAFitterN<2> fwdfitter; + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + int mRunNumber; + float d_bz; + + struct : ConfigurableGroup { + std::string prefix = "mctrackcut_group"; + Configurable min_mcPt{"min_mcPt", 0.1, "min. MC pT"}; + Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT"}; + Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta"}; + Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta"}; + } mctrackcuts; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + + ~DileptonMC() + { + if (eid_bdt) { + delete eid_bdt; + } + } + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms(&fRegistry); + + std::string mass_axis_title = "m_{ll} (GeV/c^{2})"; + std::string pair_pt_axis_title = "p_{T,ll} (GeV/c)"; + std::string pair_y_axis_title = "y_{ll}"; + std::string pair_dca_axis_title = "DCA_{ll} (#sigma)"; + int nbin_y = 20; + float min_y = -1.0; + float max_y = +1.0; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + mass_axis_title = "m_{ee} (GeV/c^{2})"; + pair_pt_axis_title = "p_{T,ee} (GeV/c)"; + pair_y_axis_title = "y_{ee}"; + pair_dca_axis_title = "DCA_{ee}^{3D} (#sigma)"; + if (cfgUseDCAxy) { + pair_dca_axis_title = "DCA_{ee}^{XY} (#sigma)"; + } + nbin_y = 20; + min_y = -1.0; + max_y = +1.0; + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + mass_axis_title = "m_{#mu#mu} (GeV/c^{2})"; + pair_pt_axis_title = "p_{T,#mu#mu} (GeV/c)"; + pair_y_axis_title = "y_{#mu#mu}"; + pair_dca_axis_title = "DCA_{#mu#mu}^{XY} (#sigma)"; + nbin_y = 25; + min_y = -4.5; + max_y = -2.0; + } + + // pair info + const AxisSpec axis_mass{ConfMllBins, mass_axis_title}; + const AxisSpec axis_pt{ConfPtllBins, pair_pt_axis_title}; + const AxisSpec axis_y{nbin_y, min_y, max_y, pair_y_axis_title}; + const AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; + const AxisSpec axis_pt_meson{ConfPtllBins, "p_{T} (GeV/c)"}; // for omega, phi meson pT spectra + const AxisSpec axis_y_meson{nbin_y, min_y, max_y, "y"}; // rapidity of meson + + const AxisSpec axis_dphi_ee{18, 0, M_PI, "#Delta#varphi = #varphi_{l1} - #varphi_{l2} (rad.)"}; // for kHFll + const AxisSpec axis_cos_theta_cs{10, 0.f, 1.f, "|cos(#theta_{CS})|"}; // for kPolarization, kUPC + const AxisSpec axis_phi_cs{18, 0.f, M_PI, "|#varphi_{CS}| (rad.)"}; // for kPolarization + const AxisSpec axis_aco{10, 0, 1.f, "#alpha = 1 - #frac{|#varphi_{l^{+}} - #varphi_{l^{-}}|}{#pi}"}; // for kUPC + const AxisSpec axis_asym_pt{10, 0, 1.f, "A = #frac{|p_{T,l^{+}} - p_{T,l^{-}}|}{|p_{T,l^{+}} + p_{T,l^{-}}|}"}; // for kUPC + const AxisSpec axis_dphi_e_ee{18, 0, M_PI, "#Delta#varphi = #varphi_{l} - #varphi_{ll} (rad.)"}; // for kUPC + + // generated info + fRegistry.add("Generated/sm/Pi0/hs", "gen. dilepton signal", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee}, true); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Eta/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/EtaPrime/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Rho/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Omega/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Omega2ll/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Phi/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Phi2ll/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/PromptJPsi/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/NonPromptJPsi/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/PromptPsi2S/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/NonPromptPsi2S/"); + fRegistry.add("Generated/sm/Omega2ll/hPtY", "pT of #omega meson", kTH2F, {axis_y_meson, axis_pt_meson}, true); + fRegistry.add("Generated/sm/Phi2ll/hPtY", "pT of #phi meson", kTH2F, {axis_y_meson, axis_pt_meson}, true); + + fRegistry.add("Generated/ccbar/c2l_c2l/hadron_hadron/hs", "generated dilepton signal", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee}, true); + fRegistry.addClone("Generated/ccbar/c2l_c2l/hadron_hadron/", "Generated/ccbar/c2l_c2l/meson_meson/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/hadron_hadron/", "Generated/ccbar/c2l_c2l/baryon_baryon/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/hadron_hadron/", "Generated/ccbar/c2l_c2l/meson_baryon/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2l_b2l/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2l_sameb/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2l_diffb/"); // LS + + // reconstructed pair info + fRegistry.add("Pair/sm/Photon/hs", "rec. dilepton signal", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Pi0/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Eta/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/EtaPrime/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Rho/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Omega/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Omega2ll/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Phi/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Phi2ll/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/PromptJPsi/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/NonPromptJPsi/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/PromptPsi2S/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/NonPromptPsi2S/"); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.add("Pair/sm/Photon/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, true); + fRegistry.add("Pair/sm/Pi0/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, true); + } + + fRegistry.add("Pair/ccbar/c2l_c2l/hadron_hadron/hs", "hs pair", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); + fRegistry.addClone("Pair/ccbar/c2l_c2l/hadron_hadron/", "Pair/ccbar/c2l_c2l/meson_meson/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/hadron_hadron/", "Pair/ccbar/c2l_c2l/baryon_baryon/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/hadron_hadron/", "Pair/ccbar/c2l_c2l/meson_baryon/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2l_b2l/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2l_sameb/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2l_diffb/"); // LS + + // for correlated bkg due to mis-identified hadrons, and true combinatorial bkg + fRegistry.add("Pair/corr_bkg_eh/uls/hs", "rec. bkg", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); + fRegistry.addClone("Pair/corr_bkg_eh/uls/", "Pair/corr_bkg_eh/lspp/"); + fRegistry.addClone("Pair/corr_bkg_eh/uls/", "Pair/corr_bkg_eh/lsmm/"); + fRegistry.addClone("Pair/corr_bkg_eh/", "Pair/corr_bkg_hh/"); + fRegistry.addClone("Pair/corr_bkg_eh/", "Pair/comb_bkg/"); + } + + float beamM1 = o2::constants::physics::MassProton; // mass of beam + float beamM2 = o2::constants::physics::MassProton; // mass of beam + float beamE1 = 0.f; // beam energy + float beamE2 = 0.f; // beam energy + float beamP1 = 0.f; // beam momentum + float beamP2 = 0.f; // beam momentum + + float leptonM1 = 0.f; + float leptonM2 = 0.f; + int pdg_lepton = 0; + void init(InitContext&) + { + if (doprocessAnalysis && doprocessAnalysis_Smeared) { + LOGF(fatal, "Cannot enable doprocessAnalysis and doprocessAnalysis_Smeared at the same time. Please choose one."); + } + + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + DefineEMEventCut(); + addhistograms(); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + DefineDielectronCut(); + leptonM1 = o2::constants::physics::MassElectron; + leptonM2 = o2::constants::physics::MassElectron; + pdg_lepton = 11; + // fitter.setPropagateToPCA(true); + // fitter.setMaxR(5.f); + // fitter.setMinParamChange(1e-3); + // fitter.setMinRelChi2Change(0.9); + // fitter.setMaxDZIni(1e9); + // fitter.setMaxChi2(1e9); + // fitter.setUseAbsDCA(true); + // fitter.setWeightedFinalPCA(false); + // fitter.setMatCorrType(matCorr); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + DefineDimuonCut(); + leptonM1 = o2::constants::physics::MassMuon; + leptonM2 = o2::constants::physics::MassMuon; + pdg_lepton = 13; + // fwdfitter.setPropagateToPCA(true); + // fwdfitter.setMaxR(90.f); + // fwdfitter.setMinParamChange(1e-3); + // fwdfitter.setMinRelChi2Change(0.9); + // fwdfitter.setMaxChi2(1e9); + // fwdfitter.setUseAbsDCA(true); + // fwdfitter.setTGeoMat(false); + } + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + // fitter.setBz(d_bz); + // fwdfitter.setBz(d_bz); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = collision.runNumber(); + // fitter.setBz(d_bz); + // fwdfitter.setBz(d_bz); + + //// for muon + // o2::base::Propagator::initFieldFromGRP(grpmag); + // if (!o2::base::GeometryManager::isGeometryLoaded()) { + // ccdb->get(geoPath); + // } + // o2::mch::TrackExtrap::setField(); + + auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", collision.timestamp()); + int beamZ1 = grplhcif->getBeamZ(o2::constants::lhc::BeamC); + int beamZ2 = grplhcif->getBeamZ(o2::constants::lhc::BeamA); + int beamA1 = grplhcif->getBeamA(o2::constants::lhc::BeamC); + int beamA2 = grplhcif->getBeamA(o2::constants::lhc::BeamA); + beamE1 = grplhcif->getBeamEnergyPerNucleonInGeV(o2::constants::lhc::BeamC); + beamE2 = grplhcif->getBeamEnergyPerNucleonInGeV(o2::constants::lhc::BeamA); + beamM1 = o2::constants::physics::MassProton * beamA1; + beamM2 = o2::constants::physics::MassProton * beamA2; + beamP1 = std::sqrt(std::pow(beamE1, 2) - std::pow(beamM1, 2)); + beamP2 = std::sqrt(std::pow(beamE2, 2) - std::pow(beamM2, 2)); + LOGF(info, "beamZ1 = %d, beamZ2 = %d, beamA1 = %d, beamA2 = %d, beamE1 = %f (GeV), beamE2 = %f (GeV), beamM1 = %f (GeV), beamM2 = %f (GeV), beamP1 = %f (GeV), beamP2 = %f (GeV)", beamZ1, beamZ2, beamA1, beamA2, beamE1, beamE2, beamM1, beamM2, beamP1, beamP2); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for pair + fDielectronCut.SetMeeRange(dielectroncuts.cfg_min_mass, dielectroncuts.cfg_max_mass); + fDielectronCut.SetPairPtRange(dielectroncuts.cfg_min_pair_pt, dielectroncuts.cfg_max_pair_pt); + fDielectronCut.SetPairYRange(dielectroncuts.cfg_min_pair_y, dielectroncuts.cfg_max_pair_y); + fDielectronCut.SetPairDCARange(dielectroncuts.cfg_min_pair_dca3d, dielectroncuts.cfg_max_pair_dca3d); // in sigma + fDielectronCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dielectroncuts.cfg_phiv_intercept) / dielectroncuts.cfg_phiv_slope; }); + fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); + fDielectronCut.ApplyPrefilter(dielectroncuts.cfg_apply_pf); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(-dielectroncuts.cfg_max_eta_track, +dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(-dielectroncuts.cfg_max_phi_track, +dielectroncuts.cfg_max_phi_track); + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(0, 16); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDielectronCut + // o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // for pair + fDimuonCut.SetMassRange(dimuoncuts.cfg_min_mass, dimuoncuts.cfg_max_mass); + fDimuonCut.SetPairPtRange(dimuoncuts.cfg_min_pair_pt, dimuoncuts.cfg_max_pair_pt); + fDimuonCut.SetPairYRange(dimuoncuts.cfg_min_pair_y, dimuoncuts.cfg_max_pair_y); + fDimuonCut.SetPairDCAxyRange(dimuoncuts.cfg_min_pair_dcaxy, dimuoncuts.cfg_max_pair_dcaxy); // DCAxy in cm + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, 1e10f); + fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_eta_track, dimuoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackPhiRange(dimuoncuts.cfg_min_phi_track, dimuoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(dimuoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 16); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + } + + template + int FindLF(TTrack const& posmc, TTrack const& negmc, TMCParticles const& mcparticles) + { + int arr[] = { + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 22, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 111, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 221, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 331, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 113, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 223, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 333, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 443, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 100443, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 553, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 100553, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 200553, mcparticles), + FindCommonMotherFrom2Prongs(posmc, negmc, -pdg_lepton, pdg_lepton, 300553, mcparticles)}; + int size = sizeof(arr) / sizeof(*arr); + int max = *std::max_element(arr, arr + size); + return max; + } + + template + bool isInAcceptance(T const& lepton) + { + float pt = 0.f, eta = 0.f; + if constexpr (isSmeared) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pt = lepton.ptSmeared(); + eta = lepton.etaSmeared(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + pt = lepton.ptSmeared_sa_muon(); + eta = lepton.etaSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt = lepton.ptSmeared_gl_muon(); + eta = lepton.etaSmeared_gl_muon(); + } else { + pt = lepton.pt(); + eta = lepton.eta(); + } + } + } else { + pt = lepton.pt(); + eta = lepton.eta(); + } + + if ((mctrackcuts.min_mcPt < pt && pt < mctrackcuts.max_mcPt) && (mctrackcuts.min_mcEta < eta && eta < mctrackcuts.max_mcEta)) { + return true; + } else { + return false; + } + } + + template + bool fillTruePairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TMCParticles const& mcparticles) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(t1, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + if (!cut.template IsSelectedPair(t1, t2, d_bz)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + if (!cut.template IsSelectedPair(t1, t2)) { + return false; + } + } + + // float pca = 999.f, lxy = 999.f; // in unit of cm + // o2::aod::pwgem::dilepton::utils::pairutil::isSVFound(fitter, collision, t1, t2, pca, lxy); + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; + } + // LOGF(info, "t1.sign() = %d, t2.sign() = %d, map_weight[std::make_pair(%d, %d)] = %f", t1.sign(), t2.sign(), t1.globalIndex(), t2.globalIndex(), weight); + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), leptonM1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + float dca_t1 = 999.f, dca_t2 = 999.f, pair_dca = 999.f; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + dca_t1 = dca3DinSigma(t1); + dca_t2 = dca3DinSigma(t2); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + if (cfgUseDCAxy) { + dca_t1 = t1.dcaXY() / std::sqrt(t1.cYY()); + dca_t2 = t2.dcaXY() / std::sqrt(t2.cYY()); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + dca_t1 = fwdDcaXYinSigma(t1); + dca_t2 = fwdDcaXYinSigma(t2); + pair_dca = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + } + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + + float dphi = v1.Phi() - v2.Phi(); + o2::math_utils::bringToPMPi(dphi); + float aco = 1.f - abs(dphi) / M_PI; + float asym = abs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + float dphi_e_ee = v1.Phi() - v12.Phi(); + o2::math_utils::bringToPMPi(dphi_e_ee); + + float cos_thetaCS = 999, phiCS = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(t1, t2, leptonM1, leptonM2, beamE1, beamE2, beamP1, beamP2, cos_thetaCS, phiCS); + o2::math_utils::bringToPMPi(phiCS); + + auto t1mc = mcparticles.iteratorAt(t1.emmcparticleId()); + auto t2mc = mcparticles.iteratorAt(t2.emmcparticleId()); + bool is_from_same_mcevent = t1mc.emmceventId() == t2mc.emmceventId(); + + if ((FindCommonMotherFrom2ProngsWithoutPDG(t1mc, t2mc) > 0 || IsHF(t1mc, t2mc, mcparticles) > 0) && is_from_same_mcevent) { // for bkg study + if (abs(t1mc.pdgCode()) != pdg_lepton || abs(t2mc.pdgCode()) != pdg_lepton) { // hh or eh correlated bkg + if (abs(t1mc.pdgCode()) != pdg_lepton && abs(t2mc.pdgCode()) != pdg_lepton) { // hh correlated bkg + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/corr_bkg_hh/uls/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/corr_bkg_hh/lspp/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/corr_bkg_hh/lsmm/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + } else { // eh correlated bkg + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/corr_bkg_eh/uls/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/corr_bkg_eh/lspp/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/corr_bkg_eh/lsmm/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + } + } + } else { // true combinatorial bkg + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/comb_bkg/uls/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/comb_bkg/lspp/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/comb_bkg/lsmm/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + } + + if (abs(t1mc.pdgCode()) != pdg_lepton || abs(t2mc.pdgCode()) != pdg_lepton) { + return false; + } + + if (!is_from_same_mcevent) { + return false; + } + int mother_id = FindLF(t1mc, t2mc, mcparticles); + int hfee_type = IsHF(t1mc, t2mc, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + return false; + } + + if (mother_id > -1 && t1mc.pdgCode() * t2mc.pdgCode() < 0) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { + if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + switch (abs(mcmother.pdgCode())) { + case 111: + fRegistry.fill(HIST("Pair/sm/Pi0/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/Pi0/hMvsPhiV"), phiv, v12.M()); + } + break; + case 221: + fRegistry.fill(HIST("Pair/sm/Eta/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + break; + case 331: + fRegistry.fill(HIST("Pair/sm/EtaPrime/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + break; + case 113: + fRegistry.fill(HIST("Pair/sm/Rho/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + break; + case 223: + fRegistry.fill(HIST("Pair/sm/Omega/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if (mcmother.daughtersIds().size() == 2) { // omeag->ee + fRegistry.fill(HIST("Pair/sm/Omega2ll/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + case 333: + fRegistry.fill(HIST("Pair/sm/Phi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if (mcmother.daughtersIds().size() == 2) { // phi->ee + fRegistry.fill(HIST("Pair/sm/Phi2ll/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + case 443: { + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/sm/PromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + case 100443: { + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fRegistry.fill(HIST("Pair/sm/NonPromptPsi2S/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/sm/PromptPsi2S/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + default: + break; + } + + } else if (!(t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && !(t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + switch (abs(mcmother.pdgCode())) { + case 22: + fRegistry.fill(HIST("Pair/sm/Photon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/Photon/hMvsPhiV"), phiv, v12.M()); + } + break; + default: + break; + } + } // end of primary/secondary selection + } // end of primary selection for same mother + } else if (hfee_type > -1) { + if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + auto mp1 = mcparticles.iteratorAt(t1mc.mothersIds()[0]); + auto mp2 = mcparticles.iteratorAt(t2mc.mothersIds()[0]); + if (t1mc.pdgCode() * t2mc.pdgCode() < 0) { // ULS + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): { + fRegistry.fill(HIST("Pair/ccbar/c2l_c2l/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if (isCharmMeson(mp1) && isCharmMeson(mp2)) { + fRegistry.fill(HIST("Pair/ccbar/c2l_c2l/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { + fRegistry.fill(HIST("Pair/ccbar/c2l_c2l/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/ccbar/c2l_c2l/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + case static_cast(EM_HFeeType::kBe_Be): { + fRegistry.fill(HIST("Pair/bbbar/b2l_b2l/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if (isBeautyMeson(mp1) && isBeautyMeson(mp2)) { + fRegistry.fill(HIST("Pair/bbbar/b2l_b2l/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (isBeautyBaryon(mp1) && isBeautyBaryon(mp2)) { + fRegistry.fill(HIST("Pair/bbbar/b2l_b2l/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/bbbar/b2l_b2l/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + case static_cast(EM_HFeeType::kBCe_BCe): { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if (isCharmMeson(mp1) && isCharmMeson(mp2)) { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + case static_cast(EM_HFeeType::kBCe_Be_SameB): { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_sameb/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_sameb/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_sameb/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_sameb/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + case static_cast(EM_HFeeType::kBCe_Be_DiffB): // LS + LOGF(info, "You should not see kBCe_Be_DiffB in ULS. Good luck."); + break; + default: + break; + } + } else { // LS + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): + LOGF(info, "You should not see kCe_Ce in LS. Good luck."); + break; + case static_cast(EM_HFeeType::kBe_Be): + LOGF(info, "You should not see kBe_Be in LS. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_BCe): + LOGF(info, "You should not see kBCe_BCe in LS. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_Be_SameB): // ULS + LOGF(info, "You should not see kBCe_Be_SameB in LS. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_Be_DiffB): { // LS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_diffb/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_diffb/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_diffb/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } else { + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2l_diffb/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee), pair_dca, weight); + } + break; + } + default: + break; + } + } + } + } // end of HF evaluation + return true; + } + + SliceCache cache; + Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter_electron = (dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < dielectroncuts.cfg_min_TPCNsigmaPi || dielectroncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + + Preslice perCollision_muon = aod::emprimarymuon::emeventId; + Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_multiplicity = cfgNtracksPV08Min <= o2::aod::mult::multNTracksPV && o2::aod::mult::multNTracksPV < cfgNtracksPV08Max; + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + template + void runTruePairing(TCollisions const& collisions, TMCLeptons const& posTracks, TMCLeptons const& negTracks, TPreslice const& perCollision, TCut const& cut, TMCCollisions const&, TMCParticles const& mcparticles) + { + for (auto& collision : collisions) { + initCCDB(collision); + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + // auto mccollision = collision.template emmcevent_as(); + // if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + // continue; + // } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); + + for (auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + auto mcpos = mcparticles.iteratorAt(pos.emmcparticleId()); + auto mccollision_from_pos = mcpos.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_pos.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mcneg = mcparticles.iteratorAt(neg.emmcparticleId()); + auto mccollision_from_neg = mcneg.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_neg.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + fillTruePairInfo(collision, pos, neg, cut, mcparticles); + } // end of ULS pair loop + + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + auto mcpos1 = mcparticles.iteratorAt(pos1.emmcparticleId()); + auto mccollision_from_pos1 = mcpos1.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_pos1.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mcpos2 = mcparticles.iteratorAt(pos2.emmcparticleId()); + auto mccollision_from_pos2 = mcpos2.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_pos2.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + fillTruePairInfo(collision, pos1, pos2, cut, mcparticles); + } // end of LS++ pair loop + + for (auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + auto mcneg1 = mcparticles.iteratorAt(neg1.emmcparticleId()); + auto mccollision_from_neg1 = mcneg1.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_neg1.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mcneg2 = mcparticles.iteratorAt(neg2.emmcparticleId()); + auto mccollision_from_neg2 = mcneg2.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_neg2.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + fillTruePairInfo(collision, neg1, neg2, cut, mcparticles); + } // end of LS-- pair loop + + } // end of collision loop + + } // end of process + + template + void runGenInfo(TCollisions const& collisions, TMCCollisions const&, TMCLeptons const& posTracksMC, TMCLeptons const& negTracksMC, TMCParticles const& mcparticles) + { + // loop over mc stack and fill histograms for pure MC truth signals + // all MC tracks which belong to the MC event corresponding to the current reconstructed event + + for (auto& collision : collisions) { + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + auto mccollision = collision.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + + auto posTracks_per_coll = posTracksMC.sliceByCachedUnsorted(aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); + auto negTracks_per_coll = negTracksMC.sliceByCachedUnsorted(aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); + + for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); + + if (!isInAcceptance(t1) || !isInAcceptance(t2)) { + continue; + } + + if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { + continue; + } + if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { + continue; + } + + int mother_id = FindLF(t1, t2, mcparticles); + int hfee_type = IsHF(t1, t2, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + continue; + } + + float pt1 = 0.f, eta1 = 0.f, phi1 = 0.f, pt2 = 0.f, eta2 = 0.f, phi2 = 0.f; + if constexpr (isSmeared) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pt1 = t1.ptSmeared(); + eta1 = t1.etaSmeared(); + phi1 = t1.phiSmeared(); + pt2 = t2.ptSmeared(); + eta2 = t2.etaSmeared(); + phi2 = t2.phiSmeared(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + pt1 = t1.ptSmeared_sa_muon(); + eta1 = t1.etaSmeared_sa_muon(); + phi1 = t1.phiSmeared_sa_muon(); + pt2 = t2.ptSmeared_sa_muon(); + eta2 = t2.etaSmeared_sa_muon(); + phi2 = t2.phiSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt1 = t1.ptSmeared_gl_muon(); + eta1 = t1.etaSmeared_gl_muon(); + phi1 = t1.phiSmeared_gl_muon(); + pt2 = t2.ptSmeared_gl_muon(); + eta2 = t2.etaSmeared_gl_muon(); + phi2 = t2.phiSmeared_gl_muon(); + } else { + pt1 = t1.pt(); + eta1 = t1.eta(); + phi1 = t1.phi(); + pt2 = t2.pt(); + eta2 = t2.eta(); + phi2 = t2.phi(); + } + } + } else { + pt1 = t1.pt(); + eta1 = t1.eta(); + phi1 = t1.phi(); + pt2 = t2.pt(); + eta2 = t2.eta(); + phi2 = t2.phi(); + } + + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, leptonM1); + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (v12.Rapidity() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < v12.Rapidity()) { + continue; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (v12.Rapidity() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < v12.Rapidity()) { + continue; + } + } + + float dphi = v1.Phi() - v2.Phi(); + o2::math_utils::bringToPMPi(dphi); + float aco = 1.f - abs(dphi) / M_PI; + float asym = abs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + float dphi_e_ee = v1.Phi() - v12.Phi(); + o2::math_utils::bringToPMPi(dphi_e_ee); + + float cos_thetaCS = 999, phiCS = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(t1, t2, leptonM1, leptonM2, beamE1, beamE2, beamP1, beamP2, cos_thetaCS, phiCS); + o2::math_utils::bringToPMPi(phiCS); + + if (mother_id > -1) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { + + switch (abs(mcmother.pdgCode())) { + case 111: + fRegistry.fill(HIST("Generated/sm/Pi0/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + break; + case 221: + fRegistry.fill(HIST("Generated/sm/Eta/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + break; + case 331: + fRegistry.fill(HIST("Generated/sm/EtaPrime/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + break; + case 113: + fRegistry.fill(HIST("Generated/sm/Rho/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + break; + case 223: + fRegistry.fill(HIST("Generated/sm/Omega/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if (mcmother.daughtersIds().size() == 2) { // omega->ee + fRegistry.fill(HIST("Generated/sm/Omega2ll/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + case 333: + fRegistry.fill(HIST("Generated/sm/Phi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if (mcmother.daughtersIds().size() == 2) { // phi->ee + fRegistry.fill(HIST("Generated/sm/Phi2ll/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + case 443: { + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fRegistry.fill(HIST("Generated/sm/NonPromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/sm/PromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + case 100443: { + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fRegistry.fill(HIST("Generated/sm/NonPromptPsi2S/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/sm/PromptPsi2S/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + default: + break; + } + } + } else if (hfee_type > -1) { + auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); + auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): { + fRegistry.fill(HIST("Generated/ccbar/c2l_c2l/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if (isCharmMeson(mp1) && isCharmMeson(mp2)) { + fRegistry.fill(HIST("Generated/ccbar/c2l_c2l/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { + fRegistry.fill(HIST("Generated/ccbar/c2l_c2l/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/ccbar/c2l_c2l/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + case static_cast(EM_HFeeType::kBe_Be): { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if (isBeautyMeson(mp1) && isBeautyMeson(mp2)) { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else if (isBeautyBaryon(mp1) && isBeautyBaryon(mp2)) { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + case static_cast(EM_HFeeType::kBCe_BCe): { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if (isCharmMeson(mp1) && isCharmMeson(mp2)) { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/bbbar/b2l_b2l/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + case static_cast(EM_HFeeType::kBCe_Be_SameB): { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_sameb/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_sameb/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_sameb/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_sameb/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + case static_cast(EM_HFeeType::kBCe_Be_DiffB): // LS + LOGF(info, "You should not see kBCe_Be_DiffB in ULS. Good luck."); + break; + default: + break; + } + } // end of HF evaluation + } // end of true ULS pair loop + + for (auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { + // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); + + if (!isInAcceptance(t1) || !isInAcceptance(t2)) { + continue; + } + + if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { + continue; + } + if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { + continue; + } + + int hfee_type = IsHF(t1, t2, mcparticles); + if (hfee_type < 0) { + continue; + } + + float pt1 = 0.f, eta1 = 0.f, phi1 = 0.f, pt2 = 0.f, eta2 = 0.f, phi2 = 0.f; + if constexpr (isSmeared) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pt1 = t1.ptSmeared(); + eta1 = t1.etaSmeared(); + phi1 = t1.phiSmeared(); + pt2 = t2.ptSmeared(); + eta2 = t2.etaSmeared(); + phi2 = t2.phiSmeared(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + pt1 = t1.ptSmeared_sa_muon(); + eta1 = t1.etaSmeared_sa_muon(); + phi1 = t1.phiSmeared_sa_muon(); + pt2 = t2.ptSmeared_sa_muon(); + eta2 = t2.etaSmeared_sa_muon(); + phi2 = t2.phiSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt1 = t1.ptSmeared_gl_muon(); + eta1 = t1.etaSmeared_gl_muon(); + phi1 = t1.phiSmeared_gl_muon(); + pt2 = t2.ptSmeared_gl_muon(); + eta2 = t2.etaSmeared_gl_muon(); + phi2 = t2.phiSmeared_gl_muon(); + } else { + pt1 = t1.pt(); + eta1 = t1.eta(); + phi1 = t1.phi(); + pt2 = t2.pt(); + eta2 = t2.eta(); + phi2 = t2.phi(); + } + } + } else { + pt1 = t1.pt(); + eta1 = t1.eta(); + phi1 = t1.phi(); + pt2 = t2.pt(); + eta2 = t2.eta(); + phi2 = t2.phi(); + } + + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, leptonM1); + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (v12.Rapidity() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < v12.Rapidity()) { + continue; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (v12.Rapidity() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < v12.Rapidity()) { + continue; + } + } + + float dphi = v1.Phi() - v2.Phi(); + o2::math_utils::bringToPMPi(dphi); + float aco = 1.f - abs(dphi) / M_PI; + float asym = abs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + float dphi_e_ee = v1.Phi() - v12.Phi(); + o2::math_utils::bringToPMPi(dphi_e_ee); + + float cos_thetaCS = 999, phiCS = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(t1, t2, leptonM1, leptonM2, beamE1, beamE2, beamP1, beamP2, cos_thetaCS, phiCS); + o2::math_utils::bringToPMPi(phiCS); + + if (hfee_type > -1) { + auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); + auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): + LOGF(info, "You should not see kCe_Ce in LS++. Good luck."); + break; + case static_cast(EM_HFeeType::kBe_Be): + LOGF(info, "You should not see kBe_Be in LS++. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_BCe): + LOGF(info, "You should not see kBCe_BCe in LS++. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_Be_SameB): // ULS + LOGF(info, "You should not see kBCe_Be_SameB in LS++. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_Be_DiffB): { // LS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + default: + break; + } + } + } // end of true LS++ pair loop + + for (auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { + // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); + + if (!isInAcceptance(t1) || !isInAcceptance(t2)) { + continue; + } + + if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { + continue; + } + if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { + continue; + } + + int hfee_type = IsHF(t1, t2, mcparticles); + if (hfee_type < 0) { + continue; + } + + float pt1 = 0.f, eta1 = 0.f, phi1 = 0.f, pt2 = 0.f, eta2 = 0.f, phi2 = 0.f; + if constexpr (isSmeared) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pt1 = t1.ptSmeared(); + eta1 = t1.etaSmeared(); + phi1 = t1.phiSmeared(); + pt2 = t2.ptSmeared(); + eta2 = t2.etaSmeared(); + phi2 = t2.phiSmeared(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + pt1 = t1.ptSmeared_sa_muon(); + eta1 = t1.etaSmeared_sa_muon(); + phi1 = t1.phiSmeared_sa_muon(); + pt2 = t2.ptSmeared_sa_muon(); + eta2 = t2.etaSmeared_sa_muon(); + phi2 = t2.phiSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt1 = t1.ptSmeared_gl_muon(); + eta1 = t1.etaSmeared_gl_muon(); + phi1 = t1.phiSmeared_gl_muon(); + pt2 = t2.ptSmeared_gl_muon(); + eta2 = t2.etaSmeared_gl_muon(); + phi2 = t2.phiSmeared_gl_muon(); + } else { + pt1 = t1.pt(); + eta1 = t1.eta(); + phi1 = t1.phi(); + pt2 = t2.pt(); + eta2 = t2.eta(); + phi2 = t2.phi(); + } + } + } else { + pt1 = t1.pt(); + eta1 = t1.eta(); + phi1 = t1.phi(); + pt2 = t2.pt(); + eta2 = t2.eta(); + phi2 = t2.phi(); + } + + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, leptonM1); + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (v12.Rapidity() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < v12.Rapidity()) { + continue; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (v12.Rapidity() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < v12.Rapidity()) { + continue; + } + } + + float dphi = v1.Phi() - v2.Phi(); + o2::math_utils::bringToPMPi(dphi); + float aco = 1.f - abs(dphi) / M_PI; + float asym = abs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + float dphi_e_ee = v1.Phi() - v12.Phi(); + o2::math_utils::bringToPMPi(dphi_e_ee); + + float cos_thetaCS = 999, phiCS = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(t1, t2, leptonM1, leptonM2, beamE1, beamE2, beamP1, beamP2, cos_thetaCS, phiCS); + o2::math_utils::bringToPMPi(phiCS); + + if (hfee_type > -1) { + auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); + auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): + LOGF(info, "You should not see kCe_Ce in LS--. Good luck."); + break; + case static_cast(EM_HFeeType::kBe_Be): + LOGF(info, "You should not see kBe_Be in LS--. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_BCe): + LOGF(info, "You should not see kBCe_BCe in LS--. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_Be_SameB): // ULS + LOGF(info, "You should not see kBCe_Be_SameB in LS--. Good luck."); + break; + case static_cast(EM_HFeeType::kBCe_Be_DiffB): { // LS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/hadron_hadron/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/meson_meson/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/baryon_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } else { + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2l_diffb/meson_baryon/hs"), v12.M(), v12.Pt(), v12.Rapidity(), abs(dphi), abs(cos_thetaCS), abs(phiCS), aco, asym, abs(dphi_e_ee)); + } + break; + } + default: + break; + } + } + } // end of true LS++ pair loop + } // end of collision loop + } + + template + bool isPairOK(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(t1, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.template IsSelectedPair(t1, t2, d_bz)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedPair(t1, t2)) { + return false; + } + } + return true; + } + + std::map, float> map_weight; // -> float + template + void fillPairWeightMap(TCollisions const& collisions, TTracks1 const& posTracks, TTracks2 const& negTracks, TPresilce const& perCollision, TCut const& cut, TAllTracks const& tracks, TMCCollisions const&, TMCParticles const& mcparticles) + { + std::vector> passed_pairIds; + passed_pairIds.reserve(posTracks.size() * negTracks.size()); + + for (auto& collision : collisions) { + initCCDB(collision); + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + // auto mccollision = collision.template emmcevent_as(); + // if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + // continue; + // } + + auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + + for (auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + auto mcpos = mcparticles.iteratorAt(pos.emmcparticleId()); + auto mccollision_from_pos = mcpos.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_pos.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mcneg = mcparticles.iteratorAt(neg.emmcparticleId()); + auto mccollision_from_neg = mcneg.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_neg.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + if (isPairOK(collision, pos, neg, cut)) { + passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); + } + } + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + auto mcpos1 = mcparticles.iteratorAt(pos1.emmcparticleId()); + auto mccollision_from_pos1 = mcpos1.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_pos1.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mcpos2 = mcparticles.iteratorAt(pos2.emmcparticleId()); + auto mccollision_from_pos2 = mcpos2.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_pos2.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + if (isPairOK(collision, pos1, pos2, cut)) { + passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); + } + } + for (auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + auto mcneg1 = mcparticles.iteratorAt(neg1.emmcparticleId()); + auto mccollision_from_neg1 = mcneg1.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_neg1.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mcneg2 = mcparticles.iteratorAt(neg2.emmcparticleId()); + auto mccollision_from_neg2 = mcneg2.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_neg2.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + if (isPairOK(collision, neg1, neg2, cut)) { + passed_pairIds.emplace_back(std::make_pair(neg1.globalIndex(), neg2.globalIndex())); + } + } + } // end of collision loop + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& pairId : passed_pairIds) { + auto t1 = tracks.rawIteratorAt(std::get<0>(pairId)); + auto t2 = tracks.rawIteratorAt(std::get<1>(pairId)); + // LOGF(info, "std::get<0>(pairId) = %d, std::get<1>(pairId) = %d, t1.globalIndex() = %d, t2.globalIndex() = %d", std::get<0>(pairId), std::get<1>(pairId), t1.globalIndex(), t2.globalIndex()); + + float n = 1.f; // include myself. + for (auto& ambId1 : t1.ambiguousElectronsIds()) { + for (auto& ambId2 : t2.ambiguousElectronsIds()) { + if (std::find(passed_pairIds.begin(), passed_pairIds.end(), std::make_pair(ambId1, ambId2)) != passed_pairIds.end()) { + n += 1.f; + } + } + } + map_weight[pairId] = 1.f / n; + } // end of passed_pairIds loop + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& pairId : passed_pairIds) { + auto t1 = tracks.rawIteratorAt(std::get<0>(pairId)); + auto t2 = tracks.rawIteratorAt(std::get<1>(pairId)); + + float n = 1.f; // include myself. + for (auto& ambId1 : t1.ambiguousMuonsIds()) { + for (auto& ambId2 : t2.ambiguousMuonsIds()) { + if (std::find(passed_pairIds.begin(), passed_pairIds.end(), std::make_pair(ambId1, ambId2)) != passed_pairIds.end()) { + n += 1.f; + } + } + } + map_weight[pairId] = 1.f / n; + } // end of passed_pairIds loop + } + passed_pairIds.clear(); + passed_pairIds.shrink_to_fit(); + } + + Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); // reconstructed tracks + Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); // reconstructed tracks + Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); // reconstructed tracks + Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); // reconstructed tracks + + Partition positive_electronsMC = o2::aod::mcparticle::pdgCode == -11; // e+ + Partition negative_electronsMC = o2::aod::mcparticle::pdgCode == 11; // e- + Partition positive_muonsMC = o2::aod::mcparticle::pdgCode == -13; // mu+ + Partition negative_muonsMC = o2::aod::mcparticle::pdgCode == 13; // mu- + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + PresliceUnsorted perMcCollision_vm = aod::emmcgenvectormeson::emmceventId; + + void processAnalysis(FilteredMyCollisions const& collisions, aod::EMMCEvents const& mccollisions, aod::EMMCParticles const& mcparticles, TLeptons const& leptons) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, mcparticles); + } + runTruePairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, positive_electronsMC, negative_electronsMC, mcparticles); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles); + } + runTruePairing(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, positive_muonsMC, negative_muonsMC, mcparticles); + } + map_weight.clear(); + } + PROCESS_SWITCH(DileptonMC, processAnalysis, "run dilepton mc analysis", true); + + Partition positive_electronsMC_smeared = o2::aod::mcparticle::pdgCode == -11; // e+ + Partition negative_electronsMC_smeared = o2::aod::mcparticle::pdgCode == 11; // e- + Partition positive_muonsMC_smeared = o2::aod::mcparticle::pdgCode == -13; // mu+ + Partition negative_muonsMC_smeared = o2::aod::mcparticle::pdgCode == 13; // mu- + + void processAnalysis_Smeared(FilteredMyCollisions const& collisions, aod::EMMCEvents const& mccollisions, TLeptons const& leptons, TSmeardMCParitlces const& mcparticles_smeared) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, mcparticles_smeared); + } + runTruePairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, mccollisions, mcparticles_smeared); + runGenInfo(collisions, mccollisions, positive_electronsMC_smeared, negative_electronsMC_smeared, mcparticles_smeared); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles_smeared); + } + runTruePairing(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, mccollisions, mcparticles_smeared); + runGenInfo(collisions, mccollisions, positive_muonsMC_smeared, negative_muonsMC_smeared, mcparticles_smeared); + } + map_weight.clear(); + } + PROCESS_SWITCH(DileptonMC, processAnalysis_Smeared, "run dilepton mc analysis with smearing", false); + + void processGen_VM(FilteredMyCollisions const& collisions, aod::EMMCEvents const&, aod::EMMCGenVectorMesons const& mcparticles) + { + // for oemga, phi efficiency + for (auto& collision : collisions) { + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + auto mccollision = collision.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + auto mctracks_per_coll = mcparticles.sliceBy(perMcCollision_vm, mccollision.globalIndex()); + + for (auto& mctrack : mctracks_per_coll) { + + if (!(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + continue; + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (mctrack.y() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < mctrack.y()) { + continue; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (mctrack.y() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < mctrack.y()) { + continue; + } + } + + switch (abs(mctrack.pdgCode())) { + case 223: + fRegistry.fill(HIST("Generated/sm/Omega2ll/hPtY"), mctrack.y(), mctrack.pt(), 1.f / mctrack.dsf()); + break; + case 333: + fRegistry.fill(HIST("Generated/sm/Phi2ll/hPtY"), mctrack.y(), mctrack.pt(), 1.f / mctrack.dsf()); + break; + default: + break; + } + + } // end of mctracks per mccollision + } // end of collision loop + } + PROCESS_SWITCH(DileptonMC, processGen_VM, "process generated info for vector mesons", false); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(DileptonMC, processDummy, "Dummy function", false); +}; + +#endif // PWGEM_DILEPTON_CORE_DILEPTONMC_H_ diff --git a/PWGEM/PhotonMeson/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx similarity index 93% rename from PWGEM/PhotonMeson/Core/DimuonCut.cxx rename to PWGEM/Dilepton/Core/DimuonCut.cxx index bbd6178ef21..ba9e1b95107 100644 --- a/PWGEM/PhotonMeson/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -14,7 +14,7 @@ // #include "Framework/Logger.h" -#include "PWGEM/PhotonMeson/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" ClassImp(DimuonCut); @@ -59,6 +59,12 @@ void DimuonCut::SetTrackEtaRange(float minEta, float maxEta) mMaxTrackEta = maxEta; LOG(info) << "Dimuon Cut, set track eta range: " << mMinTrackEta << " - " << mMaxTrackEta; } +void DimuonCut::SetTrackPhiRange(float minPhi, float maxPhi) +{ + mMinTrackPhi = minPhi; + mMaxTrackPhi = maxPhi; + LOG(info) << "Dimuon Cut, set track phi range (rad.): " << mMinTrackPhi << " - " << mMaxTrackPhi; +} void DimuonCut::SetChi2(float min, float max) { mMinChi2 = min; diff --git a/PWGEM/PhotonMeson/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h similarity index 85% rename from PWGEM/PhotonMeson/Core/DimuonCut.h rename to PWGEM/Dilepton/Core/DimuonCut.h index 9f11d45e74f..e0bcd0e6f51 100644 --- a/PWGEM/PhotonMeson/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -13,8 +13,8 @@ // Class for dimuon selection // -#ifndef PWGEM_PHOTONMESON_CORE_DIMUONCUT_H_ -#define PWGEM_PHOTONMESON_CORE_DIMUONCUT_H_ +#ifndef PWGEM_DILEPTON_CORE_DIMUONCUT_H_ +#define PWGEM_DILEPTON_CORE_DIMUONCUT_H_ #include #include @@ -27,6 +27,9 @@ #include "Framework/Logger.h" #include "Framework/DataTypes.h" #include "CommonConstants/PhysicsConstants.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; class DimuonCut : public TNamed { @@ -34,6 +37,8 @@ class DimuonCut : public TNamed DimuonCut() = default; DimuonCut(const char* name, const char* title) : TNamed(name, title) {} + ~DimuonCut() {} + enum class DimuonCuts : int { // pair cut kMass = 0, @@ -44,6 +49,7 @@ class DimuonCut : public TNamed kTrackType, kTrackPtRange, kTrackEtaRange, + kTrackPhiRange, kDCAxy, kMFTNCls, kMCHMIDNCls, @@ -79,36 +85,9 @@ class DimuonCut : public TNamed ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float dcaX1 = t1.fwdDcaX(); - float dcaY1 = t1.fwdDcaY(); - float cXX1 = t1.cXX(); - float cYY1 = t1.cYY(); - float cXY1 = t1.cXY(); - float dcaX2 = t2.fwdDcaX(); - float dcaY2 = t2.fwdDcaY(); - float cXX2 = t2.cXX(); - float cYY2 = t2.cYY(); - float cXY2 = t2.cXY(); - - float dca_xy1 = 999.f; - float det1 = cXX1 * cYY1 - cXY1 * cXY1; - if (det1 < 0) { - dca_xy1 = 999.f; - } else { - float chi2 = (dcaX1 * dcaX1 * cYY1 + dcaY1 * dcaY1 * cXX1 - 2. * dcaX1 * dcaY1 * cXY1) / det1; - dca_xy1 = std::sqrt(std::abs(chi2) / 2.); // in sigma - } - - float dca_xy2 = 999.f; - float det2 = cXX2 * cYY2 - cXY2 * cXY2; - if (det2 < 0) { - dca_xy2 = 999.f; - } else { - float chi2 = (dcaX2 * dcaX2 * cYY2 + dcaY2 * dcaY2 * cXX2 - 2. * dcaX2 * dcaY2 * cXY2) / det2; - dca_xy2 = std::sqrt(std::abs(chi2) / 2.); // in sigma - } - - float pair_dca_xy = std::sqrt((std::pow(dca_xy1, 2) + std::pow(dca_xy2, 2)) / 2.); + float dca_xy_t1 = fwdDcaXYinSigma(t1); + float dca_xy_t2 = fwdDcaXYinSigma(t2); + float pair_dca_xy = std::sqrt((dca_xy_t1 * dca_xy_t1 + dca_xy_t2 * dca_xy_t2) / 2.); if (v12.M() < mMinMass || mMaxMass < v12.M()) { return false; @@ -140,6 +119,9 @@ class DimuonCut : public TNamed if (!IsSelectedTrack(track, DimuonCuts::kTrackEtaRange)) { return false; } + if (!IsSelectedTrack(track, DimuonCuts::kTrackPhiRange)) { + return false; + } if (!IsSelectedTrack(track, DimuonCuts::kDCAxy)) { return false; } @@ -181,6 +163,9 @@ class DimuonCut : public TNamed case DimuonCuts::kTrackEtaRange: return track.eta() > mMinTrackEta && track.eta() < mMaxTrackEta; + case DimuonCuts::kTrackPhiRange: + return track.phi() > mMinTrackPhi && track.phi() < mMaxTrackPhi; + case DimuonCuts::kDCAxy: return mMinDcaXY < std::sqrt(std::pow(track.fwdDcaX(), 2) + std::pow(track.fwdDcaY(), 2)) && std::sqrt(std::pow(track.fwdDcaX(), 2) + std::pow(track.fwdDcaY(), 2)) < mMaxDcaXY; @@ -219,6 +204,7 @@ class DimuonCut : public TNamed void SetTrackType(int track_type); // 0: MFT-MCH-MID (global muon), 3: MCH-MID (standalone muon) void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); + void SetTrackPhiRange(float minPhi = 0.f, float maxPhi = 2.f * M_PI); void SetNClustersMFT(int min, int max); void SetNClustersMCHMID(int min, int max); void SetChi2(float min, float max); @@ -236,8 +222,9 @@ class DimuonCut : public TNamed float mMinPairDCAxy{0.f}, mMaxPairDCAxy{1e10f}; // range in 3D DCA in sigma // kinematic cuts - float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT - float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta + float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT + float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta + float mMinTrackPhi{0.f}, mMaxTrackPhi{2.f * M_PI}; // range in phi // track quality cuts int mTrackType{3}; @@ -254,4 +241,4 @@ class DimuonCut : public TNamed ClassDef(DimuonCut, 1); }; -#endif // PWGEM_PHOTONMESON_CORE_DIMUONCUT_H_ +#endif // PWGEM_DILEPTON_CORE_DIMUONCUT_H_ diff --git a/PWGEM/PhotonMeson/Core/EMEventCut.cxx b/PWGEM/Dilepton/Core/EMEventCut.cxx similarity index 69% rename from PWGEM/PhotonMeson/Core/EMEventCut.cxx rename to PWGEM/Dilepton/Core/EMEventCut.cxx index 46f023da0b0..64fef030c21 100644 --- a/PWGEM/PhotonMeson/Core/EMEventCut.cxx +++ b/PWGEM/Dilepton/Core/EMEventCut.cxx @@ -14,12 +14,10 @@ // #include "Framework/Logger.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" ClassImp(EMEventCut); -const char* EMEventCut::mCutNames[static_cast(EMEventCut::EMEventCuts::kNCuts)] = {"Sel8", "FT0AND", "Zvtx", "eNoTFB", "RequireNoITSROFB", "NoSameBunchPileup", "GoodVertexITSTPC", "GoodZvtxFT0vsPV"}; - void EMEventCut::SetRequireSel8(bool flag) { mRequireSel8 = flag; @@ -76,26 +74,13 @@ void EMEventCut::SetRequireGoodZvtxFT0vsPV(bool flag) LOG(info) << "EM Event Cut, require good Zvtx between FT0 vs. PV: " << mRequireGoodZvtxFT0vsPV; } -void EMEventCut::print() const +void EMEventCut::SetRequireNoCollInTimeRangeStandard(bool flag) { - LOG(info) << "EM Event Cut:"; - for (int i = 0; i < static_cast(EMEventCuts::kNCuts); i++) { - switch (static_cast(i)) { - case EMEventCuts::kFT0AND: - LOG(info) << mCutNames[i] << " = " << mRequireFT0AND; - break; - case EMEventCuts::kZvtx: - LOG(info) << mCutNames[i] << " in [" << mMinZvtx << ", " << mMaxZvtx << "]"; - break; - case EMEventCuts::kNoTFB: - LOG(info) << mCutNames[i] << " = " << mRequireNoTFB; - break; - case EMEventCuts::kNoITSROFB: - LOG(info) << mCutNames[i] << " = " << mRequireNoITSROFB; - break; - - default: - LOG(fatal) << "Cut unknown!"; - } - } + mRequireNoCollInTimeRangeStandard = flag; + LOG(info) << "EM Event Cut, require No collision in time range standard: " << mRequireNoCollInTimeRangeStandard; +} +void EMEventCut::SetRequireNoCollInTimeRangeNarrow(bool flag) +{ + mRequireNoCollInTimeRangeNarrow = flag; + LOG(info) << "EM Event Cut, require No collision in time range narrow: " << mRequireNoCollInTimeRangeNarrow; } diff --git a/PWGEM/PhotonMeson/Core/EMEventCut.h b/PWGEM/Dilepton/Core/EMEventCut.h similarity index 77% rename from PWGEM/PhotonMeson/Core/EMEventCut.h rename to PWGEM/Dilepton/Core/EMEventCut.h index 7e4d5698dec..b8af681d3dc 100644 --- a/PWGEM/PhotonMeson/Core/EMEventCut.h +++ b/PWGEM/Dilepton/Core/EMEventCut.h @@ -10,11 +10,11 @@ // or submit itself to any jurisdiction. // -// Class for em photon event selection +// Class for em event selection // -#ifndef PWGEM_PHOTONMESON_CORE_EMEVENTCUT_H_ -#define PWGEM_PHOTONMESON_CORE_EMEVENTCUT_H_ +#ifndef PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ +#define PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ #include "TNamed.h" #include "Common/CCDB/EventSelectionParams.h" @@ -27,6 +27,7 @@ class EMEventCut : public TNamed public: EMEventCut() = default; EMEventCut(const char* name, const char* title) : TNamed(name, title) {} + ~EMEventCut() {} enum class EMEventCuts : int { kSel8 = 0, @@ -38,11 +39,11 @@ class EMEventCut : public TNamed kIsVertexITSTPC, kIsGoodZvtxFT0vsPV, kOccupancy, + kNoCollInTimeRangeStandard, + kNoCollInTimeRangeNarrow, kNCuts }; - static const char* mCutNames[static_cast(EMEventCuts::kNCuts)]; - template bool IsSelected(T const& collision) const { @@ -73,6 +74,12 @@ class EMEventCut : public TNamed if (!IsSelected(collision, EMEventCuts::kOccupancy)) { return false; } + if (mRequireNoCollInTimeRangeStandard && !IsSelected(collision, EMEventCuts::kNoCollInTimeRangeStandard)) { + return false; + } + if (mRequireNoCollInTimeRangeNarrow && !IsSelected(collision, EMEventCuts::kNoCollInTimeRangeNarrow)) { + return false; + } return true; } @@ -104,13 +111,15 @@ class EMEventCut : public TNamed case EMEventCuts::kIsGoodZvtxFT0vsPV: return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); - case EMEventCuts::kOccupancy: { - if (mMinOccupancy < 0) { - return true; - } else { - return mMinOccupancy <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < mMaxOccupancy; - } - } + case EMEventCuts::kOccupancy: + return mMinOccupancy <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < mMaxOccupancy; + + case EMEventCuts::kNoCollInTimeRangeStandard: + return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + + case EMEventCuts::kNoCollInTimeRangeNarrow: + return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow); + default: return true; } @@ -126,9 +135,8 @@ class EMEventCut : public TNamed void SetRequireNoSameBunchPileup(bool flag); void SetRequireVertexITSTPC(bool flag); void SetRequireGoodZvtxFT0vsPV(bool flag); - - /// @brief Print the track selection - void print() const; + void SetRequireNoCollInTimeRangeStandard(bool flag); + void SetRequireNoCollInTimeRangeNarrow(bool flag); private: bool mRequireSel8{true}; @@ -140,8 +148,10 @@ class EMEventCut : public TNamed bool mRequireNoSameBunchPileup{false}; bool mRequireVertexITSTPC{false}; bool mRequireGoodZvtxFT0vsPV{false}; + bool mRequireNoCollInTimeRangeStandard{false}; + bool mRequireNoCollInTimeRangeNarrow{false}; ClassDef(EMEventCut, 1); }; -#endif // PWGEM_PHOTONMESON_CORE_EMEVENTCUT_H_ +#endif // PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ diff --git a/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h b/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h new file mode 100644 index 00000000000..c1af31aa27b --- /dev/null +++ b/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h @@ -0,0 +1,23 @@ +// Copyright 2019-2020 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. + +#ifndef PWGEM_DILEPTON_CORE_PWGEMDILEPTONCORELINKDEF_H_ +#define PWGEM_DILEPTON_CORE_PWGEMDILEPTONCORELINKDEF_H_ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class EMEventCut + ; +#pragma link C++ class DielectronCut + ; +#pragma link C++ class DimuonCut + ; + +#endif // PWGEM_DILEPTON_CORE_PWGEMDILEPTONCORELINKDEF_H_ diff --git a/PWGEM/Dilepton/Core/PhotonHBT.h b/PWGEM/Dilepton/Core/PhotonHBT.h new file mode 100644 index 00000000000..8198a4fec30 --- /dev/null +++ b/PWGEM/Dilepton/Core/PhotonHBT.h @@ -0,0 +1,1371 @@ +// Copyright 2019-2020 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 loops over v0 photons and makes pairs for photon HBT analysis. +// Please write to: daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_CORE_PHOTONHBT_H_ +#define PWGEM_DILEPTON_CORE_PHOTONHBT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Math/Vector3D.h" +#include "Math/GenVector/Boost.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" + +namespace o2::aod::pwgem::dilepton::core::photonhbt +{ +enum class ggHBTPairType : int { + kPCMPCM = 0, + kPCMEE = 1, + kEEEE = 2, +}; +} // namespace o2::aod::pwgem::dilepton::core::photonhbt + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; +using namespace o2::aod::pwgem::dilepton::utils; +using namespace o2::aod::pwgem::dilepton::core::photonhbt; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyCollisionsWithSWT = soa::Join; +using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; +using FilteredMyTracks = soa::Filtered; +using FilteredMyTrack = FilteredMyTracks::iterator; + +template +struct PhotonHBT { + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable cfgDo3D{"cfgDo3D", false, "enable 3D analysis"}; + Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; + // Configurable cfgSpherocityMin{"cfgSpherocityMin", -999.f, "min. spherocity"}; + // Configurable cfgSpherocityMax{"cfgSpherocityMax", +999.f, "max. spherocity"}; + Configurable maxY{"maxY", 0.8, "maximum rapidity for reconstructed particles"}; + Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; + Configurable ndepth{"ndepth", 100, "depth for event mixing"}; + Configurable ndiff_bc_mix{"ndiff_bc_mix", 5, "difference in global BC required in mixed events"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; + ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -M_PI / 2, +M_PI / 2}, "Mixing bins - event plane angle"}; + ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult + Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", true, "flag to apply weighting by 1/N"}; + + ConfigurableAxis ConfKtBins{"ConfKtBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0}, "kT bins for output histograms"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + V0PhotonCut fV0PhotonCut; + struct : ConfigurableGroup { + std::string prefix = "pcmcut_group"; + Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; + Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; + Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; + Configurable cfg_require_v0_on_wwire_ib{"cfg_require_v0_on_wwire_ib", false, "flag to select V0s on W wires ITSib"}; + Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; + Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.8, "max eta for v0 photons at PV"}; + Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; + Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; + Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; + Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; + Configurable cfg_min_cospa{"cfg_min_cospa", 0.997, "min V0 CosPA"}; + Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; + Configurable cfg_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; + Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; + + Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 10, "min ncluster tpc"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + } pcmcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 0.015, "max mass"}; // this is valid, because only ULS is used. + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 2.0, "max pair dca3d in sigma"}; + Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + Configurable cfg_apply_phiv_meedep{"cfg_apply_phiv_meedep", false, "flag to apply mee-dependent phiv cut"}; + Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "max eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1e+10, "max DCA 3D in sigma"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.2, "max p to apply ITS cluster size cut"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3.0, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + struct : ConfigurableGroup { + std::string prefix = "ggpaircut_group"; + Configurable applydRdZ{"applydRdZ", false, "apply dr-dz cut to avoid track splitting/merging only for kPCMPCM"}; + Configurable applydEtadPhi{"applydEtadPhi", false, "apply deta-dphi cut to avoid track splitting/merging"}; + Configurable cfgMinDeltaEta{"cfgMinDeltaEta", 0.f, "min. delta-eta between 2 photons"}; + Configurable cfgMinDeltaPhi{"cfgMinDeltaPhi", 0.f, "min. delta-phi between 2 photons"}; + Configurable cfgMinDeltaR{"cfgMinDeltaR", 0.f, "min. delta-r between 2 photons"}; + Configurable cfgMinDeltaZ{"cfgMinDeltaZ", 0.f, "min. delta-z between 2 photons"}; + } ggpaircuts; + + ~PhotonHBT() + { + delete emh1; + emh1 = 0x0; + delete emh2; + emh2 = 0x0; + + map_mixed_eventId_to_globalBC.clear(); + + used_photonIds.clear(); + used_photonIds.shrink_to_fit(); + used_dileptonIds.clear(); + used_dileptonIds.shrink_to_fit(); + + if (eid_bdt) { + delete eid_bdt; + } + } + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_types[2] = {"before", "after"}; + static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; + + std::mt19937 engine; + std::uniform_int_distribution dist01; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber; + float d_bz; + + std::vector zvtx_bin_edges; + std::vector cent_bin_edges; + std::vector ep_bin_edges; + std::vector occ_bin_edges; + + void init(InitContext& /*context*/) + { + if (ConfVtxBins.value[0] == VARIABLE_WIDTH) { + zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); + zvtx_bin_edges.erase(zvtx_bin_edges.begin()); + for (auto& edge : zvtx_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfVtxBins.value[0]); + float xmin = static_cast(ConfVtxBins.value[1]); + float xmax = static_cast(ConfVtxBins.value[2]); + zvtx_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + zvtx_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: zvtx_bin_edges[%d] = %f", i, zvtx_bin_edges[i]); + } + } + + if (ConfCentBins.value[0] == VARIABLE_WIDTH) { + cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); + cent_bin_edges.erase(cent_bin_edges.begin()); + for (auto& edge : cent_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: cent_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfCentBins.value[0]); + float xmin = static_cast(ConfCentBins.value[1]); + float xmax = static_cast(ConfCentBins.value[2]); + cent_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + cent_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: cent_bin_edges[%d] = %f", i, cent_bin_edges[i]); + } + } + + if (ConfEPBins.value[0] == VARIABLE_WIDTH) { + ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); + ep_bin_edges.erase(ep_bin_edges.begin()); + for (auto& edge : ep_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: ep_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfEPBins.value[0]); + float xmin = static_cast(ConfEPBins.value[1]); + float xmax = static_cast(ConfEPBins.value[2]); + ep_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + ep_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: ep_bin_edges[%d] = %f", i, ep_bin_edges[i]); + } + } + + if (ConfOccupancyBins.value[0] == VARIABLE_WIDTH) { + occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); + occ_bin_edges.erase(occ_bin_edges.begin()); + for (auto& edge : occ_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: occ_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfOccupancyBins.value[0]); + float xmin = static_cast(ConfOccupancyBins.value[1]); + float xmax = static_cast(ConfOccupancyBins.value[2]); + occ_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + occ_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: occ_bin_edges[%d] = %f", i, occ_bin_edges[i]); + } + } + + emh1 = new MyEMH(ndepth); + emh2 = new MyEMH(ndepth); + + DefineEMEventCut(); + DefinePCMCut(); + DefineDileptonCut(); + + addhistograms(); + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + std::random_device seed_gen; + engine = std::mt19937(seed_gen()); + dist01 = std::uniform_int_distribution(0, 1); + + fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{1001, -0.5, 1000.5}}, true); + if (doprocessTriggerAnalysis) { + fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = collision.runNumber(); + + if constexpr (isTriggerAnalysis) { + LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", cfg_swt_name.value); + LOGF(info, "total inspected TVX events = %d in run number %d", collision.nInspectedTVX(), collision.runNumber()); + fRegistry.fill(HIST("Event/hNInspectedTVX"), collision.runNumber(), collision.nInspectedTVX()); + } + } + + void addhistograms() + { + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); + std::string_view qvec_det_names[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; + fRegistry.add("Event/before/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); + fRegistry.add("Event/after/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); + + // pair info + const AxisSpec axis_kt{ConfKtBins, "k_{T} (GeV/c)"}; + const AxisSpec axis_qinv{60, 0.0, +0.3, "q_{inv} (GeV/c)"}; + const AxisSpec axis_kstar{60, 0.0, +0.3, "k* (GeV/c)"}; + const AxisSpec axis_qabs_lcms{60, 0.0, +0.3, "|#bf{q}|^{LCMS} (GeV/c)"}; + const AxisSpec axis_qout{60, 0.0, +0.3, "q_{out} (GeV/c)"}; // qout does not change between LAB and LCMS frame + const AxisSpec axis_qside{60, 0.0, +0.3, "q_{side} (GeV/c)"}; // qside does not change between LAB and LCMS frame + const AxisSpec axis_qlong{60, 0.0, +0.3, "q_{long} (GeV/c)"}; + + if (cfgDo3D) { + fRegistry.add("Pair/same/hs_3d", "diphoton correlation 3D LCMS", kTHnSparseD, {axis_qout, axis_qside, axis_qlong, axis_kt}, true); + } else { + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { // identical particle femtoscopy + fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D", kTHnSparseD, {axis_qinv, axis_qabs_lcms, axis_kt}, true); + } else { // non-identical particle femtoscopy + fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D", kTHnSparseD, {axis_kstar, axis_qabs_lcms, axis_kt}, true); + } + } + + fRegistry.add("Pair/same/hDeltaEtaDeltaPhi", "distance between 2 LS tracks in #eta-#varphi plane;#Delta#varphi (rad.);#Delta#eta", kTH2D, {{80, -0.2, +0.2}, {80, -0.2, 0.2}}, true); // deta, dphi of track momentum + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { // dr, dz of conversion points + fRegistry.add("Pair/same/hDeltaRDeltaZ", "diphoton distance in RZ;#Deltar = #sqrt{(#Deltax)^{2} + (#Deltay)^{2}} (cm);|#Deltaz| (cm)", kTH2D, {{40, 0, 20}, {40, 0, 20}}, true); + } + + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + void DefinePCMCut() + { + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); + + // for v0 + fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, 1e10f); + fV0PhotonCut.SetV0EtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); + fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); + fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius); + fV0PhotonCut.SetAPRange(pcmcuts.cfg_max_alpha_ap, pcmcuts.cfg_max_qt_ap); + fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); + + // for track + fV0PhotonCut.SetTrackPtRange(pcmcuts.cfg_min_pt_v0 * 0.5, 1e+10f); + fV0PhotonCut.SetTrackEtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); + + if (pcmcuts.cfg_reject_v0_on_itsib) { + fV0PhotonCut.SetNClustersITS(2, 4); + } else { + fV0PhotonCut.SetNClustersITS(0, 7); + } + fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); + fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); + + if (pcmcuts.cfg_require_v0_with_itstpc) { + fV0PhotonCut.SetRequireITSTPC(true); + fV0PhotonCut.SetMaxPCA(1.0); + fV0PhotonCut.SetRxyRange(4, 40); + } + if (pcmcuts.cfg_require_v0_with_itsonly) { + fV0PhotonCut.SetRequireITSonly(true); + fV0PhotonCut.SetMaxPCA(1.0); + fV0PhotonCut.SetRxyRange(4, 24); + } + if (pcmcuts.cfg_require_v0_with_tpconly) { + fV0PhotonCut.SetRequireTPConly(true); + fV0PhotonCut.SetMaxPCA(3.0); + fV0PhotonCut.SetRxyRange(36, 90); + } + if (pcmcuts.cfg_require_v0_on_wwire_ib) { + fV0PhotonCut.SetMaxPCA(0.3); + fV0PhotonCut.SetOnWwireIB(true); + fV0PhotonCut.SetOnWwireOB(false); + fV0PhotonCut.SetRxyRange(7, 14); + } + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDileptonCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for pair + fDielectronCut.SetMeeRange(dielectroncuts.cfg_min_mass, dielectroncuts.cfg_max_mass); + fDielectronCut.SetPairPtRange(dielectroncuts.cfg_min_pair_pt, dielectroncuts.cfg_max_pair_pt); + fDielectronCut.SetPairYRange(dielectroncuts.cfg_min_pair_y, dielectroncuts.cfg_max_pair_y); + if (dielectroncuts.cfg_apply_phiv_meedep) { + fDielectronCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dielectroncuts.cfg_phiv_intercept) / dielectroncuts.cfg_phiv_slope; }); + } else { + fDielectronCut.SetPhivPairRange(0.f, dielectroncuts.cfg_max_phiv); + } + fDielectronCut.SetPairDCARange(dielectroncuts.cfg_min_pair_dca3d, dielectroncuts.cfg_max_pair_dca3d); // in sigma + fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); + fDielectronCut.ApplyPrefilter(dielectroncuts.cfg_apply_pf); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackDca3DRange(0.f, dielectroncuts.cfg_max_dca3dsigma_track); // in sigma + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + fDielectronCut.SetMaxPinForPionRejectionTPC(dielectroncuts.cfg_max_pin_pirejTPC); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + template + void fillPairHistogram(TCollision const&, const ROOT::Math::PtEtaPhiMVector v1, const ROOT::Math::PtEtaPhiMVector v2, const float weight = 1.f) + { + float rndm = std::pow(-1, dist01(engine) % 2); // +1 or -1 to randomize order between 1 and 2. + // Lab. frame + ROOT::Math::PtEtaPhiMVector q12 = (v1 - v2) * rndm; + ROOT::Math::PtEtaPhiMVector k12 = 0.5 * (v1 + v2); + float qinv = -q12.M(); // for identical particles -> qinv = 2 x kstar + float kt = k12.Pt(); + + ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); // unit vector for out. i.e. parallel to kt + ROOT::Math::XYZVector uv_long(0, 0, 1); // unit vector for long, beam axis + ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); // unit vector for side + + ROOT::Math::PxPyPzEVector v1_cartesian(v1); + ROOT::Math::PxPyPzEVector v2_cartesian(v2); + ROOT::Math::PxPyPzEVector q12_cartesian = (v1_cartesian - v2_cartesian) * rndm; + float beta = (v1 + v2).Beta(); + float beta_x = beta * std::cos((v1 + v2).Phi()) * std::sin((v1 + v2).Theta()); + float beta_y = beta * std::sin((v1 + v2).Phi()) * std::sin((v1 + v2).Theta()); + float beta_z = beta * std::cos((v1 + v2).Theta()); + + // longitudinally co-moving system (LCMS) + ROOT::Math::Boost bst_z(0, 0, -beta_z); // Boost supports only PxPyPzEVector + ROOT::Math::PxPyPzEVector q12_lcms = bst_z(q12_cartesian); + ROOT::Math::XYZVector q_3d_lcms = q12_lcms.Vect(); // 3D q vector in LCMS + float qout_lcms = q_3d_lcms.Dot(uv_out); + float qside_lcms = q_3d_lcms.Dot(uv_side); + float qlong_lcms = q_3d_lcms.Dot(uv_long); + float qabs_lcms = q_3d_lcms.R(); + + // float qabs_lcms_tmp = std::sqrt(std::pow(qout_lcms, 2) + std::pow(qside_lcms, 2) + std::pow(qlong_lcms, 2)); + // LOGF(info, "qabs_lcms = %f, qabs_lcms_tmp = %f", qabs_lcms, qabs_lcms_tmp); + + // pair rest frame (PRF) + ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-beta_x, -beta_y, -beta_z); + ROOT::Math::PxPyPzEVector v1_prf = boostPRF(v1_cartesian); + ROOT::Math::PxPyPzEVector v2_prf = boostPRF(v2_cartesian); + ROOT::Math::PxPyPzEVector rel_k = (v1_prf - v2_prf) * rndm; + float kstar = 0.5 * rel_k.P(); + // LOGF(info, "qabs_lcms = %f, qinv = %f, kstar = %f", qabs_lcms, qinv, kstar); + + // ROOT::Math::PxPyPzEVector v1_lcms_cartesian = bst_z(v1_cartesian); + // ROOT::Math::PxPyPzEVector v2_lcms_cartesian = bst_z(v2_cartesian); + // ROOT::Math::PxPyPzEVector q12_lcms_cartesian = bst_z(q12_cartesian); + // LOGF(info, "q12.Pz() = %f, q12_cartesian.Pz() = %f", q12.Pz(), q12_cartesian.Pz()); + // LOGF(info, "v1.Pz() = %f, v2.Pz() = %f", v1.Pz(), v2.Pz()); + // LOGF(info, "v1_lcms_cartesian.Pz() = %f, v2_lcms_cartesian.Pz() = %f", v1_lcms_cartesian.Pz(), v2_lcms_cartesian.Pz()); + // LOGF(info, "q12_lcms_cartesian.Pz() = %f", q12_lcms_cartesian.Pz()); + // LOGF(info, "q_3d_lcms.Dot(uv_out) = %f, q_3d_lcms.Dot(uv_side) = %f, q_3d.Dot(uv_out) = %f, q_3d.Dot(uv_side) = %f", q_3d_lcms.Dot(uv_out), q_3d_lcms.Dot(uv_side), q_3d.Dot(uv_out), q_3d.Dot(uv_side)); + // LOGF(info, "q12_lcms.Pz() = %f, q_3d_lcms.Dot(uv_long) = %f", q12_lcms.Pz(), q_3d_lcms.Dot(uv_long)); + // ROOT::Math::PxPyPzEVector q12_lcms_tmp = bst_z(v1_cartesian) - bst_z(v2_cartesian); + // LOGF(info, "q12_lcms.Px() = %f, q12_lcms.Py() = %f, q12_lcms.Pz() = %f, q12_lcms_tmp.Px() = %f, q12_lcms_tmp.Py() = %f, q12_lcms_tmp.Pz() = %f", q12_lcms.Px(), q12_lcms.Py(), q12_lcms.Pz(), q12_lcms_tmp.Px(), q12_lcms_tmp.Py(), q12_lcms_tmp.Pz()); + // float qabs_lcms_tmp = q12_lcms.P(); + // LOGF(info, "qabs_lcms = %f, qabs_lcms_tmp = %f", qabs_lcms, qabs_lcms_tmp); + + if (cfgDo3D) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_3d"), fabs(qout_lcms), fabs(qside_lcms), fabs(qlong_lcms), kt, weight); // qosl can be [-inf, +inf] and CF is symmetric for pos and neg qosl. To reduce stat. unc. absolute value is taken here. + } else { + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { // identical particle femtoscopy + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), qinv, qabs_lcms, kt, weight); + } else { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), kstar, qabs_lcms, kt, weight); + } + } + } + + template + void runPairing(TCollisions const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TSubInfos1 const&, TSubInfos2 const&, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCut1 const& cut1, TCut2 const& cut2) + { + for (auto& collision : collisions) { + initCCDB(collision); + int ndiphoton = 0; + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + // if (collision.spherocity_ptunweighted() < cfgSpherocityMin || cfgSpherocityMax < collision.spherocity_ptunweighted()) { + // continue; + // } + // fRegistry.fill(HIST("Event/after/hSpherocity"), collision.spherocity_ptunweighted()); + } + const float eventplanes_2_for_mix[6] = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg()}; + float ep2 = eventplanes_2_for_mix[cfgEP2Estimator_for_Mix]; + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + + int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; + if (zbin < 0) { + zbin = 0; + } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { + zbin = static_cast(zvtx_bin_edges.size()) - 2; + } + + float centrality = centralities[cfgCentEstimator]; + int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; + if (centbin < 0) { + centbin = 0; + } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { + centbin = static_cast(cent_bin_edges.size()) - 2; + } + + int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; + if (epbin < 0) { + epbin = 0; + } else if (static_cast(ep_bin_edges.size()) - 2 < epbin) { + epbin = static_cast(ep_bin_edges.size()) - 2; + } + + int occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; + if (occbin < 0) { + occbin = 0; + } else if (static_cast(occ_bin_edges.size()) - 2 < occbin) { + occbin = static_cast(occ_bin_edges.size()) - 2; + } + + // LOGF(info, "collision.globalIndex() = %d, collision.posZ() = %f, centrality = %f, ep2 = %f, collision.trackOccupancyInTimeRange() = %d, zbin = %d, centbin = %d, epbin = %d, occbin = %d", collision.globalIndex(), collision.posZ(), centrality, ep2, collision.trackOccupancyInTimeRange(), zbin, centbin, epbin, occbin); + + std::tuple key_bin = std::make_tuple(zbin, centbin, epbin, occbin); + std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); + + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { + auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); + for (auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_coll, photons2_coll))) { + if (!cut1.template IsSelected(g1) || !cut2.template IsSelected(g2)) { + continue; + } + + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { // never happens. only for protection. + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + + float dz = g1.vz() - g2.vz(); + float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2)); + if (ggpaircuts.applydRdZ && std::pow(dz / ggpaircuts.cfgMinDeltaZ, 2) + std::pow(dr / ggpaircuts.cfgMinDeltaR, 2) < 1.f) { + continue; + } + + float deta_pos = pos1.eta() - pos2.eta(); + float dphi_pos = pos1.phi() - pos2.phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.eta() - ele2.eta(); + float dphi_ele = ele1.phi() - ele2.phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + + fRegistry.fill(HIST("Pair/same/hDeltaRDeltaZ"), dr, fabs(dz), 1.f); + fRegistry.fill(HIST("Pair/same/hDeltaEtaDeltaPhi"), pos1.phi() - pos2.phi(), pos1.eta() - pos2.eta(), 1.f); // distance between 2 LS tracks + fRegistry.fill(HIST("Pair/same/hDeltaEtaDeltaPhi"), ele1.phi() - ele2.phi(), ele1.eta() - ele2.eta(), 1.f); // distance between 2 LS tracks + + fillPairHistogram<0>(collision, v1, v2, 1.f); + ndiphoton++; + + std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); + std::pair pair_tmp_id2 = std::make_pair(ndf, g2.globalIndex()); + if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { + EMTrack g1tmp = EMTrack(ndf, g1.globalIndex(), collision.globalIndex(), g1.globalIndex(), g1.pt(), g1.eta(), g1.phi(), 0); + g1tmp.setConversionPointXYZ(g1.vx(), g1.vy(), g1.vz()); + g1tmp.setPositiveLegPtEtaPhiM(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + g1tmp.setNegativeLegPtEtaPhiM(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + emh1->AddTrackToEventPool(key_df_collision, g1tmp); + used_photonIds.emplace_back(pair_tmp_id1); + } + if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id2) == used_photonIds.end()) { + EMTrack g2tmp = EMTrack(ndf, g2.globalIndex(), collision.globalIndex(), g2.globalIndex(), g2.pt(), g2.eta(), g2.phi(), 0); + g2tmp.setConversionPointXYZ(g2.vx(), g2.vy(), g2.vz()); + g2tmp.setPositiveLegPtEtaPhiM(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + g2tmp.setNegativeLegPtEtaPhiM(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + emh1->AddTrackToEventPool(key_df_collision, g2tmp); + used_photonIds.emplace_back(pair_tmp_id2); + } + } // end of pairing loop + } else if constexpr (pairtype == ggHBTPairType::kEEEE) { + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + std::vector, std::pair>> used_pairs_per_collision; + used_pairs_per_collision.reserve(std::pow(positrons_per_collision.size() * electrons_per_collision.size(), 2)); + + for (auto& [pos1, ele1] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { + if (pos1.trackId() == ele1.trackId()) { // this is protection against pairing identical 2 tracks. // never happens. only for protection. + continue; + } + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut1.template IsSelectedTrack(pos1, collision) || !cut1.template IsSelectedTrack(ele1, collision)) { + continue; + } + } else { // cut-based + if (!cut1.template IsSelectedTrack(pos1, collision) || !cut1.template IsSelectedTrack(ele1, collision)) { + continue; + } + } + if (!cut1.IsSelectedPair(pos1, ele1, d_bz)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v_pos1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v_ele1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v1_ee = v_pos1 + v_ele1; + float dca_pos1_3d = dca3DinSigma(pos1); + float dca_ele1_3d = dca3DinSigma(ele1); + float dca1_3d = std::sqrt((dca_pos1_3d * dca_pos1_3d + dca_ele1_3d * dca_ele1_3d) / 2.); + float weight1 = 1.f; + if (cfgApplyWeightTTCA) { + weight1 = map_weight[std::make_pair(pos1.globalIndex(), ele1.globalIndex())]; + } + + for (auto& [pos2, ele2] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { + if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. // never happens. only for protection. + continue; + } + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { + continue; + } + } else { // cut-based + if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { + continue; + } + } + if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { + continue; + } + + if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { // this comparison is valid in the same collision. + continue; + } + + float weight2 = 1.f; + if (cfgApplyWeightTTCA) { + weight2 = map_weight[std::make_pair(pos2.globalIndex(), ele2.globalIndex())]; + } + + float dca_pos2_3d = dca3DinSigma(pos2); + float dca_ele2_3d = dca3DinSigma(ele2); + float dca2_3d = std::sqrt((dca_pos2_3d * dca_pos2_3d + dca_ele2_3d * dca_ele2_3d) / 2.); + + ROOT::Math::PtEtaPhiMVector v_pos2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v_ele2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2_ee = v_pos2 + v_ele2; + + std::pair pair_tmp = std::make_pair(std::make_pair(pos1.trackId(), ele1.trackId()), std::make_pair(pos2.trackId(), ele2.trackId())); + if (std::find(used_pairs_per_collision.begin(), used_pairs_per_collision.end(), pair_tmp) == used_pairs_per_collision.end()) { + float deta_pos = pos1.eta() - pos2.eta(); + float dphi_pos = pos1.phi() - pos2.phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.eta() - ele2.eta(); + float dphi_ele = ele1.phi() - ele2.phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + + fRegistry.fill(HIST("Pair/same/hDeltaEtaDeltaPhi"), dphi_pos, deta_pos, weight1 * weight2); // distance between 2 LS tracks + fRegistry.fill(HIST("Pair/same/hDeltaEtaDeltaPhi"), dphi_ele, deta_ele, weight1 * weight2); // distance between 2 LS tracks + fillPairHistogram<0>(collision, v1_ee, v2_ee, weight1 * weight2); + ndiphoton++; + used_pairs_per_collision.emplace_back(std::make_pair(pair_tmp.first, pair_tmp.second)); + used_pairs_per_collision.emplace_back(std::make_pair(pair_tmp.second, pair_tmp.first)); + + std::tuple tuple_tmp_id1 = std::make_tuple(ndf, collision.globalIndex(), pos1.globalIndex(), ele1.globalIndex()); + std::tuple tuple_tmp_id2 = std::make_tuple(ndf, collision.globalIndex(), pos2.globalIndex(), ele2.globalIndex()); + if (std::find(used_dileptonIds.begin(), used_dileptonIds.end(), tuple_tmp_id1) == used_dileptonIds.end()) { + std::vector possibleIds_pos1; + std::vector possibleIds_ele1; + std::copy(pos1.ambiguousElectronsIds().begin(), pos1.ambiguousElectronsIds().end(), std::back_inserter(possibleIds_pos1)); + std::copy(ele1.ambiguousElectronsIds().begin(), ele1.ambiguousElectronsIds().end(), std::back_inserter(possibleIds_ele1)); + + EMTrack g1pair = EMTrack(ndf, -1, collision.globalIndex(), -1, v1_ee.Pt(), v1_ee.Eta(), v1_ee.Phi(), v1_ee.M()); + g1pair.setGlobalPosId(pos1.globalIndex()); + g1pair.setGlobalNegId(ele1.globalIndex()); + g1pair.setPairDca3DinSigmaOTF(dca1_3d); + g1pair.setPositiveLegPtEtaPhiM(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + g1pair.setNegativeLegPtEtaPhiM(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + g1pair.setAmbPosLegSelfIds(possibleIds_pos1); + g1pair.setAmbNegLegSelfIds(possibleIds_ele1); + emh1->AddTrackToEventPool(key_df_collision, g1pair); + used_dileptonIds.emplace_back(tuple_tmp_id1); + } + if (std::find(used_dileptonIds.begin(), used_dileptonIds.end(), tuple_tmp_id2) == used_dileptonIds.end()) { + std::vector possibleIds_pos2; + std::vector possibleIds_ele2; + std::copy(pos2.ambiguousElectronsIds().begin(), pos2.ambiguousElectronsIds().end(), std::back_inserter(possibleIds_pos2)); + std::copy(ele2.ambiguousElectronsIds().begin(), ele2.ambiguousElectronsIds().end(), std::back_inserter(possibleIds_ele2)); + + EMTrack g2pair = EMTrack(ndf, -1, collision.globalIndex(), -1, v2_ee.Pt(), v2_ee.Eta(), v2_ee.Phi(), v2_ee.M()); + g2pair.setGlobalPosId(pos2.globalIndex()); + g2pair.setGlobalNegId(ele2.globalIndex()); + g2pair.setPairDca3DinSigmaOTF(dca2_3d); + g2pair.setPositiveLegPtEtaPhiM(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + g2pair.setNegativeLegPtEtaPhiM(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + g2pair.setAmbPosLegSelfIds(possibleIds_pos2); + g2pair.setAmbNegLegSelfIds(possibleIds_ele2); + emh1->AddTrackToEventPool(key_df_collision, g2pair); + used_dileptonIds.emplace_back(tuple_tmp_id2); + } + } + } // end of g2 loop + } // end of g1 loop + used_pairs_per_collision.clear(); + used_pairs_per_collision.shrink_to_fit(); + } else if constexpr (pairtype == ggHBTPairType::kPCMEE) { + auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + + for (auto& g1 : photons1_per_collision) { + if (!cut1.template IsSelected(g1)) { + continue; + } + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + ROOT::Math::PtEtaPhiMVector v1_gamma(g1.pt(), g1.eta(), g1.phi(), 0.); + + for (auto& [pos2, ele2] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { + if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. // never happens. only for protection. + continue; + } + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { + continue; + } + } else { // cut-based + if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { + continue; + } + } + if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { + continue; + } + + if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { // this comparison is valid in the same collision. + continue; + } + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(pos2.globalIndex(), ele2.globalIndex())]; + } + // LOGF(info, "g1.globalIndex() = %d, map_weight[std::make_pair(%d, %d)] = %f", g1.globalIndex(), pos2.globalIndex(), ele2.globalIndex(), weight); + + float dca_pos2_3d = dca3DinSigma(pos2); + float dca_ele2_3d = dca3DinSigma(ele2); + float dca2_3d = std::sqrt((dca_pos2_3d * dca_pos2_3d + dca_ele2_3d * dca_ele2_3d) / 2.); + + ROOT::Math::PtEtaPhiMVector v_pos2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v_ele2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2_ee = v_pos2 + v_ele2; + + float deta_pos = pos1.eta() - pos2.eta(); + float dphi_pos = pos1.phi() - pos2.phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.eta() - ele2.eta(); + float dphi_ele = ele1.phi() - ele2.phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + + fRegistry.fill(HIST("Pair/same/hDeltaEtaDeltaPhi"), dphi_pos, deta_pos, weight); + fRegistry.fill(HIST("Pair/same/hDeltaEtaDeltaPhi"), dphi_ele, deta_ele, weight); + + fillPairHistogram<0>(collision, v1_gamma, v2_ee, weight); + ndiphoton++; + std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); + std::tuple tuple_tmp_id2 = std::make_tuple(ndf, collision.globalIndex(), pos2.globalIndex(), ele2.globalIndex()); + if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { + EMTrack g1tmp = EMTrack(ndf, g1.globalIndex(), collision.globalIndex(), g1.globalIndex(), g1.pt(), g1.eta(), g1.phi(), 0); + g1tmp.setConversionPointXYZ(g1.vx(), g1.vy(), g1.vz()); + g1tmp.setPositiveLegPtEtaPhiM(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + g1tmp.setNegativeLegPtEtaPhiM(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + emh1->AddTrackToEventPool(key_df_collision, g1tmp); + used_photonIds.emplace_back(pair_tmp_id1); + } + if (std::find(used_dileptonIds.begin(), used_dileptonIds.end(), tuple_tmp_id2) == used_dileptonIds.end()) { + EMTrack g2pair = EMTrack(ndf, -1, collision.globalIndex(), -1, v2_ee.Pt(), v2_ee.Eta(), v2_ee.Phi(), v2_ee.M()); + g2pair.setPairDca3DinSigmaOTF(dca2_3d); + g2pair.setPositiveLegPtEtaPhiM(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + g2pair.setNegativeLegPtEtaPhiM(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + emh2->AddTrackToEventPool(key_df_collision, g2pair); + used_dileptonIds.emplace_back(tuple_tmp_id2); + } + } // end of g2 loop + } // end of g1 loop + } + + // event mixing + if (!cfgDoMix || !(ndiphoton > 0)) { + continue; + } + + // make a vector of selected photons in this collision. + auto selected_photons1_in_this_event = emh1->GetTracksPerCollision(key_df_collision); + auto selected_photons2_in_this_event = emh2->GetTracksPerCollision(key_df_collision); + + auto collisionIds1_in_mixing_pool = emh1->GetCollisionIdsFromEventPool(key_bin); + auto collisionIds2_in_mixing_pool = emh2->GetCollisionIdsFromEventPool(key_bin); + + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { + for (auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int64_t mix_collisionId = mix_dfId_collisionId.second; + + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto photons1_from_event_pool = emh1->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "Do event mixing: current event (%d, %d), ngamma = %d | event pool (%d, %d), ngamma = %d", ndf, collision.globalIndex(), selected_photons1_in_this_event.size(), mix_dfId, mix_collisionId, photons1_from_event_pool.size()); + + for (auto& g1 : selected_photons1_in_this_event) { + for (auto& g2 : photons1_from_event_pool) { + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + + auto pos1 = g1.getPositiveLeg(); + auto ele1 = g1.getNegativeLeg(); + auto pos2 = g2.getPositiveLeg(); + auto ele2 = g2.getNegativeLeg(); + + float dz = g1.vz() - g2.vz(); + float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2)); + if (ggpaircuts.applydRdZ && std::pow(dz / ggpaircuts.cfgMinDeltaZ, 2) + std::pow(dr / ggpaircuts.cfgMinDeltaR, 2) < 1.f) { + continue; + } + + float deta_pos = pos1.Eta() - pos2.Eta(); + float dphi_pos = pos1.Phi() - pos2.Phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.Eta() - ele2.Eta(); + float dphi_ele = ele1.Phi() - ele2.Phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + + fRegistry.fill(HIST("Pair/mix/hDeltaRDeltaZ"), dr, fabs(dz), 1.f); + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_pos, deta_pos, 1.f); // distance between 2 LS tracks + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_ele, deta_ele, 1.f); // distance between 2 LS tracks + fillPairHistogram<1>(collision, v1, v2, 1.f); + } + } + } // end of loop over mixed event pool + } else if constexpr (pairtype == ggHBTPairType::kEEEE) { + for (auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int64_t mix_collisionId = mix_dfId_collisionId.second; + + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto photons1_from_event_pool = emh1->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "Do event mixing: current event (%d, %d), ngamma = %d | event pool (%d, %d), ngamma = %d", ndf, collision.globalIndex(), selected_photons1_in_this_event.size(), mix_dfId, mix_collisionId, photons1_from_event_pool.size()); + + for (auto& g1 : selected_photons1_in_this_event) { + for (auto& g2 : photons1_from_event_pool) { + auto v1amb_pos_Ids = g1.ambiguousPosLegIds(); + auto v1amb_neg_Ids = g1.ambiguousNegLegIds(); + auto v2amb_pos_Ids = g2.ambiguousPosLegIds(); + auto v2amb_neg_Ids = g2.ambiguousNegLegIds(); + + bool is_found_pos1 = std::find(v2amb_pos_Ids.begin(), v2amb_pos_Ids.end(), g1.globalIndexPos()) != v2amb_pos_Ids.end(); + bool is_found_neg1 = std::find(v2amb_neg_Ids.begin(), v2amb_neg_Ids.end(), g1.globalIndexPos()) != v2amb_neg_Ids.end(); + bool is_found_pos2 = std::find(v1amb_pos_Ids.begin(), v1amb_pos_Ids.end(), g2.globalIndexPos()) != v1amb_pos_Ids.end(); + bool is_found_neg2 = std::find(v1amb_neg_Ids.begin(), v1amb_neg_Ids.end(), g2.globalIndexPos()) != v1amb_neg_Ids.end(); + // LOGF(info, "is_found_pos1 = %d, is_found_neg1 = %d, is_found_pos2 = %d, is_found_neg2 = %d", is_found_pos1, is_found_neg1, is_found_pos2, is_found_neg2); + + auto pos1 = g1.getPositiveLeg(); + auto ele1 = g1.getNegativeLeg(); + auto pos2 = g2.getPositiveLeg(); + auto ele2 = g2.getNegativeLeg(); + + if ((g1.dfId() == g2.dfId()) && ((is_found_pos1 && is_found_pos2) || (is_found_neg1 && is_found_neg2))) { + // LOGF(info, "event id = %d: same track is found. t1.globalIndex() = %d, t1.sign() = %d, t1.pt() = %f, t1.eta() = %f, t1.phi() = %f, t2.globalIndex() = %d, t2.sign() = %d, t2.pt() = %f, t2.eta() = %f, t2.phi() = %f, deta = %f, dphi = %f (rad.)", ev_id, t1.globalIndex(), t1.sign(), t1.pt(), t1.eta(), t1.phi(), t2.globalIndex(), t2.sign(), t2.pt(), t2.eta(), t2.phi(), t1.eta() - t2.eta(), t1.phi() - t2.phi()); + continue; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), g1.mass()); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), g2.mass()); + + float deta_pos = pos1.Eta() - pos2.Eta(); + float dphi_pos = pos1.Phi() - pos2.Phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.Eta() - ele2.Eta(); + float dphi_ele = ele1.Phi() - ele2.Phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_pos, deta_pos, 1.f); // distance between 2 LS tracks + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_ele, deta_ele, 1.f); // distance between 2 LS tracks + fillPairHistogram<1>(collision, v1, v2, 1.f); + } + } + } // end of loop over mixed event pool + } else if constexpr (pairtype == ggHBTPairType::kPCMEE) { // [photon1 from event1, photon2 from event2] and [photon1 from event2, photon2 from event1] + for (auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int64_t mix_collisionId = mix_dfId_collisionId.second; + + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto photons2_from_event_pool = emh2->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "Do event mixing: current event (%d, %d), ngamma = %d | event pool (%d, %d), nll = %d", ndf, collision.globalIndex(), selected_photons1_in_this_event.size(), mix_dfId, mix_collisionId, photons2_from_event_pool.size()); + + for (auto& g1 : selected_photons1_in_this_event) { // PCM + for (auto& g2 : photons2_from_event_pool) { // dielectron + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.0); // keep v1 for PCM + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), g2.mass()); + + auto pos1 = g1.getPositiveLeg(); + auto ele1 = g1.getNegativeLeg(); + auto pos2 = g2.getPositiveLeg(); + auto ele2 = g2.getNegativeLeg(); + + float deta_pos = pos1.Eta() - pos2.Eta(); + float dphi_pos = pos1.Phi() - pos2.Phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.Eta() - ele2.Eta(); + float dphi_ele = ele1.Phi() - ele2.Phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_pos, deta_pos, 1.f); // distance between 2 LS tracks + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_ele, deta_ele, 1.f); // distance between 2 LS tracks + fillPairHistogram<1>(collision, v1, v2, 1.f); + } + } + } // end of loop over mixed event pool2 + + for (auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int64_t mix_collisionId = mix_dfId_collisionId.second; + + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto photons1_from_event_pool = emh1->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "Do event mixing: current event (%d, %d), nll = %d | event pool (%d, %d), ngamma = %d", ndf, collision.globalIndex(), selected_photons2_in_this_event.size(), mix_dfId, mix_collisionId, photons1_from_event_pool.size()); + + for (auto& g1 : selected_photons2_in_this_event) { // dielectron + for (auto& g2 : photons1_from_event_pool) { // PCM + ROOT::Math::PtEtaPhiMVector v1(g2.pt(), g2.eta(), g2.phi(), 0.0); // keep v1 for PCM + ROOT::Math::PtEtaPhiMVector v2(g1.pt(), g1.eta(), g1.phi(), g1.mass()); + + auto pos1 = g1.getPositiveLeg(); + auto ele1 = g1.getNegativeLeg(); + auto pos2 = g2.getPositiveLeg(); + auto ele2 = g2.getNegativeLeg(); + + float deta_pos = pos1.Eta() - pos2.Eta(); + float dphi_pos = pos1.Phi() - pos2.Phi(); + o2::math_utils::bringToPMPi(dphi_pos); + float deta_ele = ele1.Eta() - ele2.Eta(); + float dphi_ele = ele1.Phi() - ele2.Phi(); + o2::math_utils::bringToPMPi(dphi_ele); + if (ggpaircuts.applydEtadPhi && std::pow(deta_pos / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_pos / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + if (ggpaircuts.applydEtadPhi && std::pow(deta_ele / ggpaircuts.cfgMinDeltaEta, 2) + std::pow(dphi_ele / ggpaircuts.cfgMinDeltaPhi, 2) < 1.f) { + continue; + } + + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_pos, deta_pos, 1.f); // distance between 2 LS tracks + fRegistry.fill(HIST("Pair/mix/hDeltaEtaDeltaPhi"), dphi_ele, deta_ele, 1.f); // distance between 2 LS tracks + fillPairHistogram<1>(collision, v1, v2, 1.f); + } + } + } // end of loop over mixed event pool1 + } + + if (ndiphoton > 0) { + emh1->AddCollisionIdAtLast(key_bin, key_df_collision); + emh2->AddCollisionIdAtLast(key_bin, key_df_collision); + map_mixed_eventId_to_globalBC[key_df_collision] = collision.globalBC(); + } + } // end of collision loop + } + + std::map, float> map_weight; // -> float + template + void fillDileptonPairWeightMap(TCollisions const& collisions, TTracks const& tracks, TCut const& cut) + { + std::vector> passed_pairIds; + passed_pairIds.reserve(positrons.size() * electrons.size()); + + for (auto& collision : collisions) { + initCCDB(collision); + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + // if (collision.spherocity_ptunweighted() < cfgSpherocityMin || cfgSpherocityMax < collision.spherocity_ptunweighted()) { + // continue; + // } + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + + for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { + if (pos.trackId() == ele.trackId()) { // this is protection against pairing identical 2 tracks. // never happens. only for protection. + continue; + } + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(pos, collision) || !cut.template IsSelectedTrack(ele, collision)) { + continue; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(pos, collision) || !cut.template IsSelectedTrack(ele, collision)) { + continue; + } + } + if (!cut.IsSelectedPair(pos, ele, d_bz)) { + continue; + } + passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), ele.globalIndex())); + } // end of dielectron pairing loop + } // end of collision loop + + for (auto& pairId : passed_pairIds) { + auto t1 = tracks.rawIteratorAt(std::get<0>(pairId)); + auto t2 = tracks.rawIteratorAt(std::get<1>(pairId)); + // LOGF(info, "std::get<0>(pairId) = %d, std::get<1>(pairId) = %d, t1.globalIndex() = %d, t2.globalIndex() = %d", std::get<0>(pairId), std::get<1>(pairId), t1.globalIndex(), t2.globalIndex()); + + float n = 1.f; // include myself. + for (auto& ambId1 : t1.ambiguousElectronsIds()) { + for (auto& ambId2 : t2.ambiguousElectronsIds()) { + if (std::find(passed_pairIds.begin(), passed_pairIds.end(), std::make_pair(ambId1, ambId2)) != passed_pairIds.end()) { + // LOGF(info, "repeated pair is found. t1.globalIndex() = %d, t2.globalIndex() = %d, ambId1 = %d, ambId2 = %d", t1.globalIndex(), t2.globalIndex(), ambId1, ambId2); + n += 1.f; + } + } + } + map_weight[pairId] = 1.f / n; + + } // end of passed_pairIds loop + + passed_pairIds.clear(); + passed_pairIds.shrink_to_fit(); + } + + Filter trackFilter = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter = (dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < dielectroncuts.cfg_min_TPCNsigmaPi || dielectroncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); + Filter ttcaFilter = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + + Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0); + Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + + using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; + MyEMH* emh1 = nullptr; + MyEMH* emh2 = nullptr; + std::vector> used_photonIds; // + std::vector> used_dileptonIds; // + std::map, uint64_t> map_mixed_eventId_to_globalBC; + + SliceCache cache; + Preslice perCollision_pcm = aod::v0photonkf::emeventId; + Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_multiplicity = cfgNtracksPV08Min <= o2::aod::mult::multNTracksPV && o2::aod::mult::multNTracksPV < cfgNtracksPV08Max; + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + int ndf = 0; + void processAnalysis(FilteredMyCollisions const& collisions, Types const&... args) + { + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + runPairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut); + } else if constexpr (pairtype == ggHBTPairType::kPCMEE) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + auto emprimaryelectrons = std::get<2>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillDileptonPairWeightMap(collisions, emprimaryelectrons, fDielectronCut); + } + runPairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDielectronCut); + } else if constexpr (pairtype == ggHBTPairType::kEEEE) { + auto emprimaryelectrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillDileptonPairWeightMap(collisions, emprimaryelectrons, fDielectronCut); + } + runPairing(collisions, nullptr, nullptr, emprimaryelectrons, emprimaryelectrons, perCollision_electron, perCollision_electron, fDielectronCut, fDielectronCut); + } + ndf++; + } + PROCESS_SWITCH(PhotonHBT, processAnalysis, "pairing for analysis", false); + + using FilteredMyCollisionsWithSWT = soa::Filtered; + void processTriggerAnalysis(FilteredMyCollisionsWithSWT const& collisions, Types const&... args) + { + if constexpr (pairtype == ggHBTPairType::kPCMPCM) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + runPairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut); + } else if constexpr (pairtype == ggHBTPairType::kPCMEE) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + auto emprimaryelectrons = std::get<2>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillDileptonPairWeightMap(collisions, emprimaryelectrons, fDielectronCut); + } + runPairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDielectronCut); + } else if constexpr (pairtype == ggHBTPairType::kEEEE) { + auto emprimaryelectrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillDileptonPairWeightMap(collisions, emprimaryelectrons, fDielectronCut); + } + runPairing(collisions, nullptr, nullptr, emprimaryelectrons, emprimaryelectrons, perCollision_electron, perCollision_electron, fDielectronCut, fDielectronCut); + } + ndf++; + } + PROCESS_SWITCH(PhotonHBT, processTriggerAnalysis, "pairing analysis on trigger data", false); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(PhotonHBT, processDummy, "Dummy function", true); +}; + +#endif // PWGEM_DILEPTON_CORE_PHOTONHBT_H_ diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h new file mode 100644 index 00000000000..ed34bd4f6cb --- /dev/null +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -0,0 +1,676 @@ +// Copyright 2019-2020 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 electrons for QC. +// Please write to: daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ +#define PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ + +#include +#include +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyCollisionsWithSWT = soa::Join; +using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; + +using MyElectrons = soa::Join; +using MyElectron = MyElectrons::iterator; +using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectron = FilteredMyElectrons::iterator; + +using MyMuons = soa::Join; +using MyMuon = MyMuons::iterator; +using FilteredMyMuons = soa::Filtered; +using FilteredMyMuon = FilteredMyMuons::iterator; + +template +struct SingleTrackQC { + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult + Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + Configurable cfgUseDCAxy{"cfgUseDCAxy", false, "flag to use DCAxy, instead of DCA3D"}; + + ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "max eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "dimuoncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + } dimuoncuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; // 1 HistogramRegistry can keep up to 512 histograms + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + + ~SingleTrackQC() + { + if (eid_bdt) { + delete eid_bdt; + } + } + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; + const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; + const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; + std::string dca_axis_title = "DCA_{e}^{3D} (#sigma)"; + if (cfgUseDCAxy) { + dca_axis_title = "DCA_{e}^{XY} (#sigma)"; + } + const AxisSpec axis_dca{{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, dca_axis_title}; + + // track info + fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); + fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/positive/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/positive/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); + fRegistry.add("Track/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.addClone("Track/positive/", "Track/negative/"); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; + const AxisSpec axis_eta{25, -4.5, -2.0, "#eta_{#mu}"}; + const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; + const AxisSpec axis_dca{{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA_{#mu}^{XY} (#sigma)"}; + + // track info + fRegistry.add("Track/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); + fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); + fRegistry.add("Track/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/positive/hDCAxySigma", "DCA x vs. y;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/positive/hDCAxRes_Pt", "DCA_{x} resolution vs. pT;p_{T} (GeV/c);DCA_{x} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/positive/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/positive/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); + fRegistry.add("Track/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); + fRegistry.add("Track/positive/hPDCA", "pDCA;p_{T} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); + fRegistry.add("Track/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); + fRegistry.addClone("Track/positive/", "Track/negative/"); + } + } + + int mRunNumber; + void init(InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + DefineEMEventCut(); + DefineDielectronCut(); + DefineDimuonCut(); + addhistograms(); + mRunNumber = 0; + + if (doprocessQC_TriggeredData) { + fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + mRunNumber = collision.runNumber(); + + if constexpr (isTriggerAnalysis) { + LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", cfg_swt_name.value); + LOGF(info, "total inspected TVX events = %d in run number %d", collision.nInspectedTVX(), collision.runNumber()); + fRegistry.fill(HIST("Event/hNInspectedTVX"), collision.runNumber(), collision.nInspectedTVX()); + } + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(dielectroncuts.cfg_min_phi_track, dielectroncuts.cfg_max_phi_track); + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(0, 16); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDielectronCut + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // for pair + fDimuonCut.SetMassRange(dimuoncuts.cfg_min_mass, dimuoncuts.cfg_max_mass); + fDimuonCut.SetPairPtRange(dimuoncuts.cfg_min_pair_pt, dimuoncuts.cfg_max_pair_pt); + fDimuonCut.SetPairDCAxyRange(dimuoncuts.cfg_min_pair_dcaxy, dimuoncuts.cfg_max_pair_dcaxy); // DCAxy in cm + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, 1e10f); + fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_eta_track, dimuoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackPhiRange(dimuoncuts.cfg_min_phi_track, dimuoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(dimuoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 16); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + } + + template + void fillElectronInfo(TTrack const& track) + { + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[track.globalIndex()]; + } + + float dca = dca3DinSigma(track); + if (cfgUseDCAxy) { + dca = abs(track.dcaXY() / std::sqrt(track.cYY())); + } + + if (track.sign() > 0) { + fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca, weight); + fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/positive/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/positive/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/positive/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/positive/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/positive/hITSClusterMap"), track.itsClusterMap()); + + fRegistry.fill(HIST("Track/positive/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/positive/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + } else { + fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca, weight); + fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/negative/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/negative/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/negative/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/negative/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/negative/hITSClusterMap"), track.itsClusterMap()); + + fRegistry.fill(HIST("Track/negative/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/negative/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + } + } + + template + void fillMuonInfo(TTrack const& track) + { + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[track.globalIndex()]; + } + float dca_xy = fwdDcaXYinSigma(track); + if (track.sign() > 0) { + fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); + fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/positive/hTrackType"), track.trackType()); + fRegistry.fill(HIST("Track/positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/positive/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); + fRegistry.fill(HIST("Track/positive/hNclsMCH"), track.nClusters()); + fRegistry.fill(HIST("Track/positive/hNclsMFT"), track.nClustersMFT()); + fRegistry.fill(HIST("Track/positive/hPDCA"), track.pt(), track.pDca()); + fRegistry.fill(HIST("Track/positive/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/positive/hMFTClusterMap"), track.mftClusterMap()); + } else { + fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); + fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/negative/hTrackType"), track.trackType()); + fRegistry.fill(HIST("Track/negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/negative/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); + fRegistry.fill(HIST("Track/negative/hNclsMCH"), track.nClusters()); + fRegistry.fill(HIST("Track/negative/hNclsMFT"), track.nClustersMFT()); + fRegistry.fill(HIST("Track/negative/hPDCA"), track.pt(), track.pDca()); + fRegistry.fill(HIST("Track/negative/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/negative/hMFTClusterMap"), track.mftClusterMap()); + } + } + + template + void runQC(TCollisions const& collisions, TTracks const& tracks, TPreslice const& perCollision, TCut const& cut) + { + for (auto& collision : collisions) { + initCCDB(collision); + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + } + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + + auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& track : tracks_per_coll) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(track, collision)) { + continue; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(track)) { + continue; + } + } + fillElectronInfo(track); + } // end of track loop + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& track : tracks_per_coll) { + if (!cut.template IsSelectedTrack(track)) { + continue; + } + fillMuonInfo(track); + } // end of track loop + } + } // end of collision loop + } + + std::unordered_map map_weight; + template + void fillTrackWeightMap(TCollisions const& collisions, TTracks const& tracks, TPreslice const& perCollision, TCut const& cut) + { + std::vector passed_trackIds; + passed_trackIds.reserve(tracks.size()); + for (auto& collision : collisions) { + initCCDB(collision); + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& track : tracks_per_coll) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(track, collision)) { + continue; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(track)) { + continue; + } + } + passed_trackIds.emplace_back(track.globalIndex()); + } // end of track loop + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& track : tracks_per_coll) { + if (!cut.template IsSelectedTrack(track)) { + continue; + } + passed_trackIds.emplace_back(track.globalIndex()); + } // end of track loop + } + } // end of collision loop + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& trackId : passed_trackIds) { + auto track = tracks.rawIteratorAt(trackId); + auto ambIds = track.ambiguousElectronsIds(); + float n = 1.f; // include myself. + for (auto& ambId : ambIds) { + if (std::find(passed_trackIds.begin(), passed_trackIds.end(), ambId) != passed_trackIds.end()) { + n += 1.f; + } + } + map_weight[trackId] = 1.f / n; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& trackId : passed_trackIds) { + auto track = tracks.rawIteratorAt(trackId); + auto ambIds = track.ambiguousMuonsIds(); + float n = 1.f; // include myself. + for (auto& ambId : ambIds) { + if (std::find(passed_trackIds.begin(), passed_trackIds.end(), ambId) != passed_trackIds.end()) { + n += 1.f; + } + } + map_weight[trackId] = 1.f / n; + } + } + + passed_trackIds.clear(); + passed_trackIds.shrink_to_fit(); + } + + SliceCache cache; + Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter_electron = (dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < dielectroncuts.cfg_min_TPCNsigmaPi || dielectroncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + + Preslice perCollision_muon = aod::emprimarymuon::emeventId; + Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_multiplicity = cfgNtracksPV08Min <= o2::aod::mult::multNTracksPV && o2::aod::mult::multNTracksPV < cfgNtracksPV08Max; + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + void processQC(FilteredMyCollisions const& collisions, Types const&... args) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto electrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, electrons, perCollision_electron, fDielectronCut); + } + runQC(collisions, electrons, perCollision_electron, fDielectronCut); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto muons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, muons, perCollision_muon, fDimuonCut); + } + runQC(collisions, muons, perCollision_muon, fDimuonCut); + } + + map_weight.clear(); + } + PROCESS_SWITCH(SingleTrackQC, processQC, "run single track QC", true); + + using FilteredMyCollisionsWithSWT = soa::Filtered; + void processQC_TriggeredData(FilteredMyCollisionsWithSWT const& collisions, Types const&... args) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto electrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, electrons, perCollision_electron, fDielectronCut); + } + runQC(collisions, electrons, perCollision_electron, fDielectronCut); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto muons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, muons, perCollision_muon, fDimuonCut); + } + runQC(collisions, muons, perCollision_muon, fDimuonCut); + } + + map_weight.clear(); + } + PROCESS_SWITCH(SingleTrackQC, processQC_TriggeredData, "run single track QC on triggered data", false); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(SingleTrackQC, processDummy, "Dummy function", false); +}; +#endif // PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h new file mode 100644 index 00000000000..0957e6e6d86 --- /dev/null +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -0,0 +1,940 @@ +// Copyright 2019-2020 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 electrons for QC in MC. +// Please write to: daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ +#define PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ + +#include +#include +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCElectrons = soa::Join; +using MyMCElectron = MyMCElectrons::iterator; +using FilteredMyMCElectrons = soa::Filtered; + +using MyMCMuons = soa::Join; +using MyMCMuon = MyMCMuons::iterator; +using FilteredMyMCMuons = soa::Filtered; + +using MySmearedElectrons = soa::Join; +using MySmearedElectron = MySmearedElectrons::iterator; + +using MySmearedMuons = soa::Join; +using MySmearedMuon = MySmearedMuons::iterator; + +template +struct SingleTrackQCMC { + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; + Configurable cfgFillQA{"cfgFillQA", false, "flag to fill QA histograms"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + Configurable cfgUseDCAxy{"cfgUseDCAxy", false, "flag to use DCAxy, instead of DCA3D"}; + + ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "max eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "dimuoncut_group"; + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + } dimuoncuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + + struct : ConfigurableGroup { + std::string prefix = "mctrackcut_group"; + Configurable min_mcPt{"min_mcPt", 0.2, "min. MC pT"}; + Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT"}; + Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta"}; + Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta"}; + } mctrackcuts; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; // 1 HistogramRegistry can keep up to 512 histograms + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + static constexpr std::string_view lepton_source_types[9] = {"lf/", "Photon/", "PromptJPsi/", "NonPromptJPsi/", "PromptPsi2S/", "NonPromptPsi2S/", "c2l/", "b2l/", "b2c2l/"}; + + ~SingleTrackQCMC() + { + if (eid_bdt) { + delete eid_bdt; + } + } + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; + const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; + const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; + const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; + std::string dca_axis_title = "DCA_{e}^{3D} (#sigma)"; + if (cfgUseDCAxy) { + dca_axis_title = "DCA_{e}^{XY} (#sigma)"; + } + const AxisSpec axis_dca{{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, dca_axis_title}; + + // generated info + fRegistry.add("Generated/lf/hs", "gen. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); + fRegistry.addClone("Generated/lf/", "Generated/PromptJPsi/"); + fRegistry.addClone("Generated/lf/", "Generated/NonPromptJPsi/"); + fRegistry.addClone("Generated/lf/", "Generated/PromptPsi2S/"); + fRegistry.addClone("Generated/lf/", "Generated/NonPromptPsi2S/"); + fRegistry.addClone("Generated/lf/", "Generated/c2l/"); + fRegistry.addClone("Generated/lf/", "Generated/b2l/"); + fRegistry.addClone("Generated/lf/", "Generated/b2c2l/"); + + // track info + fRegistry.add("Track/lf/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + if (cfgFillQA) { + fRegistry.add("Track/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/lf/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/lf/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/lf/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/lf/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/lf/positive/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/lf/positive/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/lf/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/lf/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/lf/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/lf/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/lf/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/lf/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/lf/positive/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("Track/lf/positive/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + fRegistry.add("Track/lf/positive/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + } + fRegistry.addClone("Track/lf/positive/", "Track/lf/negative/"); + fRegistry.addClone("Track/lf/", "Track/Photon/"); // this is not for efficiency! only for contamination. We don't store generated photon conversions. + fRegistry.addClone("Track/lf/", "Track/PromptJPsi/"); + fRegistry.addClone("Track/lf/", "Track/NonPromptJPsi/"); + fRegistry.addClone("Track/lf/", "Track/PromptPsi2S/"); + fRegistry.addClone("Track/lf/", "Track/NonPromptPsi2S/"); + fRegistry.addClone("Track/lf/", "Track/c2l/"); + fRegistry.addClone("Track/lf/", "Track/b2l/"); + fRegistry.addClone("Track/lf/", "Track/b2c2l/"); + + if (cfgFillQA) { + fRegistry.add("Track/PID/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/PID/positive/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/PID/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); + fRegistry.add("Track/PID/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.addClone("Track/PID/positive/", "Track/PID/negative/"); + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; + const AxisSpec axis_eta{25, -4.5, -2.0, "#eta_{#mu}"}; + const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; + const AxisSpec axis_dca{{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA_{#mu}^{XY} (#sigma)"}; + const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; + + // generated info + fRegistry.add("Generated/lf/hs", "gen. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); + fRegistry.addClone("Generated/lf/", "Generated/PromptJPsi/"); + fRegistry.addClone("Generated/lf/", "Generated/NonPromptJPsi/"); + fRegistry.addClone("Generated/lf/", "Generated/PromptPsi2S/"); + fRegistry.addClone("Generated/lf/", "Generated/NonPromptPsi2S/"); + fRegistry.addClone("Generated/lf/", "Generated/c2l/"); + fRegistry.addClone("Generated/lf/", "Generated/b2l/"); + fRegistry.addClone("Generated/lf/", "Generated/b2c2l/"); + + // track info + fRegistry.add("Track/lf/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + if (cfgFillQA) { + fRegistry.add("Track/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/lf/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); + fRegistry.add("Track/lf/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/lf/positive/hDCAxySigma", "DCA x vs. y;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/lf/positive/hDCAxRes_Pt", "DCA_{x} resolution vs. pT;p_{T} (GeV/c);DCA_{x} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/lf/positive/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/lf/positive/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); + fRegistry.add("Track/lf/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); + fRegistry.add("Track/lf/positive/hPDCA", "pDCA;p_{T} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); + fRegistry.add("Track/lf/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/lf/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/lf/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/lf/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); + fRegistry.add("Track/lf/positive/hPtGen_DeltaPtOverPtGen", "muon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("Track/lf/positive/hPtGen_DeltaEta", "muon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + fRegistry.add("Track/lf/positive/hPtGen_DeltaPhi", "muon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + } + fRegistry.addClone("Track/lf/positive/", "Track/lf/negative/"); + fRegistry.addClone("Track/lf/", "Track/Photon/"); // this is not for efficiency! only for contamination. We don't store generated photon conversions. + fRegistry.addClone("Track/lf/", "Track/PromptJPsi/"); + fRegistry.addClone("Track/lf/", "Track/NonPromptJPsi/"); + fRegistry.addClone("Track/lf/", "Track/PromptPsi2S/"); + fRegistry.addClone("Track/lf/", "Track/NonPromptPsi2S/"); + fRegistry.addClone("Track/lf/", "Track/c2l/"); + fRegistry.addClone("Track/lf/", "Track/b2l/"); + fRegistry.addClone("Track/lf/", "Track/b2c2l/"); + } + } + + int pdg_lepton = 0; + void init(InitContext&) + { + if (doprocessQCMC && doprocessQCMC_Smeared) { + LOGF(fatal, "Cannot enable processQCMC and processQCMC_Smeared at the same time. Please choose one."); + } + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + DefineEMEventCut(); + addhistograms(); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pdg_lepton = 11; + DefineDielectronCut(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + pdg_lepton = 13; + DefineDimuonCut(); + } + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(dielectroncuts.cfg_min_phi_track, dielectroncuts.cfg_max_phi_track); + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(0, 16); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, 1e10f); + fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_eta_track, dimuoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackPhiRange(dimuoncuts.cfg_min_phi_track, dimuoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(dimuoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 16); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + } + + template + bool isInAcceptance(T const& lepton) + { + float pt = 0.f, eta = 0.f; + if constexpr (isSmeared) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pt = lepton.ptSmeared(); + eta = lepton.etaSmeared(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + pt = lepton.ptSmeared_sa_muon(); + eta = lepton.etaSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt = lepton.ptSmeared_gl_muon(); + eta = lepton.etaSmeared_gl_muon(); + } else { + pt = lepton.pt(); + eta = lepton.eta(); + } + } + } else { + pt = lepton.pt(); + eta = lepton.eta(); + } + + if ((mctrackcuts.min_mcPt < pt && pt < mctrackcuts.max_mcPt) && (mctrackcuts.min_mcEta < eta && eta < mctrackcuts.max_mcEta)) { + return true; + } else { + return false; + } + } + + template + void fillTrackInfo(TTrack const& track) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fillElectronInfo(track); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + fillMuonInfo(track); + } + } + + template + void fillElectronInfo(TTrack const& track) + { + auto mctrack = track.template emmcparticle_as(); + float dca = dca3DinSigma(track); + if (cfgUseDCAxy) { + dca = abs(track.dcaXY() / std::sqrt(track.cYY())); + } + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[track.globalIndex()]; + } + // LOGF(info, "map_weight[%d] = %f", track.globalIndex(), weight); + + if (track.sign() > 0) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca, -mctrack.pdgCode() / pdg_lepton, weight); + if (cfgFillQA) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); + + fRegistry.fill(HIST("Track/PID/positive/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/PID/positive/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/PID/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); + } + } else { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca, -mctrack.pdgCode() / pdg_lepton, weight); + if (cfgFillQA) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); + + fRegistry.fill(HIST("Track/PID/negative/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/PID/negative/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/PID/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); + } + } + } + + template + void fillMuonInfo(TTrack const& track) + { + auto mctrack = track.template emmcparticle_as(); + float dca_xy = fwdDcaXYinSigma(track); + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[track.globalIndex()]; + } + // LOGF(info, "map_weight[%d] = %f", track.globalIndex(), weight); + + if (track.sign() > 0) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); + if (cfgFillQA) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTrackType"), track.trackType()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsMCH"), track.nClusters()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsMFT"), track.nClustersMFT()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPDCA"), track.pt(), track.pDca()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hMFTClusterMap"), track.mftClusterMap()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); + } + } else { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); + if (cfgFillQA) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTrackType"), track.trackType()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsMCH"), track.nClusters()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsMFT"), track.nClustersMFT()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPDCA"), track.pt(), track.pDca()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hMFTClusterMap"), track.mftClusterMap()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); + } + } + } + + template + void runQCMC(TCollisions const& collisions, TTracks const& tracks, TPreslice const& perCollision, TCut const& cut, TMCCollisions const&, TMCParticles const& mcparticles) + { + for (auto& collision : collisions) { + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + // auto mccollision = collision.template emmcevent_as(); + // if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + // continue; + // } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); + + for (auto& track : tracks_per_coll) { + auto mctrack = track.template emmcparticle_as(); + if (abs(mctrack.pdgCode()) != pdg_lepton) { + continue; + } + + auto mccollision_from_track = mctrack.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_track.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + // if (mctrack.emmceventId() != collision.emmceventId()) { + // continue; + // } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(track, collision)) { + continue; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(track)) { + continue; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedTrack(track)) { + continue; + } + } + + if (!mctrack.has_mothers()) { + continue; + } + auto mcmother = mcparticles.iteratorAt(mctrack.mothersIds()[0]); + int pdg_mother = abs(mcmother.pdgCode()); + + if (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator()) { + if (pdg_mother == 111 || pdg_mother == 221 || pdg_mother == 331 || pdg_mother == 113 || pdg_mother == 223 || pdg_mother == 333) { + fillTrackInfo<0, TMCParticles>(track); + } else if (pdg_mother == 443) { + if (IsFromBeauty(mcmother, mcparticles) > 0) { // b is found in full decay chain. + fillTrackInfo<3, TMCParticles>(track); + } else { + fillTrackInfo<2, TMCParticles>(track); + } + } else if (pdg_mother == 100443) { + if (IsFromBeauty(mcmother, mcparticles) > 0) { // b is found in full decay chain. + fillTrackInfo<5, TMCParticles>(track); + } else { + fillTrackInfo<4, TMCParticles>(track); + } + } else if (IsFromBeauty(mctrack, mcparticles) > 0) { // b is found in full decay chain. + if (IsFromCharm(mctrack, mcparticles) > 0) { // c is found in full decay chain. + fillTrackInfo<8, TMCParticles>(track); + } else { + fillTrackInfo<7, TMCParticles>(track); + } + } else if (IsFromCharm(mctrack, mcparticles) > 0) { // c is found in full decay chain. Not from b. + fillTrackInfo<6, TMCParticles>(track); + } + } else { + fillTrackInfo<1, TMCParticles>(track); + } + } // end of track loop + + } // end of collision loop + + } // end of process + + template + void runGenInfo(TCollisions const& collisions, TMCLeptons const& leptonsMC, TMCCollisions const&, TMCParticles const& mcparticles) + { + // loop over mc stack and fill histograms for pure MC truth signals + // all MC tracks which belong to the MC event corresponding to the current reconstructed event + + for (auto& collision : collisions) { + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + auto mccollision = collision.template emmcevent_as(); + // LOGF(info, "mccollision.getGeneratorId() = %d", mccollision.getGeneratorId()); + // LOGF(info, "mccollision.getSubGeneratorId() = %d", mccollision.getSubGeneratorId()); + // LOGF(info, "mccollision.getSourceId() = %d", mccollision.getSourceId()); + if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + + auto leptonsMC_per_coll = leptonsMC.sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); + + for (auto& lepton : leptonsMC_per_coll) { + if (!(lepton.isPhysicalPrimary() || lepton.producedByGenerator())) { + continue; + } + if (!isInAcceptance(lepton)) { + continue; + } + if (!lepton.has_mothers()) { + continue; + } + auto mcmother = mcparticles.iteratorAt(lepton.mothersIds()[0]); + int pdg_mother = abs(mcmother.pdgCode()); + + float pt = 0.f, eta = 0.f, phi = 0.f; + if constexpr (isSmeared) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pt = lepton.ptSmeared(); + eta = lepton.etaSmeared(); + phi = lepton.phiSmeared(); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + pt = lepton.ptSmeared_sa_muon(); + eta = lepton.etaSmeared_sa_muon(); + phi = lepton.phiSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt = lepton.ptSmeared_gl_muon(); + eta = lepton.etaSmeared_gl_muon(); + phi = lepton.phiSmeared_gl_muon(); + } else { + pt = lepton.pt(); + eta = lepton.eta(); + phi = lepton.phi(); + } + } + } else { + pt = lepton.pt(); + eta = lepton.eta(); + phi = lepton.phi(); + } + + if (pdg_mother == 111 || pdg_mother == 221 || pdg_mother == 331 || pdg_mother == 113 || pdg_mother == 223 || pdg_mother == 333) { + fRegistry.fill(HIST("Generated/lf/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } else if (pdg_mother == 443) { + if (IsFromBeauty(mcmother, mcparticles) > 0) { // b is found in full decay chain. + fRegistry.fill(HIST("Generated/NonPromptJPsi/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } else { + fRegistry.fill(HIST("Generated/PromptJPsi/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } + } else if (pdg_mother == 100443) { + if (IsFromBeauty(mcmother, mcparticles) > 0) { // b is found in full decay chain. + fRegistry.fill(HIST("Generated/NonPromptPsi2S/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } else { + fRegistry.fill(HIST("Generated/PromptPsi2S/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } + } else if (IsFromBeauty(lepton, mcparticles) > 0) { // b is found in full decay chain. + if (IsFromCharm(lepton, mcparticles) > 0) { // c is found in full decay chain. + fRegistry.fill(HIST("Generated/b2c2l/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } else { + fRegistry.fill(HIST("Generated/b2l/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } + } else if (IsFromCharm(lepton, mcparticles) > 0) { // c is found in full decay chain. Not from b. + fRegistry.fill(HIST("Generated/c2l/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); + } + } + + } // end of collision loop + } + + std::unordered_map map_weight; // map of track global index -> weight + template + void fillTrackWeightMap(TCollisions const& collisions, TTracks const& tracks, TPreslice const& perCollision, TCut const& cut, TMCCollisions const&, TMCParticles const&) + { + std::vector passed_trackIds; + passed_trackIds.reserve(tracks.size()); + for (auto& collision : collisions) { + float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + // auto mccollision = collision.template emmcevent_as(); + // if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + // continue; + // } + + auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& track : tracks_per_coll) { + auto mctrack = track.template emmcparticle_as(); + auto mccollision_from_track = mctrack.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_track.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(track, collision)) { + continue; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(track)) { + continue; + } + } + passed_trackIds.emplace_back(track.globalIndex()); + } // end of track loop + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& track : tracks_per_coll) { + auto mctrack = track.template emmcparticle_as(); + auto mccollision_from_track = mctrack.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_track.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + if (!cut.template IsSelectedTrack(track)) { + continue; + } + passed_trackIds.emplace_back(track.globalIndex()); + } // end of track loop + } + } // end of collision loop + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + for (auto& trackId : passed_trackIds) { + auto track = tracks.rawIteratorAt(trackId); + auto ambIds = track.ambiguousElectronsIds(); + float n = 1.f; // include myself. + for (auto& ambId : ambIds) { + if (std::find(passed_trackIds.begin(), passed_trackIds.end(), ambId) != passed_trackIds.end()) { + n += 1.f; + } + } + map_weight[trackId] = 1.f / n; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + for (auto& trackId : passed_trackIds) { + auto track = tracks.rawIteratorAt(trackId); + auto ambIds = track.ambiguousMuonsIds(); + float n = 1.f; // include myself. + for (auto& ambId : ambIds) { + if (std::find(passed_trackIds.begin(), passed_trackIds.end(), ambId) != passed_trackIds.end()) { + n += 1.f; + } + } + map_weight[trackId] = 1.f / n; + } + } + + passed_trackIds.clear(); + passed_trackIds.shrink_to_fit(); + } + + SliceCache cache; + Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter_electron = (dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < dielectroncuts.cfg_min_TPCNsigmaPi || dielectroncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + + Preslice perCollision_muon = aod::emprimarymuon::emeventId; + Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_multiplicity = cfgNtracksPV08Min <= o2::aod::mult::multNTracksPV && o2::aod::mult::multNTracksPV < cfgNtracksPV08Max; + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + Partition electronsMC = nabs(o2::aod::mcparticle::pdgCode) == 11; // e+, e- + Partition muonsMC = nabs(o2::aod::mcparticle::pdgCode) == 13; // mu+, mu- + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + + void processQCMC(FilteredMyCollisions const& collisions, aod::EMMCEvents const& mccollisions, aod::EMMCParticles const& mcparticles, TLeptons const& tracks) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, tracks, perCollision_electron, fDielectronCut, mccollisions, mcparticles); + } + runQCMC(collisions, tracks, perCollision_electron, fDielectronCut, mccollisions, mcparticles); + runGenInfo(collisions, electronsMC, mccollisions, mcparticles); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles); + } + runQCMC(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles); + runGenInfo(collisions, muonsMC, mccollisions, mcparticles); + } + map_weight.clear(); + } + PROCESS_SWITCH(SingleTrackQCMC, processQCMC, "run single track QC MC", true); + + Partition electronsMC_smeared = nabs(o2::aod::mcparticle::pdgCode) == 11; // e+, e- + Partition muonsMC_smeared = nabs(o2::aod::mcparticle::pdgCode) == 13; // mu+, mu- + + void processQCMC_Smeared(FilteredMyCollisions const& collisions, aod::EMMCEvents const& mccollisions, TLeptons const& tracks, TSmearedMCParticles const& mcparticles_smeared) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, tracks, perCollision_electron, fDielectronCut, mccollisions, mcparticles_smeared); + } + runQCMC(collisions, tracks, perCollision_electron, fDielectronCut, mccollisions, mcparticles_smeared); + runGenInfo(collisions, electronsMC_smeared, mccollisions, mcparticles_smeared); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (cfgApplyWeightTTCA) { + fillTrackWeightMap(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles_smeared); + } + runQCMC(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles_smeared); + runGenInfo(collisions, muonsMC_smeared, mccollisions, mcparticles_smeared); + } + map_weight.clear(); + } + PROCESS_SWITCH(SingleTrackQCMC, processQCMC_Smeared, "run single track QC MC with smearing", false); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(SingleTrackQCMC, processDummy, "Dummy function", false); +}; + +#endif // PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h new file mode 100644 index 00000000000..27b99a6e9b3 --- /dev/null +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -0,0 +1,560 @@ +// Copyright 2019-2020 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. + +#include +#include +#include +#include "Common/Core/RecoDecay.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Qvectors.h" + +#ifndef PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ +#define PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ + +namespace o2::aod +{ + +namespace pwgem::dilepton::swt +{ +enum class swtAliases : int { // software trigger aliases for EM + kHighTrackMult = 0, + kHighFt0Mult, + kSingleE, + kLMeeIMR, + kLMeeHMR, + kDiElectron, + kSingleMuLow, + kSingleMuHigh, + kDiMuon, + kNaliases +}; + +const std::unordered_map aliasLabels = { + {"fHighTrackMult", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kHighTrackMult)}, + {"fHighFt0Mult", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kHighFt0Mult)}, + {"fSingleE", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kSingleE)}, + {"fLMeeIMR", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kLMeeIMR)}, + {"fLMeeHMR", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kLMeeHMR)}, + {"fDiElectron", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kDiElectron)}, + {"fSingleMuLow", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kSingleMuLow)}, + {"fSingleMuHigh", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kSingleMuHigh)}, + {"fDiMuon", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kDiMuon)}, +}; +} // namespace pwgem::dilepton::swt + +namespace emevent +{ +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); +DECLARE_SOA_BITMAP_COLUMN(SWTAliasTmp, swtaliastmp, 16); //! Bitmask of fired trigger aliases (see above for definitions) to be join to aod::Collisions for skimming +DECLARE_SOA_BITMAP_COLUMN(SWTAlias, swtalias, 16); //! Bitmask of fired trigger aliases (see above for definitions) to be join to aod::EMEvents for analysis +DECLARE_SOA_COLUMN(NInspectedTVX, nInspectedTVX, uint64_t); +DECLARE_SOA_COLUMN(NeeULS, neeuls, int); +DECLARE_SOA_COLUMN(NeeLSpp, neelspp, int); +DECLARE_SOA_COLUMN(NeeLSmm, neelsmm, int); +DECLARE_SOA_COLUMN(Bz, bz, float); //! kG +DECLARE_SOA_COLUMN(Q2xFT0M, q2xft0m, float); //! Qx for 2nd harmonics in FT0M +DECLARE_SOA_COLUMN(Q2yFT0M, q2yft0m, float); //! Qy for 2nd harmonics in FT0M +DECLARE_SOA_COLUMN(Q2xFT0A, q2xft0a, float); //! Qx for 2nd harmonics in FT0A (i.e. positive eta) +DECLARE_SOA_COLUMN(Q2yFT0A, q2yft0a, float); //! Qy for 2nd harmonics in FT0A (i.e. positive eta) +DECLARE_SOA_COLUMN(Q2xFT0C, q2xft0c, float); //! Qx for 2nd harmonics in FT0C (i.e. negative eta) +DECLARE_SOA_COLUMN(Q2yFT0C, q2yft0c, float); //! Qy for 2nd harmonics in FT0C (i.e. negative eta) +DECLARE_SOA_COLUMN(Q2xBPos, q2xbpos, float); //! Qx for 2nd harmonics in Barrel positive eta region +DECLARE_SOA_COLUMN(Q2yBPos, q2ybpos, float); //! Qy for 2nd harmonics in Barrel positive eta region +DECLARE_SOA_COLUMN(Q2xBNeg, q2xbneg, float); //! Qx for 2nd harmonics in Barrel negative eta region +DECLARE_SOA_COLUMN(Q2yBNeg, q2ybneg, float); //! Qy for 2nd harmonics in Barrel negative eta region +DECLARE_SOA_COLUMN(Q2xBTot, q2xbtot, float); //! Qx for 2nd harmonics in Barrel full eta region +DECLARE_SOA_COLUMN(Q2yBTot, q2ybtot, float); //! Qy for 2nd harmonics in Barrel full eta region +DECLARE_SOA_COLUMN(Q3xFT0M, q3xft0m, float); //! Qx for 3rd harmonics in FT0M +DECLARE_SOA_COLUMN(Q3yFT0M, q3yft0m, float); //! Qy for 3rd harmonics in FT0M +DECLARE_SOA_COLUMN(Q3xFT0A, q3xft0a, float); //! Qx for 3rd harmonics in FT0A (i.e. positive eta) +DECLARE_SOA_COLUMN(Q3yFT0A, q3yft0a, float); //! Qy for 3rd harmonics in FT0A (i.e. positive eta) +DECLARE_SOA_COLUMN(Q3xFT0C, q3xft0c, float); //! Qx for 3rd harmonics in FT0C (i.e. negative eta) +DECLARE_SOA_COLUMN(Q3yFT0C, q3yft0c, float); //! Qy for 3rd harmonics in FT0C (i.e. negative eta) +DECLARE_SOA_COLUMN(Q3xBPos, q3xbpos, float); //! Qx for 3rd harmonics in Barrel positive eta region +DECLARE_SOA_COLUMN(Q3yBPos, q3ybpos, float); //! Qy for 3rd harmonics in Barrel positive eta region +DECLARE_SOA_COLUMN(Q3xBNeg, q3xbneg, float); //! Qx for 3rd harmonics in Barrel negative eta region +DECLARE_SOA_COLUMN(Q3yBNeg, q3ybneg, float); //! Qy for 3rd harmonics in Barrel negative eta region +DECLARE_SOA_COLUMN(Q3xBTot, q3xbtot, float); //! Qx for 3rd harmonics in Barrel full eta region +DECLARE_SOA_COLUMN(Q3yBTot, q3ybtot, float); //! Qy for 3rd harmonics in Barrel full eta region +DECLARE_SOA_COLUMN(Q4xFT0M, q4xft0m, float); //! Qx for 4th harmonics in FT0M +DECLARE_SOA_COLUMN(Q4yFT0M, q4yft0m, float); //! Qy for 4th harmonics in FT0M +DECLARE_SOA_COLUMN(Q4xFT0A, q4xft0a, float); //! Qx for 4th harmonics in FT0A (i.e. positive eta) +DECLARE_SOA_COLUMN(Q4yFT0A, q4yft0a, float); //! Qy for 4th harmonics in FT0A (i.e. positive eta) +DECLARE_SOA_COLUMN(Q4xFT0C, q4xft0c, float); //! Qx for 4th harmonics in FT0C (i.e. negative eta) +DECLARE_SOA_COLUMN(Q4yFT0C, q4yft0c, float); //! Qy for 4th harmonics in FT0C (i.e. negative eta) +DECLARE_SOA_COLUMN(Q4xBPos, q4xbpos, float); //! Qx for 4th harmonics in Barrel positive eta region +DECLARE_SOA_COLUMN(Q4yBPos, q4ybpos, float); //! Qy for 4th harmonics in Barrel positive eta region +DECLARE_SOA_COLUMN(Q4xBNeg, q4xbneg, float); //! Qx for 4th harmonics in Barrel negative eta region +DECLARE_SOA_COLUMN(Q4yBNeg, q4ybneg, float); //! Qy for 4th harmonics in Barrel negative eta region +DECLARE_SOA_COLUMN(Q4xBTot, q4xbtot, float); //! Qx for 4th harmonics in Barrel full eta region +DECLARE_SOA_COLUMN(Q4yBTot, q4ybtot, float); //! Qy for 4th harmonics in Barrel full eta region +DECLARE_SOA_COLUMN(SpherocityPtWeighted, spherocity_ptweighted, float); //! transverse spherocity +DECLARE_SOA_COLUMN(SpherocityPtUnWeighted, spherocity_ptunweighted, float); //! transverse spherocity +DECLARE_SOA_COLUMN(NtrackSpherocity, ntspherocity, int); +DECLARE_SOA_COLUMN(IsSelected, isSelected, bool); + +DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint64_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::evsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::evsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::evsel::kNoITSROFrameBorder)); }); +DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0M, ep2ft0m, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0A, ep2ft0a, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0C, ep2ft0c, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP2BPos, ep2bpos, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP2BNeg, ep2bneg, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP2BTot, ep2btot, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP3FT0M, ep3ft0m, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP3FT0A, ep3ft0a, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP3FT0C, ep3ft0c, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP3BPos, ep3bpos, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP3BNeg, ep3bneg, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP3BTot, ep3btot, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP4FT0M, ep4ft0m, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP4FT0A, ep4ft0a, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP4FT0C, ep4ft0c, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP4BPos, ep4bpos, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP4BNeg, ep4bneg, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); +DECLARE_SOA_DYNAMIC_COLUMN(EP4BTot, ep4btot, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); +} // namespace emevent + +DECLARE_SOA_TABLE(EMEvents, "AOD", "EMEVENT", //! Main event information table + o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, + collision::PosX, collision::PosY, collision::PosZ, + collision::NumContrib, evsel::NumTracksInTimeRange, emevent::Sel8); +using EMEvent = EMEvents::iterator; + +DECLARE_SOA_TABLE(EMEventsCov, "AOD", "EMEVENTCOV", //! joinable to EMEvents + collision::CovXX, collision::CovXY, collision::CovXZ, collision::CovYY, collision::CovYZ, collision::CovZZ, collision::Chi2, o2::soa::Marker<1>); +using EMEventCov = EMEventsCov::iterator; + +DECLARE_SOA_TABLE(EMEventsBz, "AOD", "EMEVENTBZ", emevent::Bz); // joinable to EMEvents +using EMEventBz = EMEventsBz::iterator; + +DECLARE_SOA_TABLE(EMEventsMult, "AOD", "EMEVENTMULT", //! event multiplicity table, joinable to EMEvents + mult::MultFT0A, mult::MultFT0C, + mult::MultTPC, mult::MultNTracksPV, mult::MultNTracksPVeta1, mult::MultNTracksPVetaHalf, + mult::IsInelGt0, mult::IsInelGt1, mult::MultFT0M); +using EMEventMult = EMEventsMult::iterator; + +DECLARE_SOA_TABLE(EMEventsCent, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents + cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentNTPV); +using EMEventCent = EMEventsCent::iterator; + +DECLARE_SOA_TABLE(EMEventsQvec, "AOD", "EMEVENTQVEC", //! event q vector table, joinable to EMEvents + emevent::Q2xFT0M, emevent::Q2yFT0M, emevent::Q2xFT0A, emevent::Q2yFT0A, emevent::Q2xFT0C, emevent::Q2yFT0C, + emevent::Q2xBPos, emevent::Q2yBPos, emevent::Q2xBNeg, emevent::Q2yBNeg, emevent::Q2xBTot, emevent::Q2yBTot, + emevent::Q3xFT0M, emevent::Q3yFT0M, emevent::Q3xFT0A, emevent::Q3yFT0A, emevent::Q3xFT0C, emevent::Q3yFT0C, + emevent::Q3xBPos, emevent::Q3yBPos, emevent::Q3xBNeg, emevent::Q3yBNeg, emevent::Q3xBTot, emevent::Q3yBTot, + // emevent::Q4xFT0M, emevent::Q4yFT0M, emevent::Q4xFT0A, emevent::Q4yFT0A, emevent::Q4xFT0C, emevent::Q4yFT0C, + // emevent::Q4xBPos, emevent::Q4yBPos, emevent::Q4xBNeg, emevent::Q4yBNeg, emevent::Q4xBTot, emevent::Q4yBTot, + + // Dynamic columns + emevent::EP2FT0M, + emevent::EP2FT0A, + emevent::EP2FT0C, + emevent::EP2BPos, + emevent::EP2BNeg, + emevent::EP2BTot, + emevent::EP3FT0M, + emevent::EP3FT0A, + emevent::EP3FT0C, + emevent::EP3BPos, + emevent::EP3BNeg, + emevent::EP3BTot); +// emevent::EP4FT0M, +// emevent::EP4FT0A, +// emevent::EP4FT0C, +// emevent::EP4BPos, +// emevent::EP4BNeg, +// emevent::EP4BTot +using EMEventQvec = EMEventsQvec::iterator; + +DECLARE_SOA_TABLE(EMSWTriggerInfos, "AOD", "EMSWTRIGGERINFO", //! joinable to EMEvents + emevent::SWTAlias, emevent::NInspectedTVX); +using EMSWTriggerInfo = EMSWTriggerInfos::iterator; + +DECLARE_SOA_TABLE(EMSWTriggerInfosTMP, "AOD", "EMSWTTMP", //! joinable to aod::Collisions + emevent::SWTAliasTmp, emevent::NInspectedTVX); +using EMSWTriggerInfoTMP = EMSWTriggerInfosTMP::iterator; + +DECLARE_SOA_TABLE(EMEventsProperty, "AOD", "EMEVENTPROP", //! joinable to EMEvents + emevent::SpherocityPtWeighted, emevent::SpherocityPtUnWeighted, emevent::NtrackSpherocity); +using EMEventProperty = EMEventsProperty::iterator; + +DECLARE_SOA_TABLE(EMEventsNee, "AOD", "EMEVENTNEE", emevent::NeeULS, emevent::NeeLSpp, emevent::NeeLSmm); // joinable to EMEvents or aod::Collisions +using EMEventNee = EMEventsNee::iterator; + +DECLARE_SOA_TABLE(EMEvSels, "AOD", "EMEVSEL", //! joinable to aod::Collisions + emevent::IsSelected); +using EMEvSel = EMEvSels::iterator; + +namespace emmcevent +{ +DECLARE_SOA_COLUMN(McCollisionId, mcCollisionId, int); +} // namespace emmcevent + +DECLARE_SOA_TABLE(EMMCEvents, "AOD", "EMMCEVENT", //! MC event information table + o2::soa::Index<>, emmcevent::McCollisionId, mccollision::GeneratorsID, + mccollision::PosX, mccollision::PosY, mccollision::PosZ, + mccollision::ImpactParameter, mccollision::EventPlaneAngle, + + // dynamic column + mccollision::GetGeneratorId, + mccollision::GetSubGeneratorId, + mccollision::GetSourceId); + +using EMMCEvent = EMMCEvents::iterator; + +namespace emmceventlabel +{ +DECLARE_SOA_INDEX_COLUMN(EMMCEvent, emmcevent); //! MC collision +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); //! Bit mask to indicate collision mismatches (bit ON means mismatch). Bit 15: indicates negative label +} // namespace emmceventlabel + +DECLARE_SOA_TABLE(EMMCEventLabels, "AOD", "EMMCEVENTLABEL", //! Table joined to the EMEvents table containing the MC index + emmceventlabel::EMMCEventId, emmceventlabel::McMask); +using EMMCEventLabel = EMMCEventLabels::iterator; + +namespace emmcparticle +{ +DECLARE_SOA_INDEX_COLUMN(EMMCEvent, emmcevent); +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) array. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return RecoDecay::phi(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); +DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! Particle rapidity + [](float pz, float e) -> float { + if ((e - pz) > static_cast(1e-7)) { + return 0.5f * std::log((e + pz) / (e - pz)); + } else { + return -999.0f; + } + }); +} // namespace emmcparticle + +// This table contains all MC truth tracks +DECLARE_SOA_TABLE_FULL(EMMCParticles, "EMMCParticles", "AOD", "EMMCPARTICLE", //! MC track information (on disk) + o2::soa::Index<>, emmcparticle::EMMCEventId, + mcparticle::PdgCode, mcparticle::Flags, + emmcparticle::MothersIds, emmcparticle::DaughtersIds, + mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, + mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, + + // dynamic column + emmcparticle::Pt, + emmcparticle::Eta, + emmcparticle::Phi, + + emmcparticle::P, + emmcparticle::Y, + mcparticle::ProducedByGenerator, + mcparticle::FromBackgroundEvent, + mcparticle::IsPhysicalPrimary); + +using EMMCParticle = EMMCParticles::iterator; + +namespace emmcgenvectormeson +{ +DECLARE_SOA_INDEX_COLUMN(EMMCEvent, emmcevent); +DECLARE_SOA_COLUMN(DownScalingFactor, dsf, float); //! down scaling factor to store this mc particle in reduced AO2D.root +} // namespace emmcgenvectormeson + +DECLARE_SOA_TABLE_FULL(EMMCGenVectorMesons, "EMMCGenVectorMesons", "AOD", "EMMCGENVM", //! generated omega, phi information + o2::soa::Index<>, emmcgenvectormeson::EMMCEventId, + mcparticle::PdgCode, mcparticle::Flags, + mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, + emmcgenvectormeson::DownScalingFactor, + + // dynamic column + emmcparticle::Pt, + emmcparticle::Eta, + emmcparticle::Phi, + + emmcparticle::P, + emmcparticle::Y, + mcparticle::ProducedByGenerator, + mcparticle::FromBackgroundEvent, + mcparticle::IsPhysicalPrimary); + +using EMMCGenVectorMeson = EMMCGenVectorMesons::iterator; + +namespace smearedtrack +{ +DECLARE_SOA_COLUMN(PtSmeared, ptSmeared, float); +DECLARE_SOA_COLUMN(EtaSmeared, etaSmeared, float); +DECLARE_SOA_COLUMN(PhiSmeared, phiSmeared, float); +DECLARE_SOA_COLUMN(Efficiency, efficiency, float); +DECLARE_SOA_COLUMN(DCA, dca, float); + +DECLARE_SOA_COLUMN(PtSmearedSAMuon, ptSmeared_sa_muon, float); +DECLARE_SOA_COLUMN(EtaSmearedSAMuon, etaSmeared_sa_muon, float); +DECLARE_SOA_COLUMN(PhiSmearedSAMuon, phiSmeared_sa_muon, float); +DECLARE_SOA_COLUMN(EfficiencySAMuon, efficiency_sa_muon, float); +DECLARE_SOA_COLUMN(DCASAMuon, dca_sa_muon, float); +DECLARE_SOA_COLUMN(PtSmearedGLMuon, ptSmeared_gl_muon, float); +DECLARE_SOA_COLUMN(EtaSmearedGLMuon, etaSmeared_gl_muon, float); +DECLARE_SOA_COLUMN(PhiSmearedGLMuon, phiSmeared_gl_muon, float); +DECLARE_SOA_COLUMN(EfficiencyGLMuon, efficiency_gl_muon, float); +DECLARE_SOA_COLUMN(DCAGLMuon, dca_gl_muon, float); +} // namespace smearedtrack + +DECLARE_SOA_TABLE(SmearedElectrons, "AOD", "SMEAREDEL", // usage Join + smearedtrack::PtSmeared, smearedtrack::EtaSmeared, smearedtrack::PhiSmeared, smearedtrack::Efficiency, smearedtrack::DCA); +using SmearedElectron = SmearedElectrons::iterator; + +DECLARE_SOA_TABLE(SmearedMuons, "AOD", "SMEAREDMU", // usage Join + smearedtrack::PtSmearedSAMuon, smearedtrack::EtaSmearedSAMuon, smearedtrack::PhiSmearedSAMuon, smearedtrack::EfficiencySAMuon, smearedtrack::DCASAMuon, + smearedtrack::PtSmearedGLMuon, smearedtrack::EtaSmearedGLMuon, smearedtrack::PhiSmearedGLMuon, smearedtrack::EfficiencyGLMuon, smearedtrack::DCAGLMuon); +using SmearedMuon = SmearedMuons::iterator; + +namespace emprimaryelectronmclabel +{ +DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace emprimaryelectronmclabel + +// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with EMPrimaryElectrons table) +DECLARE_SOA_TABLE(EMPrimaryElectronMCLabels, "AOD", "EMPRMELMCLABEL", //! + emprimaryelectronmclabel::EMMCParticleId, emprimaryelectronmclabel::McMask); +using EMPrimaryElectronMCLabel = EMPrimaryElectronMCLabels::iterator; + +namespace emprimarymuonmclabel +{ +DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace emprimarymuonmclabel + +// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with EMPrimaryMuons table) +DECLARE_SOA_TABLE(EMPrimaryMuonMCLabels, "AOD", "EMPRMMUMCLABEL", //! + emprimarymuonmclabel::EMMCParticleId, emprimarymuonmclabel::McMask); +using EMPrimaryMuonMCLabel = EMPrimaryMuonMCLabels::iterator; + +namespace emprimaryelectron +{ +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(TrackId, trackId, int); //! +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousElectrons, ambiguousElectrons); +DECLARE_SOA_COLUMN(IsAssociatedToMPC, isAssociatedToMPC, bool); //! is associated to most probable collision +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! +DECLARE_SOA_COLUMN(PrefilterBit, pfb, uint8_t); //! +DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(Theta, theta, [](float tgl) -> float { return M_PI_2 - std::atan(tgl); }); +DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + if (nl > 0) { + return static_cast(total_cluster_size) / static_cast(nl); + } else { + return 0; + } +}); +DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSib, meanClusterSizeITSib, [](uint32_t itsClusterSizes) -> float { + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 3; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + if (nl > 0) { + return static_cast(total_cluster_size) / static_cast(nl); + } else { + return 0; + } +}); +DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32_t itsClusterSizes) -> float { + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 3; layer < 7; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + if (nl > 0) { + return static_cast(total_cluster_size) / static_cast(nl); + } else { + return 0; + } +}); +} // namespace emprimaryelectron +DECLARE_SOA_TABLE(EMPrimaryElectrons, "AOD", "EMPRIMARYEL", //! + o2::soa::Index<>, emprimaryelectron::CollisionId, + emprimaryelectron::TrackId, emprimaryelectron::Sign, + track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, + track::ITSClusterSizes, track::ITSChi2NCl, track::DetectorMap, + track::X, track::Alpha, track::Y, track::Z, track::Snp, track::Tgl, emprimaryelectron::IsAssociatedToMPC, + + // dynamic column + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls, + track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, + track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz, + emprimaryelectron::Theta, + emprimaryelectron::MeanClusterSizeITS, + emprimaryelectron::MeanClusterSizeITSib, + emprimaryelectron::MeanClusterSizeITSob); +// iterators +using EMPrimaryElectron = EMPrimaryElectrons::iterator; + +DECLARE_SOA_TABLE(EMPrimaryElectronsCov, "AOD", "EMPRIMARYELCOV", //! + aod::track::CYY, + aod::track::CZY, + aod::track::CZZ, + aod::track::CSnpY, + aod::track::CSnpZ, + aod::track::CSnpSnp, + aod::track::CTglY, + aod::track::CTglZ, + aod::track::CTglSnp, + aod::track::CTglTgl, + aod::track::C1PtY, + aod::track::C1PtZ, + aod::track::C1PtSnp, + aod::track::C1PtTgl, + aod::track::C1Pt21Pt2, o2::soa::Marker<1>); +// iterators +using EMPrimaryElectronCov = EMPrimaryElectronsCov::iterator; + +DECLARE_SOA_TABLE(EMPrimaryElectronEMEventIds, "AOD", "PRMELMEVENTID", emprimaryelectron::EMEventId); // To be joined with EMPrimaryElectrons table at analysis level. +// iterators +using EMPrimaryElectronEMEventId = EMPrimaryElectronEMEventIds::iterator; + +DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBit, "AOD", "PRMELPFB", emprimaryelectron::PrefilterBit); // To be joined with EMPrimaryElectrons table at analysis level. +// iterators +using EMPrimaryElectronPrefilterBit = EMPrimaryElectronsPrefilterBit::iterator; + +DECLARE_SOA_TABLE(EMAmbiguousElectronSelfIds, "AOD", "EMAMBELSELFID", emprimaryelectron::AmbiguousElectronsIds); // To be joined with EMPrimaryElectrons table at analysis level. +// iterators +using EMAmbiguousElectronSelfId = EMAmbiguousElectronSelfIds::iterator; + +namespace emprimarymuon +{ +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(FwdTrackId, fwdtrackId, int); //! +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(MCHTrack, matchMCHTrack, int, "EMPRIMARYMUs_MatchMCHTrack"); //! Index of matched MCH track for GlobalMuonTracks and GlobalForwardTracks +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousMuons, ambiguousMuons); +DECLARE_SOA_COLUMN(IsAssociatedToMPC, isAssociatedToMPC, bool); //! is associated to most probable collision +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! +DECLARE_SOA_COLUMN(Chi2MFTsa, chi2MFTsa, float); //! chi2 of MFT standalone track +DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(Theta, theta, [](float tgl) -> float { return M_PI_2 - std::atan(tgl); }); +DECLARE_SOA_DYNAMIC_COLUMN(DcaXY, dcaXY, [](float dcaX, float dcaY) -> float { return std::sqrt(dcaX * dcaX + dcaY * dcaY); }); +DECLARE_SOA_DYNAMIC_COLUMN(NClustersMFT, nClustersMFT, //! Number of MFT clusters + [](uint64_t mftClusterSizesAndTrackFlags) -> uint8_t { + uint8_t nClusters = 0; + for (int layer = 0; layer < 10; layer++) { + if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3F) { + nClusters++; + } + } + return nClusters; + }); +DECLARE_SOA_DYNAMIC_COLUMN(MFTClusterMap, mftClusterMap, //! MFT cluster map, one bit per a layer, starting from the innermost + [](uint64_t mftClusterSizesAndTrackFlags) -> uint16_t { + uint16_t clmap = 0; + for (unsigned int layer = 0; layer < 10; layer++) { + if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3f) { + clmap |= (1 << layer); + } + } + return clmap; + }); +} // namespace emprimarymuon +DECLARE_SOA_TABLE(EMPrimaryMuons, "AOD", "EMPRIMARYMU", //! + o2::soa::Index<>, emprimarymuon::CollisionId, + emprimarymuon::FwdTrackId, fwdtrack::TrackType, + fwdtrack::Pt, fwdtrack::Eta, fwdtrack::Phi, emprimarymuon::Sign, + fwdtrack::FwdDcaX, fwdtrack::FwdDcaY, + fwdtrack::X, fwdtrack::Y, fwdtrack::Z, fwdtrack::Tgl, + + fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, + fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, + // fwdtrack::MatchScoreMCHMFT, fwdtrack::MFTTrackId, fwdtrack::MCHTrackId, + emprimarymuon::MCHTrackId, + fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, + fwdtrack::MFTClusterSizesAndTrackFlags, emprimarymuon::Chi2MFTsa, emprimarymuon::IsAssociatedToMPC, + + // dynamic column + emprimarymuon::Signed1Pt, + emprimarymuon::NClustersMFT, + emprimarymuon::MFTClusterMap, + emprimarymuon::P, + emprimarymuon::Px, + emprimarymuon::Py, + emprimarymuon::Pz, + emprimarymuon::Theta, + emprimarymuon::DcaXY); +// iterators +using EMPrimaryMuon = EMPrimaryMuons::iterator; + +DECLARE_SOA_TABLE(EMPrimaryMuonsCov, "AOD", "EMPRIMARYMUCOV", //! + aod::fwdtrack::CXX, + aod::fwdtrack::CXY, + aod::fwdtrack::CYY, + aod::fwdtrack::CPhiX, + aod::fwdtrack::CPhiY, + aod::fwdtrack::CPhiPhi, + aod::fwdtrack::CTglX, + aod::fwdtrack::CTglY, + aod::fwdtrack::CTglPhi, + aod::fwdtrack::CTglTgl, + aod::fwdtrack::C1PtX, + aod::fwdtrack::C1PtY, + aod::fwdtrack::C1PtPhi, + aod::fwdtrack::C1PtTgl, + aod::fwdtrack::C1Pt21Pt2); +// iterators +using EMPrimaryMuonCov = EMPrimaryMuonsCov::iterator; + +DECLARE_SOA_TABLE(EMPrimaryMuonEMEventIds, "AOD", "PRMMUEMEVENTID", emprimarymuon::EMEventId); // To be joined with EMPrimaryMuons table at analysis level. +// iterators +using EMPrimaryMuonEMEventId = EMPrimaryMuonEMEventIds::iterator; + +DECLARE_SOA_TABLE(EMAmbiguousMuonSelfIds, "AOD", "EMAMBMUSELFID", emprimarymuon::AmbiguousMuonsIds); // To be joined with EMPrimaryMuons table at analysis level. +// iterators +using EMAmbiguousMuonSelfId = EMAmbiguousMuonSelfIds::iterator; + +} // namespace o2::aod + +#endif // PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index 100d4c98716..c643adad8f1 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -29,3 +29,44 @@ o2physics_add_dpl_workflow(tree-creator-single-electron-qa SOURCES treeCreatorSingleElectronQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(skimmer-primary-electron + SOURCES skimmerPrimaryElectron.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(skimmer-primary-muon + SOURCES skimmerPrimaryMuon.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(skimmer-secondary-electron + SOURCES skimmerSecondaryElectron.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(create-emevent-dilepton + SOURCES createEMEventDilepton.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(skimmer-ots + SOURCES skimmerOTS.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(associate-mc-info-dilepton + SOURCES associateMCinfoDilepton.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(filter-dielectron-event + SOURCES filterDielectronEvent.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-selection + SOURCES eventSelection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx new file mode 100644 index 00000000000..6cf6b0865d0 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx @@ -0,0 +1,656 @@ +// Copyright 2019-2020 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 produces reduced events for photon analyses. +// Please write to: daiki.sekihata@cern.ch + +#include +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/TableHelper.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +using MyCollisionsMC = soa::Join; +using TracksMC = soa::Join; +using FwdTracksMC = soa::Join; + +struct AssociateMCInfoDilepton { + enum SubSystem { + kElectron = 0x1, + kFwdMuon = 0x2, + kPCM = 0x4, + }; + + Produces mcevents; + Produces mceventlabels; + Produces emmcparticles; + Produces emmcgenvms; + Produces v0legmclabels; + Produces emprimaryelectronmclabels; + Produces emprimarymuonmclabels; + + Configurable down_scaling_omega{"down_scaling_omega", 1.0, "down scaling factor to store omega"}; + Configurable down_scaling_phi{"down_scaling_phi", 1.0, "down scaling factor to store phi"}; + Configurable min_eta_gen_primary{"min_eta_gen_primary", -1.2, "min rapidity Y to store generated information"}; // smearing might be applied at analysis stage. set wider value. + Configurable max_eta_gen_primary{"max_eta_gen_primary", +1.2, "max rapidity Y to store generated information"}; // smearing might be applied at analysis stage. set wider value. + Configurable min_eta_gen_primary_fwd{"min_eta_gen_primary_fwd", -4.5, "min eta to store generated information"}; // smearing might be applied at analysis stage. set wider value. + Configurable max_eta_gen_primary_fwd{"max_eta_gen_primary_fwd", -2.0, "max eta to store generated information"}; // smearing might be applied at analysis stage. set wider value. + + HistogramRegistry registry{"EMMCEvent"}; + std::mt19937 engine; + std::uniform_real_distribution dist01; + + void init(o2::framework::InitContext&) + { + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{6, 0.5f, 6.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + hEventCounter->GetXaxis()->SetBinLabel(2, "has mc collision"); + + std::random_device seed_gen; + engine = std::mt19937(seed_gen()); + dist01 = std::uniform_real_distribution(0.0f, 1.0f); + } + + template + bool isDecayDielectronInAcceptance(TMCParticle const& mctrack, TMCParticles const& mcTracks) + { + if (!mctrack.has_daughters()) { + return false; + } + + bool is_lepton = false, is_anti_lepton = false; + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + auto daughter = mcTracks.iteratorAt(d); + if (daughter.pdgCode() == 11 && (min_eta_gen_primary < daughter.eta() && daughter.eta() < max_eta_gen_primary)) { + is_lepton = true; + } + if (daughter.pdgCode() == -11 && (min_eta_gen_primary < daughter.eta() && daughter.eta() < max_eta_gen_primary)) { + is_anti_lepton = true; + } + } + if (is_lepton && is_anti_lepton) { + return true; + } else { + return false; + } + } + + template + bool isDecayDimuonInAcceptance(TMCParticle const& mctrack, TMCParticles const& mcTracks) + { + if (!mctrack.has_daughters()) { + return false; + } + + bool is_lepton = false, is_anti_lepton = false; + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + auto daughter = mcTracks.iteratorAt(d); + if (daughter.pdgCode() == 13 && (min_eta_gen_primary_fwd < daughter.eta() && daughter.eta() < max_eta_gen_primary_fwd)) { + is_lepton = true; + } + if (daughter.pdgCode() == -13 && (min_eta_gen_primary_fwd < daughter.eta() && daughter.eta() < max_eta_gen_primary_fwd)) { + is_anti_lepton = true; + } + } + if (is_lepton && is_anti_lepton) { + return true; + } else { + return false; + } + } + + SliceCache cache; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perCollision_pcm = aod::v0photonkf::collisionId; + Preslice perCollision_el = aod::emprimaryelectron::collisionId; + Preslice perCollision_mu = aod::emprimarymuon::collisionId; + + // apply rapidity cut for electrons + Partition mcelectrons = nabs(o2::aod::mcparticle::pdgCode) == 11 && min_eta_gen_primary < o2::aod::mcparticle::eta && o2::aod::mcparticle::eta < max_eta_gen_primary; + Partition mcmuons = nabs(o2::aod::mcparticle::pdgCode) == 13 && min_eta_gen_primary_fwd < o2::aod::mcparticle::eta && o2::aod::mcparticle::eta < max_eta_gen_primary_fwd; + Partition mcvectormesons = o2::aod::mcparticle::pdgCode == 223 || o2::aod::mcparticle::pdgCode == 333; + + template + void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const& mcCollisions, aod::McParticles const& mcTracks, TTracks const& o2tracks, TFwdTracks const& o2fwdtracks, TPCMs const& v0photons, TPCMLegs const& /*v0legs*/, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) + { + // temporary variables used for the indexing of the skimmed MC stack + std::map fNewLabels; + std::map fNewLabelsReversed; + // std::map fMCFlags; + std::map fEventIdx; + std::map fEventLabels; + int fCounters[2] = {0, 0}; //! [0] - particle counter, [1] - event counter + + // first, run loop over mc collisions to create map between aod::McCollisions and aod::EMMCEvents + for (auto& mcCollision : mcCollisions) { + // make an entry for this MC event only if it was not already added to the table + if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { + mcevents(mcCollision.globalIndex(), mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + fEventLabels[mcCollision.globalIndex()] = fCounters[1]; + fCounters[1]++; + } + } // end of mc collision loop + + for (auto& collision : collisions) { + registry.fill(HIST("hEventCounter"), 1); + + // TODO: investigate the collisions without corresponding mcCollision + if (!collision.has_mcCollision()) { + continue; + } + + if (!collision.isSelected()) { + continue; + } + + registry.fill(HIST("hEventCounter"), 2); + auto mcCollision = collision.mcCollision(); + mceventlabels(fEventLabels.find(mcCollision.globalIndex())->second, collision.mcMask()); + + } // end of reconstructed collision loop + + for (auto& mcCollision : mcCollisions) { + // store MC true information + auto mcelectrons_per_mccollision = mcelectrons.sliceBy(perMcCollision, mcCollision.globalIndex()); + auto mcmuons_per_mccollision = mcmuons.sliceBy(perMcCollision, mcCollision.globalIndex()); + auto mcvectormesons_per_mccollision = mcvectormesons.sliceBy(perMcCollision, mcCollision.globalIndex()); + + for (auto& mctrack : mcelectrons_per_mccollision) { // store necessary information for denominator of efficiency + if (!mctrack.isPhysicalPrimary() && !mctrack.producedByGenerator()) { + continue; + } + // auto mcCollision = mcCollisions.iteratorAt(mctrack.mcCollisionId()); + + // only for temporary protection, as of 15.July.2024 (by Daiki Sekihata) + int motherid_tmp = -999; // first mother index tmp + if (mctrack.has_mothers()) { + motherid_tmp = mctrack.mothersIds()[0]; // first mother index + } + auto mp_tmp = mcTracks.iteratorAt(motherid_tmp); + int ndau_tmp = mp_tmp.daughtersIds()[1] - mp_tmp.daughtersIds()[0] + 1; + if (ndau_tmp < 10) { + + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + } // end of ndau protection + } // end of mc electron loop + + for (auto& mctrack : mcmuons_per_mccollision) { // store necessary information for denominator of efficiency + if (!mctrack.isPhysicalPrimary() && !mctrack.producedByGenerator()) { + continue; + } + // auto mcCollision = mcCollisions.iteratorAt(mctrack.mcCollisionId()); + + // only for temporary protection, as of 15.July.2024 (by Daiki Sekihata) + int motherid_tmp = -999; // first mother index tmp + if (mctrack.has_mothers()) { + motherid_tmp = mctrack.mothersIds()[0]; // first mother index + } + auto mp_tmp = mcTracks.iteratorAt(motherid_tmp); + int ndau_tmp = mp_tmp.daughtersIds()[1] - mp_tmp.daughtersIds()[0] + 1; + if (ndau_tmp < 10) { + + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + } // end of ndau protection + } // end of mc muon loop + + for (auto& mctrack : mcvectormesons_per_mccollision) { // store necessary information for denominator of efficiency + // Be careful!! dilepton rapidity is different from meson rapidity! No acceptance cut here. + + if (!mctrack.isPhysicalPrimary() && !mctrack.producedByGenerator()) { + continue; + } + + if (!isDecayDielectronInAcceptance(mctrack, mcTracks) && !isDecayDimuonInAcceptance(mctrack, mcTracks)) { // acceptance cut to decay dileptons + continue; + } + + // auto mcCollision = mcCollisions.iteratorAt(mctrack.mcCollisionId()); + + int ndau = mctrack.daughtersIds()[1] - mctrack.daughtersIds()[0] + 1; + if (ndau < 10) { + + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + + // store daughter of vector mesons + if (mctrack.has_daughters()) { + bool is_lepton_involved = false; + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + // TODO: remove this check as soon as issues with MC production are fixed + if (d < mcTracks.size()) { // protect against bad daughter indices + auto daughter = mcTracks.iteratorAt(d); + if (abs(daughter.pdgCode()) == 11 || abs(daughter.pdgCode()) == 13) { + is_lepton_involved = true; + break; + } + } else { + std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + + if (is_lepton_involved) { + // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + // TODO: remove this check as soon as issues with MC production are fixed + if (d < mcTracks.size()) { // protect against bad daughter indices + auto daughter = mcTracks.iteratorAt(d); + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(daughter.globalIndex()) != fNewLabels.end())) { + fNewLabels[daughter.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = daughter.globalIndex(); + // fMCFlags[daughter.globalIndex()] = mcflags; + fEventIdx[daughter.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + } else { + std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } // end of daughter loop + } + } + } // end of ndau protection + } // end of generated vector mesons loop + + } // end of mc collision loop + + if constexpr (static_cast(system & kPCM)) { + for (auto& v0 : v0photons) { + auto collision_from_v0 = collisions.iteratorAt(v0.collisionId()); + if (!collision_from_v0.has_mcCollision()) { + continue; + } + + auto ele = v0.template negTrack_as(); + auto pos = v0.template posTrack_as(); + + auto o2track_ele = o2tracks.iteratorAt(ele.trackId()); + auto o2track_pos = o2tracks.iteratorAt(pos.trackId()); + + if (!o2track_ele.has_mcParticle() || !o2track_pos.has_mcParticle()) { + continue; // If no MC particle is found, skip the v0 + } + + for (auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! + auto o2track = o2tracks.iteratorAt(leg.trackId()); + auto mctrack = o2track.template mcParticle_as(); + // LOGF(info, "mctrack.globalIndex() = %d, mctrack.index() = %d", mctrack.globalIndex(), mctrack.index()); // these are exactly the same. + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mctrack.mcCollisionId())->second; + fCounters[0]++; + } + v0legmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mp.mcCollisionId())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + } // end of leg loop + } // end of v0 loop + } + + if constexpr (static_cast(system & kElectron)) { + // auto emprimaryelectrons_coll = emprimaryelectrons.sliceBy(perCollision_el, collision.globalIndex()); + for (auto& emprimaryelectron : emprimaryelectrons) { + auto collision_from_el = collisions.iteratorAt(emprimaryelectron.collisionId()); + if (!collision_from_el.has_mcCollision()) { + continue; + } + + auto o2track = o2tracks.iteratorAt(emprimaryelectron.trackId()); + if (!o2track.has_mcParticle()) { + continue; // If no MC particle is found, skip the dilepton + } + auto mctrack = o2track.template mcParticle_as(); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mctrack.mcCollisionId())->second; + fCounters[0]++; + } + emprimaryelectronmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mp.mcCollisionId())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + + } // end of em primary electron loop + } + + if constexpr (static_cast(system & kFwdMuon)) { + // auto emprimarymuons_coll = emprimarymuons.sliceBy(perCollision_mu, collision.globalIndex()); + for (auto& emprimarymuon : emprimarymuons) { + auto collision_from_mu = collisions.iteratorAt(emprimarymuon.collisionId()); + if (!collision_from_mu.has_mcCollision()) { + continue; + } + + auto o2track = o2fwdtracks.iteratorAt(emprimarymuon.fwdtrackId()); + if (!o2track.has_mcParticle()) { + continue; // If no MC particle is found, skip the dilepton + } + auto mctrack = o2track.template mcParticle_as(); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mctrack.mcCollisionId())->second; + fCounters[0]++; + } + emprimarymuonmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mp.mcCollisionId())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + + } // end of em primary muon loop + } + + // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack + for (const auto& [newLabel, oldLabel] : fNewLabelsReversed) { + auto mctrack = mcTracks.iteratorAt(oldLabel); + // uint16_t mcflags = fMCFlags.find(oldLabel)->second; + + std::vector mothers; + if (mctrack.has_mothers()) { + for (auto& m : mctrack.mothersIds()) { + if (m < mcTracks.size()) { // protect against bad mother indices + if (fNewLabels.find(m) != fNewLabels.end()) { + mothers.push_back(fNewLabels.find(m)->second); + } + } else { + std::cout << "Mother label (" << m << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + } + + // Note that not all daughters from the original table are preserved in the skimmed MC stack + std::vector daughters; + if (mctrack.has_daughters()) { + // int ndau = mctrack.daughtersIds()[1] - mctrack.daughtersIds()[0] + 1; + // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + // TODO: remove this check as soon as issues with MC production are fixed + if (d < mcTracks.size()) { // protect against bad daughter indices + // auto dau_tmp = mcTracks.iteratorAt(d); + // // LOGF(info, "daughter pdg = %d", dau_tmp.pdgCode()); + // if ((mctrack.pdgCode() == 223 || mctrack.pdgCode() == 333) && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + // if (fNewLabels.find(d) == fNewLabels.end() && (abs(dau_tmp.pdgCode()) == 11 || abs(dau_tmp.pdgCode()) == 13)) { + // LOGF(info, "daughter lepton is not found mctrack.globalIndex() = %d, mctrack.producedByGenerator() == %d, ndau = %d | dau_tmp.globalIndex() = %d, dau_tmp.pdgCode() = %d, dau_tmp.producedByGenerator() = %d, dau_tmp.pt() = %f, dau_tmp.eta() = %f, dau_tmp.phi() = %f", mctrack.globalIndex(), mctrack.producedByGenerator(), ndau, dau_tmp.globalIndex(), dau_tmp.pdgCode(), dau_tmp.producedByGenerator(), dau_tmp.pt(), dau_tmp.eta(), dau_tmp.phi()); + // } + // } + + if (fNewLabels.find(d) != fNewLabels.end()) { + daughters.push_back(fNewLabels.find(d)->second); + } + } else { + std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + } + + emmcparticles(fEventIdx.find(oldLabel)->second, mctrack.pdgCode(), mctrack.flags(), + mothers, daughters, + mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), + mctrack.vx(), mctrack.vy(), mctrack.vz()); + + mothers.clear(); + mothers.shrink_to_fit(); + daughters.clear(); + daughters.shrink_to_fit(); + } // end loop over labels + + // only for omega, phi mesons + for (auto& mcCollision : mcCollisions) { + auto mcvectormesons_per_mccollision = mcvectormesons.sliceBy(perMcCollision, mcCollision.globalIndex()); + for (auto& mctrack : mcvectormesons_per_mccollision) { // store necessary information for denominator of efficiency + if (!mctrack.isPhysicalPrimary() && !mctrack.producedByGenerator()) { + continue; + } + + if (mctrack.pdgCode() == 223) { + if (dist01(engine) < down_scaling_omega) { + emmcgenvms(fEventLabels[mcCollision.globalIndex()], mctrack.pdgCode(), mctrack.flags(), mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), down_scaling_omega.value); + } + } else if (mctrack.pdgCode() == 333) { + if (dist01(engine) < down_scaling_phi) { + emmcgenvms(fEventLabels[mcCollision.globalIndex()], mctrack.pdgCode(), mctrack.flags(), mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), down_scaling_phi.value); + } + } + } // end of generated vector meson loop + } // end of reconstructed collision loop + + fNewLabels.clear(); + fNewLabelsReversed.clear(); + // fMCFlags.clear(); + fEventIdx.clear(); + fEventLabels.clear(); + fCounters[0] = 0; + fCounters[1] = 0; + } // end of skimmingMC + + void processMC_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::EMPrimaryElectrons const& emprimaryelectrons) + { + const uint8_t sysflag = kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, nullptr, emprimaryelectrons, nullptr); + } + + void processMC_FwdMuon(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, FwdTracksMC const& o2fwdtracks, aod::EMPrimaryMuons const& emprimarymuons) + { + const uint8_t sysflag = kFwdMuon; + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, o2fwdtracks, nullptr, nullptr, nullptr, emprimarymuons); + } + + void processMC_Electron_FwdMuon(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) + { + const uint8_t sysflag = kElectron | kFwdMuon; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, nullptr, nullptr, emprimaryelectrons, emprimarymuons); + } + + void processMC_Electron_FwdMuon_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) + { + const uint8_t sysflag = kPCM | kElectron | kFwdMuon; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, v0photons, v0legs, emprimaryelectrons, emprimarymuons); + } + + void processMC_Electron_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons) + { + const uint8_t sysflag = kPCM | kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, emprimaryelectrons, nullptr); + } + + void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) + { + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, nullptr, nullptr); + } + + void processDummy(MyCollisionsMC const&) {} + + PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron, "create em mc event table for Electron", false); + PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_FwdMuon, "create em mc event table for Forward Muon", false); + PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon, "create em mc event table for Electron, FwdMuon", false); + PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon_PCM, "create em mc event table for PCM, Electron, FwdMuon", false); + PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_PCM, "create em mc event table for PCM, Electron", false); + PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_PCM, "create em mc event table for PCM", false); + PROCESS_SWITCH(AssociateMCInfoDilepton, processDummy, "processDummy", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"associate-mc-info-dilepton"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx new file mode 100644 index 00000000000..603c97138ff --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -0,0 +1,446 @@ +// Copyright 2019-2020 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 produces reduced events for photon analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/TableHelper.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +using MyBCs = soa::Join; +using MyQvectors = soa::Join; + +using MyCollisions = soa::Join; +using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisions_Cent_Qvec = soa::Join; + +using MyCollisionsWithSWT = soa::Join; +using MyCollisionsWithSWT_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisionsWithSWT_Cent_Qvec = soa::Join; + +using MyCollisionsMC = soa::Join; +using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisionsMC_Cent_Qvec = soa::Join; + +struct CreateEMEventDilepton { + Produces event; + // Produces eventcov; + Produces event_mult; + Produces event_cent; + Produces event_qvec; + Produces emswtbit; + + enum class EMEventType : int { + kEvent = 0, + kEvent_Cent = 1, + kEvent_Cent_Qvec = 2, + }; + + // CCDB options + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; + + HistogramRegistry registry{"registry"}; + void init(o2::framework::InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{7, 0.5f, 7.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); + + registry.add("hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + + ~CreateEMEventDilepton() {} + + int mRunNumber; + float d_bz; + Service ccdb; + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + } + + Preslice perCollision_pcm = aod::v0photonkf::collisionId; + PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; + PresliceUnsorted perCollision_mu = aod::emprimarymuon::collisionId; + + template + void skimEvent(TCollisions const& collisions, TBCs const&) + { + for (auto& collision : collisions) { + if constexpr (isMC) { + if (!collision.has_mcCollision()) { + continue; + } + } + + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + + if constexpr (isTriggerAnalysis) { + if (collision.swtaliastmp_raw() == 0) { + continue; + } else { + emswtbit(collision.swtaliastmp_raw(), collision.nInspectedTVX()); + } + } + + // LOGF(info, "collision.multNTracksPV() = %d, collision.multFT0A() = %f, collision.multFT0C() = %f", collision.multNTracksPV(), collision.multFT0A(), collision.multFT0C()); + + registry.fill(HIST("hEventCounter"), 1); + + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), + collision.posX(), collision.posY(), collision.posZ(), + collision.numContrib(), collision.trackOccupancyInTimeRange()); + + // eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + + if constexpr (eventype == EMEventType::kEvent) { + event_cent(105.f, 105.f, 105.f, 105.f); + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } else if constexpr (eventype == EMEventType::kEvent_Cent) { + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } else if constexpr (eventype == EMEventType::kEvent_Cent_Qvec) { + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + float q2xft0m = 999.f, q2yft0m = 999.f, q2xft0a = 999.f, q2yft0a = 999.f, q2xft0c = 999.f, q2yft0c = 999.f, q2xbpos = 999.f, q2ybpos = 999.f, q2xbneg = 999.f, q2ybneg = 999.f, q2xbtot = 999.f, q2ybtot = 999.f; + float q3xft0m = 999.f, q3yft0m = 999.f, q3xft0a = 999.f, q3yft0a = 999.f, q3xft0c = 999.f, q3yft0c = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; + + if (collision.qvecFT0CReVec().size() >= 2) { // harmonics 2,3 + q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; + q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; + q3xft0m = collision.qvecFT0MReVec()[1], q3xft0a = collision.qvecFT0AReVec()[1], q3xft0c = collision.qvecFT0CReVec()[1], q3xbpos = collision.qvecBPosReVec()[1], q3xbneg = collision.qvecBNegReVec()[1], q3xbtot = collision.qvecBTotReVec()[1]; + q3yft0m = collision.qvecFT0MImVec()[1], q3yft0a = collision.qvecFT0AImVec()[1], q3yft0c = collision.qvecFT0CImVec()[1], q3ybpos = collision.qvecBPosImVec()[1], q3ybneg = collision.qvecBNegImVec()[1], q3ybtot = collision.qvecBTotImVec()[1]; + } else if (collision.qvecFT0CReVec().size() >= 1) { // harmonics 2 + q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; + q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; + } + event_qvec( + q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); + } else { + event_cent(105.f, 105.f, 105.f, 105.f); + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } + } // end of collision loop + } // end of skimEvent + + //---------- for data ---------- + + void processEvent(MyCollisions const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEvent, "process event info", false); + + void processEvent_Cent(MyCollisions_Cent const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEvent_Cent, "process event info", false); + + void processEvent_Cent_Qvec(MyCollisions_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEvent_Cent_Qvec, "process event info", false); + + //---------- for data with swt---------- + + void processEvent_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEvent_SWT, "process event info", false); + + void processEvent_SWT_Cent(MyCollisionsWithSWT_Cent const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEvent_SWT_Cent, "process event info", false); + + void processEvent_SWT_Cent_Qvec(MyCollisionsWithSWT_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEvent_SWT_Cent_Qvec, "process event info", false); + + //---------- for MC ---------- + + void processEventMC(MyCollisionsMC const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEventMC, "process event info", false); + + void processEventMC_Cent(MyCollisionsMC_Cent const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEventMC_Cent, "process event info", false); + + void processEventMC_Cent_Qvec(MyCollisionsMC_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventDilepton, processEventMC_Cent_Qvec, "process event info", false); + + void processDummy(aod::Collisions const&) {} + PROCESS_SWITCH(CreateEMEventDilepton, processDummy, "processDummy", true); +}; +struct AssociateDileptonToEMEvent { + Produces v0kfeventid; + Produces prmeleventid; + Produces prmmueventid; + + Preslice perCollision_pcm = aod::v0photonkf::collisionId; + PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; + PresliceUnsorted perCollision_mu = aod::emprimarymuon::collisionId; + + void init(o2::framework::InitContext&) {} + + template + void fillEventId(TCollisions const& collisions, TLeptons const& leptons, TEventIds& eventIds, TPreslice const& perCollision) + { + for (auto& collision : collisions) { + auto leptons_coll = leptons.sliceBy(perCollision, collision.collisionId()); + int nl = leptons_coll.size(); + // LOGF(info, "collision.collisionId() = %d , nl = %d", collision.collisionId(), nl); + for (int il = 0; il < nl; il++) { + eventIds(collision.globalIndex()); + } // end of photon loop + } // end of collision loop + } + + // This struct is for both data and MC. + // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventDilepton in MC. + + void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) + { + fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); + } + + void processElectron(aod::EMEvents const& collisions, aod::EMPrimaryElectrons const& tracks) + { + fillEventId(collisions, tracks, prmeleventid, perCollision_el); + } + + void processFwdMuon(aod::EMEvents const& collisions, aod::EMPrimaryMuons const& tracks) + { + fillEventId(collisions, tracks, prmmueventid, perCollision_mu); + } + + void processDummy(aod::EMEvents const&) {} + + PROCESS_SWITCH(AssociateDileptonToEMEvent, processPCM, "process pcm-event indexing", false); + PROCESS_SWITCH(AssociateDileptonToEMEvent, processElectron, "process dalitzee-event indexing", false); + PROCESS_SWITCH(AssociateDileptonToEMEvent, processFwdMuon, "process forward muon indexing", false); + PROCESS_SWITCH(AssociateDileptonToEMEvent, processDummy, "process dummy", true); +}; +struct EMEventPropertyTask { + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + using Run3Tracks = soa::Join; + + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; + + Produces evprop; + struct : ConfigurableGroup { + std::string prefix = "spherocity_cutgroup"; + Configurable require_isPVContributor{"require_isPVContributor", false, "require tracks to be PV contributors"}; + Configurable min_ntrack{"min_ntrack", 3, "min. number of tracks"}; + Configurable min_pt{"min_pt", 0.15, "min. pT of track in GeV/c"}; + Configurable min_eta{"min_eta", -0.8, "min. eta of track"}; + Configurable max_eta{"max_eta", +0.8, "max. eta of track"}; + Configurable max_dcaxy{"max_dcaxy", 2.4, "max. DCAxy of track in cm"}; + Configurable max_dcaz{"max_dcaz", 3.2, "max. DCAz of track in cm"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 50, "min. number of TPC clusters"}; + Configurable max_chi2tpc{"max_chi2tpc", 4.0, "max. chi2/ncls TPC"}; + } spherocity_cuts; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + void init(InitContext&) + { + if (fillQAHistogram) { + fRegistry.add("Spherocity/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{200, 0.0f, 10}}, false); + fRegistry.add("Spherocity/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -1.0f, 1.0f}}, false); + fRegistry.add("Spherocity/hSpherocity_ptweighted", "spherocity;Number of used tracks;spherocity", kTH2F, {{101, -0.5, 100.5}, {100, 0.0f, 1}}, false); + fRegistry.add("Spherocity/hSpherocity_ptunweighted", "spherocity;Number of used tracks;spherocity", kTH2F, {{101, -0.5, 100.5}, {100, 0.0f, 1}}, false); + } + } + + template + int getSpherocity(TTracks const& tracks, float& spherocity_ptweighted, float& spherocity_ptunweighted) + { + // Reference for spherocity : https://arxiv.org/pdf/1905.07208, https://arxiv.org/abs/2310.20406, https://arxiv.org/abs/1205.3963 + int used_ntrack_spherocity = 0; + float sum_pt = 0.f, sum_ntrack = 0.f; + + for (auto const& track : tracks) { + if (spherocity_cuts.require_isPVContributor && !track.isPVContributor()) { + continue; + } + if (track.tpcNClsFound() < spherocity_cuts.min_ncluster_tpc) { + continue; + } + + sum_pt += track.pt(); + sum_ntrack += 1.f; + + if (fillQAHistogram) { + fRegistry.fill(HIST("Spherocity/hPt"), track.pt()); + fRegistry.fill(HIST("Spherocity/hEtaPhi"), track.phi(), track.eta()); + } + used_ntrack_spherocity++; + } // end of track loop per collision + + float tempSph = 1.f, tempSph_pt1 = 1.f; + for (int i = 0; i < 360 / 0.1; i++) { + float nx = std::cos(M_PI / 180.f * i * 0.1); + float ny = std::sin(M_PI / 180.f * i * 0.1); + float sum_crossprod = 0.f, sum_crossprod_pt1 = 0.f; + for (auto const& track : tracks) { + if (spherocity_cuts.require_isPVContributor && !track.isPVContributor()) { + continue; + } + if (track.tpcNClsFound() < spherocity_cuts.min_ncluster_tpc) { + continue; + } + float px = track.px(); + float py = track.py(); + sum_crossprod += abs(px * ny - py * nx); + sum_crossprod_pt1 += abs(std::cos(track.phi()) * ny - std::sin(track.phi()) * nx); + } + float sph = std::pow(sum_crossprod / sum_pt, 2); + float sph_pt1 = std::pow(sum_crossprod_pt1 / sum_ntrack, 2); + if (sph < tempSph) { + tempSph = sph; + } + if (sph_pt1 < tempSph_pt1) { + tempSph_pt1 = sph_pt1; + } + } // end of track loop per collision + spherocity_ptweighted = std::pow(M_PI_2, 2) * tempSph; + spherocity_ptunweighted = std::pow(M_PI_2, 2) * tempSph_pt1; + if (used_ntrack_spherocity < spherocity_cuts.min_ntrack) { + spherocity_ptweighted = -1.f; + spherocity_ptunweighted = -1.f; + } + return used_ntrack_spherocity; + } + + Partition tracks_for_spherocity = spherocity_cuts.min_pt < aod::track::pt && spherocity_cuts.min_eta < o2::aod::track::eta && o2::aod::track::eta < spherocity_cuts.max_eta && nabs(o2::aod::track::dcaXY) < spherocity_cuts.max_dcaxy && nabs(o2::aod::track::dcaZ) < spherocity_cuts.max_dcaz && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true && o2::aod::track::tpcChi2NCl < spherocity_cuts.max_chi2tpc; // ITS-TPC matched tracks + + void processProp(aod::EMEvents const& collisions, Run3Tracks const&) + { + for (auto& collision : collisions) { + auto tracks_for_spherocity_per_collision = tracks_for_spherocity->sliceByCached(o2::aod::track::collisionId, collision.collisionId(), cache); + float spherocity_ptweighted = -1.f, spherocity_ptunweighted = -1.f; + int ntrack = getSpherocity(tracks_for_spherocity_per_collision, spherocity_ptweighted, spherocity_ptunweighted); + if (fillQAHistogram) { + fRegistry.fill(HIST("Spherocity/hSpherocity_ptweighted"), ntrack, spherocity_ptweighted); + fRegistry.fill(HIST("Spherocity/hSpherocity_ptunweighted"), ntrack, spherocity_ptunweighted); + } + evprop(spherocity_ptweighted, spherocity_ptunweighted, ntrack); + } // end of collision loop + } + PROCESS_SWITCH(EMEventPropertyTask, processProp, "process event property", true); + + void processDummy(aod::EMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + evprop(-1.f, -1.f, 0); + } // end of collision loop + } + PROCESS_SWITCH(EMEventPropertyTask, processDummy, "process dummy", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"create-emevent-dilepton"}), + adaptAnalysisTask(cfgc, TaskName{"associate-dilepton-to-emevent"}), + adaptAnalysisTask(cfgc, TaskName{"emevent-property"}), + }; +} diff --git a/PWGEM/Dilepton/TableProducer/eventSelection.cxx b/PWGEM/Dilepton/TableProducer/eventSelection.cxx new file mode 100644 index 00000000000..2c804ddf2d4 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/eventSelection.cxx @@ -0,0 +1,122 @@ +// Copyright 2019-2020 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 produces event selection table for PWG-EM. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +using MyCollisions = soa::Join; +using MyCollisions_Cent = soa::Join; + +using MyCollisionsMC = soa::Join; +using MyCollisionsMC_Cent = soa::Join; + +struct EMEventSelection { + Produces emevsel; + + // Configurables + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + + void init(InitContext&) {} + + template + bool isSelectedEvent(TCollision const& collision) + { + if constexpr (std::is_same_v, MyCollisionsMC::iterator> || std::is_same_v, MyCollisionsMC_Cent::iterator>) { + if (!collision.has_mcCollision()) { + return false; + } + } + + if (fabs(collision.posZ()) > cfgZvtxMax) { + return false; + } + + if (cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (cfgRequireNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + if (!(cfgOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < cfgOccupancyMax)) { + return false; + } + + if constexpr (std::is_same_v, MyCollisions_Cent::iterator>) { + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + return false; + } + } + + return true; + } + + template + void processEventSelection(TCollisions const& collisions) + { + for (auto& collision : collisions) { + emevsel(isSelectedEvent(collision)); + } // end of collision loop + } // end of process + + PROCESS_SWITCH_FULL(EMEventSelection, processEventSelection, processEventSelection, "event selection", true); + PROCESS_SWITCH_FULL(EMEventSelection, processEventSelection, processEventSelection_Cent, "event selection with cent", false); + PROCESS_SWITCH_FULL(EMEventSelection, processEventSelection, processEventSelectionMC, "event selection MC", false); + PROCESS_SWITCH_FULL(EMEventSelection, processEventSelection, processEventSelectionMC_Cent, "event selection MC with cent", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"em-event-selection"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx b/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx new file mode 100644 index 00000000000..ede8ec0003d --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx @@ -0,0 +1,1366 @@ +// Copyright 2019-2020 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. + +/// \brief write relevant information about primary electrons. +/// \author daiki.sekihata@cern.ch + +#include +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/trackUtilities.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/Core/TableHelper.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; +using MyTracksMC = soa::Join; +using MyTrackMC = MyTracksMC::iterator; + +struct filterDielectronEvent { + using MyCollisions = soa::Join; + using MyCollisionsWithSWT = soa::Join; + + SliceCache cache; + Preslice perCol = o2::aod::track::collisionId; + Produces emprimaryelectrons; + Produces emprimaryelectronscov; + Produces filter; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + // Operation and minimisation criteria + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; + Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable max_mean_its_cluster_size{"max_mean_its_cluster_size", 16.f, "max. x cos(lambda)"}; + Configurable max_p_for_its_cluster_size{"max_p_for_its_cluster_size", 0.2, "its cluster size cut is applied below this p"}; + Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", -1, "pion rejection is applied below this pin"}; + Configurable minitsncls{"minitsncls", 4, "min. number of ITS clusters"}; + Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; + Configurable minpt{"minpt", 0.15, "min pt for track"}; + Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; + Configurable dca_xy_max{"dca_xy_max", 1.0f, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0f, "max DCAz in cm"}; + Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; + Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 3.5, "max. TOF n sigma for electron inclusion"}; + Configurable minTPCNsigmaPi{"minTPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.0, "max. TPC n sigma for pion exclusion"}; + Configurable maxMee{"maxMee", 0.02, "max mee for virtual photon selection"}; + + Configurable apply_phiv{"apply_phiv", true, "flag to apply phiv cut"}; + Configurable slope{"slope", 0.0181, "slope for mee vs. phiv"}; + Configurable intercept{"intercept", -0.0370, "intercept for mee vs. phiv"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + std::pair> itsRequirement = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. + + int mRunNumber; + float d_bz; + Service ccdb; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + void init(InitContext&) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + if (fillQAHistogram) { + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/hRelSigma1Pt", "relative p_{T} resolution;p_{T} (GeV/c);#sigma_{1/p_{T}} #times p_{T}", kTH2F, {{1000, 0, 10}, {100, 0, 0.1}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNclsShared", "TPC Ncls/Nfindable;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + fRegistry.add("Pair/before/hMvsPt", "m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{100, 0, 0.1}, {200, 0, 2}}, false); + fRegistry.add("Pair/before/hMvsPhiV", "mee vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0, 0.1}}, false); + fRegistry.addClone("Pair/before/", "Pair/after/"); + fRegistry.add("Pair/uls/hM", "m_{ee};m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); + fRegistry.add("Pair/lspp/hM", "m_{ee};m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); + fRegistry.add("Pair/lsmm/hM", "m_{ee};m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); + } + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + } + + template + bool checkTrack(TCollision const& collision, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + + if (track.itsChi2NCl() > maxchi2its) { + return false; + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + if (track.itsNCls() < minitsncls) { + return false; + } + + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits < itsRequirement.first) { + return false; + } + + uint32_t itsClusterSizes = track.itsClusterSizes(); + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + if (static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl())) > max_mean_its_cluster_size && track.p() < max_p_for_its_cluster_size) { + return false; + } + + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + gpu::gpustd::array dcaInfo; + auto track_par_cov_recalc = getTrackParCov(track); + track_par_cov_recalc.setPID(o2::track::PID::Electron); + // std::array pVec_recalc = {0, 0, 0}; // px, py, pz + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + // getPxPyPz(track_par_cov_recalc, pVec_recalc); + float dcaXY = dcaInfo[0]; + float dcaZ = dcaInfo[1]; + + if (fabs(dcaXY) > dca_xy_max || fabs(dcaZ) > dca_z_max) { + return false; + } + + if (track_par_cov_recalc.getPt() < minpt || fabs(track_par_cov_recalc.getEta()) > maxeta) { + return false; + } + + float dca_3d = 999.f; + float det = track_par_cov_recalc.getSigmaY2() * track_par_cov_recalc.getSigmaZ2() - track_par_cov_recalc.getSigmaZY() * track_par_cov_recalc.getSigmaZY(); + if (det < 0) { + dca_3d = 999.f; + } else { + float chi2 = (dcaXY * dcaXY * track_par_cov_recalc.getSigmaZ2() + dcaZ * dcaZ * track_par_cov_recalc.getSigmaY2() - 2. * dcaXY * dcaZ * track_par_cov_recalc.getSigmaZY()) / det; + dca_3d = std::sqrt(fabs(chi2) / 2.); + } + if (dca_3d > dca_3d_sigma_max) { + return false; + } + + return true; + } + + template + bool isElectron(TTrack const& track) + { + if (track.tpcInnerParam() < max_pin_for_pion_rejection && (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi)) { + return false; + } + if (track.hasTOF()) { + return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl; + } else { + return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl; + } + } + + template + void fillTrackTable(TCollision const& collision, TTrack const& track) + { + if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { + gpu::gpustd::array dcaInfo; + auto track_par_cov_recalc = getTrackParCov(track); + track_par_cov_recalc.setPID(o2::track::PID::Electron); + // std::array pVec_recalc = {0, 0, 0}; // px, py, pz + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + // getPxPyPz(track_par_cov_recalc, pVec_recalc); + float dcaXY = dcaInfo[0]; + float dcaZ = dcaInfo[1]; + + float pt_recalc = track_par_cov_recalc.getPt(); + float eta_recalc = track_par_cov_recalc.getEta(); + float phi_recalc = track_par_cov_recalc.getPhi(); + + bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); + + emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), + pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), + track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl(), isAssociatedToMPC); + + emprimaryelectronscov( + track_par_cov_recalc.getSigmaY2(), + track_par_cov_recalc.getSigmaZY(), + track_par_cov_recalc.getSigmaZ2(), + track_par_cov_recalc.getSigmaSnpY(), + track_par_cov_recalc.getSigmaSnpZ(), + track_par_cov_recalc.getSigmaSnp2(), + track_par_cov_recalc.getSigmaTglY(), + track_par_cov_recalc.getSigmaTglZ(), + track_par_cov_recalc.getSigmaTglSnp(), + track_par_cov_recalc.getSigmaTgl2(), + track_par_cov_recalc.getSigma1PtY(), + track_par_cov_recalc.getSigma1PtZ(), + track_par_cov_recalc.getSigma1PtSnp(), + track_par_cov_recalc.getSigma1PtTgl(), + track_par_cov_recalc.getSigma1Pt2()); + + stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); + + if (fillQAHistogram) { + uint32_t itsClusterSizes = track.itsClusterSizes(); + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + + fRegistry.fill(HIST("Track/hPt"), pt_recalc); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); + fRegistry.fill(HIST("Track/hRelSigma1Pt"), pt_recalc, std::sqrt(track_par_cov_recalc.getSigma1Pt2()) * pt_recalc); + fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); + fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / sqrt(track_par_cov_recalc.getSigmaY2()), dcaZ / sqrt(track_par_cov_recalc.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaZ2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + } + } + } + + template + o2::track::TrackParCov propagateTrack(TCollision const& collision, TTrack const& track) + { + gpu::gpustd::array dcaInfo; + auto track_par_cov_recalc = getTrackParCov(track); + track_par_cov_recalc.setPID(o2::track::PID::Electron); + // std::array pVec_recalc = {0, 0, 0}; // px, py, pz + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + // getPxPyPz(track_par_cov_recalc, pVec_recalc); + return track_par_cov_recalc; + } + + std::vector> stored_trackIds; + std::vector> stored_pairIds; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + using MyFilteredTracks = soa::Filtered; + + Partition posTracks = o2::aod::track::signed1Pt > 0.f; + Partition negTracks = o2::aod::track::signed1Pt < 0.f; + + // ---------- for data ---------- + + void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&) + { + stored_trackIds.reserve(posTracks.size() + negTracks.size()); + + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + filter(0, 0, 0); + continue; + } + + int nee_uls = 0; + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { + if (!checkTrack(collision, pos) || !checkTrack(collision, ele)) { + continue; + } + if (!isElectron(pos) || !isElectron(ele)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); + fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); + } + if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { + fillTrackTable(collision, pos); + fillTrackTable(collision, ele); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); + } + nee_uls++; + } + + } // end of pairing loop + + if (fillQAHistogram) { + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { + if (!checkTrack(collision, pos1) || !checkTrack(collision, pos2)) { + continue; + } + if (!isElectron(pos1) || !isElectron(pos2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); + } // end of pairing loop + + for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { + if (!checkTrack(collision, ele1) || !checkTrack(collision, ele2)) { + continue; + } + if (!isElectron(ele1) || !isElectron(ele2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); + } // end of pairing loop + } + + if (nee_uls < 1) { + filter(nee_uls, 0, 0); + continue; + } + filter(nee_uls, 0, 0); + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + stored_pairIds.clear(); + stored_pairIds.shrink_to_fit(); + } + PROCESS_SWITCH(filterDielectronEvent, processRec_SA, "process reconstructed info only", true); // standalone + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) + { + stored_trackIds.reserve(tracks.size() * 2); + + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + filter(0, 0, 0); + continue; + } + + int nee_uls = 0; + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + std::vector posTracks_per_coll; + std::vector negTracks_per_coll; + posTracks_per_coll.reserve(trackIdsThisCollision.size()); + negTracks_per_coll.reserve(trackIdsThisCollision.size()); + + for (auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; + } + + if (track.sign() > 0) { + posTracks_per_coll.emplace_back(track); + } else { + negTracks_per_coll.emplace_back(track); + } + } // end of track loop + + for (auto& pos : posTracks_per_coll) { + for (auto& ele : negTracks_per_coll) { + + auto pos_prop = propagateTrack(collision, pos); + auto ele_prop = propagateTrack(collision, ele); + + std::array pVec_pos = {0, 0, 0}; // px, py, pz + getPxPyPz(pos_prop, pVec_pos); + std::array pVec_ele = {0, 0, 0}; // px, py, pz + getPxPyPz(ele_prop, pVec_ele); + + ROOT::Math::PtEtaPhiMVector v1(pos_prop.getPt(), pos_prop.getEta(), pos_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele_prop.getPt(), ele_prop.getEta(), ele_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_pos[0], pVec_pos[1], pVec_pos[2], pVec_ele[0], pVec_ele[1], pVec_ele[2], pos.sign(), ele.sign(), d_bz); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); + fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); + } + if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { + fillTrackTable(collision, pos); + fillTrackTable(collision, ele); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); + } + nee_uls++; + } + + } // end of negative track loop + } // end of postive track loop + + if (fillQAHistogram) { + for (auto& pos1 : posTracks_per_coll) { + for (auto& pos2 : posTracks_per_coll) { + if (pos1.globalIndex() == pos2.globalIndex()) { + continue; + } + + auto pos1_prop = propagateTrack(collision, pos1); + auto pos2_prop = propagateTrack(collision, pos2); + + std::array pVec_pos1 = {0, 0, 0}; // px, py, pz + getPxPyPz(pos1_prop, pVec_pos1); + std::array pVec_pos2 = {0, 0, 0}; // px, py, pz + getPxPyPz(pos2_prop, pVec_pos2); + + ROOT::Math::PtEtaPhiMVector v1(pos1_prop.getPt(), pos1_prop.getEta(), pos1_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(pos2_prop.getPt(), pos2_prop.getEta(), pos2_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); + } // end of positive track loop + } // end of postive track loop + + for (auto& ele1 : negTracks_per_coll) { + for (auto& ele2 : negTracks_per_coll) { + if (ele1.globalIndex() == ele2.globalIndex()) { + continue; + } + + auto ele1_prop = propagateTrack(collision, ele1); + auto ele2_prop = propagateTrack(collision, ele2); + + std::array pVec_ele1 = {0, 0, 0}; // px, py, pz + getPxPyPz(ele1_prop, pVec_ele1); + std::array pVec_ele2 = {0, 0, 0}; // px, py, pz + getPxPyPz(ele2_prop, pVec_ele2); + + ROOT::Math::PtEtaPhiMVector v1(ele1_prop.getPt(), ele1_prop.getEta(), ele1_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele2_prop.getPt(), ele2_prop.getEta(), ele2_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); + } // end of negative track loop + } // end of negative track loop + } + + if (nee_uls < 1) { + filter(nee_uls, 0, 0); + continue; + } + + filter(nee_uls, 0, 0); + + posTracks_per_coll.clear(); + negTracks_per_coll.clear(); + posTracks_per_coll.shrink_to_fit(); + negTracks_per_coll.shrink_to_fit(); + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + stored_pairIds.clear(); + stored_pairIds.shrink_to_fit(); + } + PROCESS_SWITCH(filterDielectronEvent, processRec_TTCA, "process reconstructed info only", false); // with TTCA + + // ---------- for data ---------- + + void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&) + { + stored_trackIds.reserve(posTracks.size() + negTracks.size()); + + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + filter(0, 0, 0); + continue; + } + if (collision.swtaliastmp_raw() == 0) { + filter(0, 0, 0); + continue; + } + + int nee_uls = 0; + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { + if (!checkTrack(collision, pos) || !checkTrack(collision, ele)) { + continue; + } + if (!isElectron(pos) || !isElectron(ele)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); + fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); + } + if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { + fillTrackTable(collision, pos); + fillTrackTable(collision, ele); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); + } + nee_uls++; + } + + } // end of pairing loop + + if (fillQAHistogram) { + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { + if (!checkTrack(collision, pos1) || !checkTrack(collision, pos2)) { + continue; + } + if (!isElectron(pos1) || !isElectron(pos2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); + } // end of pairing loop + + for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { + if (!checkTrack(collision, ele1) || !checkTrack(collision, ele2)) { + continue; + } + if (!isElectron(ele1) || !isElectron(ele2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); + } // end of pairing loop + } + + if (nee_uls < 1) { + filter(nee_uls, 0, 0); + continue; + } + filter(nee_uls, 0, 0); + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + stored_pairIds.clear(); + stored_pairIds.shrink_to_fit(); + } + PROCESS_SWITCH(filterDielectronEvent, processRec_SA_SWT, "process reconstructed info only", false); // standalone + + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) + { + stored_trackIds.reserve(tracks.size() * 2); + + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + filter(0, 0, 0); + continue; + } + if (collision.swtaliastmp_raw() == 0) { + filter(0, 0, 0); + continue; + } + + int nee_uls = 0; + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + std::vector posTracks_per_coll; + std::vector negTracks_per_coll; + posTracks_per_coll.reserve(trackIdsThisCollision.size()); + negTracks_per_coll.reserve(trackIdsThisCollision.size()); + + for (auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; + } + + if (track.sign() > 0) { + posTracks_per_coll.emplace_back(track); + } else { + negTracks_per_coll.emplace_back(track); + } + } // end of track loop + + for (auto& pos : posTracks_per_coll) { + for (auto& ele : negTracks_per_coll) { + + auto pos_prop = propagateTrack(collision, pos); + auto ele_prop = propagateTrack(collision, ele); + + std::array pVec_pos = {0, 0, 0}; // px, py, pz + getPxPyPz(pos_prop, pVec_pos); + std::array pVec_ele = {0, 0, 0}; // px, py, pz + getPxPyPz(ele_prop, pVec_ele); + + ROOT::Math::PtEtaPhiMVector v1(pos_prop.getPt(), pos_prop.getEta(), pos_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele_prop.getPt(), ele_prop.getEta(), ele_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_pos[0], pVec_pos[1], pVec_pos[2], pVec_ele[0], pVec_ele[1], pVec_ele[2], pos.sign(), ele.sign(), d_bz); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); + fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); + } + if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { + fillTrackTable(collision, pos); + fillTrackTable(collision, ele); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); + } + nee_uls++; + } + + } // end of negative track loop + } // end of postive track loop + + if (fillQAHistogram) { + for (auto& pos1 : posTracks_per_coll) { + for (auto& pos2 : posTracks_per_coll) { + if (pos1.globalIndex() == pos2.globalIndex()) { + continue; + } + + auto pos1_prop = propagateTrack(collision, pos1); + auto pos2_prop = propagateTrack(collision, pos2); + + std::array pVec_pos1 = {0, 0, 0}; // px, py, pz + getPxPyPz(pos1_prop, pVec_pos1); + std::array pVec_pos2 = {0, 0, 0}; // px, py, pz + getPxPyPz(pos2_prop, pVec_pos2); + + ROOT::Math::PtEtaPhiMVector v1(pos1_prop.getPt(), pos1_prop.getEta(), pos1_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(pos2_prop.getPt(), pos2_prop.getEta(), pos2_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); + } // end of positive track loop + } // end of postive track loop + + for (auto& ele1 : negTracks_per_coll) { + for (auto& ele2 : negTracks_per_coll) { + if (ele1.globalIndex() == ele2.globalIndex()) { + continue; + } + + auto ele1_prop = propagateTrack(collision, ele1); + auto ele2_prop = propagateTrack(collision, ele2); + + std::array pVec_ele1 = {0, 0, 0}; // px, py, pz + getPxPyPz(ele1_prop, pVec_ele1); + std::array pVec_ele2 = {0, 0, 0}; // px, py, pz + getPxPyPz(ele2_prop, pVec_ele2); + + ROOT::Math::PtEtaPhiMVector v1(ele1_prop.getPt(), ele1_prop.getEta(), ele1_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele2_prop.getPt(), ele2_prop.getEta(), ele2_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); + } // end of negative track loop + } // end of negative track loop + } + + if (nee_uls < 1) { + filter(nee_uls, 0, 0); + continue; + } + + filter(nee_uls, 0, 0); + + posTracks_per_coll.clear(); + negTracks_per_coll.clear(); + posTracks_per_coll.shrink_to_fit(); + negTracks_per_coll.shrink_to_fit(); + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + stored_pairIds.clear(); + stored_pairIds.shrink_to_fit(); + } + PROCESS_SWITCH(filterDielectronEvent, processRec_TTCA_SWT, "process reconstructed info only", false); // with TTCA + + // ---------- for MC ---------- + + using MyFilteredTracksMC = soa::Filtered; + Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; + Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; + void processMC_SA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + filter(0, 0, 0); + continue; + } + + int nee_uls = 0; + auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { + if (!checkTrack(collision, pos) || !checkTrack(collision, ele)) { + continue; + } + if (!isElectron(pos) || !isElectron(ele)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); + fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); + } + if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { + fillTrackTable(collision, pos); + fillTrackTable(collision, ele); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); + } + nee_uls++; + } + + } // end of pairing loop + + if (fillQAHistogram) { + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { + if (!checkTrack(collision, pos1) || !checkTrack(collision, pos2)) { + continue; + } + if (!isElectron(pos1) || !isElectron(pos2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); + } // end of pairing loop + + for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { + if (!checkTrack(collision, ele1) || !checkTrack(collision, ele2)) { + continue; + } + if (!isElectron(ele1) || !isElectron(ele2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); + } // end of pairing loop + } + + if (nee_uls < 1) { + filter(nee_uls, 0, 0); + continue; + } + filter(nee_uls, 0, 0); + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + stored_pairIds.clear(); + stored_pairIds.shrink_to_fit(); + } + PROCESS_SWITCH(filterDielectronEvent, processMC_SA, "process reconstructed and MC info ", false); + + void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, aod::TrackAssoc const& trackIndices) + { + stored_trackIds.reserve(tracks.size() * 2); + + for (auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + filter(0, 0, 0); + continue; + } + + int nee_uls = 0; + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + std::vector posTracks_per_coll; + std::vector negTracks_per_coll; + posTracks_per_coll.reserve(trackIdsThisCollision.size()); + negTracks_per_coll.reserve(trackIdsThisCollision.size()); + + for (auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; + } + + if (track.sign() > 0) { + posTracks_per_coll.emplace_back(track); + } else { + negTracks_per_coll.emplace_back(track); + } + } // end of track loop + + for (auto& pos : posTracks_per_coll) { + for (auto& ele : negTracks_per_coll) { + auto pos_prop = propagateTrack(collision, pos); + auto ele_prop = propagateTrack(collision, ele); + std::array pVec_pos = {0, 0, 0}; // px, py, pz + getPxPyPz(pos_prop, pVec_pos); + std::array pVec_ele = {0, 0, 0}; // px, py, pz + getPxPyPz(ele_prop, pVec_ele); + + ROOT::Math::PtEtaPhiMVector v1(pos_prop.getPt(), pos_prop.getEta(), pos_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele_prop.getPt(), ele_prop.getEta(), ele_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_pos[0], pVec_pos[1], pVec_pos[2], pVec_ele[0], pVec_ele[1], pVec_ele[2], pos.sign(), ele.sign(), d_bz); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); + fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); + } + if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { + fillTrackTable(collision, pos); + fillTrackTable(collision, ele); + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); + } + nee_uls++; + } + + } // end of negative track loop + } // end of postive track loop + + if (fillQAHistogram) { + for (auto& pos1 : posTracks_per_coll) { + for (auto& pos2 : posTracks_per_coll) { + if (pos1.globalIndex() == pos2.globalIndex()) { + continue; + } + + auto pos1_prop = propagateTrack(collision, pos1); + auto pos2_prop = propagateTrack(collision, pos2); + + std::array pVec_pos1 = {0, 0, 0}; // px, py, pz + getPxPyPz(pos1_prop, pVec_pos1); + std::array pVec_pos2 = {0, 0, 0}; // px, py, pz + getPxPyPz(pos2_prop, pVec_pos2); + + ROOT::Math::PtEtaPhiMVector v1(pos1_prop.getPt(), pos1_prop.getEta(), pos1_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(pos2_prop.getPt(), pos2_prop.getEta(), pos2_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); + } // end of positive track loop + } // end of postive track loop + + for (auto& ele1 : negTracks_per_coll) { + for (auto& ele2 : negTracks_per_coll) { + if (ele1.globalIndex() == ele2.globalIndex()) { + continue; + } + + auto ele1_prop = propagateTrack(collision, ele1); + auto ele2_prop = propagateTrack(collision, ele2); + + std::array pVec_ele1 = {0, 0, 0}; // px, py, pz + getPxPyPz(ele1_prop, pVec_ele1); + std::array pVec_ele2 = {0, 0, 0}; // px, py, pz + getPxPyPz(ele2_prop, pVec_ele2); + + ROOT::Math::PtEtaPhiMVector v1(ele1_prop.getPt(), ele1_prop.getEta(), ele1_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(ele2_prop.getPt(), ele2_prop.getEta(), ele2_prop.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); + } // end of negative track loop + } // end of negative track loop + } + + if (nee_uls < 1) { + filter(nee_uls, 0, 0); + continue; + } + filter(nee_uls, 0, 0); + + posTracks_per_coll.clear(); + negTracks_per_coll.clear(); + posTracks_per_coll.shrink_to_fit(); + negTracks_per_coll.shrink_to_fit(); + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + stored_pairIds.clear(); + stored_pairIds.shrink_to_fit(); + } + PROCESS_SWITCH(filterDielectronEvent, processMC_TTCA, "process reconstructed info only", false); // with TTCA +}; +struct prefilterPrimaryElectron { + Produces ele_pfb; + void process(aod::EMPrimaryElectrons const& primaryelectrons) + { + for (int i = 0; i < primaryelectrons.size(); i++) { + ele_pfb(0); + } + } +}; +struct associateAmbiguousElectron { + Produces em_amb_ele_ids; + + SliceCache cache; + PresliceUnsorted perTrack = o2::aod::emprimaryelectron::trackId; + std::vector ambele_self_Ids; + + void process(aod::EMPrimaryElectrons const& electrons) + { + for (auto& electron : electrons) { + auto electrons_with_same_trackId = electrons.sliceBy(perTrack, electron.trackId()); + ambele_self_Ids.reserve(electrons_with_same_trackId.size()); + for (auto& amb_ele : electrons_with_same_trackId) { + if (amb_ele.globalIndex() == electron.globalIndex()) { // don't store myself. + continue; + } + ambele_self_Ids.emplace_back(amb_ele.globalIndex()); + } + em_amb_ele_ids(ambele_self_Ids); + ambele_self_Ids.clear(); + ambele_self_Ids.shrink_to_fit(); + } + } +}; +struct createEMEvent2VP { + using MyBCs = soa::Join; + using MyQvectors = soa::Join; + + using MyCollisions = soa::Join; + using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. + using MyCollisions_Cent_Qvec = soa::Join; + + using MyCollisionsWithSWT = soa::Join; + using MyCollisionsWithSWT_Cent = soa::Join; // centrality table has dependency on multiplicity table. + using MyCollisionsWithSWT_Cent_Qvec = soa::Join; + + using MyCollisionsMC = soa::Join; + using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. + using MyCollisionsMC_Cent_Qvec = soa::Join; + + Produces event; + // Produces eventcov; + Produces event_mult; + Produces event_cent; + Produces event_qvec; + Produces emswtbit; + + enum class EMEventType : int { + kEvent = 0, + kEvent_Cent = 1, + kEvent_Cent_Qvec = 2, + }; + + HistogramRegistry registry{"registry"}; + void init(o2::framework::InitContext&) + { + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{7, 0.5f, 7.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); + + registry.add("hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + + ~createEMEvent2VP() + { + swt_names.clear(); + swt_names.shrink_to_fit(); + } + + std::vector mTOIidx; + std::vector swt_names; + uint64_t mNinspectedTVX{0}; + + int mRunNumber; + + template + void skimEvent(TCollisions const& collisions, TBCs const&) + { + for (auto& collision : collisions) { + if constexpr (isMC) { + if (!collision.has_mcCollision()) { + continue; + } + } + + if constexpr (isTriggerAnalysis) { + if (collision.swtaliastmp_raw() == 0) { + continue; + } + } + + auto bc = collision.template foundBC_as(); + + if (!collision.isSelected()) { + continue; + } + + if (!(collision.neeuls() >= 1 || collision.neeuls() + collision.ngpcm() >= 2)) { + continue; + } + + if constexpr (isTriggerAnalysis) { + emswtbit(collision.swtaliastmp_raw(), collision.nInspectedTVX()); + } + + // LOGF(info, "collision.neeuls() = %d, collision.ngpcm() = %d", collision.neeuls(), collision.ngpcm()); + // LOGF(info, "collision.multNTracksPV() = %d, collision.multFT0A() = %f, collision.multFT0C() = %f", collision.multNTracksPV(), collision.multFT0A(), collision.multFT0C()); + + registry.fill(HIST("hEventCounter"), 1); + + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), + collision.posX(), collision.posY(), collision.posZ(), + collision.numContrib(), collision.trackOccupancyInTimeRange()); + + // eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + + if constexpr (eventype == EMEventType::kEvent) { + event_cent(105.f, 105.f, 105.f, 105.f); + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } else if constexpr (eventype == EMEventType::kEvent_Cent) { + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } else if constexpr (eventype == EMEventType::kEvent_Cent_Qvec) { + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + float q2xft0m = 999.f, q2yft0m = 999.f, q2xft0a = 999.f, q2yft0a = 999.f, q2xft0c = 999.f, q2yft0c = 999.f, q2xbpos = 999.f, q2ybpos = 999.f, q2xbneg = 999.f, q2ybneg = 999.f, q2xbtot = 999.f, q2ybtot = 999.f; + float q3xft0m = 999.f, q3yft0m = 999.f, q3xft0a = 999.f, q3yft0a = 999.f, q3xft0c = 999.f, q3yft0c = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; + + if (collision.qvecFT0CReVec().size() >= 2) { // harmonics 2,3 + q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; + q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; + q3xft0m = collision.qvecFT0MReVec()[1], q3xft0a = collision.qvecFT0AReVec()[1], q3xft0c = collision.qvecFT0CReVec()[1], q3xbpos = collision.qvecBPosReVec()[1], q3xbneg = collision.qvecBNegReVec()[1], q3xbtot = collision.qvecBTotReVec()[1]; + q3yft0m = collision.qvecFT0MImVec()[1], q3yft0a = collision.qvecFT0AImVec()[1], q3yft0c = collision.qvecFT0CImVec()[1], q3ybpos = collision.qvecBPosImVec()[1], q3ybneg = collision.qvecBNegImVec()[1], q3ybtot = collision.qvecBTotImVec()[1]; + } else if (collision.qvecFT0CReVec().size() >= 1) { // harmonics 2 + q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; + q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; + } + event_qvec( + q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); + } else { + event_cent(105.f, 105.f, 105.f, 105.f); + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } + } // end of collision loop + } // end of skimEvent + + void processEvent(MyCollisions const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEvent, "process event info", false); + + void processEvent_Cent(MyCollisions_Cent const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEvent_Cent, "process event info", false); + + void processEvent_Cent_Qvec(MyCollisions_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEvent_Cent_Qvec, "process event info", false); + + void processEvent_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEvent_SWT, "process event info", false); + + void processEvent_SWT_Cent(MyCollisionsWithSWT_Cent const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEvent_SWT_Cent, "process event info", false); + + void processEvent_SWT_Cent_Qvec(MyCollisionsWithSWT_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEvent_SWT_Cent_Qvec, "process event info", false); + + void processEventMC(MyCollisionsMC const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEventMC, "process event info", false); + + void processEventMC_Cent(MyCollisionsMC_Cent const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEventMC_Cent, "process event info", false); + + void processEventMC_Cent_Qvec(MyCollisionsMC_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(createEMEvent2VP, processEventMC_Cent_Qvec, "process event info", false); + + void processDummy(aod::Collisions const&) {} + PROCESS_SWITCH(createEMEvent2VP, processDummy, "processDummy", true); +}; +struct AssociateDileptonToEMEvent2VP { + Produces v0kfeventid; + Produces prmeleventid; + + Preslice perCollision_pcm = aod::v0photonkf::collisionId; + PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; + + void init(o2::framework::InitContext&) {} + + template + void fillEventId(TCollisions const& collisions, TLeptons const& leptons, TEventIds& eventIds, TPreslice const& perCollision) + { + for (auto& collision : collisions) { + auto leptons_coll = leptons.sliceBy(perCollision, collision.collisionId()); + int nl = leptons_coll.size(); + // LOGF(info, "collision.collisionId() = %d , nl = %d", collision.collisionId(), nl); + for (int il = 0; il < nl; il++) { + eventIds(collision.globalIndex()); + } // end of photon loop + } // end of collision loop + } + + // This struct is for both data and MC. + // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventDilepton in MC. + + void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) + { + fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); + } + + void processElectron(aod::EMEvents const& collisions, aod::EMPrimaryElectrons const& tracks) + { + fillEventId(collisions, tracks, prmeleventid, perCollision_el); + } + + void processDummy(aod::EMEvents const&) {} + + PROCESS_SWITCH(AssociateDileptonToEMEvent2VP, processPCM, "process pcm-event indexing", false); + PROCESS_SWITCH(AssociateDileptonToEMEvent2VP, processElectron, "process dalitzee-event indexing", false); + PROCESS_SWITCH(AssociateDileptonToEMEvent2VP, processDummy, "process dummy", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"filter-dielectron-event"}), + adaptAnalysisTask(cfgc, TaskName{"prefilter-primary-electron"}), + adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-electron"}), + adaptAnalysisTask(cfgc, TaskName{"create-emevent-2vp"}), + adaptAnalysisTask(cfgc, TaskName{"associate-dilepton-to-emevent2VP"}), + }; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx b/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx new file mode 100644 index 00000000000..3ea6dc842d8 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx @@ -0,0 +1,128 @@ +// Copyright 2019-2020 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 produces trigger information. OTS = offline trigger selection. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "CCDB/BasicCCDBManager.h" +#include "EventFiltering/Zorro.h" +#include "Common/Core/TableHelper.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct skimmerOTS { + Produces swt_tmp; + + // CCDB options + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfg_swt_names{"cfg_swt_names", "fHighTrackMult,fHighFt0Mult", "comma-separated software trigger names"}; // !trigger names have to be pre-registered in dileptonTable.h for bit operation! + + std::vector swt_names; + int mRunNumber; + Service ccdb; + + HistogramRegistry registry{"registry"}; + void init(o2::framework::InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + LOGF(info, "enable software triggers : %s", cfg_swt_names.value.data()); + std::stringstream tokenizer(cfg_swt_names.value); + std::string token; + while (std::getline(tokenizer, token, ',')) { + swt_names.emplace_back(token); + } + + const int nbin = swt_names.size(); + auto hEventCounter = registry.add("hEventCounter", "hEventCounter;;Number of Events", kTH1D, {{nbin + 1, 0.5f, nbin + 1 + 0.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + for (int idx = 0; idx < nbin; idx++) { + hEventCounter->GetXaxis()->SetBinLabel(idx + 2, swt_names[idx].data()); + } + + registry.add("hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + + ~skimmerOTS() + { + swt_names.clear(); + swt_names.shrink_to_fit(); + } + + Zorro zorro; + std::vector mTOIidx; + uint64_t mNinspectedTVX{0}; + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + mTOIidx = zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), cfg_swt_names.value); + for (auto& idx : mTOIidx) { + LOGF(info, "Trigger of Interest : index = %d", idx); + } + mNinspectedTVX = zorro.getInspectedTVX()->GetBinContent(1); + LOGF(info, "total inspected TVX events = %d in run number %d", mNinspectedTVX, bc.runNumber()); + registry.fill(HIST("hNInspectedTVX"), bc.runNumber(), mNinspectedTVX); + + mRunNumber = bc.runNumber(); + } + + using MyBCs = soa::Join; + using MyCollisions = soa::Join; + + void process(MyCollisions const& collisions, MyBCs const&) + { + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + uint16_t trigger_bitmap = 0; + registry.fill(HIST("hEventCounter"), 1); // all + if (zorro.isSelected(bc.globalBC())) { // triggered event + auto swt_bitset = zorro.getLastResult(); // this has to be called after zorro::isSelected, or simply call zorro.fetch + // LOGF(info, "swt_bitset.to_string().c_str() = %s", swt_bitset.to_string().c_str()); + for (size_t idx = 0; idx < mTOIidx.size(); idx++) { + if (swt_bitset.test(mTOIidx[idx])) { + auto swtname = swt_names[idx]; + trigger_bitmap |= BIT(o2::aod::pwgem::dilepton::swt::aliasLabels.at(swtname)); + // LOGF(info, "swtname = %s is fired. swt index in original swt table = %d, swt index for EM table = %d", swtname.data(), mTOIidx[idx], o2::aod::pwgem::dilepton::swt::aliasLabels.at(swtname)); + registry.fill(HIST("hEventCounter"), idx + 2); // fired trigger + } + } + } + // LOGF(info, "trigger_bitmap = %d, mNinspectedTVX = %d", trigger_bitmap, mNinspectedTVX); + swt_tmp(trigger_bitmap, mNinspectedTVX); + } // end of collision loop + } +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-ots"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx similarity index 59% rename from PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectron.cxx rename to PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index bac1d967584..4c3d50f2356 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -9,10 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \brief write relevant information for dalitz ee analysis to an AO2D.root file. This file is then the only necessary input to perform pcm analysis. +/// \brief write relevant information about primary electrons. /// \author daiki.sekihata@cern.ch -#include +#include #include "Math/Vector4D.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -25,16 +25,19 @@ #include "Common/Core/trackUtilities.h" #include "CommonConstants/PhysicsConstants.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" +#include "Common/Core/TableHelper.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" using namespace o2; using namespace o2::soa; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -using namespace o2::pwgem::photonmeson; + +using MyCollisions = soa::Join; +using MyCollisionsWithSWT = soa::Join; using MyTracks = soa::Join; using MyTrackMC = MyTracksMC::iterator; struct skimmerPrimaryElectron { - enum class EM_EEPairType : int { - kULS = 0, - kLSpp = +1, - kLSnn = -1, - }; - SliceCache cache; Preslice perCol = o2::aod::track::collisionId; Produces emprimaryelectrons; Produces emprimaryelectronscov; - // Produces events_bz; // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -63,56 +59,32 @@ struct skimmerPrimaryElectron { Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; // Operation and minimisation criteria + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; - Configurable max_mean_itsob_cluster_size{"max_mean_itsob_cluster_size", 16.f, "max. x cos(lambda)"}; // this is to suppress random combination. default 4 + 1 for skimming. + Configurable max_mean_its_cluster_size{"max_mean_its_cluster_size", 16.f, "max. x cos(lambda)"}; // this is to suppress random combination. default 4 + 1 for skimming. Configurable minitsncls{"minitsncls", 4, "min. number of ITS clusters"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.05, "min pt for track"}; - Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; + Configurable minpt{"minpt", 0.15, "min pt for track"}; + Configurable maxeta{"maxeta", 0.8, "eta acceptance"}; Configurable dca_xy_max{"dca_xy_max", 1.0f, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 1.0f, "max DCAz in cm"}; Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; - Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -3.0, "min. TPC n sigma for electron inclusion"}; - Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 4.0, "max. TPC n sigma for electron inclusion"}; - Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 4.0, "max. TOF n sigma for electron inclusion"}; - Configurable minTPCNsigmaPi{"minTPCNsigmaPi", 0.0, "min. TPC n sigma for pion exclusion"}; // set to -2 for lowB, -999 for nominalB - Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 0.0, "max. TPC n sigma for pion exclusion"}; - Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 2.0, "max. TPC n sigma for kaon exclusion"}; - Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 2.0, "max. TPC n sigma for proton exclusion"}; - Configurable maxMee{"maxMee", 1e+10, "max. mee to store ee pairs"}; - Configurable storeLS{"storeLS", false, "flag to store LS pairs"}; - Configurable applyKaRej_TPC{"applyKaRej_TPC", false, "flag to apply Kaon rejection in TPC at the skimming level"}; // used for CEFP only - Configurable applyPrRej_TPC{"applyPrRej_TPC", false, "flag to apply Kaon rejection in TPC at the skimming level"}; // used for CEFP only - - HistogramRegistry fRegistry{ - "fRegistry", - { - {"hNpairs", "hNpairs;pair type;Number of Pairs", {HistType::kTH1F, {{3, -1.5f, +1.5f}}}}, - {"Track/hTPCdEdx_Pin_before", "TPC dE/dx vs. p_{in};p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{1000, 0.f, 10.f}, {200, 0.f, 200.f}}}}, - {"Track/hTPCdEdx_Pin_after", "TPC dE/dx vs. p_{in};p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{1000, 0.f, 10.f}, {200, 0.f, 200.f}}}}, - {"Track/hTOFbeta_Pin_before", "TOF beta vs. p_{in};p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{1000, 0.f, 10.f}, {240, 0.f, 1.2f}}}}, - {"Track/hTOFbeta_Pin_after", "TOF beta vs. p_{in};p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{1000, 0.f, 10.f}, {240, 0.f, 1.2f}}}}, - {"Track/hTPCNsigmaEl_before", "TPC n sigma e vs. p_{in};p_{in} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTOFNsigmaEl_before", "TOF n sigma e vs. p_{in};p_{in} (GeV/c);n #sigma_{e}^{TOF}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTPCNsigmaMu_before", "TPC n sigma #mu vs. p_{in};p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTOFNsigmaMu_before", "TOF n sigma #mu vs. p_{in};p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTPCNsigmaPi_before", "TPC n sigma #pi vs. p_{in};p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTOFNsigmaPi_before", "TOF n sigma #pi vs. p_{in};p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTPCNsigmaEl_after", "TPC n sigma e vs. p_{in};p_{in} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTOFNsigmaEl_after", "TOF n sigma e vs. p_{in};p_{in} (GeV/c);n #sigma_{e}^{TOF}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTPCNsigmaMu_after", "TPC n sigma #mu vs. p_{in};p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTOFNsigmaMu_after", "TOF n sigma #mu vs. p_{in};p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTPCNsigmaPi_after", "TPC n sigma #pi vs. p_{in};p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Track/hTOFNsigmaPi_after", "TOF n sigma #pi vs. p_{in};p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, - {"Pair/hMeePtee_ULS", "ULS m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", {HistType::kTH2F, {{400, 0.f, 4.f}, {100, 0.f, 10.f}}}}, - {"Pair/hMeePtee_LSpp", "LS++ m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", {HistType::kTH2F, {{400, 0.f, 4.f}, {100, 0.f, 10.f}}}}, - {"Pair/hMeePtee_LSnn", "LS-- m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", {HistType::kTH2F, {{400, 0.f, 4.f}, {100, 0.f, 10.f}}}}, - }, - }; + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; + Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 3.5, "max. TOF n sigma for electron inclusion"}; + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.5, "max. TPC n sigma for pion exclusion"}; + Configurable minTPCNsigmaPi{"minTPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; // set to -2 for lowB, -1e+10 for nominalB + Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 2.5, "max. TPC n sigma for kaon exclusion"}; + Configurable minTPCNsigmaKa{"minTPCNsigmaKa", -2.5, "min. TPC n sigma for kaon exclusion"}; + Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 2.5, "max. TPC n sigma for proton exclusion"}; + Configurable minTPCNsigmaPr{"minTPCNsigmaPr", -2.5, "min. TPC n sigma for proton exclusion"}; + Configurable requireTOF{"requireTOF", false, "require TOF hit"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; std::pair> itsRequirement = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. @@ -130,6 +102,37 @@ struct skimmerPrimaryElectron { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + + if (fillQAHistogram) { + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -182,6 +185,10 @@ struct skimmerPrimaryElectron { } } + if (requireTOF && !(track.hasTOF() && abs(track.tofNSigmaEl()) < maxTOFNsigmaEl)) { + return false; + } + if (track.tpcChi2NCl() > maxchi2tpc) { return false; } @@ -204,14 +211,14 @@ struct skimmerPrimaryElectron { uint32_t itsClusterSizes = track.itsClusterSizes(); int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 3; layer < 7; layer++) { + for (unsigned int layer = 0; layer < 7; layer++) { int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; if (cluster_size_per_layer > 0) { nl++; } total_cluster_size += cluster_size_per_layer; } - if (static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl())) > max_mean_itsob_cluster_size) { + if (static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl())) > max_mean_its_cluster_size) { return false; } @@ -227,19 +234,24 @@ struct skimmerPrimaryElectron { return false; } - if ((0.0 < track.beta() && track.beta() < 0.95) || 1.05 < track.beta()) { + if (track.hasTOF() && (maxTOFNsigmaEl < fabs(track.tofNSigmaEl()))) { return false; } gpu::gpustd::array dcaInfo; auto track_par_cov_recalc = getTrackParCov(track); + track_par_cov_recalc.setPID(o2::track::PID::Electron); std::array pVec_recalc = {0, 0, 0}; // px, py, pz o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); getPxPyPz(track_par_cov_recalc, pVec_recalc); float dcaXY = dcaInfo[0]; float dcaZ = dcaInfo[1]; - if (track_par_cov_recalc.getPt() < minpt || abs(track_par_cov_recalc.getEta()) > maxeta) { + if (fabs(dcaXY) > dca_xy_max || fabs(dcaZ) > dca_z_max) { + return false; + } + + if (track_par_cov_recalc.getPt() < minpt || fabs(track_par_cov_recalc.getEta()) > maxeta) { return false; } @@ -249,7 +261,7 @@ struct skimmerPrimaryElectron { dca_3d = 999.f; } else { float chi2 = (dcaXY * dcaXY * track_par_cov_recalc.getSigmaZ2() + dcaZ * dcaZ * track_par_cov_recalc.getSigmaY2() - 2. * dcaXY * dcaZ * track_par_cov_recalc.getSigmaZY()) / det; - dca_3d = std::sqrt(std::abs(chi2) / 2.); + dca_3d = std::sqrt(std::fabs(chi2) / 2.); } if (dca_3d > dca_3d_sigma_max) { return false; @@ -261,7 +273,7 @@ struct skimmerPrimaryElectron { template bool isElectron(TTrack const& track) { - return isElectron_TPChadrej(track) || isElectron_TOFrecovery(track); + return isElectron_TPChadrej(track) || isElectron_TOFreq(track); } template @@ -273,49 +285,34 @@ struct skimmerPrimaryElectron { if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi) { return false; } - if (applyKaRej_TPC && abs(track.tpcNSigmaKa()) < maxTPCNsigmaKa) { + if (minTPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < maxTPCNsigmaKa) { return false; } - if (applyPrRej_TPC && abs(track.tpcNSigmaPr()) < maxTPCNsigmaPr) { + if (minTPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < maxTPCNsigmaPr) { + return false; + } + if (track.hasTOF() && (maxTOFNsigmaEl < fabs(track.tofNSigmaEl()))) { return false; } - return true; } template - bool isElectron_TOFrecovery(TTrack const& track) + bool isElectron_TOFreq(TTrack const& track) { if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi) { return false; } - return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && abs(track.tofNSigmaEl()) < maxTOFNsigmaEl; - } - - template - void fillTrackHistogram(TCollision const& collision, TTracks const& tracks) - { - for (auto& track : tracks) { - if (!checkTrack(collision, track) || !isElectron(track)) { - continue; - } - fRegistry.fill(HIST("Track/hTPCdEdx_Pin_before"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTOFbeta_Pin_before"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/hTPCNsigmaEl_before"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl_before"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu_before"), track.tpcInnerParam(), track.tpcNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu_before"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTPCNsigmaPi_before"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi_before"), track.tpcInnerParam(), track.tofNSigmaPi()); - } + return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl; } template void fillTrackTable(TCollision const& collision, TTrack const& track) { - if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::make_pair(collision.globalIndex(), track.globalIndex())) == stored_trackIds.end()) { + if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { gpu::gpustd::array dcaInfo; auto track_par_cov_recalc = getTrackParCov(track); + track_par_cov_recalc.setPID(o2::track::PID::Electron); std::array pVec_recalc = {0, 0, 0}; // px, py, pz o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); getPxPyPz(track_par_cov_recalc, pVec_recalc); @@ -325,14 +322,8 @@ struct skimmerPrimaryElectron { float pt_recalc = track_par_cov_recalc.getPt(); float eta_recalc = track_par_cov_recalc.getEta(); float phi_recalc = track_par_cov_recalc.getPhi(); - // float tgl_recalc = track_par_cov_recalc.getTgl(); - // float cYY_recalc = track_par_cov_recalc.getSigmaY2(); - // float cZZ_recalc = track_par_cov_recalc.getSigmaZ2(); - // float cZY_recalc = track_par_cov_recalc.getSigmaZY(); - // if (collision.globalIndex() != track.collisionId()) { - // LOGF(info, "dca_xy: before = %f , after = %f | pT: before = %f , after = %f | cYY : before = %f , after = %f", track.dcaXY(), dcaInfo[0], track.pt(), pt_recalc, track.cYY(), cYY_recalc); - // } + bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, @@ -341,7 +332,7 @@ struct skimmerPrimaryElectron { track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), - track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl()); + track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl(), isAssociatedToMPC); emprimaryelectronscov( track_par_cov_recalc.getSigmaY2(), @@ -360,92 +351,55 @@ struct skimmerPrimaryElectron { track_par_cov_recalc.getSigma1PtTgl(), track_par_cov_recalc.getSigma1Pt2()); - fRegistry.fill(HIST("Track/hTPCdEdx_Pin_after"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTOFbeta_Pin_after"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/hTPCNsigmaEl_after"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl_after"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu_after"), track.tpcInnerParam(), track.tpcNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu_after"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTPCNsigmaPi_after"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi_after"), track.tpcInnerParam(), track.tofNSigmaPi()); - stored_trackIds.emplace_back(std::make_pair(collision.globalIndex(), track.globalIndex())); - } - } + stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); - template - void fillPairInfo(TCollision const& collision, TTracks1 const& tracks1, TTracks2 const& tracks2) - { - if constexpr (pairtype == EM_EEPairType::kULS) { // ULS - for (auto& t1 : tracks1) { - for (auto& t2 : tracks2) { - if (!checkTrack(collision, t1) || !checkTrack(collision, t2)) { - continue; - } - if (!isElectron(t1) || !isElectron(t2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/hMeePtee_ULS"), v12.M(), v12.Pt()); - - if (v12.M() > maxMee) { // don't store - continue; - } - fRegistry.fill(HIST("hNpairs"), static_cast(pairtype)); - fillTrackTable(collision, t1); - fillTrackTable(collision, t2); - } // end of t2 - } // end of t1 - } else { // LS - std::vector> used_pairs; - used_pairs.reserve(tracks1.size() * tracks2.size()); - - for (auto& t1 : tracks1) { - for (auto& t2 : tracks2) { - if (t1.globalIndex() == t2.globalIndex()) { - continue; + if (fillQAHistogram) { + uint32_t itsClusterSizes = track.itsClusterSizes(); + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 3; layer < 7; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; } + total_cluster_size += cluster_size_per_layer; + } - if (std::find(used_pairs.begin(), used_pairs.end(), std::make_pair(t1.globalIndex(), t2.globalIndex())) == used_pairs.end()) { - if (!checkTrack(collision, t1) || !checkTrack(collision, t2)) { - continue; - } - if (!isElectron(t1) || !isElectron(t2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - if (pairtype == EM_EEPairType::kLSpp) { - fRegistry.fill(HIST("Pair/hMeePtee_LSpp"), v12.M(), v12.Pt()); - } else if (pairtype == EM_EEPairType::kLSnn) { - fRegistry.fill(HIST("Pair/hMeePtee_LSnn"), v12.M(), v12.Pt()); - } - - if (v12.M() > maxMee) { // don't store - continue; - } - fRegistry.fill(HIST("hNpairs"), static_cast(pairtype)); - fillTrackTable(collision, t1); - fillTrackTable(collision, t2); - - used_pairs.emplace_back(std::make_pair(t1.globalIndex(), t2.globalIndex())); - used_pairs.emplace_back(std::make_pair(t2.globalIndex(), t1.globalIndex())); - } - } // end of t2 - } // end of t1 - used_pairs.clear(); - used_pairs.shrink_to_fit(); + fRegistry.fill(HIST("Track/hPt"), pt_recalc); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); + fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); + fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / sqrt(track_par_cov_recalc.getSigmaY2()), dcaZ / sqrt(track_par_cov_recalc.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaZ2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); + } } } - std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl && ((0.96f < o2::aod::pidtofbeta::beta && o2::aod::pidtofbeta::beta < 1.04f) || o2::aod::pidtofbeta::beta < 0.f); + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + std::vector> stored_trackIds; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < minTPCNsigmaPi || maxTPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; @@ -453,25 +407,26 @@ struct skimmerPrimaryElectron { // ---------- for data ---------- - void processRec_SA(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { stored_trackIds.reserve(tracks.size()); for (auto& collision : collisions) { - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); - // events_bz(d_bz); - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - fillTrackHistogram(collision, posTracks_per_coll); - fillTrackHistogram(collision, negTracks_per_coll); + if (!collision.isSelected()) { + continue; + } - fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS - if (storeLS) { - fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ - fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (auto& track : tracks_per_coll) { + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; + } + fillTrackTable(collision, track); } + } // end of collision loop stored_trackIds.clear(); @@ -479,61 +434,102 @@ struct skimmerPrimaryElectron { } PROCESS_SWITCH(skimmerPrimaryElectron, processRec_SA, "process reconstructed info only", true); // standalone - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - void processRec_TTCA(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks, aod::TrackAssoc const& trackIndices) + void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) { stored_trackIds.reserve(tracks.size() * 2); for (auto& collision : collisions) { - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); - // events_bz(d_bz); + + if (!collision.isSelected()) { + continue; + } auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); - std::vector posTracks_per_coll; - std::vector negTracks_per_coll; - posTracks_per_coll.reserve(trackIdsThisCollision.size()); - negTracks_per_coll.reserve(trackIdsThisCollision.size()); for (auto& trackId : trackIdsThisCollision) { - auto track = trackId.template track_as(); + auto track = trackId.template track_as(); if (!checkTrack(collision, track) || !isElectron(track)) { continue; } + fillTrackTable(collision, track); + } + } // end of collision loop - if (track.sign() > 0) { - posTracks_per_coll.emplace_back(track); - } else { - negTracks_per_coll.emplace_back(track); + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryElectron, processRec_TTCA, "process reconstructed info only", false); // with TTCA + + void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (auto& track : tracks_per_coll) { + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; } + fillTrackTable(collision, track); } - fillTrackHistogram(collision, posTracks_per_coll); - fillTrackHistogram(collision, negTracks_per_coll); + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryElectron, processRec_SA_SWT, "process reconstructed info only", false); // standalone with swt + + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) + { + stored_trackIds.reserve(tracks.size() * 2); + + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); - fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS - if (storeLS) { - fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ - fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- + if (!collision.isSelected()) { + continue; + } + if (collision.swtaliastmp_raw() == 0) { + continue; } - posTracks_per_coll.clear(); - negTracks_per_coll.clear(); - posTracks_per_coll.shrink_to_fit(); - negTracks_per_coll.shrink_to_fit(); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + + for (auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; + } + fillTrackTable(collision, track); + } } // end of collision loop stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } - PROCESS_SWITCH(skimmerPrimaryElectron, processRec_TTCA, "process reconstructed info only", false); // with TTCA + PROCESS_SWITCH(skimmerPrimaryElectron, processRec_TTCA_SWT, "process reconstructed info only", false); // with TTCA with swt // ---------- for MC ---------- using MyFilteredTracksMC = soa::Filtered; Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; - void processMC_SA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + void processMC_SA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) { stored_trackIds.reserve(tracks.size()); @@ -541,19 +537,19 @@ struct skimmerPrimaryElectron { if (!collision.has_mcCollision()) { continue; } - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); - // events_bz(d_bz); - auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - fillTrackHistogram(collision, posTracks_per_coll); - fillTrackHistogram(collision, negTracks_per_coll); + if (!collision.isSelected()) { + continue; + } - fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS - if (storeLS) { - fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ - fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (auto& track : tracks_per_coll) { + if (!checkTrack(collision, track) || !isElectron(track)) { + continue; + } + fillTrackTable(collision, track); } } // end of collision loop @@ -562,7 +558,7 @@ struct skimmerPrimaryElectron { } PROCESS_SWITCH(skimmerPrimaryElectron, processMC_SA, "process reconstructed and MC info ", false); - void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks, aod::TrackAssoc const& trackIndices) + void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks, aod::TrackAssoc const& trackIndices) { stored_trackIds.reserve(tracks.size() * 2); @@ -570,42 +566,22 @@ struct skimmerPrimaryElectron { if (!collision.has_mcCollision()) { continue; } - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); - // events_bz(d_bz); + + if (!collision.isSelected()) { + continue; + } auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); - std::vector posTracks_per_coll; - std::vector negTracks_per_coll; - posTracks_per_coll.reserve(trackIdsThisCollision.size()); - negTracks_per_coll.reserve(trackIdsThisCollision.size()); for (auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); if (!checkTrack(collision, track) || !isElectron(track)) { continue; } - - if (track.sign() > 0) { - posTracks_per_coll.emplace_back(track); - } else { - negTracks_per_coll.emplace_back(track); - } + fillTrackTable(collision, track); } - - fillTrackHistogram(collision, posTracks_per_coll); - fillTrackHistogram(collision, negTracks_per_coll); - - fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS - if (storeLS) { - fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ - fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- - } - - posTracks_per_coll.clear(); - negTracks_per_coll.clear(); - posTracks_per_coll.shrink_to_fit(); - negTracks_per_coll.shrink_to_fit(); } // end of collision loop stored_trackIds.clear(); @@ -641,8 +617,8 @@ struct prefilterPrimaryElectron { Configurable mincrossedrows{"mincrossedrows", 40, "min crossed rows"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max chi2/NclsITS"}; - Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -4.0, "min. TPC n sigma for electron inclusion"}; - Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 4.0, "max. TPC n sigma for electron inclusion"}; + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -3.0, "min. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; @@ -712,6 +688,12 @@ struct prefilterPrimaryElectron { o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + template + bool isITSonlyTrack(TTrack const& track) + { + return track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF(); + } + template bool checkTrack(TCollision const& collision, TTrack const& track) { @@ -736,19 +718,19 @@ struct prefilterPrimaryElectron { } gpu::gpustd::array dcaInfo; - auto track_par_recalc = getTrackPar(track); + auto track_par_cov_recalc = getTrackParCov(track); std::array pVec_recalc = {0, 0, 0}; // px, py, pz - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_recalc, 2.f, matCorr, &dcaInfo); - getPxPyPz(track_par_recalc, pVec_recalc); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + getPxPyPz(track_par_cov_recalc, pVec_recalc); - if (abs(dcaInfo[0]) < min_dcatopv) { + if (fabs(dcaInfo[0]) < min_dcatopv) { return false; } - if (isITSonlyTrack(track) && track_par_recalc.getPt() > max_pt_itsonly) { + if (isITSonlyTrack(track) && track_par_cov_recalc.getPt() > max_pt_itsonly) { return false; } - if (abs(track_par_recalc.getEta()) > maxeta) { + if (fabs(track_par_cov_recalc.getEta()) > maxeta) { return false; } @@ -767,25 +749,25 @@ struct prefilterPrimaryElectron { std::array pVec_recalc = {0, 0, 0}; // px, py, pz if constexpr (loose_track_sign > 0) { // positive track is loose track - auto track_par_recalc = getTrackPar(pos); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_recalc, 2.f, matCorr, &dcaInfo); - getPxPyPz(track_par_recalc, pVec_recalc); + auto track_par_cov_recalc = getTrackParCov(pos); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + getPxPyPz(track_par_cov_recalc, pVec_recalc); ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(track_par_recalc.getPt(), track_par_recalc.getEta(), track_par_recalc.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; mee = v12.M(); - phiv = getPhivPair(pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); } else { - auto track_par_recalc = getTrackPar(ele); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_recalc, 2.f, matCorr, &dcaInfo); - getPxPyPz(track_par_recalc, pVec_recalc); + auto track_par_cov_recalc = getTrackParCov(ele); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + getPxPyPz(track_par_cov_recalc, pVec_recalc); - ROOT::Math::PtEtaPhiMVector v1(track_par_recalc.getPt(), track_par_recalc.getEta(), track_par_recalc.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v1(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; mee = v12.M(); - phiv = getPhivPair(pos.px(), pos.py(), pos.pz(), pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], pos.sign(), ele.sign(), d_bz); + phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], pos.sign(), ele.sign(), d_bz); } fRegistry.fill(HIST("hMvsPhiV_PV"), phiv, mee); @@ -799,7 +781,7 @@ struct prefilterPrimaryElectron { Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& min_dcatopv < nabs(o2::aod::track::dcaXY) && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; @@ -807,13 +789,16 @@ struct prefilterPrimaryElectron { Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0); - void processPrefilter_TTCA(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const&, aod::EMPrimaryElectrons const& primaryelectrons, aod::TrackAssoc const& trackIndices) + void processPrefilter_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const&, aod::EMPrimaryElectrons const& primaryelectrons, aod::TrackAssoc const& trackIndices) { - std::map pfb_map; // map track.globalIndex -> prefilter bit + std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit for (auto& collision : collisions) { - auto bc = collision.template bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); + if (!collision.isSelected()) { + continue; + } auto positrons_per_coll = positrons->sliceByCachedUnsorted(o2::aod::emprimaryelectron::collisionId, collision.globalIndex(), cache); // signal sample auto electrons_per_coll = electrons->sliceByCachedUnsorted(o2::aod::emprimaryelectron::collisionId, collision.globalIndex(), cache); // signal sample @@ -851,7 +836,7 @@ struct prefilterPrimaryElectron { pfb_map[empos.globalIndex()] |= (uint8_t(1) << static_cast(EM_Electron_PF::kElFromPC)); } } // end of loose electron loop - } // end of signal positon loop + } // end of signal positon loop for (auto& emele : electrons_per_coll) { // auto ele = tracks.rawIteratorAt(emele.trackId()); // use rawIterator, if the table is filtered. @@ -867,7 +852,7 @@ struct prefilterPrimaryElectron { pfb_map[emele.globalIndex()] |= (uint8_t(1) << static_cast(EM_Electron_PF::kElFromPC)); } } // end of loose positon loop - } // end of signal electron loop + } // end of signal electron loop posTracks_per_coll.clear(); negTracks_per_coll.clear(); @@ -883,13 +868,16 @@ struct prefilterPrimaryElectron { } PROCESS_SWITCH(prefilterPrimaryElectron, processPrefilter_TTCA, "process prefilter with TTCA", false); - void processPrefilter_SA(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&, aod::EMPrimaryElectrons const& primaryelectrons) + void processPrefilter_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&, aod::EMPrimaryElectrons const& primaryelectrons) { - std::map pfb_map; // map track.globalIndex -> prefilter bit + std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit for (auto& collision : collisions) { - auto bc = collision.template bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); + if (!collision.isSelected()) { + continue; + } auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample @@ -956,11 +944,11 @@ struct associateAmbiguousElectron { for (auto& electron : electrons) { auto electrons_with_same_trackId = electrons.sliceBy(perTrack, electron.trackId()); ambele_self_Ids.reserve(electrons_with_same_trackId.size()); - for (auto& amp_ele : electrons_with_same_trackId) { - if (amp_ele.globalIndex() == electron.globalIndex()) { // don't store myself. + for (auto& amb_ele : electrons_with_same_trackId) { + if (amb_ele.globalIndex() == electron.globalIndex()) { // don't store myself. continue; } - ambele_self_Ids.emplace_back(amp_ele.globalIndex()); + ambele_self_Ids.emplace_back(amb_ele.globalIndex()); } em_amb_ele_ids(ambele_self_Ids); ambele_self_Ids.clear(); diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx similarity index 66% rename from PWGEM/PhotonMeson/TableProducer/skimmerPrimaryMuon.cxx rename to PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index ab1340b97f8..fc46cf4760e 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -21,6 +21,7 @@ #include "Framework/AnalysisDataModel.h" #include "CommonConstants/PhysicsConstants.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/Core/TableHelper.h" #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" @@ -33,7 +34,7 @@ #include "MCHTracking/TrackParam.h" #include "ReconstructionDataFormats/TrackFwd.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" using namespace o2; using namespace o2::soa; @@ -41,18 +42,19 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; +using MyCollisions = soa::Join; +using MyCollisionsWithSWT = soa::Join; + using MyTracks = soa::Join; // muon tracks are repeated. i.e. not exclusive. +using MyTrack = MyTracks::iterator; + using MyTracksMC = soa::Join; +using MyTrackMC = MyTracksMC::iterator; using MFTTracksMC = soa::Join; +using MFTTrackMC = MFTTracksMC::iterator; struct skimmerPrimaryMuon { - enum class EM_MuMuPairType : int { - kULS = 0, - kLSpp = +1, - kLSnn = -1, - }; - // Index used to set different options for Muon propagation enum class MuonExtrapolation : int { kToVertex = 0, // propagtion to vertex by default @@ -70,18 +72,18 @@ struct skimmerPrimaryMuon { Produces emprimarymuonscov; // Configurables + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - Configurable minpt{"minpt", 0.1, "min pt for track"}; + Configurable minpt{"minpt", 0.2, "min pt for muon"}; Configurable mineta{"mineta", -4.0, "eta acceptance"}; Configurable maxeta{"maxeta", -2.5, "eta acceptance"}; Configurable mineta_mft{"mineta_mft", -3.6, "eta acceptance"}; Configurable maxeta_mft{"maxeta_mft", -2.5, "eta acceptance"}; Configurable minRabs{"minRabs", 17.6, "min. R at absorber end"}; Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; - Configurable maxPDCA{"maxPDCA", 1e+3, "max. p DCA to reject beam-gas background"}; o2::ccdb::CcdbApi ccdbApi; Service ccdb; @@ -91,7 +93,7 @@ struct skimmerPrimaryMuon { HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view muon_types[5] = {"MFTMCHMID/", "MFTMCHMIDOtherMatch/", "MFTMCH/", "MCHMID/", "MCH/"}; - void init(InitContext const&) + void init(InitContext&) { ccdb->setURL(ccdburl); ccdb->setCaching(true); @@ -99,7 +101,6 @@ struct skimmerPrimaryMuon { ccdb->setFatalWhenNull(false); ccdbApi.init(ccdburl); - o2::mch::TrackExtrap::setField(); addHistograms(); mRunNumber = 0; @@ -129,32 +130,34 @@ struct skimmerPrimaryMuon { fRegistry.add("Event/hNmuon", "Number of #mu per event;N_{#mu^{#minus}};N_{#mu^{+}}", kTH2F, {{101, -0.5f, 100.5}, {101, -0.5f, 100.5}}, false); // for track - auto hMuonType = fRegistry.add("Track/hMuonType", "muon type", kTH1F, {{5, -0.5f, 4.5f}}); - hMuonType->GetXaxis()->SetBinLabel(1, "MFT-MCH-MID (global muon)"); - hMuonType->GetXaxis()->SetBinLabel(2, "MFT-MCH-MID (global muon other match)"); - hMuonType->GetXaxis()->SetBinLabel(3, "MFT-MCH"); - hMuonType->GetXaxis()->SetBinLabel(4, "MCH-MID"); - hMuonType->GetXaxis()->SetBinLabel(5, "MCH standalone"); - - fRegistry.add("Track/MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{360, 0, 2 * M_PI}, {30, -5.0f, -2.0f}}, false); - fRegistry.add("Track/MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); - fRegistry.add("Track/MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); - fRegistry.add("Track/MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{200, 0.0f, 200}}, false); - fRegistry.add("Track/MFTMCHMID/hPDCA", "pDCA;p_{T,#mu} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/MFTMCHMID/hPDCA_recalc", "pDCA relcalculated;p_{T,#mu} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/MFTMCHMID/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hMatchScoreMCHMFT", "match score MCH-MFT;score", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hDCAxy2D", "DCA xy;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); - fRegistry.add("Track/MFTMCHMID/hDCAxy2DinSigma", "DCA xy;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); - fRegistry.add("Track/MFTMCHMID/hDCAxySigma", "DCA_{xy};DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T,#mu};p_{T,#mu} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {100, 0, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T,#mu};p_{T,#mu} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {100, 0, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMFT_DCAxySigma", "chi2 match MCH-MFT;DCA_{xy,#mu} (#sigma);MFT-MCH matching chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); - fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);MFT-MCH matching chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); - fRegistry.addClone("Track/MFTMCHMID/", "Track/MCHMID/"); + if (fillQAHistogram) { + auto hMuonType = fRegistry.add("Track/hMuonType", "muon type", kTH1F, {{5, -0.5f, 4.5f}}); + hMuonType->GetXaxis()->SetBinLabel(1, "MFT-MCH-MID (global muon)"); + hMuonType->GetXaxis()->SetBinLabel(2, "MFT-MCH-MID (global muon other match)"); + hMuonType->GetXaxis()->SetBinLabel(3, "MFT-MCH"); + hMuonType->GetXaxis()->SetBinLabel(4, "MCH-MID"); + hMuonType->GetXaxis()->SetBinLabel(5, "MCH standalone"); + + fRegistry.add("Track/MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{360, 0, 2 * M_PI}, {30, -5.0f, -2.0f}}, false); + fRegistry.add("Track/MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); + fRegistry.add("Track/MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); + fRegistry.add("Track/MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{200, 0.0f, 200}}, false); + fRegistry.add("Track/MFTMCHMID/hPDCA", "pDCA;p_{T,#mu} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); + fRegistry.add("Track/MFTMCHMID/hPDCA_recalc", "pDCA relcalculated;p_{T,#mu} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); + fRegistry.add("Track/MFTMCHMID/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hMatchScoreMCHMFT", "match score MCH-MFT;score", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hDCAxy2D", "DCA xy;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); + fRegistry.add("Track/MFTMCHMID/hDCAxy2DinSigma", "DCA xy;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); + fRegistry.add("Track/MFTMCHMID/hDCAxySigma", "DCA_{xy};DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T,#mu};p_{T,#mu} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {100, 0, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T,#mu};p_{T,#mu} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {100, 0, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMFT_DCAxySigma", "chi2 match MCH-MFT;DCA_{xy,#mu} (#sigma);MFT-MCH matching chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); + fRegistry.add("Track/MFTMCHMID/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);MFT-MCH matching chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); + fRegistry.addClone("Track/MFTMCHMID/", "Track/MCHMID/"); + } } template @@ -162,18 +165,11 @@ struct skimmerPrimaryMuon { { o2::dataformats::GlobalFwdTrack propmuonAtPV = PropagateMuon(track, collision, skimmerPrimaryMuon::MuonExtrapolation::kToVertex); // this is for MCH-MID tracks that cannot see the primary vertex. o2::dataformats::GlobalFwdTrack propmuonAtDCA = PropagateMuon(track, collision, skimmerPrimaryMuon::MuonExtrapolation::kToDCA); - o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(track, collision, skimmerPrimaryMuon::MuonExtrapolation::kToRabs); - float p = propmuonAtDCA.getP(); - float pt = propmuonAtDCA.getPt(); - float eta = propmuonAtDCA.getEta(); - float phi = propmuonAtDCA.getPhi(); - if (static_cast(track.trackType()) > 2) { // only for MUON standalone - p = propmuonAtPV.getP(); - pt = propmuonAtPV.getPt(); - eta = propmuonAtPV.getEta(); - phi = propmuonAtPV.getPhi(); - } + float p = propmuonAtPV.getP(); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); o2::math_utils::bringTo02Pi(phi); if (phi < 0.f || 2.f * M_PI < phi) { @@ -192,6 +188,7 @@ struct skimmerPrimaryMuon { float rAtAbsorberEnd = track.rAtAbsorberEnd(); if (static_cast(track.trackType()) > 2) { // only for MUON standalone + o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(track, collision, skimmerPrimaryMuon::MuonExtrapolation::kToRabs); float xAbs = propmuonAtRabs.getX(); float yAbs = propmuonAtRabs.getY(); rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); @@ -218,6 +215,7 @@ struct skimmerPrimaryMuon { dcaXYinSigma = std::sqrt(std::abs(chi2) / 2.); // in sigma } + fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(muon_types[mu_id]) + HIST("hPt"), pt); fRegistry.fill(HIST("Track/") + HIST(muon_types[mu_id]) + HIST("hEtaPhi"), phi, eta); fRegistry.fill(HIST("Track/") + HIST(muon_types[mu_id]) + HIST("hNclusters"), track.nClusters()); @@ -237,35 +235,14 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("Track/") + HIST(muon_types[mu_id]) + HIST("hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um } - template - bool isGlobalMuon(TTrack const& track) - { - if (track.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { - return false; - } - if (track.eta() < mineta_mft || maxeta_mft < track.eta()) { - return false; - } - return true; - } - - template - bool isStandaloneMuon(TTrack const& track) - { - if (track.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - return false; - } - return true; - } - template o2::dataformats::GlobalFwdTrack PropagateMuon(T const& muon, C const& collision, const skimmerPrimaryMuon::MuonExtrapolation endPoint) { double chi2 = muon.chi2(); SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), muon.signed1Pt()); - std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), - muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), - muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; + std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), + muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), + muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; SMatrix55 tcovs(v1.begin(), v1.end()); o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2}; o2::dataformats::GlobalFwdTrack propmuon; @@ -302,6 +279,10 @@ struct skimmerPrimaryMuon { propmuon.setZ(fwdtrack.getZ()); propmuon.setCovariances(fwdtrack.getCovariances()); } + + v1.clear(); + v1.shrink_to_fit(); + return propmuon; } @@ -315,16 +296,13 @@ struct skimmerPrimaryMuon { } o2::dataformats::GlobalFwdTrack propmuonAtPV = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToVertex); - o2::dataformats::GlobalFwdTrack propmuonAtDCA = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToDCA); - o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToRabs); - - // float pt = propmuonAtDCA.getPt(); - float eta = propmuonAtDCA.getEta(); - float phi = propmuonAtDCA.getPhi(); - if (static_cast(muon.trackType()) > 2) { // only for MUON standalone - // pt = propmuonAtPV.getPt(); - eta = propmuonAtPV.getEta(); - phi = propmuonAtPV.getPhi(); + + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + + if (pt < minpt) { + return false; } if (eta < mineta || maxeta < eta) { @@ -345,6 +323,7 @@ struct skimmerPrimaryMuon { return false; } } else if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToRabs); float xAbs = propmuonAtRabs.getX(); float yAbs = propmuonAtRabs.getY(); rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); // Redo propagation only for muon tracks // propagation of MFT tracks alredy done in reconstruction @@ -358,21 +337,15 @@ struct skimmerPrimaryMuon { return true; } - template + template void fillMuonTable(TMuon const& muon, TCollision const& collision, const int new_muon_sa_id) { o2::dataformats::GlobalFwdTrack propmuonAtPV = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToVertex); o2::dataformats::GlobalFwdTrack propmuonAtDCA = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToDCA); - o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToRabs); - - float pt = propmuonAtDCA.getPt(); - float eta = propmuonAtDCA.getEta(); - float phi = propmuonAtDCA.getPhi(); - if (static_cast(muon.trackType()) > 2) { // only for MUON standalone - pt = propmuonAtPV.getPt(); - eta = propmuonAtPV.getEta(); - phi = propmuonAtPV.getPhi(); - } + + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); o2::math_utils::bringTo02Pi(phi); @@ -381,20 +354,22 @@ struct skimmerPrimaryMuon { float rAtAbsorberEnd = muon.rAtAbsorberEnd(); if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(muon, collision, skimmerPrimaryMuon::MuonExtrapolation::kToRabs); float xAbs = propmuonAtRabs.getX(); float yAbs = propmuonAtRabs.getY(); rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); // Redo propagation only for muon tracks // propagation of MFT tracks alredy done in reconstruction } + bool isAssociatedToMPC = collision.globalIndex() == muon.collisionId(); auto fwdcov = propmuonAtDCA.getCovariances(); if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { - auto mftsa_track = muon.template matchMFTTrack_as(); + auto mftsa_track = muon.template matchMFTTrack_as(); emprimarymuons(collision.globalIndex(), muon.globalIndex(), muon.trackType(), pt, eta, phi, muon.sign(), dcaX, dcaY, propmuonAtDCA.getX(), propmuonAtDCA.getY(), propmuonAtDCA.getZ(), propmuonAtDCA.getTgl(), muon.nClusters(), muon.pDca(), rAtAbsorberEnd, muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), new_muon_sa_id, - muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), mftsa_track.mftClusterSizesAndTrackFlags()); + muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), mftsa_track.mftClusterSizesAndTrackFlags(), mftsa_track.chi2(), isAssociatedToMPC); emprimarymuonscov( fwdcov(0, 0), fwdcov(0, 1), fwdcov(1, 1), @@ -406,7 +381,7 @@ struct skimmerPrimaryMuon { propmuonAtDCA.getX(), propmuonAtDCA.getY(), propmuonAtDCA.getZ(), propmuonAtDCA.getTgl(), muon.nClusters(), muon.pDca(), rAtAbsorberEnd, muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), new_muon_sa_id, - muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), 0); + muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), 0, 999999.f, isAssociatedToMPC); emprimarymuonscov( fwdcov(0, 0), fwdcov(0, 1), fwdcov(1, 1), @@ -426,18 +401,21 @@ struct skimmerPrimaryMuon { std::map, int> map_new_sa_muon_index; // new standalone muon index - // Filter muonFilter = (o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) || o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)); - // using MyFilteredTracks = soa::Filtered; + // Preslice fwdtrackIndicesPerMFTsa = aod::fwdtrack::matchMFTTrackId; + Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; Partition global_muons = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack); // MFT-MCH-MID Partition sa_muons = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack); // MCH-MID - void processRec_SA(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::MFTTracks const&) + void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::MFTTracks const&) { for (auto& collision : collisions) { - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); fRegistry.fill(HIST("Event/hCollisionCounter"), 0.f); + if (!collision.isSelected()) { + continue; + } auto sa_muons_per_coll = sa_muons->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); auto global_muons_per_coll = global_muons->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); @@ -446,19 +424,18 @@ struct skimmerPrimaryMuon { int offset = emprimarymuons.lastIndex() + 1; for (auto& track : sa_muons_per_coll) { - fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); - fillTrackHistogram<3>(track, collision); - fRegistry.fill(HIST("Track/MCHMID/hNclustersMFT"), 0); - + if (fillQAHistogram) { + fillTrackHistogram<3>(track, collision); + } if (isSelected(track, collision)) { map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; counter++; } } // end of standalone muon loop for (auto& track : global_muons_per_coll) { - fillTrackHistogram<0>(track, collision); - auto mftsa_track = track.template matchMFTTrack_as(); - fRegistry.fill(HIST("Track/MFTMCHMID/hNclustersMFT"), mftsa_track.nClusters()); + if (fillQAHistogram) { + fillTrackHistogram<0>(track, collision); + } if (map_new_sa_muon_index.find(std::make_pair(collision.globalIndex(), track.matchMCHTrackId())) == map_new_sa_muon_index.end()) { // don't apply muon selection to MCH-MID track in MFT-MCH-MID track map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())] = counter + offset; @@ -478,30 +455,26 @@ struct skimmerPrimaryMuon { // LOGF(info, "collisionId = %d, fwdtrackId = %d, new_fwdtrackId = %d", collisionId, fwdtrackId, new_fwdtrackId); auto track = tracks.iteratorAt(std::get<1>(key)); if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - fillMuonTable(track, collision, value); + fillMuonTable(track, collision, value); } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { - fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); + fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); } } - // auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); - // for (auto& track : tracks_per_coll) { - // fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); - // LOGF(info, "SA | track.globalIndex() = %d, track.trackType() = %d, track.matchMFTTrackId() = %d, track.matchMCHTrackId() = %d, track.offsets() = %d", track.globalIndex(), track.trackType(), track.matchMFTTrackId(), track.matchMCHTrackId(), track.offsets()); - // } // end of track loop - map_new_sa_muon_index.clear(); } // end of collision loop } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_SA, "process reconstructed info only with standalone", true); - Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; - void processRec_TTCA(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::MFTTracks const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::MFTTracks const&, aod::FwdTrackAssoc const& fwdtrackIndices) { for (auto& collision : collisions) { - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); fRegistry.fill(HIST("Event/hCollisionCounter"), 0.f); + if (!collision.isSelected()) { + continue; + } int counter = 0; int offset = emprimarymuons.lastIndex() + 1; @@ -509,26 +482,151 @@ struct skimmerPrimaryMuon { auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (auto& fwdtrackId : fwdtrackIdsThisCollision) { auto track = fwdtrackId.template fwdtrack_as(); - fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); // LOGF(info, "TTCA | collision.globalIndex() = %d, track.globalIndex() = %d, track.trackType() = %d, track.matchMFTTrackId() = %d, track.matchMCHTrackId() = %d, track.offsets() = %d", collision.globalIndex(), track.globalIndex(), track.trackType(), track.matchMFTTrackId(), track.matchMCHTrackId(), track.offsets()); - // auto collision_in_track = track.collision_as(); + // auto collision_in_track = track.collision_as(); // auto bc_in_track = collision_in_track.bc_as(); // LOGF(info, "track.globalIndex() = %d , bc_in_track.globalBC() = %lld", track.globalIndex(), bc_in_track.globalBC()); if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - fillTrackHistogram<3>(track, collision); - fRegistry.fill(HIST("Track/MCHMID/hNclustersMFT"), 0); - + if (fillQAHistogram) { + fillTrackHistogram<3>(track, collision); + } if (isSelected(track, collision)) { map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; counter++; } } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (fillQAHistogram) { + fillTrackHistogram<0>(track, collision); + } + if (map_new_sa_muon_index.find(std::make_pair(collision.globalIndex(), track.matchMCHTrackId())) == map_new_sa_muon_index.end()) { + map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())] = counter + offset; + counter++; + } + if (isSelected(track, collision)) { + map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; + counter++; + } + } + } // end of track loop + + for (const auto& [key, value] : map_new_sa_muon_index) { + // int collisionId = std::get<0>(key); + // int fwdtrackId = std::get<1>(key); + // int new_fwdtrackId = value; + auto track = tracks.iteratorAt(std::get<1>(key)); + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + fillMuonTable(track, collision, value); + } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); + } + } + + map_new_sa_muon_index.clear(); + } // end of collision loop + } + PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA, "process reconstructed info only with TTCA", false); + + void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::MFTTracks const&) + { + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + fRegistry.fill(HIST("Event/hCollisionCounter"), 0.f); + if (!collision.isSelected()) { + continue; + } + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + auto sa_muons_per_coll = sa_muons->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + auto global_muons_per_coll = global_muons->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + + int counter = 0; + int offset = emprimarymuons.lastIndex() + 1; + + for (auto& track : sa_muons_per_coll) { + if (fillQAHistogram) { + fillTrackHistogram<3>(track, collision); + } + if (isSelected(track, collision)) { + map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; + counter++; + } + } // end of standalone muon loop + for (auto& track : global_muons_per_coll) { + if (fillQAHistogram) { fillTrackHistogram<0>(track, collision); - auto mftsa_track = track.template matchMFTTrack_as(); - fRegistry.fill(HIST("Track/MFTMCHMID/hNclustersMFT"), mftsa_track.nClusters()); + } + + if (map_new_sa_muon_index.find(std::make_pair(collision.globalIndex(), track.matchMCHTrackId())) == map_new_sa_muon_index.end()) { // don't apply muon selection to MCH-MID track in MFT-MCH-MID track + map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())] = counter + offset; + counter++; + } + if (isSelected(track, collision)) { + map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; + counter++; + } + } // end of global muon loop + + // fill table after mapping + for (const auto& [key, value] : map_new_sa_muon_index) { + // int collisionId = std::get<0>(key); + // int fwdtrackId = std::get<1>(key); + // int new_fwdtrackId = value; + // LOGF(info, "collisionId = %d, fwdtrackId = %d, new_fwdtrackId = %d", collisionId, fwdtrackId, new_fwdtrackId); + auto track = tracks.iteratorAt(std::get<1>(key)); + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + fillMuonTable(track, collision, value); + } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); + } + } + + map_new_sa_muon_index.clear(); + } // end of collision loop + } + PROCESS_SWITCH(skimmerPrimaryMuon, processRec_SA_SWT, "process reconstructed info only with standalone", false); + + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::MFTTracks const&, aod::FwdTrackAssoc const& fwdtrackIndices) + { + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + fRegistry.fill(HIST("Event/hCollisionCounter"), 0.f); + if (!collision.isSelected()) { + continue; + } + if (collision.swtaliastmp_raw() == 0) { + continue; + } + int counter = 0; + int offset = emprimarymuons.lastIndex() + 1; + + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + for (auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto track = fwdtrackId.template fwdtrack_as(); + // LOGF(info, "TTCA | collision.globalIndex() = %d, track.globalIndex() = %d, track.trackType() = %d, track.matchMFTTrackId() = %d, track.matchMCHTrackId() = %d, track.offsets() = %d", collision.globalIndex(), track.globalIndex(), track.trackType(), track.matchMFTTrackId(), track.matchMCHTrackId(), track.offsets()); + + // auto collision_in_track = track.collision_as(); + // auto bc_in_track = collision_in_track.bc_as(); + // LOGF(info, "track.globalIndex() = %d , bc_in_track.globalBC() = %lld", track.globalIndex(), bc_in_track.globalBC()); + + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (fillQAHistogram) { + fillTrackHistogram<3>(track, collision); + } + if (isSelected(track, collision)) { + map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; + counter++; + } + } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (fillQAHistogram) { + fillTrackHistogram<0>(track, collision); + } if (map_new_sa_muon_index.find(std::make_pair(collision.globalIndex(), track.matchMCHTrackId())) == map_new_sa_muon_index.end()) { map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())] = counter + offset; counter++; @@ -546,29 +644,32 @@ struct skimmerPrimaryMuon { // int new_fwdtrackId = value; auto track = tracks.iteratorAt(std::get<1>(key)); if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - fillMuonTable(track, collision, value); + fillMuonTable(track, collision, value); } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { - fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); + fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); } } map_new_sa_muon_index.clear(); } // end of collision loop } - PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA, "process reconstructed info only with TTCA", false); + PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_SWT, "process reconstructed info only with TTCA", false); Partition global_muons_mc = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack); // MFT-MCH-MID Partition sa_muons_mc = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack); // MCH-MID - void processMC_SA(soa::Join const& collisions, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, MFTTracksMC const&) + void processMC_SA(soa::Join const& collisions, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, MFTTracksMC const&) { for (auto& collision : collisions) { if (!collision.has_mcCollision()) { continue; } - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); fRegistry.fill(HIST("Event/hCollisionCounter"), 0.f); + if (!collision.isSelected()) { + continue; + } auto sa_muons_mc_per_coll = sa_muons_mc->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); auto global_muons_mc_per_coll = global_muons_mc->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); @@ -577,10 +678,9 @@ struct skimmerPrimaryMuon { int offset = emprimarymuons.lastIndex() + 1; for (auto& track : sa_muons_mc_per_coll) { - fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); - fillTrackHistogram<3>(track, collision); - fRegistry.fill(HIST("Track/MCHMID/hNclustersMFT"), 0); - + if (fillQAHistogram) { + fillTrackHistogram<3>(track, collision); + } if (isSelected(track, collision)) { map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; counter++; @@ -591,10 +691,9 @@ struct skimmerPrimaryMuon { if (!sa_muon.has_mcParticle()) { continue; } - fillTrackHistogram<0>(track, collision); - auto mftsa_track = track.template matchMFTTrack_as(); - fRegistry.fill(HIST("Track/MFTMCHMID/hNclustersMFT"), mftsa_track.nClusters()); - + if (fillQAHistogram) { + fillTrackHistogram<0>(track, collision); + } if (map_new_sa_muon_index.find(std::make_pair(collision.globalIndex(), track.matchMCHTrackId())) == map_new_sa_muon_index.end()) { // don't apply muon selection to MCH-MID track in MFT-MCH-MID track map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())] = counter + offset; counter++; @@ -613,32 +712,29 @@ struct skimmerPrimaryMuon { // LOGF(info, "collisionId = %d, fwdtrackId = %d, new_fwdtrackId = %d", collisionId, fwdtrackId, new_fwdtrackId); auto track = tracks.iteratorAt(std::get<1>(key)); if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - fillMuonTable(track, collision, value); + fillMuonTable(track, collision, value); } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { - fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); + fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); } } - // auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); - // for (auto& track : tracks_per_coll) { - // fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); - // LOGF(info, "SA | track.globalIndex() = %d, track.trackType() = %d, track.matchMFTTrackId() = %d, track.matchMCHTrackId() = %d, track.offsets() = %d", track.globalIndex(), track.trackType(), track.matchMFTTrackId(), track.matchMCHTrackId(), track.offsets()); - // } // end of track loop - map_new_sa_muon_index.clear(); } // end of collision loop } PROCESS_SWITCH(skimmerPrimaryMuon, processMC_SA, "process reconstructed and MC info", false); - void processMC_TTCA(soa::Join const& collisions, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, MFTTracksMC const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processMC_TTCA(soa::Join const& collisions, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, MFTTracksMC const&, aod::FwdTrackAssoc const& fwdtrackIndices) { for (auto& collision : collisions) { if (!collision.has_mcCollision()) { continue; } - auto bc = collision.bc_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); fRegistry.fill(HIST("Event/hCollisionCounter"), 0.f); + if (!collision.isSelected()) { + continue; + } int counter = 0; int offset = emprimarymuons.lastIndex() + 1; @@ -646,13 +742,12 @@ struct skimmerPrimaryMuon { auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (auto& fwdtrackId : fwdtrackIdsThisCollision) { auto track = fwdtrackId.template fwdtrack_as(); - fRegistry.fill(HIST("Track/hMuonType"), track.trackType()); // LOGF(info, "TTCA | track.globalIndex() = %d, track.trackType() = %d, track.matchMFTTrackId() = %d, track.matchMCHTrackId() = %d, track.offsets() = %d", track.globalIndex(), track.trackType(), track.matchMFTTrackId(), track.matchMCHTrackId(), track.offsets()); if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - fillTrackHistogram<3>(track, collision); - fRegistry.fill(HIST("Track/MCHMID/hNclustersMFT"), 0); - + if (fillQAHistogram) { + fillTrackHistogram<3>(track, collision); + } if (isSelected(track, collision)) { map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.globalIndex())] = counter + offset; counter++; @@ -662,10 +757,9 @@ struct skimmerPrimaryMuon { if (!sa_muon.has_mcParticle()) { continue; } - fillTrackHistogram<0>(track, collision); - auto mftsa_track = track.template matchMFTTrack_as(); - fRegistry.fill(HIST("Track/MFTMCHMID/hNclustersMFT"), mftsa_track.nClusters()); - + if (fillQAHistogram) { + fillTrackHistogram<0>(track, collision); + } if (map_new_sa_muon_index.find(std::make_pair(collision.globalIndex(), track.matchMCHTrackId())) == map_new_sa_muon_index.end()) { map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())] = counter + offset; counter++; @@ -683,9 +777,9 @@ struct skimmerPrimaryMuon { // int new_fwdtrackId = value; auto track = tracks.iteratorAt(std::get<1>(key)); if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { - fillMuonTable(track, collision, value); + fillMuonTable(track, collision, value); } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { - fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); + fillMuonTable(track, collision, map_new_sa_muon_index[std::make_pair(collision.globalIndex(), track.matchMCHTrackId())]); } } diff --git a/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx new file mode 100644 index 00000000000..889dcfa2dcf --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx @@ -0,0 +1,621 @@ +// Copyright 2019-2020 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. + +/// \brief write relevant information about primary electrons. +/// \author daiki.sekihata@cern.ch + +#include +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/trackUtilities.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +using MyCollisions = soa::Join; +using MyCollisionsMC = soa::Join; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; +using MyTracksMC = soa::Join; +using MyTrackMC = MyTracksMC::iterator; + +struct skimmerSecondaryElectron { + // enum class EM_EEPairType : int { + // kULS = 0, + // kLSpp = +1, + // kLSmm = -1, + // }; + + SliceCache cache; + Preslice perCol = o2::aod::track::collisionId; + Produces emprimaryelectrons; + Produces emprimaryelectronscov; + Produces event; + Produces event_mult; + Produces event_cent; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + // Operation and minimisation criteria + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; + Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable minitsncls{"minitsncls", 4, "min. number of ITS clusters"}; + Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; + Configurable minpt{"minpt", 0.15, "min pt for track"}; + Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; + Configurable dca_xy_max{"dca_xy_max", 1.0f, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0f, "max DCAz in cm"}; + Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -3.0, "min. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", +4.0, "max. TPC n sigma for electron inclusion"}; + Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; + Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; + Configurable mee_min{"mee_min", 0.0f, "minimum mee to distinguish photon conversion and dalitz decay"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + std::pair> itsRequirement = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. + + int mRunNumber; + float d_bz; + Service ccdb; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + void init(InitContext&) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + if (fillQAHistogram) { + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFbeta", "TOF beta;p_{in} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); + fRegistry.add("Track/h1overTOFbeta", "TOF beta;p_{in} (GeV/c);1/#beta", kTH2F, {{1000, 0, 10}, {1000, 0.8, 1.8}}, false); + fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {32, 0, 16}}, false); + fRegistry.add("Pair/hMvsPhiV", "mee vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0, 0.1}}, false); + } + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + } + + template + bool checkTrack(TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + + if (track.itsChi2NCl() > maxchi2its) { + return false; + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + if (track.itsNCls() < minitsncls) { + return false; + } + + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits < itsRequirement.first) { + return false; + } + + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (abs(track.dcaXY()) > dca_xy_max || abs(track.dcaZ()) > dca_z_max) { + return false; + } + + if (track.pt() < minpt || abs(track.eta()) > maxeta) { + return false; + } + + return true; + } + + template + void fillTrackTable(TCollision const& collision, TTrack const& track) + { + if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { + gpu::gpustd::array dcaInfo; + auto track_par_cov_recalc = getTrackParCov(track); + track_par_cov_recalc.setPID(o2::track::PID::Electron); + std::array pVec_recalc = {0, 0, 0}; // px, py, pz + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); + getPxPyPz(track_par_cov_recalc, pVec_recalc); + float dcaXY = dcaInfo[0]; + float dcaZ = dcaInfo[1]; + + float pt_recalc = track_par_cov_recalc.getPt(); + float eta_recalc = track_par_cov_recalc.getEta(); + float phi_recalc = track_par_cov_recalc.getPhi(); + + bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); + + emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), + pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), + track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl(), isAssociatedToMPC); + + emprimaryelectronscov( + track_par_cov_recalc.getSigmaY2(), + track_par_cov_recalc.getSigmaZY(), + track_par_cov_recalc.getSigmaZ2(), + track_par_cov_recalc.getSigmaSnpY(), + track_par_cov_recalc.getSigmaSnpZ(), + track_par_cov_recalc.getSigmaSnp2(), + track_par_cov_recalc.getSigmaTglY(), + track_par_cov_recalc.getSigmaTglZ(), + track_par_cov_recalc.getSigmaTglSnp(), + track_par_cov_recalc.getSigmaTgl2(), + track_par_cov_recalc.getSigma1PtY(), + track_par_cov_recalc.getSigma1PtZ(), + track_par_cov_recalc.getSigma1PtSnp(), + track_par_cov_recalc.getSigma1PtTgl(), + track_par_cov_recalc.getSigma1Pt2()); + + stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); + + if (fillQAHistogram) { + uint32_t itsClusterSizes = track.itsClusterSizes(); + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 3; layer < 7; layer++) { + int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + + fRegistry.fill(HIST("Track/hPt"), pt_recalc); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); + fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); + fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / sqrt(track_par_cov_recalc.getSigmaY2()), dcaZ / sqrt(track_par_cov_recalc.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaZ2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/hTOFbeta"), track.tpcInnerParam(), track.beta()); + fRegistry.fill(HIST("Track/h1overTOFbeta"), track.tpcInnerParam(), 1. / track.beta()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); + } + } + } + + std::vector> stored_trackIds; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; + Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + using MyFilteredTracks = soa::Filtered; + + Partition posTracks = o2::aod::track::signed1Pt > 0.f; + Partition negTracks = o2::aod::track::signed1Pt < 0.f; + + // ---------- for data ---------- + + void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample + + int npair = 0; + for (auto& [pos, neg] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + + if (!checkTrack(pos) || !checkTrack(neg)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float mee = v12.M(); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), neg.px(), neg.py(), neg.pz(), pos.sign(), neg.sign(), d_bz); + + if (mee < mee_min || slope * phiv + intercept < mee) { // select phocon conversions + continue; + } + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/hMvsPhiV"), phiv, mee); + } + fillTrackTable(collision, pos); + fillTrackTable(collision, neg); + npair++; + } + + if (npair < 0.5) { + continue; + } + + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), + collision.posX(), collision.posY(), collision.posZ(), + collision.numContrib(), collision.trackOccupancyInTimeRange()); + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerSecondaryElectron, processRec, "process reconstructed info only", true); // standalone + + // ---------- for MC ---------- + using MyFilteredTracksMC = soa::Filtered; + Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; + Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; + void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + auto bc = collision.bc_as(); + initCCDB(bc); + + if (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + + auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample + auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample + + int npair = 0; + for (auto& [pos, neg] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (!checkTrack(pos) || !checkTrack(neg)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float mee = v12.M(); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), neg.px(), neg.py(), neg.pz(), pos.sign(), neg.sign(), d_bz); + + if (mee < mee_min || slope * phiv + intercept < mee) { // select phocon conversions + continue; + } + if (fillQAHistogram) { + fRegistry.fill(HIST("Pair/hMvsPhiV"), phiv, mee); + } + fillTrackTable(collision, pos); + fillTrackTable(collision, neg); + npair++; + } + + if (npair < 0.5) { + continue; + } + + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), + collision.posX(), collision.posY(), collision.posZ(), + collision.numContrib(), collision.trackOccupancyInTimeRange()); + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerSecondaryElectron, processMC, "process reconstructed and MC info ", false); +}; + +struct AssociateMCInfoSecondaryElectron { + Produces mcevents; + Produces mceventlabels; + Produces emmcparticles; + Produces emprimaryelectronmclabels; + + HistogramRegistry registry{"EMMCEvent"}; + void init(o2::framework::InitContext&) + { + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{6, 0.5f, 6.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + hEventCounter->GetXaxis()->SetBinLabel(2, "has mc collision"); + } + + void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::McParticles const& mcTracks, MyTracksMC const& o2tracks, aod::EMEvents const& emevents, aod::EMPrimaryElectrons const& emprimaryelectrons) + { + // temporary variables used for the indexing of the skimmed MC stack + std::map fNewLabels; + std::map fNewLabelsReversed; + // std::map fMCFlags; + std::map fEventIdx; + std::map fEventLabels; + int fCounters[2] = {0, 0}; //! [0] - particle counter, [1] - event counter + + for (auto& emevent : emevents) { + registry.fill(HIST("hEventCounter"), 1); + auto collision = collisions.iteratorAt(emevent.collisionId()); + auto mcCollision = collision.mcCollision(); + + if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { + mcevents(mcCollision.globalIndex(), mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + fEventLabels[mcCollision.globalIndex()] = fCounters[1]; + fCounters[1]++; + } + + mceventlabels(fEventLabels.find(mcCollision.globalIndex())->second, collision.mcMask()); + } // end of reconstructed collision loop + + for (auto& emprimaryelectron : emprimaryelectrons) { + auto collision_from_el = collisions.iteratorAt(emprimaryelectron.collisionId()); + if (!collision_from_el.has_mcCollision()) { + continue; + } + auto mcCollision_from_el = collision_from_el.mcCollision(); + + auto o2track = o2tracks.iteratorAt(emprimaryelectron.trackId()); + if (!o2track.has_mcParticle()) { + continue; // If no MC particle is found, skip the dilepton + } + auto mctrack = o2track.template mcParticle_as(); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision_from_el.globalIndex())->second; + fCounters[0]++; + } + emprimaryelectronmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision_from_el.globalIndex())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + + } // end of em primary electron loop + + // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack + for (const auto& [newLabel, oldLabel] : fNewLabelsReversed) { + auto mctrack = mcTracks.iteratorAt(oldLabel); + // uint16_t mcflags = fMCFlags.find(oldLabel)->second; + + std::vector mothers; + if (mctrack.has_mothers()) { + for (auto& m : mctrack.mothersIds()) { + if (m < mcTracks.size()) { // protect against bad mother indices + if (fNewLabels.find(m) != fNewLabels.end()) { + mothers.push_back(fNewLabels.find(m)->second); + } + } else { + std::cout << "Mother label (" << m << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + } + + // Note that not all daughters from the original table are preserved in the skimmed MC stack + std::vector daughters; + if (mctrack.has_daughters()) { + // int ndau = mctrack.daughtersIds()[1] - mctrack.daughtersIds()[0] + 1; + // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + // TODO: remove this check as soon as issues with MC production are fixed + if (d < mcTracks.size()) { // protect against bad daughter indices + // auto dau_tmp = mcTracks.iteratorAt(d); + // // LOGF(info, "daughter pdg = %d", dau_tmp.pdgCode()); + // if ((mctrack.pdgCode() == 223 || mctrack.pdgCode() == 333) && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + // if (fNewLabels.find(d) == fNewLabels.end() && (abs(dau_tmp.pdgCode()) == 11 || abs(dau_tmp.pdgCode()) == 13)) { + // LOGF(info, "daughter lepton is not found mctrack.globalIndex() = %d, mctrack.producedByGenerator() == %d, ndau = %d | dau_tmp.globalIndex() = %d, dau_tmp.pdgCode() = %d, dau_tmp.producedByGenerator() = %d, dau_tmp.pt() = %f, dau_tmp.eta() = %f, dau_tmp.phi() = %f", mctrack.globalIndex(), mctrack.producedByGenerator(), ndau, dau_tmp.globalIndex(), dau_tmp.pdgCode(), dau_tmp.producedByGenerator(), dau_tmp.pt(), dau_tmp.eta(), dau_tmp.phi()); + // } + // } + + if (fNewLabels.find(d) != fNewLabels.end()) { + daughters.push_back(fNewLabels.find(d)->second); + } + } else { + std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + } + + emmcparticles(fEventIdx.find(oldLabel)->second, mctrack.pdgCode(), mctrack.flags(), + mothers, daughters, + mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), + mctrack.vx(), mctrack.vy(), mctrack.vz()); + + mothers.clear(); + mothers.shrink_to_fit(); + daughters.clear(); + daughters.shrink_to_fit(); + } // end loop over labels + + fNewLabels.clear(); + fNewLabelsReversed.clear(); + // fMCFlags.clear(); + fEventIdx.clear(); + fEventLabels.clear(); + fCounters[0] = 0; + fCounters[1] = 0; + } + + void processDummy(MyCollisions const&) {} + + PROCESS_SWITCH(AssociateMCInfoSecondaryElectron, processMC, "create em mc event table for Electron", false); + PROCESS_SWITCH(AssociateMCInfoSecondaryElectron, processDummy, "processDummy", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"skimmer-secondary-electron"}), + adaptAnalysisTask(cfgc, TaskName{"associate-mc-info-secondary-electron"}), + }; +} diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx index 076121e8afe..c1413a8aa68 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx @@ -14,6 +14,7 @@ // This code will create data table for inputs to machine learning for electrons. // Please write to: daiki.sekihata@cern.ch +#include #include "Math/Vector4D.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -32,8 +33,10 @@ #include "DetectorsBase/GeometryManager.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DCAFitter/DCAFitterN.h" #include "CCDB/BasicCCDBManager.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" using namespace o2; using namespace o2::framework; @@ -87,12 +90,13 @@ DECLARE_SOA_COLUMN(MotherPdgCodes, motherpdgCodes, std::vector); //! eta va DECLARE_SOA_TABLE(MyTracks, "AOD", "MYTRACK", //! o2::soa::Index<>, mytrack::MyCollisionId, mytrack::Sign, track::Pt, track::Eta, track::Phi, - track::DcaXY, track::DcaZ, mytrack::DCAresXY, mytrack::DCAresZ, + track::DcaXY, track::DcaZ, mytrack::DCAresXY, mytrack::DCAresZ, track::CZY, track::TPCNClsFindable, mytrack::TPCNClsFound, mytrack::TPCNClsCrossedRows, track::TPCChi2NCl, track::TPCInnerParam, track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, pidtofbeta::Beta, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, - track::TOFChi2, track::ITSClusterMap, track::ITSChi2NCl, track::ITSClusterSizes, + track::TOFChi2, track::ITSChi2NCl, track::ITSClusterSizes, + track::TRDSignal, track::TRDPattern, mytrack::MCVx, mytrack::MCVy, mytrack::MCVz, mcparticle::PdgCode, mytrack::IsPhysicalPrimary, mytrack::MotherIds, mytrack::MotherPdgCodes); @@ -112,17 +116,21 @@ DECLARE_SOA_COLUMN(Phi, phi, float); //! DECLARE_SOA_COLUMN(PhiV, phiv, float); //! DECLARE_SOA_COLUMN(PairDCAxy, pairDCAxy, float); //! DECLARE_SOA_COLUMN(PairDCAz, pairDCAz, float); //! - -DECLARE_SOA_COLUMN(IsSM, isSM, bool); //! -DECLARE_SOA_COLUMN(IsHF, isHF, int); //! -DECLARE_SOA_COLUMN(PairType, pairtype, int); //! -DECLARE_SOA_COLUMN(IsPrompt, isPrompt, bool); //! +DECLARE_SOA_COLUMN(CosOpAng, cosOpAng, float); //! +DECLARE_SOA_COLUMN(CosPA, cosPA, float); //! +DECLARE_SOA_COLUMN(Lxy, lxy, float); //! +DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); //! +DECLARE_SOA_COLUMN(IsSM, isSM, bool); //! +DECLARE_SOA_COLUMN(IsHF, isHF, int); //! +DECLARE_SOA_COLUMN(PairType, pairtype, int); //! +DECLARE_SOA_COLUMN(IsPrompt, isPrompt, bool); //! } // namespace mypair // reconstructed track information DECLARE_SOA_TABLE(MyPairs, "AOD", "MYPAIR", //! o2::soa::Index<>, mypair::MyCollisionId, mypair::PosTrackId, mypair::NegTrackId, mypair::Mass, mypair::Pt, mypair::Eta, mypair::Phi, mypair::PhiV, mypair::PairDCAxy, mypair::PairDCAz, + mypair::CosOpAng, mypair::CosPA, mypair::Lxy, mypair::Chi2PCA, mypair::IsSM, mypair::IsHF, mypair::PairType, mypair::IsPrompt, mcparticle::PdgCode, mcparticle::StatusCode, mcparticle::Flags, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, @@ -160,24 +168,93 @@ struct TreeCreatorElectronML { }; // Configurables + + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; + Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; + Configurable d_UseWeightedPCA{"d_UseWeightedPCA", false, "Vertices use cov matrices"}; + Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; + + // track Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + Configurable mintpcclusters{"mintpcclusters", 90, "min. tpc clusters"}; Configurable maxchi2tpc{"maxchi2tpc", 4.0, "max. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 5.0, "max. chi2/NclsITS"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; + Configurable minpt{"minpt", 0.2, "min. pT"}; + Configurable maxDcaZ{"maxDcaZ", 1.0, "max DCA Z"}; + Configurable maxDcaXY{"maxDcaXY", 1.0, "max DCA XY"}; + Configurable minITSClusters{"minITSLayers", 5, "min. of ITS clusters"}; + Configurable minITSClustersIB{"minITSClustersIB", 3, "min. number of ITS clusters in inner barrel"}; + Configurable downSampleEl{"downSampleEl", 1.0, "down scaling factor for electrons"}; + Configurable downSamplePi{"downSamplePi", 1.0, "down scaling factor for pions"}; + Configurable downSampleKa{"downSampleKa", 1.0, "down scaling factor for kaons"}; + Configurable downSamplePr{"downSamplePr", 1.0, "down scaling factor for protons"}; + Configurable downSampleMu{"downSampleMu", 1.0, "down scaling factor for muons"}; + Configurable downSampleNucl{"downSampleNucl", 1.0, "down scaling factor for nuclei"}; + + // pair + Configurable minPairPt{"minPairPt", 0.2, "min. pT,ee"}; + Configurable minMass{"minMass", 0.0, "min. pair invariant mass"}; + Configurable maxMass{"maxMass", 9999.0, "max. pair invariant mass"}; Configurable doLS{"doLS", true, "process also LS spectra"}; Configurable combBgReductionFactor{"combBgReductionFactor", 1.0, "reduction factor for combinatorial background"}; - Configurable singleTrackBgReductionFactor{"singleTrackBgReductionFactor", 1.0, "reduction factor for background"}; int mRunNumber; float d_bz; + o2::vertexing::DCAFitterN<2> fitter; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + o2::base::MatLayerCylSet* lut = nullptr; Service ccdb; + + std::mt19937 engine; + std::uniform_real_distribution dist01; + void init(InitContext&) { + + std::random_device seed_gen; + engine = std::mt19937(seed_gen()); + dist01 = std::uniform_real_distribution(0.0f, 1.0f); + mRunNumber = 0; d_bz = 0; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + + if (useMatCorrType == 1) { + LOGF(info, "TGeo correction requested, loading geometry"); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + } + if (useMatCorrType == 2) { + LOGF(info, "LUT correction requested, loading LUT"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + } + + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(d_UseAbsDCA); + fitter.setWeightedFinalPCA(d_UseWeightedPCA); + + if (useMatCorrType == 1) { + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; + } else if (useMatCorrType == 2) { + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + } + fitter.setMatCorrType(matCorr); } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -186,22 +263,33 @@ struct TreeCreatorElectronML { return; } + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + fitter.setBz(d_bz); + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", run3grp_timestamp); + o2::parameters::GRPObject* grpo = 0x0; o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); if (grpo) { o2::base::Propagator::initFieldFromGRP(grpo); // Fetch magnetic field from ccdb for current collision d_bz = grpo->getNominalL3Field(); LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; } else { - grpmag = ccdb->getForTimeStamp("GLO/Config/GRPMagField", run3grp_timestamp); + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " - << "GLO/Config/GRPMagField" - << " of object GRPMagField and " - << "GLO/GRP/GRP" - << " of object GRPObject for timestamp " << run3grp_timestamp; + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; } o2::base::Propagator::initFieldFromGRP(grpmag); // Fetch magnetic field from ccdb for current collision @@ -209,6 +297,13 @@ struct TreeCreatorElectronML { LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; } mRunNumber = bc.runNumber(); + // Set magnetic field value once known + fitter.setBz(d_bz); + + if (useMatCorrType == 2) { + // setMatLUT only after magfield has been initalized (setMatLUT has implicit and problematic init field call if not) + o2::base::Propagator::Instance()->setMatLUT(lut); + } } template @@ -359,13 +454,177 @@ struct TreeCreatorElectronML { if (track.tpcNClsCrossedRows() < mincrossedrows) { return false; } + if (track.tpcNClsFound() < mintpcclusters) { + return false; + } if (track.itsChi2NCl() < -1) { // if tracks are not reconstructed properly, chi2/ITSncls is set to -999; return false; } + if (track.itsNCls() < minITSClusters) { + return false; + } + if (track.itsNClsInnerBarrel() < minITSClustersIB) { + return false; + } return true; } - Filter trackFilter = nabs(o2::aod::track::eta) < maxeta && o2::aod::track::tpcChi2NCl < maxchi2tpc && nabs(o2::aod::track::dcaXY) < 1.f && nabs(o2::aod::track::dcaZ) < 1.f; + template + bool IsSelectedPair(TMom const& v12) + { + if (v12.Pt() < minPairPt) { + return false; + } + if (v12.M() < minMass) { + return false; + } + if (v12.M() > maxMass) { + return false; + } + return true; + } + + bool downSample(int pdg) + { // pdg=0: combinatorial background for pairs + float factor = 1.; + switch (pdg) { + case 11: + factor = downSampleEl; + break; + case 211: + factor = downSamplePi; + break; + case 321: + factor = downSampleKa; + break; + case 2212: + factor = downSamplePr; + break; + case 13: + factor = downSampleMu; + break; + case 0: + factor = combBgReductionFactor; + break; + default: + factor = downSampleNucl; + } + if (dist01(engine) <= factor) { + return true; + } + return false; + } + + template + void doPair(TTrack const& t1, TTrack const& t2, int pairtype, TMCParticles const& mctracks, TCollision const& collision, std::map& fNewLabels, std::vector& fSelected_old_labels, int& fCounter) + { + if (!IsSelected(t1) || !IsSelected(t2)) { + return; + } + + if (!t1.has_mcParticle() || !t2.has_mcParticle()) { + return; + } + + auto mc1 = mctracks.iteratorAt(t1.mcParticleId()); + auto mc2 = mctracks.iteratorAt(t2.mcParticleId()); + + if (abs(mc1.pdgCode()) != 11 || abs(mc2.pdgCode()) != 11) { + return; + } // charge swap is accepted. + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if (!IsSelectedPair(v12)) { + return; + } + + float phiv = get_phiv(t1, t2); + float pair_dca_xy = sqrt((pow(t1.dcaXY() / sqrt(t1.cYY()), 2) + pow(t2.dcaXY() / sqrt(t2.cYY()), 2)) / 2.); + float pair_dca_z = sqrt((pow(t1.dcaZ() / sqrt(t1.cZZ()), 2) + pow(t2.dcaZ() / sqrt(t2.cZZ()), 2)) / 2.); + + float cosOpAng = (v1.Px() * v2.Px() + v1.Py() * v2.Py() + v1.Pz() * v2.Pz()) / sqrt((v1.Px() * v1.Px() + v1.Py() * v1.Py() + v1.Pz() * v1.Pz()) * (v2.Px() * v2.Px() + v2.Py() * v2.Py() + v2.Pz() * v2.Pz())); + float pca = 999.f; + float lxy = 999.f; + float cosPA = 999.f; + o2::aod::pwgem::dilepton::utils::pairutil::isSVFound(fitter, collision, t1, t1, pca, lxy, cosPA); + float lxy_proper = lxy * v12.M() / v12.Pt(); + + bool isSM = false; + int isHF = o2::aod::pwgem::dilepton::utils::mcutil::IsHF(mc1, mc2, mctracks); // if isHF == true, pdgCode is set to 0, because this pair is correlated HF ee pair decayed from different 2 mothers. Check pdg code of legs. + + bool is_prompt = false; + int pdgCode = 0; + int statusCode = 0; + uint8_t flags = 0; + float vx = 0.f; + float vy = 0.f; + float vz = 0.f; + bool is_comb_bg = false; + if (pairtype == EM_EEPairType::kULS) { + int common_mother_id = FindCommonMotherFrom2Prongs(mc1, mc2, mctracks); + if (common_mother_id > 0) { + isSM = true; + } + if (isSM) { + auto mcpair = mctracks.iteratorAt(common_mother_id); + is_prompt = true; // only relevant for prompt jpsi + pdgCode = mcpair.pdgCode(); + statusCode = mcpair.statusCode(); + flags = mcpair.flags(); + vx = mcpair.vx(); + vy = mcpair.vy(); + vz = mcpair.vz(); + + int motherid_pair = mcpair.mothersIds()[0]; // first mother index + while (motherid_pair > -1) { + if (motherid_pair < mctracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mctracks.iteratorAt(motherid_pair); + + if (std::to_string(mp.pdgCode()).find("5") != std::string::npos) { + is_prompt = false; + break; + } + + if (mp.has_mothers()) { + motherid_pair = mp.mothersIds()[0]; + } else { + motherid_pair = -999; + } + } else { + LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid_pair, mctracks.size()); + } + } + } else if (isHF == static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kUndef)) { + is_comb_bg = true; + } + } else { // LS + if (isHF == static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kUndef)) { + is_comb_bg = true; + } + } + + if (!is_comb_bg || downSample(0)) { + if (!(fNewLabels.find(t1.globalIndex()) != fNewLabels.end())) { + fNewLabels[t1.globalIndex()] = fCounter; + fSelected_old_labels.push_back(t1.globalIndex()); + fCounter++; + } + if (!(fNewLabels.find(t2.globalIndex()) != fNewLabels.end())) { + fNewLabels[t2.globalIndex()] = fCounter; + fSelected_old_labels.push_back(t2.globalIndex()); + fCounter++; + } + mypair(mycollision.lastIndex(), fNewLabels[t1.globalIndex()], fNewLabels[t2.globalIndex()], + v12.M(), v12.Pt(), v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, cosOpAng, cosPA, lxy_proper, pow(pca, 2), + isSM, isHF, pairtype, is_prompt, pdgCode, statusCode, flags, + vx, vy, vz); + } + } + + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& nabs(o2::aod::track::dcaXY) < maxDcaXY&& nabs(o2::aod::track::dcaZ) < maxDcaZ; using MyFilteredTracksMC = soa::Filtered; Preslice perCollision = aod::track::collisionId; @@ -420,19 +679,17 @@ struct TreeCreatorElectronML { } } - int pdgCode = mctrack.pdgCode(); - double pt = track.pt(); - double pseudoRndm = pt * 1000. - (int16_t)(pt * 1000); - if (abs(pdgCode) == 11 || pseudoRndm <= singleTrackBgReductionFactor) { + if (downSample(abs(mctrack.pdgCode()))) { mytrack(mycollision.lastIndex(), - track.sign(), pt, track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), + track.sign(), track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), track.cZY(), track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.tofChi2(), track.itsClusterMap(), track.itsChi2NCl(), track.itsClusterSizes(), + track.tofChi2(), track.itsChi2NCl(), track.itsClusterSizes(), + track.trdSignal(), track.trdPattern(), mctrack.vx(), mctrack.vy(), mctrack.vz(), - pdgCode, mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); + mctrack.pdgCode(), mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); } mothers_id.shrink_to_fit(); mothers_pdg.shrink_to_fit(); @@ -451,6 +708,7 @@ struct TreeCreatorElectronML { int fCounter = 0; for (auto& collision : collisions) { + std::vector fSelected_old_labels; // TODO: investigate the collisions without corresponding mcCollision if (!collision.has_mcCollision()) { continue; @@ -469,233 +727,62 @@ struct TreeCreatorElectronML { auto negTracks_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); auto posTracks_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - for (auto& track : tracks) { - if (!IsSelected(track)) { - continue; - } - - if (!track.has_mcParticle()) { - continue; // If no MC particle is found, skip the track - } - - auto mctrack = track.mcParticle_as(); - - if (abs(mctrack.pdgCode()) != 11) { - continue; - } - - if (!(fNewLabels.find(track.globalIndex()) != fNewLabels.end())) { - fNewLabels[track.globalIndex()] = fCounter; - - // store all mother relation - std::vector mothers_id; - std::vector mothers_pdg; - if (mctrack.has_mothers()) { - int motherid = mctrack.mothersIds()[0]; // first mother index - while (motherid > -1) { - if (motherid < mctracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mctracks.iteratorAt(motherid); - mothers_id.emplace_back(motherid); - mothers_pdg.emplace_back(mp.pdgCode()); - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; - } else { - motherid = -999; - } - } else { - LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid, mctracks.size()); - } - } - } - - mytrack(mycollision.lastIndex(), - track.sign(), track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), - track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.tofChi2(), track.itsClusterMap(), track.itsChi2NCl(), track.itsClusterSizes(), - mctrack.vx(), mctrack.vy(), mctrack.vz(), - mctrack.pdgCode(), mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); - - mothers_id.shrink_to_fit(); - mothers_pdg.shrink_to_fit(); - fCounter++; - } - - } // end of track loop - for (auto& [ele, pos] : combinations(CombinationsFullIndexPolicy(negTracks_coll, posTracks_coll))) { - if (!IsSelected(ele) || !IsSelected(pos)) { - continue; - } - - if (!ele.has_mcParticle() || !pos.has_mcParticle()) { - continue; - } - - auto mcpos = pos.mcParticle_as(); - auto mcele = ele.mcParticle_as(); - - if (abs(mcele.pdgCode()) != 11 || abs(mcpos.pdgCode()) != 11) { - continue; - } // charge swap is accepted. - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - float phiv = get_phiv(ele, pos); - float pair_dca_xy = sqrt((pow(pos.dcaXY() / sqrt(pos.cYY()), 2) + pow(ele.dcaXY() / sqrt(ele.cYY()), 2)) / 2.); - float pair_dca_z = sqrt((pow(pos.dcaZ() / sqrt(pos.cZZ()), 2) + pow(ele.dcaZ() / sqrt(ele.cZZ()), 2)) / 2.); - - bool isSM = false; - int common_mother_id = FindCommonMotherFrom2Prongs(mcpos, mcele, mctracks); - if (common_mother_id > 0) { - isSM = true; - } - int isHF = o2::aod::pwgem::dilepton::mcutil::IsHF(mcpos, mcele, mctracks); // if isHF == true, pdgCode is set to 0, because this pair is correlated HF ee pair decayed from different 2 mothers. Check pdg code of legs. + doPair(pos, ele, EM_EEPairType::kULS, mctracks, collision, fNewLabels, fSelected_old_labels, fCounter); + } - if (isSM) { - auto mcpair = mctracks.iteratorAt(common_mother_id); - bool is_prompt = true; // only relevant for prompt jpsi + if (!doLS) { + continue; + } + for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_coll, posTracks_coll))) { + doPair(pos1, pos2, EM_EEPairType::kLSpp, mctracks, collision, fNewLabels, fSelected_old_labels, fCounter); + } - int motherid_pair = mcpair.mothersIds()[0]; // first mother index - while (motherid_pair > -1) { - if (motherid_pair < mctracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mctracks.iteratorAt(motherid_pair); + for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_coll, negTracks_coll))) { + doPair(ele1, ele2, EM_EEPairType::kLSnn, mctracks, collision, fNewLabels, fSelected_old_labels, fCounter); + } - if (std::to_string(mp.pdgCode()).find("5") != std::string::npos) { - is_prompt = false; - break; - } + // single tracks, only if selected in at least one pair + for (uint64_t track_label : fSelected_old_labels) { + auto track = tracks.rawIteratorAt(track_label); + auto mctrack = track.mcParticle_as(); + // store all mother relation + std::vector mothers_id; + std::vector mothers_pdg; + if (mctrack.has_mothers()) { + int motherid = mctrack.mothersIds()[0]; // first mother index + while (motherid > -1) { + if (motherid < mctracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mctracks.iteratorAt(motherid); + mothers_id.emplace_back(motherid); + mothers_pdg.emplace_back(mp.pdgCode()); if (mp.has_mothers()) { - motherid_pair = mp.mothersIds()[0]; + motherid = mp.mothersIds()[0]; } else { - motherid_pair = -999; + motherid = -999; } } else { - LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid_pair, mctracks.size()); + LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid, mctracks.size()); } } - - mypair(mycollision.lastIndex(), fNewLabels[pos.globalIndex()], fNewLabels[ele.globalIndex()], - v12.M(), v12.Pt(), v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kULS, is_prompt, mcpair.pdgCode(), mcpair.statusCode(), mcpair.flags(), - mcpair.vx(), mcpair.vy(), mcpair.vz()); - // LOGF(info, "mcpair.pdgCode() = %d", mcpair.pdgCode()); - } else if (isHF > -1) { - // isSM and isHF are not satisfied at the same time. - mypair(mycollision.lastIndex(), fNewLabels[pos.globalIndex()], fNewLabels[ele.globalIndex()], - v12.M(), v12.Pt(), v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kULS, false, 0, 0, 0, - 0, 0, 0); - } else { // this is combinatorial bkg - double pt = v12.Pt(); - double pseudoRndm = pt * 1000. - (int16_t)(pt * 1000); - if (pseudoRndm <= combBgReductionFactor) { - mypair(mycollision.lastIndex(), fNewLabels[pos.globalIndex()], fNewLabels[ele.globalIndex()], - v12.M(), pt, v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kULS, false, 0, 0, 0, - 0, 0, 0); - } - } - - } // end of uls pair loop - - if (!doLS) { - continue; - } - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_coll, posTracks_coll))) { - if (!IsSelected(pos1) || !IsSelected(pos2)) { - continue; - } - - if (!pos1.has_mcParticle() || !pos2.has_mcParticle()) { - continue; - } - - auto mcpos1 = pos1.mcParticle_as(); - auto mcpos2 = pos2.mcParticle_as(); - - if (abs(mcpos1.pdgCode()) != 11 || abs(mcpos2.pdgCode()) != 11) { - continue; - } // charge swap is accepted. - - ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - float phiv = get_phiv(pos1, pos2); - float pair_dca_xy = sqrt((pow(pos2.dcaXY() / sqrt(pos2.cYY()), 2) + pow(pos1.dcaXY() / sqrt(pos1.cYY()), 2)) / 2.); - float pair_dca_z = sqrt((pow(pos2.dcaZ() / sqrt(pos2.cZZ()), 2) + pow(pos1.dcaZ() / sqrt(pos1.cZZ()), 2)) / 2.); - - bool isSM = false; - int isHF = o2::aod::pwgem::dilepton::mcutil::IsHF(mcpos1, mcpos2, mctracks); - if (isHF != static_cast(o2::aod::pwgem::dilepton::mcutil::EM_HFeeType::kUndef)) { - // isSM and isHF are not satisfied at the same time. - mypair(mycollision.lastIndex(), fNewLabels[pos1.globalIndex()], fNewLabels[pos2.globalIndex()], - v12.M(), v12.Pt(), v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kLSpp, false, 0, 0, 0, - 0, 0, 0); - } else { // this is combinatorial bkg - double pt = v12.Pt(); - double pseudoRndm = pt * 1000. - (int16_t)(pt * 1000); - if (pseudoRndm <= combBgReductionFactor) { - mypair(mycollision.lastIndex(), fNewLabels[pos1.globalIndex()], fNewLabels[pos2.globalIndex()], - v12.M(), pt, v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kLSpp, false, 0, 0, 0, - 0, 0, 0); - } } - } // end of lspp pair loop + mytrack(mycollision.lastIndex(), + track.sign(), track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), track.cZY(), + track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofChi2(), track.itsChi2NCl(), track.itsClusterSizes(), + track.trdSignal(), track.trdPattern(), + mctrack.vx(), mctrack.vy(), mctrack.vz(), + mctrack.pdgCode(), mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_coll, negTracks_coll))) { - if (!IsSelected(ele1) || !IsSelected(ele2)) { - continue; - } - if (!ele1.has_mcParticle() || !ele2.has_mcParticle()) { - continue; - } - - auto mcele1 = ele1.mcParticle_as(); - auto mcele2 = ele2.mcParticle_as(); - - if (abs(mcele1.pdgCode()) != 11 || abs(mcele2.pdgCode()) != 11) { - continue; - } // charge swap is accepted. - - ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - float phiv = get_phiv(ele1, ele2); - float pair_dca_xy = sqrt((pow(ele2.dcaXY() / sqrt(ele2.cYY()), 2) + pow(ele1.dcaXY() / sqrt(ele1.cYY()), 2)) / 2.); - float pair_dca_z = sqrt((pow(ele2.dcaZ() / sqrt(ele2.cZZ()), 2) + pow(ele1.dcaZ() / sqrt(ele1.cZZ()), 2)) / 2.); - - bool isSM = false; - int isHF = o2::aod::pwgem::dilepton::mcutil::IsHF(mcele1, mcele2, mctracks); - if (isHF != static_cast(o2::aod::pwgem::dilepton::mcutil::EM_HFeeType::kUndef)) { - // isSM and isHF are not satisfied at the same time. - mypair(mycollision.lastIndex(), fNewLabels[ele1.globalIndex()], fNewLabels[ele2.globalIndex()], - v12.M(), v12.Pt(), v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kLSnn, false, 0, 0, 0, - 0, 0, 0); - } else { // this is combinatorial bkg - double pt = v12.Pt(); - double pseudoRndm = pt * 1000. - (int16_t)(pt * 1000); - if (pseudoRndm <= combBgReductionFactor) { - mypair(mycollision.lastIndex(), fNewLabels[ele1.globalIndex()], fNewLabels[ele2.globalIndex()], - v12.M(), pt, v12.Eta(), v12.Phi(), phiv, pair_dca_xy, pair_dca_z, - isSM, isHF, EM_EEPairType::kLSnn, false, 0, 0, 0, - 0, 0, 0); - } - } + mothers_id.shrink_to_fit(); + mothers_pdg.shrink_to_fit(); - } // end of lsnn pair loop + } // end of track loop } // end of collision loop fNewLabels.clear(); diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index dcfc802163c..a3f25e08021 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -38,6 +38,7 @@ #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" #include "PWGEM/Dilepton/DataModel/lmeeMLTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" using namespace o2; @@ -649,7 +650,7 @@ struct TreeCreatorElectronMLDDA { ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); if (v12.M() < slope * phiv + intercept) { // photon conversion is found. @@ -946,7 +947,7 @@ struct TreeCreatorElectronMLDDA { ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); if (v12.M() < slope * phiv + intercept) { // photon conversion is found. stored_secondary_electronIds.emplace_back(pos.globalIndex()); @@ -968,7 +969,7 @@ struct TreeCreatorElectronMLDDA { ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); if (v12.M() < slope * phiv + intercept) { // photon conversion is found. stored_secondary_electronIds.emplace_back(ele.globalIndex()); @@ -995,7 +996,7 @@ struct TreeCreatorElectronMLDDA { ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); registry.fill(HIST("hMvsPhiV_primary"), phiv, v12.M()); if (v12.M() < max_mee_pi0 && dist01(engine) < downscaling_primary_electron) { // e from pi0 dalitz decay is found. fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary)); @@ -1018,7 +1019,7 @@ struct TreeCreatorElectronMLDDA { ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); registry.fill(HIST("hMvsPhiV_primary"), phiv, v12.M()); if (v12.M() < max_mee_pi0 && dist01(engine) < downscaling_primary_electron) { // e from pi0 dalitz decay is found. fillTrackTable(collision, ele, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary)); diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorSingleElectronQA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorSingleElectronQA.cxx index 7df8006a49e..b7f09e9349d 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorSingleElectronQA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorSingleElectronQA.cxx @@ -12,7 +12,6 @@ /// \brief write relevant information for dalitz ee analysis to an AO2D.root file. This file is then the only necessary input to perform pcm analysis. /// \author daiki.sekihata@cern.ch -#include #include #include "Framework/runDataProcessing.h" @@ -313,26 +312,19 @@ struct TreeCreatorSingleElectronQA { track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl()); + track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), true); } SliceCache cache; Preslice perCollision_track = o2::aod::track::collisionId; - PresliceUnsorted preslice_collisions_per_bc = o2::aod::evsel::foundBCId; - std::unordered_map map_ncolls_per_bc; Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; Filter pidFilter = (minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < minTPCNsigmaPi || maxTPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using MyFilteredTracks = soa::Filtered; // ---------- for data ---------- - void processRec(MyCollisions_Cent const& collisions, MyBCs const& bcs, MyFilteredTracks const& tracks) + void processRec(MyCollisions_Cent const& collisions, MyBCs const&, MyFilteredTracks const& tracks) { - for (auto& bc : bcs) { - auto collisions_per_bc = collisions.sliceBy(preslice_collisions_per_bc, bc.globalIndex()); - map_ncolls_per_bc[bc.globalIndex()] = collisions_per_bc.size(); - } - for (auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); @@ -343,7 +335,7 @@ struct TreeCreatorSingleElectronQA { } fRegistry.fill(HIST("hCollisionCounter"), 1.f); - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.sel8(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), map_ncolls_per_bc[bc.globalIndex()], + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange()); event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); @@ -366,13 +358,8 @@ struct TreeCreatorSingleElectronQA { // ---------- for MC ---------- using MyFilteredTracksMC = soa::Filtered; - void processMC(MyCollisionsMC_Cent const& collisions, aod::McCollisions const&, MyBCs const& bcs, MyFilteredTracksMC const& tracks) + void processMC(MyCollisionsMC_Cent const& collisions, aod::McCollisions const&, MyBCs const&, MyFilteredTracksMC const& tracks) { - for (auto& bc : bcs) { - auto collisions_per_bc = collisions.sliceBy(preslice_collisions_per_bc, bc.globalIndex()); - map_ncolls_per_bc[bc.globalIndex()] = collisions_per_bc.size(); - } - for (auto& collision : collisions) { if (!collision.has_mcCollision()) { continue; @@ -386,7 +373,7 @@ struct TreeCreatorSingleElectronQA { } fRegistry.fill(HIST("hCollisionCounter"), 1.f); - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.sel8(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), map_ncolls_per_bc[bc.globalIndex()], + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange()); event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); diff --git a/PWGEM/Dilepton/Tasks/CMakeLists.txt b/PWGEM/Dilepton/Tasks/CMakeLists.txt index 5feb3996e13..230d687ddcc 100644 --- a/PWGEM/Dilepton/Tasks/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/CMakeLists.txt @@ -15,12 +15,12 @@ o2physics_add_dpl_workflow(efficiency-ee PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) -o2physics_add_executable(lmee-lf-cocktail +o2physics_add_dpl_workflow(lmee-lf-cocktail SOURCES lmeeLFCocktail.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::SimulationDataFormat O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_executable(lmee-hf-cocktail +o2physics_add_dpl_workflow(lmee-hf-cocktail SOURCES lmeeHFCocktail.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -34,3 +34,84 @@ o2physics_add_dpl_workflow(smearing SOURCES smearing.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(create-resolution-map + SOURCES createResolutionMap.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(table-reader-barrel + SOURCES tableReaderBarrel.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-qc + SOURCES eventQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(single-electron-qc + SOURCES singleElectronQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(single-electron-qc-mc + SOURCES singleElectronQCMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(vp-pair-qc + SOURCES vpPairQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(vp-pair-qc-mc + SOURCES vpPairQCMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(single-muon-qc + SOURCES singleMuonQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(single-muon-qc-mc + SOURCES singleMuonQCMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dielectron + SOURCES dielectron.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2::DCAFitter O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dielectron-mc + SOURCES dielectronMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2::DCAFitter O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dimuon + SOURCES dimuon.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::DCAFitter O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dimuon-mc + SOURCES dimuonMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::DCAFitter O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(photon-hbt-pcmpcm + SOURCES PhotonHBTPCMPCM.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(photon-hbt-eeee + SOURCES PhotonHBTEEEE.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(photon-hbt-pcmee + SOURCES PhotonHBTPCMEE.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/Dilepton/Tasks/MCtemplates.cxx b/PWGEM/Dilepton/Tasks/MCtemplates.cxx index 5b1bf9548ae..c41d27f91d1 100644 --- a/PWGEM/Dilepton/Tasks/MCtemplates.cxx +++ b/PWGEM/Dilepton/Tasks/MCtemplates.cxx @@ -243,13 +243,13 @@ struct AnalysisTrackSelection { if (fConfigQA) { if (fConfigMCTruthGen) { // Add histogram classes for each MC signal at generated level - std::vector mcnamesgen; + // std::vector mcnamesgen; for (int isig = 0; isig < sigNamesArray->GetEntries(); ++isig) { MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(sigNamesArray->At(isig)->GetName()); if (sig) { if (sig->GetNProngs() == 1) { // NOTE: only 1 prong signals TString nameStr2 = Form("MCTruthGenTrack_%s", sig->GetName()); - mcnamesgen.push_back(nameStr2); + // mcnamesgen.push_back(nameStr2); histClasses += Form("%s;", nameStr2.Data()); // TODO: Add these names to a std::vector to avoid using Form in the process function } } diff --git a/PWGEM/Dilepton/Tasks/PhotonHBTEEEE.cxx b/PWGEM/Dilepton/Tasks/PhotonHBTEEEE.cxx new file mode 100644 index 00000000000..b26a40af6fc --- /dev/null +++ b/PWGEM/Dilepton/Tasks/PhotonHBTEEEE.cxx @@ -0,0 +1,44 @@ +// Copyright 2019-2020 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 loops over v0 photons and makes pairs for photon HBT analysis. +// Please write to: daiki.sekihata@cern.ch + +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Math/Vector3D.h" +#include "Math/LorentzRotation.h" +#include "Math/GenVector/Boost.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +#include "PWGEM/Dilepton/Core/PhotonHBT.h" + +using namespace o2; +using namespace o2::aod; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"photon-hbt-eeee"})}; +} diff --git a/PWGEM/Dilepton/Tasks/PhotonHBTPCMEE.cxx b/PWGEM/Dilepton/Tasks/PhotonHBTPCMEE.cxx new file mode 100644 index 00000000000..3e792f9d27a --- /dev/null +++ b/PWGEM/Dilepton/Tasks/PhotonHBTPCMEE.cxx @@ -0,0 +1,44 @@ +// Copyright 2019-2020 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 loops over v0 photons and makes pairs for photon HBT analysis. +// Please write to: daiki.sekihata@cern.ch + +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Math/Vector3D.h" +#include "Math/LorentzRotation.h" +#include "Math/GenVector/Boost.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +#include "PWGEM/Dilepton/Core/PhotonHBT.h" + +using namespace o2; +using namespace o2::aod; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"photon-hbt-pcmee"})}; +} diff --git a/PWGEM/Dilepton/Tasks/PhotonHBTPCMPCM.cxx b/PWGEM/Dilepton/Tasks/PhotonHBTPCMPCM.cxx new file mode 100644 index 00000000000..ddcbe423eae --- /dev/null +++ b/PWGEM/Dilepton/Tasks/PhotonHBTPCMPCM.cxx @@ -0,0 +1,44 @@ +// Copyright 2019-2020 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 loops over v0 photons and makes pairs for photon HBT analysis. +// Please write to: daiki.sekihata@cern.ch + +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Math/Vector3D.h" +#include "Math/LorentzRotation.h" +#include "Math/GenVector/Boost.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +#include "PWGEM/Dilepton/Core/PhotonHBT.h" + +using namespace o2; +using namespace o2::aod; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"photon-hbt-pcmpcm"})}; +} diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx new file mode 100644 index 00000000000..24efd7f232d --- /dev/null +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -0,0 +1,407 @@ +// Copyright 2019-2020 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. +// +// +// Analysis task to produce resolution mapfor electrons/muons in dilepton analysis +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "Framework/DataTypes.h" +#include "Framework/HistogramRegistry.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "TGeoGlobalMagField.h" +#include "Field/MagneticField.h" + +#include "DetectorsBase/Propagator.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHTracking/TrackExtrap.h" +#include "MCHTracking/TrackParam.h" +#include "ReconstructionDataFormats/TrackFwd.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::soa; + +using MyCollisions = Join; +using MyCollision = MyCollisions::iterator; + +using MyMCTracks = soa::Join; +using MyMCTrack = MyMCTracks::iterator; + +using MyMCFwdTracks = soa::Join; +using MyMCFwdTrack = MyMCFwdTracks::iterator; + +struct CreateResolutionMap { + // Index used to set different options for Muon propagation + enum class MuonExtrapolation : int { + kToVertex = 0, // propagtion to vertex by default + kToDCA = 1, + kToRabs = 2, + }; + using SMatrix55 = ROOT::Math::SMatrix>; + using SMatrix5 = ROOT::Math::SVector; + + Configurable applyEveSel_at_skimming{"applyEveSel_at_skimming", false, "flag to apply minimal event selection at the skimming level"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + + struct : ConfigurableGroup { + std::string prefix = "electroncut_group"; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.01, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -1.5, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +1.5, "max eta for single track"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 4, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 80, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_min_tpc_cr_findable_ratio{"cfg_min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; + } electroncuts; + + struct : ConfigurableGroup { + std::string prefix = "muoncut_group"; + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.01, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -5.0, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", -1.5, "max eta for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + } muoncuts; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + o2::globaltracking::MatchGlobalFwd mMatching; + int mRunNumber = 0; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + + const AxisSpec axis_pt_gen{{0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.50, 6.00, 6.50, 7.00, 7.50, 8.00, 8.50, 9.00, 9.50, 10.00, 11.00, 12.00, 13.00, 14.00, 15.00, 16.00, 17.00, 18.00, 19.00, 20.00}, "p_{T,l}^{gen} (GeV/c)"}; + const AxisSpec axis_dpt{400, -1, 1, "(p_{T,l}^{gen.} - p_{T,l}^{rec.})/p_{T,l}^{gen.}"}; + const AxisSpec axis_deta{500, -0.5, +0.5, "#eta_{l}^{gen.} - #eta_{l}^{rec.}"}; + const AxisSpec axis_dphi{500, -0.5, +0.5, "#varphi_{l}^{gen.} - #varphi_{l}^{rec.} (rad.)"}; + + registry.add("Electron/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt}}, true); + registry.add("Electron/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta}}, true); + registry.add("Electron/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("Electron/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.addClone("Electron/", "StandaloneMuon/"); + registry.addClone("Electron/", "GlobalMuon/"); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + mRunNumber = bc.runNumber(); + std::map metadata; + auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, mRunNumber); + auto ts = soreor.first; + auto grpmag = ccdbApi.retrieveFromTFileAny(grpmagPath, metadata, ts); + o2::base::Propagator::initFieldFromGRP(grpmag); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + o2::mch::TrackExtrap::setField(); + } + + std::pair> itsRequirement_ibany = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. + std::pair> itsRequirement_ib1st = {1, {0}}; // first hit on ITS ib layers. + + template + bool checkTrack(TTrack const& track) + { + if (track.tpcChi2NCl() > electroncuts.cfg_max_chi2tpc) { + return false; + } + + if (track.itsChi2NCl() > electroncuts.cfg_max_chi2its) { + return false; + } + + if (track.itsNCls() < electroncuts.cfg_min_ncluster_its) { + return false; + } + + auto hits = std::count_if(itsRequirement_ibany.second.begin(), itsRequirement_ibany.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits < itsRequirement_ibany.first) { + return false; + } + if (electroncuts.cfg_require_itsib_1st) { + auto hit_ib1st = std::count_if(itsRequirement_ib1st.second.begin(), itsRequirement_ib1st.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hit_ib1st < itsRequirement_ib1st.first) { + return false; + } + } + + if (track.tpcNClsFound() < electroncuts.cfg_min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < electroncuts.cfg_min_ncrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < electroncuts.cfg_min_tpc_cr_findable_ratio) { + return false; + } + + return true; + } + + template + o2::dataformats::GlobalFwdTrack PropagateMuon(T const& muon, C const& collision, const CreateResolutionMap::MuonExtrapolation endPoint) + { + double chi2 = muon.chi2(); + SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), muon.signed1Pt()); + std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), + muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), + muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2}; + o2::dataformats::GlobalFwdTrack propmuon; + + if (static_cast(muon.trackType()) > 2) { // MCH-MID or MCH standalone + o2::dataformats::GlobalFwdTrack track; + track.setParameters(tpars); + track.setZ(fwdtrack.getZ()); + track.setCovariances(tcovs); + auto mchTrack = mMatching.FwdtoMCH(track); + + if (endPoint == CreateResolutionMap::MuonExtrapolation::kToVertex) { + o2::mch::TrackExtrap::extrapToVertex(mchTrack, collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covYY()); + } + if (endPoint == CreateResolutionMap::MuonExtrapolation::kToDCA) { + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrack, collision.posZ()); + } + if (endPoint == CreateResolutionMap::MuonExtrapolation::kToRabs) { + o2::mch::TrackExtrap::extrapToZ(mchTrack, -505.); + } + + auto proptrack = mMatching.MCHtoFwd(mchTrack); + propmuon.setParameters(proptrack.getParameters()); + propmuon.setZ(proptrack.getZ()); + propmuon.setCovariances(proptrack.getCovariances()); + } else if (static_cast(muon.trackType()) < 2) { // MFT-MCH-MID + double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + auto Bz = field->getBz(centerMFT); // Get field at centre of MFT + auto geoMan = o2::base::GeometryManager::meanMaterialBudget(muon.x(), muon.y(), muon.z(), collision.posX(), collision.posY(), collision.posZ()); + auto x2x0 = static_cast(geoMan.meanX2X0); + fwdtrack.propagateToVtxhelixWithMCS(collision.posZ(), {collision.posX(), collision.posY()}, {collision.covXX(), collision.covYY()}, Bz, x2x0); + propmuon.setParameters(fwdtrack.getParameters()); + propmuon.setZ(fwdtrack.getZ()); + propmuon.setCovariances(fwdtrack.getCovariances()); + } + + v1.clear(); + v1.shrink_to_fit(); + + return propmuon; + } + + template + bool checkFwdTrack(TMuon const& muon, TCollision const& collision) + { + o2::dataformats::GlobalFwdTrack propmuonAtPV = PropagateMuon(muon, collision, CreateResolutionMap::MuonExtrapolation::kToVertex); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + + if (pt < muoncuts.cfg_min_pt_track) { + return false; + } + + if (eta < muoncuts.cfg_min_eta_track || muoncuts.cfg_max_eta_track < eta) { + return false; + } + + o2::math_utils::bringTo02Pi(phi); + if (phi < 0.f || 2.f * M_PI < phi) { + return false; + } + + float rAtAbsorberEnd = muon.rAtAbsorberEnd(); + if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + o2::dataformats::GlobalFwdTrack propmuonAtRabs = PropagateMuon(muon, collision, CreateResolutionMap::MuonExtrapolation::kToRabs); + float xAbs = propmuonAtRabs.getX(); + float yAbs = propmuonAtRabs.getY(); + rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); // Redo propagation only for muon tracks // propagation of MFT tracks alredy done in reconstruction + } + + if (rAtAbsorberEnd < muoncuts.cfg_min_rabs || muoncuts.cfg_max_rabs < rAtAbsorberEnd) { + return false; + } + + if (rAtAbsorberEnd < 26.5) { + if (muon.pDca() > 594.f) { + return false; + } + } else { + if (muon.pDca() > 324.f) { + return false; + } + } + + if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && muon.chi2MatchMCHMFT() > muoncuts.cfg_max_matching_chi2_mftmch) { + return false; + } + + auto mctrack = muon.template mcParticle_as(); + if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + registry.fill(HIST("StandaloneMuon/Ptgen_RelDeltaPt"), mctrack.pt(), (mctrack.pt() - pt) / mctrack.pt()); + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaEta"), mctrack.pt(), mctrack.eta() - eta); + if (mctrack.pdgCode() == -13) { // positive muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Pos"), mctrack.pt(), mctrack.phi() - phi); + } else if (mctrack.pdgCode() == 13) { // negative muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Neg"), mctrack.pt(), mctrack.phi() - phi); + } + } else if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + registry.fill(HIST("GlobalMuon/Ptgen_RelDeltaPt"), mctrack.pt(), (mctrack.pt() - pt) / mctrack.pt()); + registry.fill(HIST("GlobalMuon/Ptgen_DeltaEta"), mctrack.pt(), mctrack.eta() - eta); + if (mctrack.pdgCode() == -13) { // positive muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Pos"), mctrack.pt(), mctrack.phi() - phi); + } else if (mctrack.pdgCode() == 13) { // negative muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Neg"), mctrack.pt(), mctrack.phi() - phi); + } + } + return true; + } + + SliceCache cache; + Preslice perCollision_mid = o2::aod::track::collisionId; + Preslice perCollision_fwd = o2::aod::fwdtrack::collisionId; + + Filter collisionFilter = o2::aod::evsel::sel8 == true && nabs(o2::aod::collision::posZ) < 10.f; + using MyFilteredCollisions = soa::Filtered; + + Filter trackFilter_mid = o2::aod::track::pt > electroncuts.cfg_min_pt_track&& electroncuts.cfg_min_eta_track < o2::aod::track::eta&& o2::aod::track::eta < electroncuts.cfg_max_eta_track&& o2::aod::track::tpcChi2NCl < electroncuts.cfg_max_chi2tpc&& o2::aod::track::itsChi2NCl < electroncuts.cfg_max_chi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true && nabs(o2::aod::track::dcaXY) < electroncuts.cfg_max_dcaxy&& nabs(o2::aod::track::dcaZ) < electroncuts.cfg_max_dcaz; + using MyFilteredMCTracks = soa::Filtered; + + Partition sa_muons = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack); // MCH-MID + Partition global_muons = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack); // MFT-MCH-MID + + void process(MyFilteredCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredMCTracks const& tracks, MyMCFwdTracks const&, aod::McCollisions const&, aod::McParticles const&) + { + for (auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.has_mcCollision()) { + continue; + } + + auto mccollision = collision.template mcCollision_as(); + if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCollision_mid, collision.globalIndex()); + for (auto& track : tracks_per_coll) { + if (!track.has_mcParticle()) { + continue; + } + auto mctrack = track.template mcParticle_as(); + if (mctrack.mcCollisionId() != collision.mcCollisionId()) { + continue; + } + if (abs(mctrack.pdgCode()) != 11 || !(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + continue; + } + if (!checkTrack(track)) { + continue; + } + + registry.fill(HIST("Electron/Ptgen_RelDeltaPt"), mctrack.pt(), (mctrack.pt() - track.pt()) / mctrack.pt()); + registry.fill(HIST("Electron/Ptgen_DeltaEta"), mctrack.pt(), mctrack.eta() - track.eta()); + if (mctrack.pdgCode() == -11) { // positron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Pos"), mctrack.pt(), mctrack.phi() - track.phi()); + } else if (mctrack.pdgCode() == 11) { // electron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Neg"), mctrack.pt(), mctrack.phi() - track.phi()); + } + + } // end of track loop + + auto sa_muons_per_coll = sa_muons->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + auto global_muons_per_coll = global_muons->sliceByCached(o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + + for (auto& muon : sa_muons_per_coll) { + if (!muon.has_mcParticle()) { + continue; + } + auto mctrack = muon.template mcParticle_as(); + if (mctrack.mcCollisionId() != collision.mcCollisionId()) { + continue; + } + if (abs(mctrack.pdgCode()) != 13 || !(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + continue; + } + if (!checkFwdTrack(muon, collision)) { + continue; + } + } // end of standalone muon loop + + for (auto& muon : global_muons_per_coll) { + if (!muon.has_mcParticle()) { + continue; + } + auto mctrack = muon.template mcParticle_as(); + if (mctrack.mcCollisionId() != collision.mcCollisionId()) { + continue; + } + if (abs(mctrack.pdgCode()) != 13 || !(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + continue; + } + if (!checkFwdTrack(muon, collision)) { + continue; + } + + } // end of global muon loop + + } // end of collision loop + } +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"create-resolution-map"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dielectron.cxx b/PWGEM/Dilepton/Tasks/dielectron.cxx new file mode 100644 index 00000000000..c8fa31b0e3b --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dielectron.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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 is for dielectron analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/Dilepton.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dielectron"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dielectronMC.cxx b/PWGEM/Dilepton/Tasks/dielectronMC.cxx new file mode 100644 index 00000000000..3c525c29c6e --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dielectronMC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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 dalitz ee table for dalitz QC. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/DileptonMC.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dielectron-mc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dimuon.cxx b/PWGEM/Dilepton/Tasks/dimuon.cxx new file mode 100644 index 00000000000..51b92ab81b7 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dimuon.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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 is for dimuon analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/Dilepton.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dimuon"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dimuonMC.cxx b/PWGEM/Dilepton/Tasks/dimuonMC.cxx new file mode 100644 index 00000000000..f505c073dc3 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dimuonMC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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 dalitz ee table for dalitz QC. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/DileptonMC.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dimuon-mc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx index c9860ca0916..7cc41a190d2 100644 --- a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx +++ b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx @@ -46,6 +46,7 @@ #include "DataFormatsParameters/GRPMagField.h" #include "Field/MagneticField.h" #include "TGeoGlobalMagField.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" using std::cout; using std::endl; @@ -88,7 +89,7 @@ using MyBarrelTracksSelectedNoSkimmed = soa::Join; -using MyMCTrackNoSkimmed = soa::Join; +using MyMCTrackNoSkimmed = soa::Join; constexpr static uint32_t gkEventFillMapNoSkimmed = VarManager::ObjTypes::Collision; constexpr static uint32_t gkMCEventFillMapNoSkimmed = VarManager::ObjTypes::CollisionMC; @@ -101,7 +102,7 @@ using MyEventsSelected = soa::Join; using MyBarrelTracks = soa::Join; using MyBarrelTracksSelected = soa::Join; -using MyMCReducedTracks = soa::Join; +using MyMCReducedTracks = soa::Join; // constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; constexpr static uint32_t gkMCEventFillMap = VarManager::ObjTypes::ReducedEventMC; @@ -118,9 +119,12 @@ struct AnalysisEventSelection { Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigOnlyInjectedEvents{"cfgOnlyInjectedEvents", false, "Use only on Non-skimmed data! If true, select only injected events"}; + Configurable> fSubGenIDs{"cfgSubGenIDs", {0, 1, 2, 3}, "Use only on Non-skimmed data! Provide a comma separated list of subGenIDs to select, e.g. 0,1,2,3"}; HistogramManager* fHistMan; AnalysisCompositeCut* fEventCut; + HistogramRegistry registry{"HistoAnalysisEvent", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { @@ -135,8 +139,13 @@ struct AnalysisEventSelection { fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;", fConfigAddEventHistogram); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); + + AxisSpec axisSubGen = {4, -0.5, 3.5, "MC SubGenerator ID"}; + registry.add("Generator/SubGenerator_BeforeCuts", "", HistType::kTH1D, {axisSubGen}, true); + registry.add("Generator/SubGenerator_SelectedInjected", "", HistType::kTH1D, {axisSubGen}, true); + registry.add("Generator/SubGenerator_AfterCuts", "", HistType::kTH1D, {axisSubGen}, true); } } @@ -147,23 +156,40 @@ struct AnalysisEventSelection { VarManager::ResetValues(0, VarManager::kNEventWiseVariables); bool pass = true; + int32_t subGeneratorID = -999; VarManager::FillEvent(event); if constexpr ((TEventMCFillMap & VarManager::ObjTypes::ReducedEventMC) > 0) { VarManager::FillEvent(event.reducedMCevent()); + // TODO: Get access to subgenerator ID in skimmed data + // generatorID = event.reducedMCevent().generatorsID(); } if constexpr ((TEventMCFillMap & VarManager::ObjTypes::CollisionMC) > 0) { if (!event.has_mcCollision()) { pass = false; } else { VarManager::FillEvent(event.mcCollision()); + subGeneratorID = event.mcCollision().getSubGeneratorId(); } } + + registry.fill(HIST("Generator/SubGenerator_BeforeCuts"), subGeneratorID); + + // check if SubGeneratorID is part of list: + // if SubGenerator is not part of it, reject event, return + // fill event histos only if event is from SubGenerator + if (fConfigOnlyInjectedEvents && !(std::find(fSubGenIDs->begin(), fSubGenIDs->end(), subGeneratorID) != fSubGenIDs->end())) { + eventSel(0); + return; + } + if (fConfigQA) { fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event + registry.fill(HIST("Generator/SubGenerator_SelectedInjected"), subGeneratorID); } if (fEventCut->IsSelected(VarManager::fgValues) && pass) { if (fConfigQA) { fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + registry.fill(HIST("Generator/SubGenerator_AfterCuts"), subGeneratorID); } eventSel(1); } else { @@ -196,6 +222,7 @@ struct AnalysisEventSelection { PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy process function", false); PROCESS_SWITCH(AnalysisEventSelection, processDummyNoSkimmed, "Dummy process function", false); }; + struct AnalysisEventQa { Filter filterEventSelected = aod::emanalysisflags::isEventSelected == 1; @@ -413,16 +440,17 @@ struct AnalysisTrackSelection { // 3D histos for efficiency Configurable fConfigUsePtVec{"cfgUsePtVecEff", true, "If true, non-linear pt bins but vector pt bins"}; - ConfigurableAxis ptBinsVec{"ptBinsVec", {0., 0., 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.155, 0.16, 0.165, 0.17, 0.175, 0.18, 0.185, 0.19, 0.195, 0.20, 0.205, 0.21, 0.215, 0.22, 0.225, 0.23, 0.235, 0.24, 0.245, 0.25, 0.255, 0.26, 0.265, 0.27, 0.275, 0.28, 0.285, 0.29, 0.295, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.43, 0.46, 0.49, 0.52, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.90, 1.00, 1.10, 1.20, 1.40, 1.60, 1.80, 2.00, 2.40, 2.80, 3.20, 3.70, 4.50, 6.00, 8.00, 10.}, "Pt binning vector"}; + ConfigurableAxis ptBinsVec{"ptBinsVec", {0., 0., 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.155, 0.16, 0.165, 0.17, 0.175, 0.18, 0.185, 0.19, 0.195, 0.20, 0.205, 0.21, 0.215, 0.22, 0.225, 0.23, 0.235, 0.24, 0.245, 0.25, 0.255, 0.26, 0.265, 0.27, 0.275, 0.28, 0.285, 0.29, 0.295, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.43, 0.46, 0.49, 0.52, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.90, 1.00, 1.10, 1.20, 1.40, 1.60, 1.80, 2.00, 2.40, 2.80, 3.20, 3.70, 4.50, 6.00, 8.00, 10., 12., 14., 16., 18., 20.}, "Pt binning vector"}; ConfigurableAxis ptBins{"ptBins", {10, 0.f, 10.f}, "Pt binning"}; ConfigurableAxis etaBins{"etaBins", {16, -0.8f, 0.8f}, "Eta binning"}; ConfigurableAxis phiBins{"phiBins", {63, -0.f, 6.3f}, "Phi binning"}; Configurable fConfigRecWithMC{"cfgEffRecWithMCVars", false, "If true, fill also 3D histograms at reconstructed level with mc variables"}; + Configurable fConfigMCCollz{"cfgMCCollz", false, "If true, look only at reconstructed track associated to mc track from a MC collision within 10cm"}; // Resolution histos Configurable fConfigResolutionOn{"cfgResolution", false, "If true, fill resolution histograms"}; Configurable fConfigUsePtVecRes{"cfgUsePtVecRes", true, "If true, non-linear pt bins predefined in res histos"}; - ConfigurableAxis ptResBinsVec{"ptResBinsVec", {0., 0., 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.155, 0.16, 0.165, 0.17, 0.175, 0.18, 0.185, 0.19, 0.195, 0.20, 0.205, 0.21, 0.215, 0.22, 0.225, 0.23, 0.235, 0.24, 0.245, 0.25, 0.255, 0.26, 0.265, 0.27, 0.275, 0.28, 0.285, 0.29, 0.295, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.43, 0.46, 0.49, 0.52, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.90, 1.00, 1.10, 1.20, 1.40, 1.60, 1.80, 2.00, 2.40, 2.80, 3.20, 3.70, 4.50, 6.00, 8.00, 10., 12.0, 14., 16., 18., 20.}, "Pt binning vector for resolution"}; + ConfigurableAxis ptResBinsVec{"ptResBinsVec", {0., 0., 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.155, 0.16, 0.165, 0.17, 0.175, 0.18, 0.185, 0.19, 0.195, 0.20, 0.205, 0.21, 0.215, 0.22, 0.225, 0.23, 0.235, 0.24, 0.245, 0.25, 0.255, 0.26, 0.265, 0.27, 0.275, 0.28, 0.285, 0.29, 0.295, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.43, 0.46, 0.49, 0.52, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.90, 1.00, 1.10, 1.20, 1.40, 1.60, 1.80, 2.00, 2.40, 2.80, 3.20, 3.70, 4.50, 6.00, 8.00, 10., 12., 14., 16., 18., 20.}, "Pt binning vector for resolution"}; ConfigurableAxis ptResBins{"ptResBins", {20, 0.f, 20.f}, "Pt binning for resolution"}; ConfigurableAxis deltaptResBins{"deltaptResBins", {500, -0.5f, 0.5f}, "DeltaPt binning for resolution"}; ConfigurableAxis deltaetaResBins{"deltaetaResBins", {500, -0.5f, 0.5f}, "DeltaEta binning for resolution"}; @@ -452,6 +480,13 @@ struct AnalysisTrackSelection { std::vector> fHistRecNegPart; std::vector> fHistRecPosPartMC; std::vector> fHistRecNegPartMC; + // + std::vector> fHistRecPosSingleRecPartMC; + std::vector> fHistRecNegSingleRecPartMC; + std::vector> fHistRecPosClassCollDoubleCountPartMC; + std::vector> fHistRecNegClassCollDoubleCountPartMC; + std::vector> fHistRecPosClassAmbigCollDoubleCountPartMC; + std::vector> fHistRecNegClassAmbigCollDoubleCountPartMC; // Res histos std::vector> fHistRes; @@ -460,7 +495,7 @@ struct AnalysisTrackSelection { HistogramManager* fHistManQA; // histo manager std::vector fHistNamesRecoQA; // list of histo names for all reconstructed tracks in histo manager std::vector> fHistNamesMCMatchedQA; // list of histo names for reconstructed signals in histo manager - std::vector> fHistNamesMCQA; // list of histo names for generated signals in histo manager + std::vector fHistNamesMCQA; // list of histo names for generated signals in histo manager void init(o2::framework::InitContext&) { @@ -474,6 +509,9 @@ struct AnalysisTrackSelection { AxisSpec axisEta{etaBins, "#it{#eta}_{e}"}; AxisSpec axisPhi{phiBins, "#it{#varphi}_{e} (rad)"}; AxisSpec axisPt{ptBins, "#it{p}_{T,e} (GeV/#it{c})"}; + AxisSpec axisMCColl = {3, -0.5, 2.5, "MCcoll info"}; + AxisSpec axisDoubleCount = {2, -0.5, 1.5, "Double count info"}; + AxisSpec axisAmbig = {2, -0.5, 1.5, "Ambiguous info"}; // List of track cuts TString cutNamesStr = fConfigCuts.value; @@ -542,21 +580,51 @@ struct AnalysisTrackSelection { if (fConfigRecWithMC) { for (unsigned int list_i = 0; list_i < fTrackCuts.size(); ++list_i) { for (unsigned int i = 0; i < fMCSignals.size(); ++i) { - if (!fConfigUsePtVec) { fHistRecPosPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); fHistRecNegPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecPosSingleRecPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_SingleRec_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecNegSingleRecPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_SingleRec_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecPosClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_ClassCollDoubleCount_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisMCColl, axisDoubleCount}, true)); + fHistRecNegClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_ClassCollDoubleCount_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisMCColl, axisDoubleCount}, true)); } else { fHistRecPosPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); fHistRecNegPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecPosSingleRecPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_SingleRec_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecNegSingleRecPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_SingleRec_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecPosClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_ClassCollDoubleCount_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisMCColl, axisDoubleCount}, true)); + fHistRecNegClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_ClassCollDoubleCount_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisMCColl, axisDoubleCount}, true)); } + fHistRecPosClassAmbigCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Pos_ClassAmigCollDoubleCount_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisAmbig, axisMCColl, axisDoubleCount}, true)); + fHistRecNegClassAmbigCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/%s_MCVars/Nrec_Neg_ClassAmigCollDoubleCount_%s", fTrackCuts.at(list_i).GetName(), fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisAmbig, axisMCColl, axisDoubleCount}, true)); } } + // Histo without track cut + for (unsigned int i = 0; i < fMCSignals.size(); ++i) { + + if (!fConfigUsePtVec) { + fHistRecPosPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecNegPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecPosSingleRecPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_SingleRec_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecNegSingleRecPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_SingleRec_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisEta, axisPhi}, true)); + fHistRecPosClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_ClassCollDoubleCount_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisMCColl, axisDoubleCount}, true)); + fHistRecNegClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_ClassCollDoubleCount_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisPt, axisMCColl, axisDoubleCount}, true)); + + } else { + fHistRecPosPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecNegPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecPosSingleRecPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_SingleRec_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecNegSingleRecPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_SingleRec_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisEta, axisPhi}, true)); + fHistRecPosClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_ClassCollDoubleCount_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisMCColl, axisDoubleCount}, true)); + fHistRecNegClassCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_ClassCollDoubleCount_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {{ptBinsVec, "#it{p}_{T,e} (GeV/#it{c})"}, axisMCColl, axisDoubleCount}, true)); + } + fHistRecPosClassAmbigCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Pos_ClassAmigCollDoubleCount_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisAmbig, axisMCColl, axisDoubleCount}, true)); + fHistRecNegClassAmbigCollDoubleCountPartMC.push_back(registry.add(Form("SingleElectron/NoCut_MCVars/Nrec_Neg_ClassAmigCollDoubleCount_%s", fMCSignals.at(i).GetName()), "", HistType::kTH3D, {axisAmbig, axisMCColl, axisDoubleCount}, true)); + } } // Resolution histogramms if (fConfigResolutionOn) { - // Binning for resolution AxisSpec axisPtRes{ptResBins, "#it{p}^{gen}_{T,e} (GeV/#it{c})"}; AxisSpec axisDeltaptRes{deltaptResBins, "(p^{gen}_{T} - p^{rec}_{T}) / p^{gen}_{T} (GeV/c)"}; @@ -598,19 +666,20 @@ struct AnalysisTrackSelection { } // Add histogram classes for each MC signal at generated level - std::vector mcnamesgen; + // std::vector mcnamesgen; for (unsigned int isig = 0; isig < fMCSignals.size(); ++isig) { TString nameStr2 = Form("MCTruthGen_%s", fMCSignals.at(isig).GetName()); - mcnamesgen.push_back(nameStr2); + fHistNamesMCQA.push_back(nameStr2); + // mcnamesgen.push_back(nameStr2); histClassesQA += Form("%s;", nameStr2.Data()); } - fHistNamesMCQA.push_back(mcnamesgen); + // fHistNamesMCQA.push_back(mcnamesgen); fHistManQA = new HistogramManager("SingleElectronQA", "aa", VarManager::kNVars); fHistManQA->SetUseDefaultVariableNames(kTRUE); fHistManQA->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); DefineHistograms(fHistManQA, histClassesQA.Data(), fConfigAddTrackHistogram); // define all histograms - VarManager::SetUseVars(fHistManQA->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistManQA->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fQASingleElectronList = fHistManQA->GetMainHistogramList(); } fOutputQA.setObject(fQASingleElectronList); @@ -700,6 +769,16 @@ struct AnalysisTrackSelection { runRecTrack(tracks, tracksMC, true, write); } + template + void runDataFillMore(TEvents const& events, TEventsMC eventsMC, TTracks const& tracks, TTracksMC const& tracksMC, TAmbigTracks const& ambiTracksMid) + { + + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::ResetValues(0, VarManager::kNMCParticleVariables); + + runRecTrackMore(events, eventsMC, tracks, tracksMC, ambiTracksMid); + } + template void runMCFill(TEventsMC const& eventMC, TTracksMC const& tracksMC) { @@ -708,6 +787,14 @@ struct AnalysisTrackSelection { runMCGenTrack(tracksMC); } + template + void runMCFillMore(TEventsMC const& eventMC, TTracksMC const& tracksMC) + { + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEvent(eventMC); + runMCGenTrackMore(tracksMC, eventMC); + } + template void runDataSelection(TTracks const& tracks, TTracksMC const& tracksMC) { @@ -717,9 +804,52 @@ struct AnalysisTrackSelection { template void runMCGenTrack(TTracksMC const& groupedMCTracks) + { + for (auto& mctrack : groupedMCTracks) { + VarManager::ResetValues(0, VarManager::kNMCParticleVariables); + VarManager::FillTrackMC(groupedMCTracks, mctrack); + int isig = 0; + for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = groupedMCTracks.rawIteratorAt(mctrack.globalIndex()); + checked = (*sig).CheckSignal(true, mctrack_raw); + } else { + checked = (*sig).CheckSignal(true, mctrack); + } + if (checked) { + if (mctrack.pdgCode() > 0) { + fHistGenNegPart[isig]->Fill(mctrack.pt(), mctrack.eta(), mctrack.phi()); + if constexpr (smeared) + fHistGenSmearedNegPart[isig]->Fill(mctrack.ptSmeared(), mctrack.etaSmeared(), mctrack.phiSmeared()); + } else { + fHistGenPosPart[isig]->Fill(mctrack.pt(), mctrack.eta(), mctrack.phi()); + if constexpr (smeared) + fHistGenSmearedPosPart[isig]->Fill(mctrack.ptSmeared(), mctrack.etaSmeared(), mctrack.phiSmeared()); + } + if (fConfigQA) { + fHistManQA->FillHistClass(fHistNamesMCQA[isig].Data(), VarManager::fgValues); + } + } + } + } + } + + template + void runMCGenTrackMore(TTracksMC const& groupedMCTracks, TEventsMC const& /*eventMC*/) { for (auto& mctrack : groupedMCTracks) { + + bool mccollisionwithin10 = false; + auto mccollision = mctrack.mcCollision(); + Double_t zmc = mccollision.posZ(); + if (TMath::Abs(zmc) < 10.) + mccollisionwithin10 = true; + + if (!mccollisionwithin10 && fConfigMCCollz) + continue; + VarManager::ResetValues(0, VarManager::kNMCParticleVariables); VarManager::FillTrackMC(groupedMCTracks, mctrack); int isig = 0; @@ -742,7 +872,8 @@ struct AnalysisTrackSelection { fHistGenSmearedPosPart[isig]->Fill(mctrack.ptSmeared(), mctrack.etaSmeared(), mctrack.phiSmeared()); } if (fConfigQA) - fHistManQA->FillHistClass(Form("MCTruthGen_%s", (*sig).GetName()), VarManager::fgValues); + // fHistManQA->FillHistClass(Form("MCTruthGen_%s", (*sig).GetName()), VarManager::fgValues); + fHistManQA->FillHistClass(fHistNamesMCQA[isig].Data(), VarManager::fgValues); } } } @@ -900,6 +1031,254 @@ struct AnalysisTrackSelection { } // end loop over reconstructed track belonging to the events } + template + void runRecTrackMore(TEvents const& events, TEventsMC const& /*eventsMC*/, TTracks const& groupedTracks, TTracksMC const& tracksMC, TAmbigTracks const& ambiTracksMid) + { + + std::map fRecTrackLabels[fTrackCuts.size() + 1]; + + uint32_t filterMap = 0; + trackSel.reserve(groupedTracks.size()); + + for (auto& track : groupedTracks) { + + // How many time the associated MC track was seen for this cut + Int_t fRecCounters[fTrackCuts.size() + 1]; + for (unsigned int k = 0; k < fTrackCuts.size() + 1; k++) { + fRecCounters[k] = 0; + } + + filterMap = 0; + Int_t ambiguousinfo = 0; + Int_t collisioninfo = -1; + Int_t mcCollisionIddmctrack = -999; + Int_t mcCollisionIdrectrack = -999; + bool mccollisionwithin10 = false; + + VarManager::FillTrack(track); // compute track quantities + + // Do ambiguous tracks + for (auto& ambiTrackMid : ambiTracksMid) { + if (ambiTrackMid.trackId() == track.globalIndex()) { + ambiguousinfo = 1; + break; + } + } + + // Do matching + // if (!track.has_collision()) printf("CollisionId %d\n",track.collisionId()); + if (track.has_collision()) { + Int_t reccollisionid = track.collisionId(); + if (ambiguousinfo == 1) + printf("Has reccollision but is ambiguous\n"); + // printf("Look for the reconstructed collision %d\n",reccollisionid); + bool pass = 0; + for (auto& event : events) { + if (event.isEventSelected() == 1) { + VarManager::FillEvent(event); + // printf("Global index of collision %d\n",event.globalIndex()); + if (reccollisionid == event.globalIndex()) { + pass = 1; + // printf("Found a collision with the same id %d and %d\n",reccollisionid,event.globalIndex()); + if (ambiguousinfo == 1) + printf("Has reccollision and found it in the list but is ambiguous\n"); + if (event.has_mcCollision()) { + mcCollisionIdrectrack = event.mcCollisionId(); + if (ambiguousinfo == 1) + printf("Has reccollision with mccollision but is ambiguous\n"); + } else { + if (ambiguousinfo == 1) + printf("Has reccollision but without mccollision and is ambiguous\n"); + } + break; + } + } + } + if (!pass) // rec collision of track is not selected by isSelected + continue; + // else rec collision of track is selected by isSelected + } else { + // printf("Not attached to a reconstructed collision\n"); + } + + if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { + // If no MC particle is found, skip the track + if (track.has_mcParticle()) { + // if (ambiguousinfo == 1) printf("Has mcparticle but is ambiguous\n"); + // printf("Found a mc track\n"); + auto mctrack = track.template mcParticle_as(); + mcCollisionIddmctrack = mctrack.mcCollisionId(); + auto mccollision = mctrack.mcCollision(); + Double_t zmc = mccollision.posZ(); + if (TMath::Abs(zmc) < 10.) + mccollisionwithin10 = true; + VarManager::FillTrackMC(tracksMC, mctrack); + } + } + + // no track cut + if (fConfigQA) { + fHistManQA->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); + } + + // if (ambiguousinfo == 1) printf("Values are %d and %d\n",mcCollisionIddmctrack,mcCollisionIdrectrack); + // compute collision and mccollision info + if (mcCollisionIddmctrack != -999 && mcCollisionIdrectrack != -999) { + if (mcCollisionIddmctrack == mcCollisionIdrectrack) + collisioninfo = 0; + else + collisioninfo = 1; + } else { + collisioninfo = 2; + } + // printf("collision info %d\n",collisioninfo); + + // compute track selection and publish the bit map + int i = 0; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, i++) { + if ((*cut).IsSelected(VarManager::fgValues)) { + filterMap |= (uint32_t(1) << i); + if (fConfigQA) { + fHistManQA->FillHistClass(fHistNamesRecoQA[i].Data(), VarManager::fgValues); + } + } + } + + // compute MC matching decisions + uint32_t mcDecision = 0; + int isig = 0; + Int_t mctrackindex = -999; + Int_t doublereconstructedtrack[fTrackCuts.size() + 1]; + for (unsigned int k = 0; k < fTrackCuts.size() + 1; k++) { + doublereconstructedtrack[k] = 0; + } + for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { + if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { + if (track.has_mcParticle()) { + auto mctrack = track.template mcParticle_as(); + if ((*sig).CheckSignal(true, mctrack)) { + mcDecision |= (uint32_t(1) << isig); + mctrackindex = mctrack.globalIndex(); + } + } + } + } + + // // Double reconstructed track only for the signal (they should not be redundant or crossing!!) + // for (unsigned int i = 0; i < fMCSignals.size(); i++) { + // if (!(mcDecision & (uint32_t(1) << i))) { + // continue; + // } + + // no track cuts + if (!(fRecTrackLabels[fTrackCuts.size()].find(mctrackindex) != fRecTrackLabels[fTrackCuts.size()].end())) { + fRecTrackLabels[fTrackCuts.size()][mctrackindex] = fRecCounters[fTrackCuts.size()]; + fRecCounters[fTrackCuts.size()]++; + } else { + // printf("For cut %d, found a mc collision track already reconstructed %d for selected collision with the same mc collision %d\n",j,mctrackindex,mcCollisionId); + doublereconstructedtrack[fTrackCuts.size()] = 1; + fRecTrackLabels[fTrackCuts.size()][mctrackindex] = fRecTrackLabels[fTrackCuts.size()].find(mctrackindex)->second + 1; + } + // track cuts + for (unsigned int j = 0; j < fTrackCuts.size(); j++) { + if (filterMap & (uint8_t(1) << j)) { + + if (!(fRecTrackLabels[j].find(mctrackindex) != fRecTrackLabels[j].end())) { + fRecTrackLabels[j][mctrackindex] = fRecCounters[j]; + fRecCounters[j]++; + } else { + // printf("For cut %d, found a mc collision track already reconstructed %d for selected collision with the same mc collision %d\n",j,mctrackindex,mcCollisionId); + doublereconstructedtrack[j] = 1; + fRecTrackLabels[j][mctrackindex] = fRecTrackLabels[j].find(mctrackindex)->second + 1; + } + } + } + // } + + // fill histograms + for (unsigned int i = 0; i < fMCSignals.size(); i++) { + if (!(mcDecision & (uint32_t(1) << i))) { + continue; + } + Double_t mmcpt = -10000.; + Double_t mmceta = -10000.; + Double_t mmcphi = -1000.; + // No track cut + if (fConfigRecWithMC) { + if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrack) > 0) { + auto mctrack = track.reducedMCTrack(); + mmcpt = mctrack.pt(); + mmceta = mctrack.eta(); + mmcphi = mctrack.phi(); + } + if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { + if (track.has_mcParticle()) { + auto mctrack = track.template mcParticle_as(); + mmcpt = mctrack.pt(); + mmceta = mctrack.eta(); + mmcphi = mctrack.phi(); + } + } + + if ((mccollisionwithin10 && fConfigMCCollz) || (!fConfigMCCollz)) { + if (track.sign() < 0) { + fHistRecNegPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (doublereconstructedtrack[fTrackCuts.size()] == 0) + fHistRecNegSingleRecPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (TMath::Abs(mmceta) < 0.8) { + fHistRecNegClassCollDoubleCountPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(mmcpt, collisioninfo, doublereconstructedtrack[fTrackCuts.size()]); + fHistRecNegClassAmbigCollDoubleCountPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(ambiguousinfo, collisioninfo, doublereconstructedtrack[fTrackCuts.size()]); + } + } else { + fHistRecPosPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (doublereconstructedtrack[fTrackCuts.size()] == 0) + fHistRecPosSingleRecPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (TMath::Abs(mmceta) < 0.8) { + fHistRecPosClassCollDoubleCountPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(mmcpt, collisioninfo, doublereconstructedtrack[fTrackCuts.size()]); + fHistRecPosClassAmbigCollDoubleCountPartMC[fTrackCuts.size() * fMCSignals.size() + i]->Fill(ambiguousinfo, collisioninfo, doublereconstructedtrack[fTrackCuts.size()]); + } + } + } + } + // track cuts + for (unsigned int j = 0; j < fTrackCuts.size(); j++) { + if (filterMap & (uint8_t(1) << j)) { + if (track.sign() < 0) { + fHistRecNegPart[j * fMCSignals.size() + i]->Fill(track.pt(), track.eta(), track.phi()); + } else { + fHistRecPosPart[j * fMCSignals.size() + i]->Fill(track.pt(), track.eta(), track.phi()); + } + + if (fConfigRecWithMC) { + if ((mccollisionwithin10 && fConfigMCCollz) || (!fConfigMCCollz)) { + if (track.sign() < 0) { + fHistRecNegPartMC[j * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (doublereconstructedtrack[j] == 0) + fHistRecNegSingleRecPartMC[j * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (TMath::Abs(mmceta) < 0.8) { + fHistRecNegClassCollDoubleCountPartMC[j * fMCSignals.size() + i]->Fill(mmcpt, collisioninfo, doublereconstructedtrack[j]); + fHistRecNegClassAmbigCollDoubleCountPartMC[j * fMCSignals.size() + i]->Fill(ambiguousinfo, collisioninfo, doublereconstructedtrack[fTrackCuts.size()]); + } + } else { + fHistRecPosPartMC[j * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (doublereconstructedtrack[j] == 0) + fHistRecPosSingleRecPartMC[j * fMCSignals.size() + i]->Fill(mmcpt, mmceta, mmcphi); + if (TMath::Abs(mmceta) < 0.8) { + fHistRecPosClassCollDoubleCountPartMC[j * fMCSignals.size() + i]->Fill(mmcpt, collisioninfo, doublereconstructedtrack[j]); + fHistRecPosClassAmbigCollDoubleCountPartMC[j * fMCSignals.size() + i]->Fill(ambiguousinfo, collisioninfo, doublereconstructedtrack[fTrackCuts.size()]); + } + } + } + } + + if (fConfigQA) + fHistManQA->FillHistClass(fHistNamesMCMatchedQA[j][i].Data(), VarManager::fgValues); + } + } // end loop over cuts + } // end loop over MC signals + } // end loop over reconstructed track belonging to the events + } + void processSkimmed(soa::Filtered const& events, MyBarrelTracks const& tracks, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) { runSelection(events, tracks, eventsMC, tracksMC, true); @@ -925,15 +1304,48 @@ struct AnalysisTrackSelection { } void processMCNoSkimmed(soa::Filtered::iterator const& eventMC, MyMCTrackNoSkimmed const& tracksMC) + // void processMCNoSkimmed(aod::McCollisions::iterator const& eventMC, MyMCTrackNoSkimmed const& tracksMC) { runMCFill(eventMC, tracksMC); } + // void processMCNoSkimmed(MyMCTrackNoSkimmed const& tracksMC) + // { + // runMCGenTrack(tracksMC); + // } + + void processMCNoSkimmedMore(soa::Filtered::iterator const& eventMC, MyMCTrackNoSkimmed const& tracksMC) + // void processMCNoSkimmedMore(aod::McCollisions::iterator const& eventMC, MyMCTrackNoSkimmed const& tracksMC) + { + runMCFillMore(eventMC, tracksMC); + } + + // void processMCNoSkimmedMore(MyMCTrackNoSkimmed const& tracksMC, aod::McCollisions const& eventsMC) + // { + // runMCGenTrackMore(tracksMC, eventsMC); + // } + void processDataNoSkimmed(soa::Filtered::iterator const& event, MyBarrelTracksNoSkimmed const& tracks, aod::McParticles const& tracksMC) { runDataFill(event, tracks, tracksMC, false); } + // void processDataNoSkimmed(MyBarrelTracksNoSkimmed const& tracks, aod::McParticles const& tracksMC) + // { + // runRecTrack(tracks, tracksMC, true, false); + // // runDataFill(event, tracks, tracksMC, false); + // } + + void processDataNoSkimmedMore(soa::Filtered const& events, aod::McCollisions const& eventsMC, MyBarrelTracksNoSkimmed const& tracks, aod::McParticles const& tracksMC, aod::AmbiguousTracks const& ambiTracksMid) + { + runDataFillMore(events, eventsMC, tracks, tracksMC, ambiTracksMid); + } + + // void processDataNoSkimmedMore(MyBarrelTracksNoSkimmed const& tracks, aod::McParticles const& tracksMC, aod::AmbiguousTracks const& ambiTracksMid, MyEventsNoSkimmed const& events, aod::McCollisions const& eventsMC) + // { + // runRecTrackMore(events, eventsMC, tracks, tracksMC, ambiTracksMid); + // } + void processDummy(MyEvents&) { // do nothing @@ -946,7 +1358,9 @@ struct AnalysisTrackSelection { PROCESS_SWITCH(AnalysisTrackSelection, processDataSelectionNoSkimmed, "Run barrel track selection without skimming", false); PROCESS_SWITCH(AnalysisTrackSelection, processMCNoSkimmed, "Run the barrel MC track filling without skimming", false); + PROCESS_SWITCH(AnalysisTrackSelection, processMCNoSkimmedMore, "Run the barrel MC track filling without skimming", false); PROCESS_SWITCH(AnalysisTrackSelection, processDataNoSkimmed, "Run the barrel data track filling without skimming", false); + PROCESS_SWITCH(AnalysisTrackSelection, processDataNoSkimmedMore, "Run the barrel data track filling without skimming", false); PROCESS_SWITCH(AnalysisTrackSelection, processSkimmed, "Run the data and mc barrel data track selection and filling on DQ skimmed tracks", false); PROCESS_SWITCH(AnalysisTrackSelection, processDataSkimmed, "Run the barrel data track selection and filling on DQ skimmed tracks", false); PROCESS_SWITCH(AnalysisTrackSelection, processMCSkimmed, "Run the barrel mc track filling on DQ skimmed tracks", false); @@ -1200,6 +1614,7 @@ struct AnalysisSameEventPairing { template void runDataPairing(TEvent const& event, TTracks const& tracks, TTracksMC const& tracksMC) { + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); // fill event information which might be needed in histograms that combine track and event properties VarManager::FillEvent(event); @@ -1622,7 +2037,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, Configurab histMan->AddHistogram(objArray->At(iclass)->GetName(), "Phi", "MC generator #varphi distribution", false, 500, -6.3, 6.3, VarManager::kMCPhi); } if (classStr.Contains("MCTruthGen")) { - dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth"); + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_track"); } if (classStr.Contains("DileptonsSelected")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair_barrel"); diff --git a/PWGEM/Dilepton/Tasks/eventQC.cxx b/PWGEM/Dilepton/Tasks/eventQC.cxx new file mode 100644 index 00000000000..f18b44291f2 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/eventQC.cxx @@ -0,0 +1,617 @@ +// Copyright 2019-2020 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 is for event QC for PWG-EM. +// Please write to: daiki.sekihata@cern.ch + +#include +#include +#include + +#include "TString.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CCDB/BasicCCDBManager.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +using MyBCs = soa::Join; +using MyQvectors = soa::Join; + +using MyCollisions = soa::Join; +using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisions_Cent_Qvec = soa::Join; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; + +struct eventQC { + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + Configurable cfgFillPID{"cfgFillPID", false, "fill PID histograms"}; + Configurable> cfgnMods{"cfgnMods", {2, 3}, "Modulation of interest. Please keep increasing order"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + ConfigurableAxis ConfPtBins{"ConfPtBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pT bins for output histograms"}; + Configurable cfgNbinsEta{"cfgNbinsEta", 40, "number of eta bins for output histograms"}; + Configurable cfgNbinsPhi{"cfgNbinsPhi", 360, "number of phi bins for output histograms"}; + + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + struct : ConfigurableGroup { + std::string prefix = "trackcut_group"; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.15, "min pT for single track"}; + Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.9, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.9, "max eta for single track"}; + Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 80, "min ncrossed rows"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 1, "min ncluster its"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + } trackcuts; + + Service ccdb; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_types[2] = {"before/", "after/"}; + + void init(InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + addhistograms(); + } + + ~eventQC() {} + + void addhistograms() + { + // event info + + const int nbin_ev = 13; + auto hCollisionCounter = fRegistry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{nbin_ev, 0.5, nbin_ev + 0.5}}, false); + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "FT0AND"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "No TF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "No ITS ROF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "No Same Bunch Pileup"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "Is Vertex ITS-TPC"); + hCollisionCounter->GetXaxis()->SetBinLabel(8, "Is Vertex ITS-TPC-TRD"); + hCollisionCounter->GetXaxis()->SetBinLabel(9, "Is Vertex ITS-TPC-TOF"); + hCollisionCounter->GetXaxis()->SetBinLabel(10, "sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(11, "|Z_{vtx}| < 10 cm"); + hCollisionCounter->GetXaxis()->SetBinLabel(12, "NoCollInTimeRangeStandard"); + hCollisionCounter->GetXaxis()->SetBinLabel(13, "accepted"); + + fRegistry.add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry.add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry.add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); + fRegistry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{100, 0, 100}, {600, 0, 6000}}, false); + fRegistry.add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); + fRegistry.add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{60, 0, 60000}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hNTracksPVvsOccupancy", "hNTracksPVvsOccupancy;N_{track} to PV;N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hNGlobalTracksvsOccupancy", "hNGlobalTracksvsOccupancy;N_{track}^{global};N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hNGlobalTracksPVvsOccupancy", "hNGlobalTracksPVvsOccupancy;N_{track}^{global} to PV;N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); + fRegistry.addClone("Event/before/", "Event/after/"); + + fRegistry.add("Event/after/hMultNGlobalTracks", "hMultNGlobalTracks; N_{track}^{global}", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry.add("Event/after/hCentFT0CvsMultNGlobalTracks", "hCentFT0CvsMultNGlobalTracks;centrality FT0C (%);N_{track}^{global}", kTH2F, {{100, 0, 100}, {600, 0, 6000}}, false); + fRegistry.add("Event/after/hMultFT0CvsMultNGlobalTracks", "hMultFT0CvsMultNGlobalTracks;mult. FT0C;N_{track}^{global}", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); + fRegistry.add("Event/after/hMultNGlobalTracksPV", "hMultNGlobalTracksPV; N_{track}^{global} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry.add("Event/after/hCentFT0CvsMultNGlobalTracksPV", "hCentFT0CvsMultNGlobalTracksPV;centrality FT0C (%);N_{track}^{global} to PV", kTH2F, {{100, 0, 100}, {600, 0, 6000}}, false); + fRegistry.add("Event/after/hMultFT0CvsMultNGlobalTracksPV", "hMultFT0CvsMultNGlobalTracksPV;mult. FT0C;N_{track}^{global} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); + + for (int i = 0; i < static_cast(cfgnMods->size()); i++) { + int nmod = cfgnMods->at(i); + fRegistry.add(Form("Event/after/Qvector/hQ%dxFT0M_CentFT0C", nmod), Form("hQ%dxFT0M_CentFT0C;centrality FT0C (%%);Q_{%d,x}^{FT0M}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dyFT0M_CentFT0C", nmod), Form("hQ%dyFT0M_CentFT0C;centrality FT0C (%%);Q_{%d,y}^{FT0M}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dxFT0A_CentFT0C", nmod), Form("hQ%dxFT0A_CentFT0C;centrality FT0C (%%);Q_{%d,x}^{FT0A}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dyFT0A_CentFT0C", nmod), Form("hQ%dyFT0A_CentFT0C;centrality FT0C (%%);Q_{%d,y}^{FT0A}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dxFT0C_CentFT0C", nmod), Form("hQ%dxFT0C_CentFT0C;centrality FT0C (%%);Q_{%d,x}^{FT0C}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dyFT0C_CentFT0C", nmod), Form("hQ%dyFT0C_CentFT0C;centrality FT0C (%%);Q_{%d,y}^{FT0C}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dxBPos_CentFT0C", nmod), Form("hQ%dxBPos_CentFT0C;centrality FT0C (%%);Q_{%d,x}^{BPos}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dyBPos_CentFT0C", nmod), Form("hQ%dyBPos_CentFT0C;centrality FT0C (%%);Q_{%d,y}^{BPos}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dxBNeg_CentFT0C", nmod), Form("hQ%dxBNeg_CentFT0C;centrality FT0C (%%);Q_{%d,x}^{BNeg}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dyBNeg_CentFT0C", nmod), Form("hQ%dyBNeg_CentFT0C;centrality FT0C (%%);Q_{%d,y}^{BNeg}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dxBTot_CentFT0C", nmod), Form("hQ%dxBTot_CentFT0C;centrality FT0C (%%);Q_{%d,x}^{BTot}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry.add(Form("Event/after/Qvector/hQ%dyBTot_CentFT0C", nmod), Form("hQ%dyBTot_CentFT0C;centrality FT0C (%%);Q_{%d,y}^{BTot}", nmod, nmod), kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + + fRegistry.add(Form("Event/after/Qvector/hEP%dFT0M_CentFT0C", nmod), Form("event plane FT0M;centrality FT0C (%%);#Psi_{%d}^{FT0M} (rad.)", nmod), kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry.add(Form("Event/after/Qvector/hEP%dFT0A_CentFT0C", nmod), Form("event plane FT0A;centrality FT0C (%%);#Psi_{%d}^{FT0A} (rad.)", nmod), kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry.add(Form("Event/after/Qvector/hEP%dFT0C_CentFT0C", nmod), Form("event plane FT0C;centrality FT0C (%%);#Psi_{%d}^{FT0C} (rad.)", nmod), kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry.add(Form("Event/after/Qvector/hEP%dBPos_CentFT0C", nmod), Form("event plane BPos;centrality FT0C (%%);#Psi_{%d}^{BPos} (rad.)", nmod), kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry.add(Form("Event/after/Qvector/hEP%dBNeg_CentFT0C", nmod), Form("event plane BNeg;centrality FT0C (%%);#Psi_{%d}^{BNeg} (rad.)", nmod), kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry.add(Form("Event/after/Qvector/hEP%dBTot_CentFT0C", nmod), Form("event plane BTot;centrality FT0C (%%);#Psi_{%d}^{BTot} (rad.)", nmod), kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0MQ%dBPos_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0M} #upoint Q_{%d}^{BPos};centrality FT0C (%%);Q_{%d}^{FT0M} #upoint Q_{%d}^{BPos}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0MQ%dBNeg_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0M} #upoint Q_{%d}^{BNeg};centrality FT0C (%%);Q_{%d}^{FT0M} #upoint Q_{%d}^{BNeg}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dBPosQ%dBNeg_CentFT0C", nmod, nmod), Form("Q_{%d}^{BPos} #upoint Q_{%d}^{BNeg};centrality FT0C (%%);Q_{%d}^{BPos} #upoint Q_{%d}^{BNeg}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0CQ%dBPos_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0C} #upoint Q_{%d}^{BPos};centrality FT0C (%%);Q_{%d}^{FT0C} #upoint Q_{%d}^{BPos}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0CQ%dBNeg_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0C} #upoint Q_{%d}^{BNeg};centrality FT0C (%%);Q_{%d}^{FT0C} #upoint Q_{%d}^{BNeg}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0CQ%dBTot_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0C} #upoint Q_{%d}^{BTot};centrality FT0C (%%);Q_{%d}^{FT0C} #upoint Q_{%d}^{BTot}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0AQ%dBPos_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0A} #upoint Q_{%d}^{BPos};centrality FT0C (%%);Q_{%d}^{FT0A} #upoint Q_{%d}^{BPos}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0AQ%dBNeg_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0A} #upoint Q_{%d}^{BNeg};centrality FT0C (%%);Q_{%d}^{FT0A} #upoint Q_{%d}^{BNeg}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0AQ%dBTot_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0A} #upoint Q_{%d}^{BTot};centrality FT0C (%%);Q_{%d}^{FT0A} #upoint Q_{%d}^{BTot}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + fRegistry.add(Form("Event/after/Qvector/hPrfQ%dFT0AQ%dFT0C_CentFT0C", nmod, nmod), Form("Q_{%d}^{FT0A} #upoint Q_{%d}^{FT0C};centrality FT0C (%%);Q_{%d}^{FT0A} #upoint Q_{%d}^{FT0C}", nmod, nmod, nmod, nmod), kTProfile, {{100, 0, 100}}, false); + } + + std::vector tmp_ptbins; + for (int i = 0; i < 100; i++) { + tmp_ptbins.emplace_back(0.01 * i); // every 0.01 GeV/c from 0 to 1 GeV/c + } + for (int i = 0; i < 91; i++) { + tmp_ptbins.emplace_back(0.1 * i + 1.f); // every 0.1 GeV/c from 1 to 10 GeV/c + } + const AxisSpec axis_pt_tmp{tmp_ptbins, "p_{T} (GeV/c)"}; + + const AxisSpec axis_pt{ConfPtBins, "p_{T} (GeV/c)"}; + const AxisSpec axis_eta{cfgNbinsEta, -1.0, +1.0, "#eta"}; + const AxisSpec axis_phi{cfgNbinsPhi, 0.0, 2 * M_PI, "#varphi (rad.)"}; + const AxisSpec axis_sign{3, -1.5, +1.5, "sign"}; + fRegistry.add("Track/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_sign}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/hRelSigma1Pt", "relative p_{T} resolution;p_{T} (GeV/c);#sigma_{1/p_{T}} #times p_{T}", kTH2F, {axis_pt_tmp, {100, 0, 0.1}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {axis_pt_tmp, {500, 0., 500}}, false); + fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {axis_pt_tmp, {500, 0., 500}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + + if (cfgFillPID) { + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); + fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + } + } + + template + void fillTrackInfo(TTrack const& track) + { + fRegistry.fill(HIST("Track/hs"), track.pt(), track.eta(), track.phi(), track.sign()); + fRegistry.fill(HIST("Track/hQoverPt"), track.signed1Pt()); + fRegistry.fill(HIST("Track/hRelSigma1Pt"), track.pt(), track.sigma1Pt() * track.pt()); + fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + + if (cfgFillPID) { + int nsize = 0; + for (int il = 0; il < 7; il++) { + nsize += track.itsClsSizeInLayer(il); + } + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(nsize) / static_cast(track.itsNCls()) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + } + } + + template + void fillEventInfo(TCollision const& collision) + { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 10.0); + } + if (fabs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 12.0); + } + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hNTracksPVvsOccupancy"), collision.multNTracksPV(), collision.trackOccupancyInTimeRange()); + + if constexpr (std::is_same_v, FilteredMyCollision_Cent> || std::is_same_v, FilteredMyCollision_Cent_Qvec>) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C"), collision.centFT0C()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M"), collision.centFT0M()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); + } + + if constexpr (ev_id == 1 && std::is_same_v, FilteredMyCollision_Cent_Qvec>) { + if (std::find(cfgnMods->begin(), cfgnMods->end(), 2) != cfgnMods->end()) { + fillQvectorInfo(collision); + } + if (std::find(cfgnMods->begin(), cfgnMods->end(), 3) != cfgnMods->end()) { + fillQvectorInfo(collision); + } + if (std::find(cfgnMods->begin(), cfgnMods->end(), 4) != cfgnMods->end()) { + fillQvectorInfo(collision); + } + } + } + + template + void fillQvectorInfo(TCollision const& collision) + { + int idx = std::distance(cfgnMods->begin(), std::find(cfgnMods->begin(), cfgnMods->end(), nmod)); + float qxft0m = collision.qvecFT0MReVec()[idx], qxft0a = collision.qvecFT0AReVec()[idx], qxft0c = collision.qvecFT0CReVec()[idx], qxbpos = collision.qvecBPosReVec()[idx], qxbneg = collision.qvecBNegReVec()[idx], qxbtot = collision.qvecBTotReVec()[idx]; + float qyft0m = collision.qvecFT0MImVec()[idx], qyft0a = collision.qvecFT0AImVec()[idx], qyft0c = collision.qvecFT0CImVec()[idx], qybpos = collision.qvecBPosImVec()[idx], qybneg = collision.qvecBNegImVec()[idx], qybtot = collision.qvecBTotImVec()[idx]; + std::array qft0m = {qxft0m, qyft0m}; + std::array qft0a = {qxft0a, qyft0a}; + std::array qft0c = {qxft0c, qyft0c}; + std::array qbpos = {qxbpos, qybpos}; + std::array qbneg = {qxbneg, qybneg}; + std::array qbtot = {qxbtot, qybtot}; + std::vector> qvectors = {qft0m, qft0a, qft0c, qbpos, qbneg, qbtot}; + + if (!isGoodQvector(qvectors)) { + return; + } + + if constexpr (nmod == 2) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2xFT0M_CentFT0C"), collision.centFT0C(), qxft0m); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2yFT0M_CentFT0C"), collision.centFT0C(), qyft0m); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2xFT0A_CentFT0C"), collision.centFT0C(), qxft0a); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2yFT0A_CentFT0C"), collision.centFT0C(), qyft0a); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2xFT0C_CentFT0C"), collision.centFT0C(), qxft0c); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2yFT0C_CentFT0C"), collision.centFT0C(), qyft0c); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2xBPos_CentFT0C"), collision.centFT0C(), qxbpos); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2yBPos_CentFT0C"), collision.centFT0C(), qybpos); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2xBNeg_CentFT0C"), collision.centFT0C(), qxbneg); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2yBNeg_CentFT0C"), collision.centFT0C(), qybneg); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2xBTot_CentFT0C"), collision.centFT0C(), qxbtot); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ2yBTot_CentFT0C"), collision.centFT0C(), qybtot); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP2FT0M_CentFT0C"), collision.centFT0C(), getEP(qxft0m, qyft0m, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP2FT0A_CentFT0C"), collision.centFT0C(), getEP(qxft0a, qyft0a, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP2FT0C_CentFT0C"), collision.centFT0C(), getEP(qxft0c, qyft0c, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP2BPos_CentFT0C"), collision.centFT0C(), getEP(qxbpos, qybpos, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP2BNeg_CentFT0C"), collision.centFT0C(), getEP(qxbneg, qybneg, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP2BTot_CentFT0C"), collision.centFT0C(), getEP(qxbtot, qybtot, nmod)); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0MQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0m, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0MQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0m, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2BPosQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qbpos, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0AQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0AQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0AQ2BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbtot)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0CQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0CQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0CQ2BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbtot)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ2FT0AQ2FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qft0c)); + } else if constexpr (nmod == 3) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3xFT0M_CentFT0C"), collision.centFT0C(), qxft0m); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3yFT0M_CentFT0C"), collision.centFT0C(), qyft0m); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3xFT0A_CentFT0C"), collision.centFT0C(), qxft0a); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3yFT0A_CentFT0C"), collision.centFT0C(), qyft0a); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3xFT0C_CentFT0C"), collision.centFT0C(), qxft0c); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3yFT0C_CentFT0C"), collision.centFT0C(), qyft0c); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3xBPos_CentFT0C"), collision.centFT0C(), qxbpos); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3yBPos_CentFT0C"), collision.centFT0C(), qybpos); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3xBNeg_CentFT0C"), collision.centFT0C(), qxbneg); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3yBNeg_CentFT0C"), collision.centFT0C(), qybneg); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3xBTot_CentFT0C"), collision.centFT0C(), qxbtot); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ3yBTot_CentFT0C"), collision.centFT0C(), qybtot); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP3FT0M_CentFT0C"), collision.centFT0C(), getEP(qxft0m, qyft0m, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP3FT0A_CentFT0C"), collision.centFT0C(), getEP(qxft0a, qyft0a, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP3FT0C_CentFT0C"), collision.centFT0C(), getEP(qxft0c, qyft0c, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP3BPos_CentFT0C"), collision.centFT0C(), getEP(qxbpos, qybpos, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP3BNeg_CentFT0C"), collision.centFT0C(), getEP(qxbneg, qybneg, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP3BTot_CentFT0C"), collision.centFT0C(), getEP(qxbtot, qybtot, nmod)); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0MQ3BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0m, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0MQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0m, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3BPosQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qbpos, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0AQ3BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0AQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0AQ3BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbtot)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0CQ3BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0CQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0CQ3BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbtot)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ3FT0AQ3FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qft0c)); + } else if constexpr (nmod == 4) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4xFT0M_CentFT0C"), collision.centFT0C(), qxft0m); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4yFT0M_CentFT0C"), collision.centFT0C(), qyft0m); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4xFT0A_CentFT0C"), collision.centFT0C(), qxft0a); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4yFT0A_CentFT0C"), collision.centFT0C(), qyft0a); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4xFT0C_CentFT0C"), collision.centFT0C(), qxft0c); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4yFT0C_CentFT0C"), collision.centFT0C(), qyft0c); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4xBPos_CentFT0C"), collision.centFT0C(), qxbpos); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4yBPos_CentFT0C"), collision.centFT0C(), qybpos); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4xBNeg_CentFT0C"), collision.centFT0C(), qxbneg); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4yBNeg_CentFT0C"), collision.centFT0C(), qybneg); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4xBTot_CentFT0C"), collision.centFT0C(), qxbtot); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hQ4yBTot_CentFT0C"), collision.centFT0C(), qybtot); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP4FT0M_CentFT0C"), collision.centFT0C(), getEP(qxft0m, qyft0m, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP4FT0A_CentFT0C"), collision.centFT0C(), getEP(qxft0a, qyft0a, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP4FT0C_CentFT0C"), collision.centFT0C(), getEP(qxft0c, qyft0c, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP4BPos_CentFT0C"), collision.centFT0C(), getEP(qxbpos, qybpos, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP4BNeg_CentFT0C"), collision.centFT0C(), getEP(qxbneg, qybneg, nmod)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hEP4BTot_CentFT0C"), collision.centFT0C(), getEP(qxbtot, qybtot, nmod)); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0MQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0m, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0MQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0m, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4BPosQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qbpos, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0AQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0AQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0AQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qbtot)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0CQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbpos)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0CQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbneg)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0CQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0c, qbtot)); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("Qvector/hPrfQ4FT0AQ4FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(qft0a, qft0c)); + } + } + + float getEP(float qx, float qy, int nmod) + { + return std::atan2(qy, qx) / static_cast(nmod); + } + + template + bool isGoodQvector(TQvectors const& qvectors) + { + bool is_good = true; + for (auto& qvec : qvectors) { + if (fabs(qvec[0]) > 20.f || fabs(qvec[1]) > 20.f) { + is_good = false; + break; + } + } + return is_good; + } + + template + bool isSelectedTrack(TTrack const& track) + { + if (track.itsNCls() < trackcuts.cfg_min_ncluster_its) { + return false; + } + + if (track.itsNClsInnerBarrel() < trackcuts.cfg_min_ncluster_itsib) { + return false; + } + + if (track.tpcNClsFound() < trackcuts.cfg_min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < trackcuts.cfg_min_ncrossedrows_tpc) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < trackcuts.cfg_min_cr2findable_ratio_tpc) { + return false; + } + + return true; + } + + template + bool isSelectedEvent(TCollision const& collision) + { + if (!collision.sel8()) { + return false; + } + + if (fabs(collision.posZ()) > eventcuts.cfgZvtxMax) { + return false; + } + + if (eventcuts.cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (eventcuts.cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (eventcuts.cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (eventcuts.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (eventcuts.cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (eventcuts.cfgRequireNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + if (!(eventcuts.cfgOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgOccupancyMax)) { + return false; + } + + return true; + } + + Filter collisionFilter_evsel = o2::aod::evsel::sel8 == true && nabs(o2::aod::collision::posZ) < eventcuts.cfgZvtxMax; + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; + using FilteredMyCollisions = soa::Filtered; + using FilteredMyCollisions_Cent = soa::Filtered; + using FilteredMyCollisions_Cent_Qvec = soa::Filtered; + + using FilteredMyCollision = FilteredMyCollisions::iterator; + using FilteredMyCollision_Cent = FilteredMyCollisions_Cent::iterator; + using FilteredMyCollision_Cent_Qvec = FilteredMyCollisions_Cent_Qvec::iterator; + + Filter trackFilter = (trackcuts.cfg_min_pt_track < o2::aod::track::pt && o2::aod::track::pt < trackcuts.cfg_max_pt_track) && (trackcuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < trackcuts.cfg_max_eta_track) && nabs(o2::aod::track::dcaXY) < trackcuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < trackcuts.cfg_max_dcaz && o2::aod::track::tpcChi2NCl < trackcuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < trackcuts.cfg_max_chi2its && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + using FilteredMyTracks = soa::Filtered; + + SliceCache cache; + Preslice perCol = o2::aod::track::collisionId; + + template + void processQC(TCollisions const& collisions, FilteredMyTracks const& tracks) + { + for (auto& collision : collisions) { + if constexpr (std::is_same_v, FilteredMyCollisions_Cent> || std::is_same_v, FilteredMyCollisions_Cent_Qvec>) { + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + } + fillEventInfo<0>(collision); + if (!isSelectedEvent(collision)) { + continue; + } + fillEventInfo<1>(collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 13); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 13); // accepted + + int nGlobalTracks = 0, nGlobalTracksPV = 0; + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (auto& track : tracks_per_coll) { + if (!isSelectedTrack(track)) { + continue; + } + fillTrackInfo(track); + + if (fabs(track.eta()) < 0.8) { + nGlobalTracks++; + if (track.isPVContributor()) { + nGlobalTracksPV++; + } + } + } + + fRegistry.fill(HIST("Event/after/hMultNGlobalTracks"), nGlobalTracks); + fRegistry.fill(HIST("Event/after/hMultNGlobalTracksPV"), nGlobalTracksPV); + fRegistry.fill(HIST("Event/after/hMultFT0CvsMultNGlobalTracks"), collision.multFT0C(), nGlobalTracks); + fRegistry.fill(HIST("Event/after/hMultFT0CvsMultNGlobalTracksPV"), collision.multFT0C(), nGlobalTracksPV); + fRegistry.fill(HIST("Event/after/hNGlobalTracksvsOccupancy"), nGlobalTracks, collision.trackOccupancyInTimeRange()); + fRegistry.fill(HIST("Event/after/hNGlobalTracksPVvsOccupancy"), nGlobalTracksPV, collision.trackOccupancyInTimeRange()); + if constexpr (std::is_same_v, FilteredMyCollisions_Cent> || std::is_same_v, FilteredMyCollisions_Cent_Qvec>) { + fRegistry.fill(HIST("Event/after/hCentFT0CvsMultNGlobalTracks"), collision.centFT0C(), nGlobalTracks); + fRegistry.fill(HIST("Event/after/hCentFT0CvsMultNGlobalTracksPV"), collision.centFT0C(), nGlobalTracksPV); + } + } // end of collision loop + + } // end of process + + PROCESS_SWITCH_FULL(eventQC, processQC, processEventQC, "event QC", true); + PROCESS_SWITCH_FULL(eventQC, processQC, processEventQC_Cent, "event QC + centrality", false); + PROCESS_SWITCH_FULL(eventQC, processQC, processEventQC_Cent_Qvec, "event QC + centrality + q vector", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"event-qc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx b/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx index 1a5b49faf8f..f1b9148ab8e 100644 --- a/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx +++ b/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx @@ -20,15 +20,15 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::pwgem::dilepton::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using McParticlesSmeared = soa::Join; +using McParticlesSmeared = soa::Join; enum EFromHFType { kNoE = -1, @@ -115,7 +115,6 @@ struct MyConfigs : ConfigurableGroup { ConfigurableAxis fConfigEtaBins{"cfgEtaBins", {200, -10.f, 10.f}, "eta binning"}; ConfigurableAxis fConfigMeeBins{"cfgMeeBins", {800, 0.f, 8.f}, "Mee binning"}; ConfigurableAxis fConfigPteeBins{"cfgPteeBins", {400, 0.f, 10.f}, "pTee binning"}; - Configurable fConfigCheckPartonic{"cfgCheckPartonic", true, "check entire partonic history for pairs"}; }; struct lmeehfcocktailprefilter { @@ -148,15 +147,16 @@ struct lmeehfcocktailprefilter { int bQuarkOriginId = -1; int isHF = EFromHFType::kNoHFE; - if (direct_charm_mother && bHadronId < 0) { // c->e - isHF = EFromHFType::kCE; - auto cHadron = mcParticles.iteratorAt(cHadronId); - cQuarkId = searchMothers(cHadron, mcParticles, 4, true); - if (cQuarkId > -1) { - auto cQuark = mcParticles.iteratorAt(cQuarkId); - cQuarkOriginId = searchMothers(cQuark, mcParticles, 4, false); + + if (direct_beauty_mother) { // b->e + isHF = EFromHFType::kBE; + auto bHadron = mcParticles.iteratorAt(bHadronId); + bQuarkId = searchMothers(bHadron, mcParticles, 5, true); + if (bQuarkId > -1) { + auto bQuark = mcParticles.iteratorAt(bQuarkId); + bQuarkOriginId = searchMothers(bQuark, mcParticles, 5, false); } - } else if (direct_charm_mother && bHadronId > -1) { // b->c->e + } else if (bHadronId > -1 && direct_charm_mother) { // b->c->e isHF = EFromHFType::kBCE; auto bHadron = mcParticles.iteratorAt(bHadronId); bQuarkId = searchMothers(bHadron, mcParticles, 5, true); @@ -170,15 +170,16 @@ struct lmeehfcocktailprefilter { auto cQuark = mcParticles.iteratorAt(cQuarkId); cQuarkOriginId = searchMothers(cQuark, mcParticles, 4, false); } - } else if (direct_beauty_mother) { // b->e - isHF = EFromHFType::kBE; - auto bHadron = mcParticles.iteratorAt(bHadronId); - bQuarkId = searchMothers(bHadron, mcParticles, 5, true); - if (bQuarkId > -1) { - auto bQuark = mcParticles.iteratorAt(bQuarkId); - bQuarkOriginId = searchMothers(bQuark, mcParticles, 5, false); + } else if (bHadronId < 0 && direct_charm_mother) { // c->e + isHF = EFromHFType::kCE; + auto cHadron = mcParticles.iteratorAt(cHadronId); + cQuarkId = searchMothers(cHadron, mcParticles, 4, true); + if (cQuarkId > -1) { + auto cQuark = mcParticles.iteratorAt(cQuarkId); + cQuarkOriginId = searchMothers(cQuark, mcParticles, 4, false); } } + hfTable(isHF, bHadronId, cHadronId, bQuarkId, cQuarkId, bQuarkOriginId, cQuarkOriginId); } } @@ -188,15 +189,18 @@ struct lmeehfcocktailbeauty { HistogramRegistry registry{"registry", {}}; - std::vector>> hEta, hPt, hULS_Mee; - std::vector>> hPtEta, hULS_MeePtee; - std::vector> hLSpp_Mee, hLSmm_Mee; - std::vector> hLSpp_MeePtee, hLSmm_MeePtee; + std::vector>> hEta, hPt; + std::vector>> hPtEta; + std::vector> hLS_Mee, hULS_Mee; + std::vector> hLS_MeePtee, hULS_MeePtee; + + std::vector> hLS_Mee_wPartonicCheck, hULS_Mee_wPartonicCheck; + std::vector> hLS_MeePtee_wPartonicCheck, hULS_MeePtee_wPartonicCheck; MyConfigs myConfigs; Filter hfFilter = o2::aod::hftable::isHF == static_cast(EFromHFType::kBE) || o2::aod::hftable::isHF == static_cast(EFromHFType::kBCE); - using MyFilteredMcParticlesSmeared = soa::Filtered>; + using MyFilteredMcParticlesSmeared = soa::Filtered>; Preslice perCollision = aod::mcparticle::mcCollisionId; @@ -207,8 +211,6 @@ struct lmeehfcocktailbeauty { { registry.add("NEvents", "NEvents", HistType::kTH1F, {{1, 0, 1}}, false); - const char* typeNamesPairULS[4] = {"Be_Be", "BCe_BCe", "BCe_Be_SameB", "allB"}; - const char* typeNamesPairLS = "BCe_Be_DiffB"; const char* typeNamesSingle[2] = {"be", "bce"}; const char* typeTitlesSingle[2] = {"b->e", "b->c->e"}; @@ -233,31 +235,26 @@ struct lmeehfcocktailbeauty { // pair histograms // ULS - for (int i = 0; i < 4; i++) { - std::vector> hMee_temp; - std::vector> hMeePtee_temp; - for (int j = 0; j < 3; j++) { - hMee_temp.push_back(registry.add(Form("ULS_Mee_%s_%s", typeNamesPairULS[i], stageNames[j]), Form("ULS Mee %s %s", typeNamesPairULS[i], stageNames[j]), HistType::kTH1F, {mass_axis}, true)); - hMeePtee_temp.push_back(registry.add(Form("ULS_MeePtee_%s_%s", typeNamesPairULS[i], stageNames[j]), Form("ULS Mee vs. Ptee %s %s", typeNamesPairULS[i], stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); - } - hULS_Mee.push_back(hMee_temp); - hULS_MeePtee.push_back(hMeePtee_temp); + for (int j = 0; j < 3; j++) { + hULS_Mee.push_back(registry.add(Form("ULS_Mee_%s", stageNames[j]), Form("ULS Mee %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hULS_MeePtee.push_back(registry.add(Form("ULS_MeePtee_%s", stageNames[j]), Form("ULS Mee vs. Ptee %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + + hULS_Mee_wPartonicCheck.push_back(registry.add(Form("ULS_Mee_wPartonicCheck_%s", stageNames[j]), Form("ULS Mee wPartonicCheck %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hULS_MeePtee_wPartonicCheck.push_back(registry.add(Form("ULS_MeePtee_wPartonicCheck_%s", stageNames[j]), Form("ULS Mee vs. Ptee wPartonicCheck %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); } // LS for (int j = 0; j < 3; j++) { - hLSpp_Mee.push_back(registry.add(Form("LSpp_Mee_%s_%s", typeNamesPairLS, stageNames[j]), Form("LS++ Mee %s %s", typeNamesPairLS, stageNames[j]), HistType::kTH1F, {mass_axis}, true)); - hLSmm_Mee.push_back(registry.add(Form("LSmm_Mee_%s_%s", typeNamesPairLS, stageNames[j]), Form("LS-- Mee %s %s", typeNamesPairLS, stageNames[j]), HistType::kTH1F, {mass_axis}, true)); - hLSpp_MeePtee.push_back(registry.add(Form("LSpp_MeePtee_%s_%s", typeNamesPairLS, stageNames[j]), Form("LS++ Mee vs. Ptee %s %s", typeNamesPairLS, stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); - hLSmm_MeePtee.push_back(registry.add(Form("LSmm_MeePtee_%s_%s", typeNamesPairLS, stageNames[j]), Form("LS-- Mee vs. Ptee %s %s", typeNamesPairLS, stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + hLS_Mee.push_back(registry.add(Form("LS_Mee_%s", stageNames[j]), Form("LS Mee %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hLS_MeePtee.push_back(registry.add(Form("LS_MeePtee_%s", stageNames[j]), Form("LS Mee vs. Ptee %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + + hLS_Mee_wPartonicCheck.push_back(registry.add(Form("LS_Mee_wPartonicCheck_%s", stageNames[j]), Form("LS Mee wPartonicCheck %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hLS_MeePtee_wPartonicCheck.push_back(registry.add(Form("LS_MeePtee_wPartonicCheck_%s", stageNames[j]), Form("LS Mee vs. Ptee wPartonicCheck %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); } } - void processBeauty(aod::McCollisions const& collisions, MyFilteredMcParticlesSmeared const& mcParticles, aod::McParticles const& mcParticlesAll) + void processBeauty(aod::McCollisions const& collisions, MyFilteredMcParticlesSmeared const& mcParticles) { for (auto const& p : mcParticles) { - if (myConfigs.fConfigCheckPartonic && p.bQuarkOriginId() < 0) { - continue; - } int from_quark = p.isHF() - 2; doSingle(p, hEta[from_quark], hPt[from_quark], hPtEta[from_quark], myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } @@ -270,49 +267,41 @@ struct lmeehfcocktailbeauty { auto const positronsGrouped = Positrons->sliceBy(perCollision, collision.globalIndex()); // ULS spectrum for (auto const& [particle1, particle2] : combinations(o2::soa::CombinationsFullIndexPolicy(electronsGrouped, positronsGrouped))) { - if (myConfigs.fConfigCheckPartonic) { - if (particle1.bQuarkOriginId() < 0 || particle2.bQuarkOriginId() < 0 || particle1.bQuarkOriginId() != particle2.bQuarkOriginId()) - continue; + + if (particle1.mothersIds()[0] == particle2.mothersIds()[0]) { + LOG(error) << "Something is wrong here. There should not be dielectrons with same mother."; } - int type = IsHF(particle1, particle2, mcParticlesAll); - if (type == static_cast(EM_HFeeType::kUndef)) + + doPair(particle1, particle2, hULS_Mee, hULS_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + + if (particle1.bQuarkOriginId() < 0 || particle2.bQuarkOriginId() < 0 || particle1.bQuarkOriginId() != particle2.bQuarkOriginId()) continue; - if ((type < static_cast(EM_HFeeType::kBe_Be)) || (type > static_cast(EM_HFeeType::kBCe_Be_SameB))) { - LOG(error) << "Something is wrong here. There should only be pairs of type kBe_Be = 1, kBCe_BCe = 2 and kBCe_Be_SameB = 3 left at this point."; - } - doPair(particle1, particle2, hULS_Mee[type - 1], hULS_MeePtee[type - 1], myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); - doPair(particle1, particle2, hULS_Mee[3], hULS_MeePtee[3], myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); // fill the 'allB' histograms that holds the sum of the others + doPair(particle1, particle2, hULS_Mee_wPartonicCheck, hULS_MeePtee_wPartonicCheck, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } // LS spectrum for (auto const& [particle1, particle2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(electronsGrouped, electronsGrouped))) { - if (myConfigs.fConfigCheckPartonic) { - if (particle1.bQuarkOriginId() < 0 || particle2.bQuarkOriginId() < 0 || particle1.bQuarkOriginId() != particle2.bQuarkOriginId()) - continue; + + if (particle1.mothersIds()[0] == particle2.mothersIds()[0]) { + LOG(error) << "Something is wrong here. There should not be dielectrons with same mother."; } - int type = IsHF(particle1, particle2, mcParticlesAll); - if (type == static_cast(EM_HFeeType::kUndef)) + + doPair(particle1, particle2, hLS_Mee, hLS_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + + if (particle1.bQuarkOriginId() < 0 || particle2.bQuarkOriginId() < 0 || particle1.bQuarkOriginId() != particle2.bQuarkOriginId()) continue; - if (myConfigs.fConfigCheckPartonic) { - if (type != static_cast(EM_HFeeType::kBCe_Be_DiffB)) { - LOG(error) << "Something is wrong here. There should only be pairs of type kBCe_Be_DiffB = 4 left at this point."; - } - } - doPair(particle1, particle2, hLSmm_Mee, hLSmm_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + doPair(particle1, particle2, hLS_Mee_wPartonicCheck, hLS_MeePtee_wPartonicCheck, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } for (auto const& [particle1, particle2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(positronsGrouped, positronsGrouped))) { - if (myConfigs.fConfigCheckPartonic) { - if (particle1.bQuarkOriginId() < 0 || particle2.bQuarkOriginId() < 0 || particle1.bQuarkOriginId() != particle2.bQuarkOriginId()) - continue; + + if (particle1.mothersIds()[0] == particle2.mothersIds()[0]) { + LOG(error) << "Something is wrong here. There should not be dielectrons with same mother."; } - int type = IsHF(particle1, particle2, mcParticlesAll); - if (type == static_cast(EM_HFeeType::kUndef)) + + doPair(particle1, particle2, hLS_Mee, hLS_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + + if (particle1.bQuarkOriginId() < 0 || particle2.bQuarkOriginId() < 0 || particle1.bQuarkOriginId() != particle2.bQuarkOriginId()) continue; - if (myConfigs.fConfigCheckPartonic) { - if (type != static_cast(EM_HFeeType::kBCe_Be_DiffB)) { - LOG(error) << "Something is wrong here. There should only be pairs of type kBCe_Be_DiffB = 4 left at this point."; - } - } - doPair(particle1, particle2, hLSpp_Mee, hLSpp_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + doPair(particle1, particle2, hLS_Mee_wPartonicCheck, hLS_MeePtee_wPartonicCheck, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } } } @@ -332,11 +321,13 @@ struct lmeehfcocktailcharm { std::vector> hEta, hPt, hULS_Mee, hLS_Mee; std::vector> hPtEta, hULS_MeePtee, hLS_MeePtee; + std::vector> hULS_Mee_wPartonicCheck, hLS_Mee_wPartonicCheck; + std::vector> hULS_MeePtee_wPartonicCheck, hLS_MeePtee_wPartonicCheck; MyConfigs myConfigs; Filter hfFilter = o2::aod::hftable::isHF == static_cast(EFromHFType::kCE); - using MyFilteredMcParticlesSmeared = soa::Filtered>; + using MyFilteredMcParticlesSmeared = soa::Filtered>; Preslice perCollision = aod::mcparticle::mcCollisionId; @@ -347,7 +338,6 @@ struct lmeehfcocktailcharm { { registry.add("NEvents", "NEvents", HistType::kTH1F, {{1, 0, 1}}, false); - const char* typeNamesPairULS = "Ce_Ce"; const char* typeNamesSingle = "ce"; const char* typeTitlesSingle = "c->e"; @@ -366,21 +356,25 @@ struct lmeehfcocktailcharm { // pair histograms // ULS for (int j = 0; j < 3; j++) { - hULS_Mee.push_back(registry.add(Form("ULS_Mee_%s_%s", typeNamesPairULS, stageNames[j]), Form("ULS Mee %s %s", typeNamesPairULS, stageNames[j]), HistType::kTH1F, {mass_axis}, true)); - hULS_MeePtee.push_back(registry.add(Form("ULS_MeePtee_%s_%s", typeNamesPairULS, stageNames[j]), Form("ULS MeePtee %s %s", typeNamesPairULS, stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + hULS_Mee.push_back(registry.add(Form("ULS_Mee_%s", stageNames[j]), Form("ULS Mee %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hULS_MeePtee.push_back(registry.add(Form("ULS_MeePtee_%s", stageNames[j]), Form("ULS Mee vs Ptee %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + + hULS_Mee_wPartonicCheck.push_back(registry.add(Form("ULS_Mee_wPartonicCheck_%s", stageNames[j]), Form("ULS Mee wPartonicCheck %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hULS_MeePtee_wPartonicCheck.push_back(registry.add(Form("ULS_MeePtee_wPartonicCheck_%s", stageNames[j]), Form("ULS Mee vs Ptee wPartonicCheck %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); } + // LS for (int j = 0; j < 3; j++) { - hLS_Mee.push_back(registry.add(Form("LS_Mee_%s_%s", typeNamesPairULS, stageNames[j]), Form("LS Mee %s %s", typeNamesPairULS, stageNames[j]), HistType::kTH1F, {mass_axis}, true)); - hLS_MeePtee.push_back(registry.add(Form("LS_MeePtee_%s_%s", typeNamesPairULS, stageNames[j]), Form("LS MeePtee %s %s", typeNamesPairULS, stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + hLS_Mee.push_back(registry.add(Form("LS_Mee_%s", stageNames[j]), Form("LS Mee %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hLS_MeePtee.push_back(registry.add(Form("LS_MeePtee_%s", stageNames[j]), Form("LS Mee vs Ptee %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); + + hLS_Mee_wPartonicCheck.push_back(registry.add(Form("LS_Mee_wPartonicCheck_%s", stageNames[j]), Form("LS Mee wPartonicCheck %s", stageNames[j]), HistType::kTH1F, {mass_axis}, true)); + hLS_MeePtee_wPartonicCheck.push_back(registry.add(Form("LS_MeePtee_wPartonicCheck_%s", stageNames[j]), Form("LS Mee vs Ptee wPartonicCheck %s", stageNames[j]), HistType::kTH2F, {mass_axis, ptee_axis}, true)); } } - void processCharm(aod::McCollisions const& collisions, MyFilteredMcParticlesSmeared const& mcParticles, aod::McParticles const& mcParticlesAll) + void processCharm(aod::McCollisions const& collisions, MyFilteredMcParticlesSmeared const& mcParticles) { for (auto const& p : mcParticles) { - if (myConfigs.fConfigCheckPartonic && p.cQuarkOriginId() < 0) { - continue; - } doSingle(p, hEta, hPt, hPtEta, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } @@ -392,29 +386,41 @@ struct lmeehfcocktailcharm { auto const positronsGrouped = Positrons->sliceBy(perCollision, collision.globalIndex()); // ULS spectrum for (auto const& [particle1, particle2] : combinations(o2::soa::CombinationsFullIndexPolicy(electronsGrouped, positronsGrouped))) { - if (myConfigs.fConfigCheckPartonic) { - if (particle1.cQuarkOriginId() < 0 || particle2.cQuarkOriginId() < 0 || particle1.cQuarkOriginId() != particle2.cQuarkOriginId()) - continue; - } - if (IsHF(particle1, particle2, mcParticlesAll) != static_cast(EM_HFeeType::kCe_Ce)) { - LOG(error) << "Something is wrong here. There should only be pairs of type kCe_Ce = 0 left at this point."; + + if (particle1.mothersIds()[0] == particle2.mothersIds()[0]) { + LOG(error) << "Something is wrong here. There should not be dielectrons with same mother."; } + doPair(particle1, particle2, hULS_Mee, hULS_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + + if (particle1.cQuarkOriginId() < 0 || particle2.cQuarkOriginId() < 0 || particle1.cQuarkOriginId() != particle2.cQuarkOriginId()) + continue; + doPair(particle1, particle2, hULS_Mee_wPartonicCheck, hULS_MeePtee_wPartonicCheck, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } // LS for (auto const& [particle1, particle2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(electronsGrouped, electronsGrouped))) { - if (myConfigs.fConfigCheckPartonic) { - if (particle1.cQuarkOriginId() < 0 || particle2.cQuarkOriginId() < 0 || particle1.cQuarkOriginId() != particle2.cQuarkOriginId()) - continue; + + if (particle1.mothersIds()[0] == particle2.mothersIds()[0]) { + LOG(error) << "Something is wrong here. There should not be dielectrons with same mother."; } + doPair(particle1, particle2, hLS_Mee, hLS_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + + if (particle1.cQuarkOriginId() < 0 || particle2.cQuarkOriginId() < 0 || particle1.cQuarkOriginId() != particle2.cQuarkOriginId()) + continue; + doPair(particle1, particle2, hLS_Mee_wPartonicCheck, hLS_MeePtee_wPartonicCheck, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } for (auto const& [particle1, particle2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(positronsGrouped, positronsGrouped))) { - if (myConfigs.fConfigCheckPartonic) { - if (particle1.cQuarkOriginId() < 0 || particle2.cQuarkOriginId() < 0 || particle1.cQuarkOriginId() != particle2.cQuarkOriginId()) - continue; + + if (particle1.mothersIds()[0] == particle2.mothersIds()[0]) { + LOG(error) << "Something is wrong here. There should not be dielectrons with same mother."; } + doPair(particle1, particle2, hLS_Mee, hLS_MeePtee, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); + + if (particle1.cQuarkOriginId() < 0 || particle2.cQuarkOriginId() < 0 || particle1.cQuarkOriginId() != particle2.cQuarkOriginId()) + continue; + doPair(particle1, particle2, hLS_Mee_wPartonicCheck, hLS_MeePtee_wPartonicCheck, myConfigs.fConfigPtMin, myConfigs.fConfigEtaMax); } } } diff --git a/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx b/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx index 2799fcd8341..e8daf38bebe 100644 --- a/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx +++ b/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx @@ -10,986 +10,473 @@ // or submit itself to any jurisdiction. // // -// Analysis task for lmee light flavour cocktail +/// \file lmeeLFCocktail.cxx +/// \analysis task for lmee light flavour cocktail +/// \author Daniel Samitz, , SMI Vienna -#include -#include "Framework/Task.h" +#include "Math/Vector4D.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" -#include "SimulationDataFormat/MCTrack.h" -#include "PWGEM/Dilepton/Utils/MomentumSmearer.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "TFile.h" -#include "TF1.h" -#include "TRandom.h" -#include "TDatabasePDG.h" -#include "TGenPhaseSpace.h" -#include "TGrid.h" -#include "TTree.h" -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +using namespace o2; using namespace o2::framework; -using namespace ROOT::Math; - -struct eeTTree { - float fd1DCA; - float fd2DCA; - float fpairDCA; - float fd1origpt; - float fd1origp; - float fd1origeta; - float fd1origphi; - float fd2origpt; - float fd2origp; - float fd2origeta; - float fd2origphi; - float fd1pt; - float fd1p; - float fd1eta; - float fd1phi; - float fd2pt; - float fd2p; - float fd2eta; - float fd2phi; - float feeorigpt; - float feeorigp; - float feeorigm; - float feeorigeta; - float feeorigphi; - float feeorigphiv; - float feept; - float feemt; - float feep; - float feem; - float feeeta; - float feephi; - float feephiv; - float fmotherpt; - float fmothermt; - float fmotherp; - float fmotherm; - float fmothereta; - float fmotherphi; - int fID; - int fdectyp; - int fdau3pdg; - float fweight; - float fwEffpT; - float fwMultpT; - float fwMultmT; - float fwMultpT2; - float fwMultmT2; - bool fpass; - float feeorigrap; // only in histogram, not in tree? - float feerap; // only in histogram, not in tree? -}; - -struct lmeelfcocktail { - OutputObj tree{"eeTTree"}; - - HistogramRegistry registry{"registry", {}}; - Int_t nInputParticles = 17; - std::vector fParticleListNames = {"Pi0", "Eta", "EtaP", "EtaP_dalitz_photon", "EtaP_dalitz_omega", "Rho", "Omega", "Omega_2body", "Omega_dalitz", "Phi", "Phi_2body", "Phi_dalitz_eta", "Phi_dalitz_pi0", "Jpsi", "Jpsi_2body", "Jpsi_radiative", "Virtual_Photon"}; - TH1F* fhwEffpT; - TH1F* fhwMultpT; - TH1F* fhwMultmT; - TH1F* fhwMultpT2; - TH1F* fhwMultmT2; - TH1F* fhKW; - TF1* ffVPHpT; - std::vector> fmee_orig, fmotherpT_orig, fphi_orig, frap_orig, fmee_orig_wALT, fmotherpT_orig_wALT, fmee, fphi, frap, fmee_wALT; - std::vector> fpteevsmee_wALT, fpteevsmee_orig_wALT, fpteevsmee_orig, fpteevsmee; +using McParticlesSmeared = soa::Join; - eeTTree treeWords; - - std::vector DCATemplateEdges; - int nbDCAtemplate; - TH1F** fh_DCAtemplates; +struct lmeelfcocktail { - MomentumSmearer smearer; + enum recLevel { + kGen = 0, + kRec, + kNRecLevels + }; + + struct mesonInfo { + TString name; + std::vector decayModes; + }; + + std::map decays = { + {-1, "e_e/"}, + {-2, "e_e_e_e/"}, + {22, "gamma_e_e/"}, + {223, "omega_e_e/"}, + {211 * 211, "pi_pi_e_e/"}, + {111, "pi0_e_e/"}, + {221, "eta_e_e/"}}; + + std::map mesons = { + {111, {"pi0/", {22, -2}}}, + {221, {"eta/", {22, 211 * 211, -2}}}, + {331, {"etaP/", {22, 223, 211 * 211}}}, + {113, {"rho/", {-1}}}, + {223, {"omega/", {-1, 111}}}, + {333, {"phi/", {-1, 111, 221}}}}; + + std::map histogramId; + + std::vector stage = {"gen/", "rec/"}; - Double_t eMass; + HistogramRegistry registry{"registry", {}}; - Configurable fCollisionSystem{"cfgCollisionSystem", 200, "set the collision system"}; - Configurable fConfigWriteTTree{"cfgWriteTTree", false, "write tree output"}; - Configurable fConfigDoPairing{"cfgDoPairing", true, "do like and unlike sign pairing"}; Configurable fConfigMaxEta{"cfgMaxEta", 0.8, "maxium |eta|"}; Configurable fConfigMinPt{"cfgMinPt", 0.2, "minium pT"}; Configurable fConfigMaxPt{"cfgMaxPt", 8.0, "maximum pT"}; - Configurable fConfigNBinsMee{"cfgNBinsMee", 1200, "number of bins in invariant mass"}; - Configurable fConfigMinMee{"cfgMinMee", 0.0, "lowest bin in invariant mass"}; - Configurable fConfigMaxMee{"cfgMaxMee", 6.0, "highest bin in invariant mass"}; - Configurable fConfigNBinsPtee{"cfgNBinsPtee", 400, "number of bins in pT"}; - Configurable fConfigMinPtee{"cfgMinPtee", 0.0, "lowest bin in pT"}; - Configurable fConfigMaxPtee{"cfgMaxPtee", 10.0, "hightest bin in pT"}; - Configurable fConfigALTweight{"cfgALTweight", 1, "set alternative weighting type"}; - Configurable fConfigResFileName{"cfgResFileName", "", "name of resolution file"}; - Configurable fConfigEffFileName{"cfgEffFileName", "", "name of efficiency file"}; Configurable fConfigMinOpAng{"cfgMinOpAng", 0.050, "minimum opening angle"}; - Configurable fConfigNBinsPhi{"cfgNBinsPhi", 240, "number of bins in phi"}; - Configurable fConfigNBinsRap{"cfgNBinsRap", 240, "number of bins in rap"}; - Configurable fConfigMaxAbsRap{"cfgMaxAbsRap", 1.2, "bin range in rap"}; - Configurable fConfigEffHistName{"cfgEffHistName", "fhwEffpT", "hisogram name in efficiency file"}; - Configurable fConfigResPHistName{"cfgResPHistName", "ptSlices", "histogram name for p in resolution file"}; - Configurable fConfigResPtHistName{"cfgResPtHistName", "RelPtResArrCocktail", "histogram name for pt in resolution file"}; - Configurable fConfigResEtaHistName{"cfgResEtaHistName", "EtaResArr", "histogram name for eta in resolution file"}; - Configurable fConfigResPhiPosHistName{"cfgResPhiPosHistName", "PhiPosResArr", "histogram name for phi pos in resolution file"}; - Configurable fConfigResPhiNegHistName{"cfgResPhiNegHistName", "PhiEleResArr", "hisogram for phi neg in resolution file"}; - Configurable fConfigDCAFileName{"cfgDCAFileName", "", "DCA file name"}; - Configurable fConfigDCAHistName{"cfgDCAHistName", "fh_DCAtemplate", "histogram name in DCA file"}; - Configurable fConfigMultFileName{"cfgMultFileName", "", "multiplicity file name"}; - Configurable fConfigMultHistPtName{"cfgMultHistPtName", "fhwMultpT", "hisogram name for pt in multiplicity file"}; - Configurable fConfigMultHistPt2Name{"cfgMultHistPt2Name", "fhwMultpT_upperlimit", "histogram name for pt 2 in multiplicity file"}; - Configurable fConfigMultHistMtName{"cfgMultHistMtName", "fhwMultmT", "histogram name for mt in multiplicity file"}; - Configurable fConfigMultHistMt2Name{"cfgMultHistMt2Name", "fhwMultmT_upperlimit", "histogram name for mt 2 in multiplicity file"}; - Configurable fConfigKWMax{"cfgKWMax", 1.1, "upper bound of Kroll-Wada"}; - Configurable fConfigDoVirtPh{"cfgDoVirtPh", false, "generate one virt. photon for each pion"}; - Configurable fConfigPhotonPtFileName{"cfgPhotonPtFileName", "", "file name for photon pT parametrization"}; - Configurable fConfigPhotonPtDirName{"cfgPhotonPtDirName", "", "directory name for photon pT parametrization"}; - Configurable fConfigPhotonPtFuncName{"cfgPhotonPtFuncName", "111_pt", "function name for photon pT parametrization"}; - - ConfigurableAxis fConfigPtBins{"cfgPtBins", {VARIABLE_WIDTH, 0., 0.5, 1, 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8.}, "pT bins"}; - ConfigurableAxis fConfigMBins{"cfgMBins", {VARIABLE_WIDTH, 0., 0.08, 0.14, 0.2, 1.1, 2.7, 2.8, 3.2, 5.0}, "mee bins"}; - ConfigurableAxis fConfigDCABins{"cfgDCABins", {VARIABLE_WIDTH, 0., 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 3., 4., 5., 7., 10.}, "DCA bins"}; - - Configurable> fConfigDCATemplateEdges{"cfgDCATemplateEdges", {0., .3, .4, .6, 1., 2.}, "DCA template edges"}; - - void init(o2::framework::InitContext&) + Configurable fConfigMinPtee{"cfgMinPtee", 0.0, "minimum pair pT"}; + ConfigurableAxis fConfigMeeBins{"cfgMeeBins", {600, 0.f, 6.f}, "Mee binning"}; + ConfigurableAxis fConfigPteeBins{"cfgPteeBins", {400, 0.f, 10.f}, "pTee binning"}; + ConfigurableAxis fConfigPtBins{"cfgPtBins", {200, 0.f, 10.f}, "pT binning"}; + ConfigurableAxis fConfigEtaBins{"cfgEtaBins", {200, -5.f, 5.f}, "eta binning"}; + ConfigurableAxis fConfigPhiBins{"cfgPhiBins", {200, -TMath::Pi(), TMath::Pi()}, "phi binning"}; + ConfigurableAxis fConfigPhiVBins{"cfgPhiVBins", {200, 0, TMath::Pi()}, "phiV binning"}; + ConfigurableAxis fConfigOpAngBins{"cfgOpAngBins", {200, 0, TMath::Pi()}, "opening angle binning"}; + ConfigurableAxis fConfigDcaBins{"cfgDcaBins", {VARIABLE_WIDTH, 0., 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 3., 4., 5., 7., 10.}, "dca binning"}; + + std::vector> histograms1D; + std::vector> histograms2D; + + template + bool from_primary(T& p1, U& mcParticles) { - if (fConfigWriteTTree) { - SetTree(); + if (!p1.has_mothers()) { + return false; } - SetHistograms(); - DCATemplateEdges = fConfigDCATemplateEdges; - nbDCAtemplate = DCATemplateEdges.size(); - DCATemplateEdges.push_back(10000000.); - - if ((TString(fConfigEffFileName).BeginsWith("alien://") && TString(fConfigEffFileName).EndsWith(".root")) || (TString(fConfigResFileName).BeginsWith("alien://") && TString(fConfigResFileName).EndsWith(".root")) || (TString(fConfigDCAFileName).BeginsWith("alien://") && TString(fConfigDCAFileName).EndsWith(".root")) || (TString(fConfigMultFileName).BeginsWith("alien://") && TString(fConfigMultFileName).EndsWith(".root")) || (TString(fConfigPhotonPtFileName).BeginsWith("alien://") && TString(fConfigPhotonPtFileName).EndsWith(".root"))) { - LOGP(info, "Connecting to grid via TGrid"); - TGrid::Connect("alien://"); + auto mother = mcParticles.iteratorAt(p1.mothersIds()[0]); + if (mother.has_mothers()) { + return false; } - - GetEffHisto(TString(fConfigEffFileName), TString(fConfigEffHistName)); - InitSmearer(TString(fConfigResFileName), TString(fConfigResPtHistName), TString(fConfigResEtaHistName), TString(fConfigResPhiPosHistName), TString(fConfigResPhiNegHistName)); - GetDCATemplates(TString(fConfigDCAFileName), TString(fConfigDCAHistName)); - GetMultHisto(TString(fConfigMultFileName), TString(fConfigMultHistPtName), TString(fConfigMultHistPt2Name), TString(fConfigMultHistMtName), TString(fConfigMultHistMt2Name)); - if (fConfigDoVirtPh) { - GetPhotonPtParametrization(TString(fConfigPhotonPtFileName), TString(fConfigPhotonPtDirName), TString(fConfigPhotonPtFuncName)); - } - - eMass = (TDatabasePDG::Instance()->GetParticle(11))->Mass(); - - fillKrollWada(); + return true; } - void run(o2::framework::ProcessingContext& pc) + bool isAcceptedSingle(ROOT::Math::PtEtaPhiMVector p1) { - // get number of events per timeframe - auto Nparts = pc.inputs().getNofParts(0); - - for (auto i = 0U; i < Nparts; ++i) { - registry.fill(HIST("NEvents"), 0.5); - // get the tracks - auto mctracks = pc.inputs().get>("mctracks", i); - - std::vector eBuff; - std::vector echBuff; - std::vector eweightBuff; - - bool skipNext = false; - - int trackID = -1; - // Loop over all MC particle - for (auto& mctrack : mctracks) { - trackID++; - if (o2::mcgenstatus::getHepMCStatusCode(mctrack.getStatusCode()) != 1) - continue; - if (abs(mctrack.GetPdgCode()) == 11) { - // get the electron - //--------------- - if (fConfigDoPairing) { - // LS and ULS spectra - PxPyPzEVector e, dielectron; - Char_t ech, dielectron_ch; - Double_t eweight, dielectron_weight; - e.SetPxPyPzE(mctrack.Px(), mctrack.Py(), mctrack.Pz(), - mctrack.GetEnergy()); - if (mctrack.GetPdgCode() > 0) { - ech = 1.; - } else { - ech = -1.; - } - eweight = mctrack.getWeight(); - // put in the buffer - //----------------- - eBuff.push_back(e); - echBuff.push_back(ech); - eweightBuff.push_back(eweight); - // loop the buffer and pair - //------------------------ - for (Int_t jj = eBuff.size() - 2; jj >= 0; jj--) { - dielectron = eBuff.at(jj) + e; - dielectron_ch = (echBuff.at(jj) + ech) / 2; - dielectron_weight = eweightBuff.at(jj) * eweight; - - if (dielectron_ch == 0) - registry.fill(HIST("ULS_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (dielectron_ch > 0) - registry.fill(HIST("LSpp_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (dielectron_ch < 0) - registry.fill(HIST("LSmm_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (e.Pt() > fConfigMinPt && eBuff.at(jj).Pt() > fConfigMinPt && e.Pt() < fConfigMaxPt && eBuff.at(jj).Pt() < fConfigMaxPt && TMath::Abs(e.Eta()) < fConfigMaxEta && TMath::Abs(eBuff.at(jj).Eta()) < fConfigMaxEta && e.Vect().Unit().Dot(eBuff.at(jj).Vect().Unit()) < TMath::Cos(fConfigMinOpAng)) { - if (dielectron_ch == 0) - registry.fill(HIST("ULS"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (dielectron_ch > 0) - registry.fill(HIST("LSpp"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (dielectron_ch < 0) - registry.fill(HIST("LSmm"), dielectron.M(), dielectron.Pt(), dielectron_weight); - } - } - } - - if (skipNext) { - skipNext = false; - continue; // skip if marked as second electron - } - - if (!(mctrack.getMotherTrackId() > -1)) - continue; // has no mother - - auto const& mother = mctracks[mctrack.getMotherTrackId()]; - - if (mother.getMotherTrackId() > -1) - continue; // mother is not primary - - if (mctrack.getSecondMotherTrackId() - mctrack.getMotherTrackId() > 0) - continue; // more than one mother - - // skip for the moment other particles rather than pi0, eta, etaprime, - // omega, rho, phi. - switch (mother.GetPdgCode()) { - case 111: - break; - case 221: - break; - case 331: - break; - case 113: - break; - case 223: - break; - case 333: - break; - case 443: - break; - default: - continue; - } - - /* - // Not sure about this cut. From GammaConv group. Harmless a priori. - if (!(fabs(mctrack.GetEnergy() - mctrack.Pz()) > 0.)) - continue; - - // ???? this applied only to first daughter! - Double_t yPre = (mctrack.GetEnergy() + mctrack.Pz()) / (mctrack.GetEnergy() - mctrack.Pz()); - Double_t y = 0.5 * TMath::Log(yPre); - if (fConfigDoRapidityCut) { // Apply rapidity cut on mother consistent with GammaConv group. (??? but it is not applied on mother?) - if (yPre <= 0.) - continue; - if (TMath::Abs(y) > fConfigRapidityCut) - continue; - } else { - if (yPre == 0.) - continue; - }*/ - - treeWords.fdectyp = mother.getLastDaughterTrackId() - mother.getFirstDaughterTrackId() + 1; // fdectyp: decay type (based on number of daughters). - if (treeWords.fdectyp > 4) - continue; // exclude five or more particles decay - - if (trackID == mctracks.size()) - continue; // no particle left in the list - auto mctrack2 = mctracks[trackID + 1]; - if (!(mctrack2.getMotherTrackId() == mctrack.getMotherTrackId())) - continue; // no matching second electron - if (!(mctrack.getSecondMotherTrackId() == -1)) - continue; // second daughter has more than one mother - if (!(abs(mctrack2.GetPdgCode()) == 11)) - continue; // not an electron - - skipNext = true; // is matching electron --> next particle in list will be skipped - - PxPyPzEVector dau1, dau2, ee; - dau1.SetPxPyPzE(mctrack.Px(), mctrack.Py(), mctrack.Pz(), mctrack.GetEnergy()); - dau2.SetPxPyPzE(mctrack2.Px(), mctrack2.Py(), mctrack2.Pz(), mctrack2.GetEnergy()); - - // create dielectron before resolution effects: - ee = dau1 + dau2; - - // get info of the other particles in the decay: - treeWords.fdau3pdg = 0; - for (Int_t jj = mother.getFirstDaughterTrackId(); jj <= mother.getLastDaughterTrackId(); jj++) { - if (jj == trackID || jj == trackID + 1) { - continue; // first or second electron - } - auto mctrack3 = mctracks[jj]; - treeWords.fdau3pdg = abs(mctrack3.GetPdgCode()); - } - - // get index for histograms - Int_t hindex[3]; - for (Int_t jj = 0; jj < 3; jj++) { - hindex[jj] = -1; - } - switch (mother.GetPdgCode()) { - case 111: - hindex[0] = 0; - break; - case 221: - hindex[0] = 1; - break; - case 331: - hindex[0] = 2; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 22) - hindex[1] = 3; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 223) - hindex[1] = 4; - break; - case 113: - hindex[0] = 5; - break; - case 223: - hindex[0] = 6; - if (treeWords.fdectyp == 2) - hindex[1] = 7; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 111) - hindex[1] = 8; - break; - case 333: - hindex[0] = 9; - if (treeWords.fdectyp == 2) - hindex[1] = 10; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 221) - hindex[1] = 11; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 111) - hindex[1] = 12; - break; - case 443: - hindex[0] = 13; - if (treeWords.fdectyp == 2) - hindex[1] = 14; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 22) - hindex[1] = 15; - break; - } - - hindex[2] = nInputParticles; - - if (hindex[0] < 0) { - LOGP(error, "hindex[0]<0"); - continue; - } - - // Fill tree words before resolution/acceptance - treeWords.fd1origpt = dau1.Pt(); - treeWords.fd1origp = dau1.P(); - treeWords.fd1origeta = dau1.Eta(); - treeWords.fd1origphi = dau1.Phi(); - treeWords.fd2origpt = dau2.Pt(); - treeWords.fd2origp = dau2.P(); - treeWords.fd2origeta = dau2.Eta(); - treeWords.fd2origphi = dau2.Phi(); - treeWords.feeorigpt = ee.Pt(); - treeWords.feeorigp = ee.P(); - treeWords.feeorigm = ee.M(); - treeWords.feeorigeta = ee.Eta(); - treeWords.feeorigrap = ee.Rapidity(); - treeWords.feeorigphi = ee.Phi(); - if (mctrack.GetPdgCode() > 0) { - treeWords.feeorigphiv = PhiV(dau1, dau2); - } else { - treeWords.feeorigphiv = PhiV(dau2, dau1); - } - - // get the efficiency weight - Int_t effbin = fhwEffpT->FindBin(treeWords.fd1origpt); - treeWords.fwEffpT = fhwEffpT->GetBinContent(effbin); - effbin = fhwEffpT->FindBin(treeWords.fd2origpt); - treeWords.fwEffpT = treeWords.fwEffpT * fhwEffpT->GetBinContent(effbin); - - // Resolution and acceptance - //------------------------- - int ch1 = 1; - int ch2 = 1; - if (mctrack.GetPdgCode() > 0) { - ch1 = -1; - } - if (mctrack2.GetPdgCode() > 0) { - ch2 = -1; - } - dau1 = applySmearingPxPyPzE(ch1, dau1); - dau2 = applySmearingPxPyPzE(ch2, dau2); - - treeWords.fd1pt = dau1.Pt(); - treeWords.fd1eta = dau1.Eta(); - treeWords.fd2pt = dau2.Pt(); - treeWords.fd2eta = dau2.Eta(); - treeWords.fpass = true; - if (treeWords.fd1pt < fConfigMinPt || treeWords.fd2pt < fConfigMinPt) - treeWords.fpass = false; // leg pT cut - if (treeWords.fd1pt > fConfigMaxPt || treeWords.fd2pt > fConfigMaxPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Vect().Unit().Dot(dau2.Vect().Unit()) > TMath::Cos(fConfigMinOpAng)) - treeWords.fpass = false; // opening angle cut - if (TMath::Abs(treeWords.fd1eta) > fConfigMaxEta || TMath::Abs(treeWords.fd2eta) > fConfigMaxEta) - treeWords.fpass = false; - - // get the pair DCA (based in smeared pT) - for (int jj = 0; jj < nbDCAtemplate; jj++) { // loop over DCA templates - if (dau1.Pt() >= DCATemplateEdges[jj] && dau1.Pt() < DCATemplateEdges[jj + 1]) { - treeWords.fd1DCA = fh_DCAtemplates[jj]->GetRandom(); - } - if (dau2.Pt() >= DCATemplateEdges[jj] && dau2.Pt() < DCATemplateEdges[jj + 1]) { - treeWords.fd2DCA = fh_DCAtemplates[jj]->GetRandom(); - } - } - treeWords.fpairDCA = sqrt((pow(treeWords.fd1DCA, 2) + pow(treeWords.fd2DCA, 2)) / 2); - - // Fill tree words after resolution/acceptance - ee = dau1 + dau2; - treeWords.fd1p = dau1.P(); - treeWords.fd1phi = dau1.Phi(); - treeWords.fd2p = dau2.P(); - treeWords.fd2phi = dau2.Phi(); - treeWords.feept = ee.Pt(); - treeWords.feemt = ee.Mt(); - treeWords.feep = ee.P(); - treeWords.feem = ee.M(); - treeWords.feeeta = ee.Eta(); - treeWords.feerap = ee.Rapidity(); - treeWords.feephi = ee.Phi(); - if (mctrack.GetPdgCode() > 0) { - treeWords.feephiv = PhiV(dau1, dau2); - } else { - treeWords.feephiv = PhiV(dau2, dau1); - } - treeWords.fmotherpt = mother.GetPt(); - treeWords.fmotherm = sqrt(pow(mother.GetEnergy(), 2) + pow(mother.GetP(), 2)); - treeWords.fmothermt = sqrt(pow(treeWords.fmotherm, 2) + pow(treeWords.fmotherpt, 2)); - treeWords.fmotherp = mother.GetP(); - treeWords.fmothereta = mother.GetEta(); - treeWords.fmotherphi = mother.GetPhi(); - treeWords.fID = mother.GetPdgCode(); - treeWords.fweight = mctrack.getWeight(); // get particle weight from generator - - // get multiplicity based weight: - int iwbin = fhwMultpT->FindBin(treeWords.fmotherpt); - treeWords.fwMultpT = fhwMultpT->GetBinContent(iwbin); // pT weight - treeWords.fwMultpT2 = fhwMultpT2->GetBinContent(iwbin); // pT weight - double min_mT = fhwMultmT->GetBinLowEdge(1); // consider as minimum valid mT value the edge of the weight histo. - if (treeWords.fmothermt > min_mT) { - iwbin = fhwMultmT->FindBin(treeWords.fmothermt); - treeWords.fwMultmT = fhwMultmT->GetBinContent(iwbin); // mT weight - treeWords.fwMultmT2 = fhwMultmT2->GetBinContent(iwbin); // mT weight - } else { - LOGP(error, "Generated particle with mT < Pion mass cannot be weighted"); - treeWords.fwMultmT = 0.; - treeWords.fwMultmT2 = 0.; - } - - // Which ALT weight to use?: - Double_t fwALT = treeWords.fwEffpT; // by default use pt efficiency weight - if (fConfigALTweight == 1) - fwALT = treeWords.fwMultmT; // mT multiplicity weight - if (fConfigALTweight == 11) - fwALT = treeWords.fwMultmT2; // mT multiplicity weight, higher mult - if (fConfigALTweight == 2) - fwALT = treeWords.fwMultpT; // pT multiplicity weight - if (fConfigALTweight == 22) - fwALT = treeWords.fwMultpT2; // pT multiplicity weight, higher mult - - // fill the tree - if (fConfigWriteTTree) { - tree->Fill(); - } - - // fill the histograms - if (treeWords.fdectyp < 4) { // why here <4 and before <5 ??? - for (Int_t jj = 0; jj < 3; jj++) { // fill the different hindex -> particles - if (hindex[jj] > -1) { - fmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.fweight); - if (fConfigALTweight == 1 || fConfigALTweight == 11) { - fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmothermt, treeWords.fweight); - } else if (fConfigALTweight == 2 || fConfigALTweight == 22 || fConfigALTweight == 0) { - fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight); - } - fpteevsmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, treeWords.fweight); - fphi_orig[hindex[jj]]->Fill(treeWords.feeorigphi, treeWords.fweight); - frap_orig[hindex[jj]]->Fill(treeWords.feeorigrap, treeWords.fweight); - fmee_orig_wALT[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.fweight * fwALT); - fpteevsmee_orig_wALT[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, treeWords.fweight * fwALT); - if (fConfigALTweight == 1 || fConfigALTweight == 11) { - fmotherpT_orig_wALT[hindex[jj]]->Fill(treeWords.fmothermt, treeWords.fweight * fwALT); - } else if (fConfigALTweight == 2 || fConfigALTweight == 22 || fConfigALTweight == 0) { - fmotherpT_orig_wALT[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight * fwALT); - } - if (treeWords.fpass) { - fmee[hindex[jj]]->Fill(treeWords.feem, treeWords.fweight); - fpteevsmee[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, treeWords.fweight); - fphi[hindex[jj]]->Fill(treeWords.feephi, treeWords.fweight); - frap[hindex[jj]]->Fill(treeWords.feerap, treeWords.fweight); - registry.fill(HIST("DCAeevsmee"), treeWords.feem, treeWords.fpairDCA, treeWords.fweight); - registry.fill(HIST("DCAeevsptee"), treeWords.feept, treeWords.fpairDCA, treeWords.fweight); - fmee_wALT[hindex[jj]]->Fill(treeWords.feem, treeWords.fweight * fwALT); - fpteevsmee_wALT[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, treeWords.fweight * fwALT); - } - } - } - } + if (p1.Pt() < fConfigMinPt) + return false; + if (p1.Pt() > fConfigMaxPt) + return false; + if (abs(p1.Eta()) > fConfigMaxEta) + return false; + return true; + } - if (fConfigDoVirtPh) { - // Virtual photon generation - //------------------------- - // We will generate one virtual photon per histogrammed pion - if (mother.GetPdgCode() == 111) { - // get mass and pt from histos and flat eta and phi - Double_t VPHpT = ffVPHpT->GetRandom(); - Double_t VPHmass = fhKW->GetRandom(); - Double_t VPHeta = -1. + gRandom->Rndm() * 2.; - Double_t VPHphi = 2.0 * TMath::ACos(-1.) * gRandom->Rndm(); - TLorentzVector beam; - beam.SetPtEtaPhiM(VPHpT, VPHeta, VPHphi, VPHmass); - Double_t decaymasses[2] = {(TDatabasePDG::Instance()->GetParticle(11))->Mass(), (TDatabasePDG::Instance()->GetParticle(11))->Mass()}; - TGenPhaseSpace VPHgen; - Bool_t SetDecay; - SetDecay = VPHgen.SetDecay(beam, 2, decaymasses); - if (SetDecay == 0) - LOGP(error, "Decay not permitted by kinematics"); - Double_t VPHweight = VPHgen.Generate(); - // get electrons from the decay - TLorentzVector *decay1, *decay2; - decay1 = VPHgen.GetDecay(0); - decay2 = VPHgen.GetDecay(1); - dau1.SetPxPyPzE(decay1->Px(), decay1->Py(), decay1->Pz(), decay1->E()); - dau2.SetPxPyPzE(decay2->Px(), decay2->Py(), decay2->Pz(), decay2->E()); - - // create dielectron before resolution effects: - ee = dau1 + dau2; - - // get index for histograms - hindex[0] = nInputParticles - 1; - hindex[1] = -1; - hindex[2] = -1; - - // Fill tree words before resolution/acceptance - treeWords.fd1origpt = dau1.Pt(); - treeWords.fd1origp = dau1.P(); - treeWords.fd1origeta = dau1.Eta(); - treeWords.fd1origphi = dau1.Phi(); - treeWords.fd2origpt = dau2.Pt(); - treeWords.fd2origp = dau2.P(); - treeWords.fd2origeta = dau2.Eta(); - treeWords.fd2origphi = dau2.Phi(); - treeWords.feeorigpt = ee.Pt(); - treeWords.feeorigp = ee.P(); - treeWords.feeorigm = ee.M(); - treeWords.feeorigeta = ee.Eta(); - treeWords.feeorigrap = ee.Rapidity(); - treeWords.feeorigphi = ee.Phi(); - treeWords.feeorigphiv = PhiV(dau1, dau2); - - // get the efficiency weight - Int_t effbin = fhwEffpT->FindBin(treeWords.fd1origpt); - treeWords.fwEffpT = fhwEffpT->GetBinContent(effbin); - effbin = fhwEffpT->FindBin(treeWords.fd2origpt); - treeWords.fwEffpT = treeWords.fwEffpT * fhwEffpT->GetBinContent(effbin); - - // Resolution and acceptance - //------------------------- - dau1 = applySmearingPxPyPzE(1, dau1); - dau2 = applySmearingPxPyPzE(-1, dau2); - treeWords.fpass = true; - if (dau1.Pt() < fConfigMinPt || dau2.Pt() < fConfigMinPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Pt() > fConfigMaxPt || dau2.Pt() > fConfigMaxPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Vect().Unit().Dot(dau2.Vect().Unit()) > TMath::Cos(fConfigMinOpAng)) - treeWords.fpass = false; // opening angle cut - if (TMath::Abs(dau1.Eta()) > fConfigMaxEta || TMath::Abs(dau2.Eta()) > fConfigMaxEta) - treeWords.fpass = false; - - treeWords.fpairDCA = 10000.; // ?? - - // Fill tree words after resolution/acceptance - ee = dau1 + dau2; - treeWords.fd1pt = dau1.Pt(); - treeWords.fd1p = dau1.P(); - treeWords.fd1eta = dau1.Eta(); - treeWords.fd1phi = dau1.Phi(); - treeWords.fd2pt = dau2.Pt(); - treeWords.fd2p = dau2.P(); - treeWords.fd2eta = dau2.Eta(); - treeWords.fd2phi = dau2.Phi(); - treeWords.feept = ee.Pt(); - treeWords.feemt = ee.Mt(); - treeWords.feep = ee.P(); - treeWords.feem = ee.M(); - treeWords.feeeta = ee.Eta(); - treeWords.feerap = ee.Rapidity(); - treeWords.feephi = ee.Phi(); - treeWords.feephiv = PhiV(dau1, dau2); - treeWords.fmotherpt = beam.Pt(); - treeWords.fmothermt = sqrt(pow(beam.M(), 2) + pow(beam.Pt(), 2)); - treeWords.fmotherp = beam.P(); - treeWords.fmotherm = beam.M(); - treeWords.fmothereta = beam.Eta(); - treeWords.fmotherphi = beam.Phi(); - treeWords.fID = 0; // set ID to Zero for VPH - treeWords.fweight = VPHweight; - // get multiplicity based weight: - treeWords.fwMultmT = 1; // no weight for photons so far - - // Fill the tree - if (fConfigWriteTTree) { // many parameters not set for photons: d1DCA,fd2DCA, fdectyp,fdau3pdg,fwMultpT,fwMultpT2,fwMultmT2 - tree->Fill(); - } - - // Fill the histograms - for (Int_t jj = 0; jj < 3; jj++) { // fill the different hindex -> particles - if (hindex[jj] > -1) { - fmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, VPHweight); - fpteevsmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, VPHweight); - fphi_orig[hindex[jj]]->Fill(treeWords.feeorigphi, VPHweight); - frap_orig[hindex[jj]]->Fill(treeWords.feeorigrap, VPHweight); - fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight); - if (treeWords.fpass) { - fmee[hindex[jj]]->Fill(treeWords.feem, VPHweight); - fpteevsmee[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, VPHweight); - fphi[hindex[jj]]->Fill(treeWords.feephi, VPHweight); - frap[hindex[jj]]->Fill(treeWords.feerap, VPHweight); - } - } - } - - } // mother.pdgCode()==111 - } // fConfigDoVirtPh - - } // abs(pdgCode())==11 - - } // loop over mctracks - - // Clear buffers - eBuff.clear(); - echBuff.clear(); - eweightBuff.clear(); + bool isAcceptedPair(ROOT::Math::PtEtaPhiMVector p1, ROOT::Math::PtEtaPhiMVector p2) + { + if (!isAcceptedSingle(p1)) { + return false; + } + if (!isAcceptedSingle(p2)) { + return false; } + ROOT::Math::PtEtaPhiMVector p12 = p1 + p2; + if (p12.Pt() < fConfigMinPtee) + return false; + if (TMath::ACos(p1.Vect().Unit().Dot(p2.Vect().Unit())) < fConfigMinOpAng) + return false; + return true; } - Double_t PhiV(PxPyPzEVector e1, PxPyPzEVector e2) + template + bool isAcceptedPair(T& p1, T& p2) { - Double_t outPhiV; - XYZVector p1 = e1.Vect(); - XYZVector p2 = e2.Vect(); - XYZVector p12 = p1 + p2; - XYZVector u = p12.Unit(); - XYZVector p1u = p1.Unit(); - XYZVector p2u = p2.Unit(); - XYZVector v = p1u.Cross(p2u); - XYZVector w = u.Cross(v); - XYZVector zu(0, 0, 1); - XYZVector wc = u.Cross(zu); - outPhiV = TMath::ACos(wc.Unit().Dot(w.Unit())); - return outPhiV; + ROOT::Math::PtEtaPhiMVector v1(p1.ptSmeared(), p1.etaSmeared(), p1.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(p2.ptSmeared(), p2.etaSmeared(), p2.phiSmeared(), o2::constants::physics::MassElectron); + return isAcceptedPair(v1, v2); } - PxPyPzEVector applySmearingPxPyPzE(int ch, PxPyPzEVector vec) + template + bool isAcceptedSingle(T& p1) { - PxPyPzEVector vecsmeared; - float ptsmeared, etasmeared, phismeared; - smearer.applySmearing(ch, vec.Pt(), vec.Eta(), vec.Phi(), ptsmeared, etasmeared, phismeared); - float sPx = ptsmeared * cos(phismeared); - float sPy = ptsmeared * sin(phismeared); - float sPz = ptsmeared * sinh(etasmeared); - float sP = ptsmeared * cosh(etasmeared); - float sE = sqrt(sP * sP + eMass * eMass); - - vecsmeared.SetPxPyPzE(sPx, sPy, sPz, sE); - - return vecsmeared; + ROOT::Math::PtEtaPhiMVector v1(p1.ptSmeared(), p1.etaSmeared(), p1.phiSmeared(), o2::constants::physics::MassElectron); + return isAcceptedSingle(v1); } - void SetHistograms() + void addHistogram1D_stage(TString histname, AxisSpec axis, int& i, TString s) { - - AxisSpec ptAxis = {fConfigNBinsPtee, fConfigMinPtee, fConfigMaxPtee, "#it{p}_{T,ee} (GeV/c)"}; - AxisSpec mAxis = {fConfigNBinsMee, fConfigMinMee, fConfigMaxMee, "#it{m}_{ee} (GeV/c^{2})"}; - AxisSpec phiAxis = {fConfigNBinsPhi, -TMath::TwoPi() / 2, TMath::TwoPi() / 2, "#it{phi}_{ee}"}; - AxisSpec rapAxis = {fConfigNBinsRap, -fConfigMaxAbsRap, fConfigMaxAbsRap, "#it{y}_{ee}"}; - - registry.add("NEvents", "NEvents", HistType::kTH1F, {{1, 0, 1}}, false); - - if (fConfigDoPairing) { - registry.add("ULS", "ULS", HistType::kTH2F, {mAxis, ptAxis}, true); - registry.add("LSpp", "LSpp", HistType::kTH2F, {mAxis, ptAxis}, true); - registry.add("LSmm", "LSmm", HistType::kTH2F, {mAxis, ptAxis}, true); - - registry.add("ULS_orig", "ULS_orig", HistType::kTH2F, {mAxis, ptAxis}, true); - registry.add("LSpp_orig", "LSpp_orig", HistType::kTH2F, {mAxis, ptAxis}, true); - registry.add("LSmm_orig", "LSmm_orig", HistType::kTH2F, {mAxis, ptAxis}, true); - } - - registry.add("DCAeevsmee", "DCAeevsmee", HistType::kTH2F, {{fConfigMBins, "#it{m}_{ee} (GeV/c^{2})"}, {fConfigDCABins, "DCA_{xy}^{ee} (cm)"}}, true); - registry.add("DCAeevsptee", "DCAeevsptee", HistType::kTH2F, {{fConfigPtBins, "#it{p}_{T,ee} (GeV/c)"}, {fConfigDCABins, "DCA_{xy}^{ee} (cm)"}}, true); - - for (auto& particle : fParticleListNames) { - fmee.push_back(registry.add(Form("mee_%s", particle.Data()), Form("mee_%s", particle.Data()), HistType::kTH1F, {mAxis}, true)); - fmee_orig.push_back(registry.add(Form("mee_orig_%s", particle.Data()), Form("mee_orig_%s", particle.Data()), HistType::kTH1F, {mAxis}, true)); - fmotherpT_orig.push_back(registry.add(Form("motherpT_orig_%s", particle.Data()), Form("motherpT_orig_%s", particle.Data()), HistType::kTH1F, {ptAxis}, true)); - fphi.push_back(registry.add(Form("phi_%s", particle.Data()), Form("phi_%s", particle.Data()), HistType::kTH1F, {phiAxis}, true)); - fphi_orig.push_back(registry.add(Form("phi_orig_%s", particle.Data()), Form("phi_orig_%s", particle.Data()), HistType::kTH1F, {phiAxis}, true)); - frap.push_back(registry.add(Form("rap_%s", particle.Data()), Form("rap_%s", particle.Data()), HistType::kTH1F, {rapAxis}, true)); - frap_orig.push_back(registry.add(Form("rap_orig_%s", particle.Data()), Form("rap_orig_%s", particle.Data()), HistType::kTH1F, {rapAxis}, true)); - fpteevsmee.push_back(registry.add(Form("pteevsmee_%s", particle.Data()), Form("pteevsmee_%s", particle.Data()), HistType::kTH2F, {mAxis, ptAxis}, true)); - fpteevsmee_orig.push_back(registry.add(Form("pteevsmee_orig_%s", particle.Data()), Form("pteevsmee_orig_%s", particle.Data()), HistType::kTH2F, {mAxis, ptAxis}, true)); - fmee_wALT.push_back(registry.add(Form("mee_wALT_%s", particle.Data()), Form("mee_wALT_%s", particle.Data()), HistType::kTH1F, {mAxis}, true)); - fmee_orig_wALT.push_back(registry.add(Form("mee_orig_wALT_%s", particle.Data()), Form("mee_orig_wALT_%s", particle.Data()), HistType::kTH1F, {mAxis}, true)); - fmotherpT_orig_wALT.push_back(registry.add(Form("motherpT_orig_wALT_%s", particle.Data()), Form("motherpT_orig_wALT%s", particle.Data()), HistType::kTH1F, {ptAxis}, true)); - fpteevsmee_wALT.push_back(registry.add(Form("pteevsmee_wALT%s", particle.Data()), Form("pteevsmee_wALT_%s", particle.Data()), HistType::kTH2F, {mAxis, ptAxis}, true)); - fpteevsmee_orig_wALT.push_back(registry.add(Form("pteevsmee_orig_wALT%s", particle.Data()), Form("pteevsmee_orig_wALT_%s", particle.Data()), HistType::kTH2F, {mAxis, ptAxis}, true)); + i++; + TString name = s + histname; + histogramId[name] = i; + histograms1D.push_back(registry.add(name, histname, HistType::kTH1F, {axis}, true)); + for (auto const& [pdg, meson] : mesons) { + i++; + name = s + meson.name + histname; + histogramId[name] = i; + histograms1D.push_back(registry.add(name, histname, HistType::kTH1F, {axis}, true)); + for (auto const& mode : meson.decayModes) { + i++; + name = s + meson.name + decays[mode] + histname; + histogramId[name] = i; + histograms1D.push_back(registry.add(name, histname, HistType::kTH1F, {axis}, true)); + } } - - fmee.push_back(registry.add("mee", "mee", HistType::kTH1F, {mAxis}, true)); - fmee_orig.push_back(registry.add("mee_orig", "mee_orig", HistType::kTH1F, {mAxis}, true)); - fmotherpT_orig.push_back(registry.add("motherpT_orig", "motherpT_orig", HistType::kTH1F, {ptAxis}, true)); - fphi.push_back(registry.add("phi", "phi", HistType::kTH1F, {phiAxis}, true)); - fphi_orig.push_back(registry.add("phi_orig", "phi_orig", HistType::kTH1F, {phiAxis}, true)); - frap.push_back(registry.add("rap", "rap", HistType::kTH1F, {rapAxis}, true)); - frap_orig.push_back(registry.add("rap_orig", "rap_orig", HistType::kTH1F, {rapAxis}, true)); - fpteevsmee.push_back(registry.add("pteevsmee", "pteevsmee", HistType::kTH2F, {mAxis, ptAxis}, true)); - fpteevsmee_orig.push_back(registry.add("pteevsmee_orig", "pteevsmee_orig", HistType::kTH2F, {mAxis, ptAxis}, true)); - fmee_wALT.push_back(registry.add("mee_wALT", "mee_wALT", HistType::kTH1F, {mAxis}, true)); - fmee_orig_wALT.push_back(registry.add("mee_orig_wALT", "mee_orig_wALT", HistType::kTH1F, {mAxis}, true)); - fmotherpT_orig_wALT.push_back(registry.add("motherpT_orig_wALT", "motherpT_orig_wALT", HistType::kTH1F, {ptAxis}, true)); - fpteevsmee_wALT.push_back(registry.add("pteevsmee_wALT", "pteevsmee_wALT", HistType::kTH2F, {mAxis, ptAxis}, true)); - fpteevsmee_orig_wALT.push_back(registry.add("pteevsmee_orig_wALT", "pteevsmee_orig_wALT", HistType::kTH2F, {mAxis, ptAxis}, true)); } - void SetTree() + void addHistogram1D(TString histname, AxisSpec axis, int& i) { - tree.setObject(new TTree("eeTTree", "eeTTree")); - - tree->Branch("fd1DCA", &treeWords.fd1DCA, "fd1DCA/F"); - tree->Branch("fd2DCA", &treeWords.fd2DCA, "fd2DCA/F"); - tree->Branch("fpairDCA", &treeWords.fpairDCA, "fpairDCA/F"); - tree->Branch("fd1origpt", &treeWords.fd1origpt, "fd1origpt/F"); - tree->Branch("fd1origp", &treeWords.fd1origp, "fd1origp/F"); - tree->Branch("fd1origeta", &treeWords.fd1origeta, "fd1origeta/F"); - tree->Branch("fd1origphi", &treeWords.fd1origphi, "fd1origphi/F"); - tree->Branch("fd2origpt", &treeWords.fd2origpt, "fd2origpt/F"); - tree->Branch("fd2origp", &treeWords.fd2origp, "fd2origp/F"); - tree->Branch("fd2origeta", &treeWords.fd2origeta, "fd2origeta/F"); - tree->Branch("fd2origphi", &treeWords.fd2origphi, "fd2origphi/F"); - tree->Branch("fd1pt", &treeWords.fd1pt, "fd1pt/F"); - tree->Branch("fd1p", &treeWords.fd1p, "fd1p/F"); - tree->Branch("fd1eta", &treeWords.fd1eta, "fd1eta/F"); - tree->Branch("fd1phi", &treeWords.fd1phi, "fd1phi/F"); - tree->Branch("fd2pt", &treeWords.fd2pt, "fd2pt/F"); - tree->Branch("fd2p", &treeWords.fd2p, "fd2p/F"); - tree->Branch("fd2eta", &treeWords.fd2eta, "fd2eta/F"); - tree->Branch("fd2phi", &treeWords.fd2phi, "fd2phi/F"); - tree->Branch("feeorigpt", &treeWords.feeorigpt, "feeorigpt/F"); - tree->Branch("feeorigp", &treeWords.feeorigp, "feeorigp/F"); - tree->Branch("feeorigm", &treeWords.feeorigm, "feeorigm/F"); - tree->Branch("feeorigeta", &treeWords.feeorigeta, "feeorigeta/F"); - tree->Branch("feeorigphi", &treeWords.feeorigphi, "feeorigphi/F"); - tree->Branch("feeorigphiv", &treeWords.feeorigphiv, "feeorigphiv/F"); - tree->Branch("feept", &treeWords.feept, "feept/F"); - tree->Branch("feemt", &treeWords.feemt, "feemt/F"); - tree->Branch("feep", &treeWords.feep, "feep/F"); - tree->Branch("feem", &treeWords.feem, "feem/F"); - tree->Branch("feeeta", &treeWords.feeeta, "feeeta/F"); - tree->Branch("feephi", &treeWords.feephi, "feephi/F"); - tree->Branch("feephiv", &treeWords.feephiv, "feephiv/F"); - tree->Branch("fmotherpt", &treeWords.fmotherpt, "fmotherpt/F"); - tree->Branch("fmothermt", &treeWords.fmothermt, "fmothermt/F"); - tree->Branch("fmotherp", &treeWords.fmotherp, "fmotherp/F"); - tree->Branch("fmotherm", &treeWords.fmotherm, "fmotherm/F"); - tree->Branch("fmothereta", &treeWords.fmothereta, "fmothereta/F"); - tree->Branch("fmotherphi", &treeWords.fmotherphi, "fmotherphi/F"); - tree->Branch("fID", &treeWords.fID, "fID/I"); - tree->Branch("fdectyp", &treeWords.fdectyp, "fdectyp/I"); - tree->Branch("fdau3pdg", &treeWords.fdau3pdg, "fdau3pdg/I"); - tree->Branch("fweight", &treeWords.fweight, "fweight/F"); - tree->Branch("fwEffpT", &treeWords.fwEffpT, "fwEffpT/F"); - tree->Branch("fwMultpT", &treeWords.fwMultpT, "fwMultpT/F"); - tree->Branch("fwMultmT", &treeWords.fwMultmT, "fwMultmT/F"); - tree->Branch("fwMultpT2", &treeWords.fwMultpT2, "fwMultpT2/F"); - tree->Branch("fwMultmT2", &treeWords.fwMultmT2, "fwMultmT2/F"); - tree->Branch("fpass", &treeWords.fpass, "fpass/B"); + for (auto s : stage) { + addHistogram1D_stage(histname, axis, i, s); + } } - void GetEffHisto(TString filename, TString histname) + void addHistogram1D_mother(TString histname, AxisSpec axis, int& i) // mother histograms only for gen. level, no decay channels { - // get efficiency histo - LOGP(info, "Set Efficiency histo"); - // Get Efficiency weight file: - TFile* fFile = TFile::Open(filename.Data()); - if (!fFile) { - LOGP(error, "Could not open Efficiency file {}", filename.Data()); - return; - } - if (fFile->GetListOfKeys()->Contains(histname.Data())) { - fhwEffpT = reinterpret_cast(fFile->Get(histname.Data())); // histo: eff weight in function of pT. - fhwEffpT->SetDirectory(nullptr); - } else { - LOGP(error, "Could not open histogram {} from file {}", histname.Data(), filename.Data()); + i++; + TString name = stage[0] + histname; + histogramId[name] = i; + histograms1D.push_back(registry.add(name, histname, HistType::kTH1F, {axis}, true)); + for (auto const& [pdg, meson] : mesons) { + i++; + name = stage[0] + meson.name + histname; + histogramId[name] = i; + histograms1D.push_back(registry.add(name, histname, HistType::kTH1F, {axis}, true)); } - - fFile->Close(); } - void InitSmearer(TString filename, TString ptHistName, TString etaHistName, TString phiPosHistName, TString phiNegHistName) + void addHistogram2D_stage(TString histname, AxisSpec axis1, AxisSpec axis2, int& i, TString s) { - smearer.setResFileName(filename); - smearer.setResPtHistName(ptHistName); - smearer.setResEtaHistName(etaHistName); - smearer.setResPhiPosHistName(phiPosHistName); - smearer.setResPhiNegHistName(phiNegHistName); - smearer.init(); + i++; + TString name = s + histname; + histogramId[name] = i; + histograms2D.push_back(registry.add(name, histname, HistType::kTH2F, {axis1, axis2}, true)); + for (auto const& [pdg, meson] : mesons) { + i++; + name = s + meson.name + histname; + histogramId[name] = i; + histograms2D.push_back(registry.add(name, histname, HistType::kTH2F, {axis1, axis2}, true)); + for (auto const& mode : meson.decayModes) { + i++; + name = s + meson.name + decays[mode] + histname; + histogramId[name] = i; + histograms2D.push_back(registry.add(name, histname, HistType::kTH2F, {axis1, axis2}, true)); + } + } } - void GetDCATemplates(TString filename, TString histname) + void addHistogram2D(TString histname, AxisSpec axis1, AxisSpec axis2, int& i) { - // get dca tamplates - LOGP(info, "Set DCA templates"); - // Get file: - TFile* fFile = TFile::Open(filename.Data()); - if (!fFile) { - LOGP(error, "Could not open DCATemplate file {}", filename.Data()); - return; + for (auto s : stage) { + addHistogram2D_stage(histname, axis1, axis2, i, s); } - fh_DCAtemplates = new TH1F*[nbDCAtemplate]; - for (int jj = 0; jj < nbDCAtemplate; jj++) { - if (fFile->GetListOfKeys()->Contains(Form("%s%d", histname.Data(), jj + 1))) { - fh_DCAtemplates[jj] = reinterpret_cast(fFile->Get(Form("%s%d", histname.Data(), jj + 1))); - } else { - LOGP(error, "Could not open {}{} from file {}", histname.Data(), jj + 1, filename.Data()); - } - } - fFile->Close(); } - void GetMultHisto(TString filename, TString histnamept, TString histnamept2, TString histnamemt, TString histnamemt2) + void fillHistogram1D(TString histname, int s, int pdg, int other_daughter_pdg, float value, float weight) { - // get multiplicity weights - LOGP(info, "Set Multiplicity weight files"); - TFile* fFile = TFile::Open(filename.Data()); - if (!fFile) { - LOGP(error, "Could not open Multiplicity weight file {}", filename.Data()); - return; - } + histograms1D[histogramId[stage[s] + histname]]->Fill(value, weight); + histograms1D[histogramId[stage[s] + mesons[pdg].name + histname]]->Fill(value, weight); + histograms1D[histogramId[stage[s] + mesons[pdg].name + decays[other_daughter_pdg] + histname]]->Fill(value, weight); + } - if (fFile->GetListOfKeys()->Contains(histnamept.Data())) { - fhwMultpT = reinterpret_cast(fFile->Get(histnamept.Data())); // histo: multiplicity weight in function of pT. - } else { - LOGP(error, "Could not open {} from file {}", histnamept.Data(), filename.Data()); - } + void fillHistogram1D_mother(TString histname, int pdg, float value, float weight) + { + histograms1D[histogramId[stage[0] + histname]]->Fill(value, weight); + histograms1D[histogramId[stage[0] + mesons[pdg].name + histname]]->Fill(value, weight); + } - if (fFile->GetListOfKeys()->Contains(histnamemt.Data())) { - fhwMultmT = reinterpret_cast(fFile->Get(histnamemt.Data())); // histo: multiplicity weight in function of mT. - } else { - LOGP(error, "Could not open {} from file {}", histnamemt.Data(), filename.Data()); - } + void fillHistogram2D(TString histname, int s, int pdg, int other_daughter_pdg, float value1, float value2, float weight) + { + histograms2D[histogramId[stage[s] + histname]]->Fill(value1, value2, weight); + histograms2D[histogramId[stage[s] + mesons[pdg].name + histname]]->Fill(value1, value2, weight); + histograms2D[histogramId[stage[s] + mesons[pdg].name + decays[other_daughter_pdg] + histname]]->Fill(value1, value2, weight); + } - if (fFile->GetListOfKeys()->Contains(histnamept2.Data())) { - fhwMultpT2 = reinterpret_cast(fFile->Get(histnamept2.Data())); // histo: multiplicity weight in function of pT. - } else { - LOGP(error, "Could not open {} from file {}", histnamept2.Data(), filename.Data()); + void init(InitContext& context) + { + AxisSpec mass_axis = {fConfigMeeBins, "m_{ee} (GeV/#it{c}^{2})"}; + AxisSpec ptee_axis = {fConfigPteeBins, "#it{p}_{T,ee} (GeV/#it{c})"}; + AxisSpec eta_axis = {fConfigEtaBins, "#it{#eta}_{e}"}; + AxisSpec pt_axis = {fConfigPtBins, "#it{p}_{T,e} (GeV/c)"}; + AxisSpec phi_axis = {fConfigPhiBins, "#it{#varphi}_{e}"}; + AxisSpec phiV_axis = {fConfigPhiVBins, "#it{#varphi}_{V,ee}"}; + AxisSpec opAng_axis = {fConfigOpAngBins, "#it{#omega}_{ee}"}; + AxisSpec eta_axis_mother = {fConfigEtaBins, "#it{#eta}_{mother}"}; + AxisSpec pt_axis_mother = {fConfigPtBins, "#it{p}_{T,mother} (GeV/#it{c})"}; + AxisSpec phi_axis_mother = {fConfigPhiBins, "#it{#varphi}_{mother}"}; + AxisSpec dca_axis = {fConfigDcaBins, "DCA_{e}"}; + AxisSpec dcaee_axis = {fConfigDcaBins, "DCA_{ee}"}; + + if (context.mOptions.get("processPairing")) { + registry.add("gen/ULS", "ULS gen.", HistType::kTH2F, {mass_axis, ptee_axis}, true); + registry.add("gen/LSpp", "LS++ gen.", HistType::kTH2F, {mass_axis, ptee_axis}, true); + registry.add("gen/LSmm", "LS-- gen.", HistType::kTH2F, {mass_axis, ptee_axis}, true); + registry.add("rec/ULS", "ULS rec.", HistType::kTH2F, {mass_axis, ptee_axis}, true); + registry.add("rec/LSpp", "LS++ rec.", HistType::kTH2F, {mass_axis, ptee_axis}, true); + registry.add("rec/LSmm", "LS-- rec.", HistType::kTH2F, {mass_axis, ptee_axis}, true); } - - if (fFile->GetListOfKeys()->Contains(histnamemt2.Data())) { - fhwMultmT2 = reinterpret_cast(fFile->Get(histnamemt2)); // histo: multiplicity weight in function of mT. - } else { - LOGP(error, "Could not open {} from file {}", histnamemt2.Data(), filename.Data()); + if (context.mOptions.get("processCocktail")) { + int i = -1; + addHistogram1D("Pt", pt_axis, i); + addHistogram1D("Eta", eta_axis, i); + addHistogram1D("Phi", phi_axis, i); + addHistogram1D_mother("Mother_Pt", pt_axis_mother, i); + addHistogram1D_mother("Mother_Eta", eta_axis_mother, i); + addHistogram1D_mother("Mother_Phi", phi_axis_mother, i); + addHistogram1D("PhiV", phiV_axis, i); + addHistogram1D("OpAng", opAng_axis, i); + addHistogram1D("Mee", mass_axis, i); + addHistogram1D("Ptee", ptee_axis, i); + addHistogram1D_stage("Dca", dca_axis, i, "rec/"); + addHistogram1D_stage("Dcaee", dcaee_axis, i, "rec/"); + i = -1; + addHistogram2D("MeeVsPtee", mass_axis, ptee_axis, i); + addHistogram2D_stage("DcaVsPt", dca_axis, pt_axis, i, "rec/"); + addHistogram2D_stage("DcaeeVsPtee", dcaee_axis, ptee_axis, i, "rec/"); + addHistogram2D_stage("DcaeeVsMee", dcaee_axis, mass_axis, i, "rec/"); } - fFile->Close(); } - void GetPhotonPtParametrization(TString filename, TString dirname, TString funcname) + void processCocktail(McParticlesSmeared const& mcParticles) { - LOGP(info, "Set photon parametrization"); - - if (filename.EndsWith(".root")) { // read from ROOT file - TFile* fFile = TFile::Open(filename.Data()); - if (!fFile) { - LOGP(error, "Could not open photon parametrization from file {}", filename.Data()); - return; + for (auto const& particle : mcParticles) { + if (particle.has_mothers()) { + continue; + } + int pdg = abs(particle.pdgCode()); + if (mesons.find(pdg) == mesons.end()) { + LOG(error) << "Found mother particle with pdg = " << pdg << " that is not in list of mesons"; } - bool good = false; - if (fFile->GetListOfKeys()->Contains(dirname.Data())) { - TDirectory* dir = fFile->GetDirectory(dirname.Data()); - if (dir->GetListOfKeys()->Contains(funcname.Data())) { - ffVPHpT = reinterpret_cast(dir->Get(funcname.Data())); - ffVPHpT->SetNpx(10000); - good = true; + if (!particle.has_daughters()) { + LOG(error) << "Found meson with pdg = " << pdg << "that has no daughters"; + } + + int other_daughter_pdg = -1; + int nEle = 0; + int nPos = 0; + + ROOT::Math::PtEtaPhiMVector pEleGen, pPosGen, pEleRec, pPosRec; + float weight(1.), effEle(1.), effPos(1.), dcaEle(0.), dcaPos(0.); + for (const auto& daughter : particle.daughters_as()) { + int temp_pdg = daughter.pdgCode(); + if (temp_pdg == 11) { + ROOT::Math::PtEtaPhiMVector temp_p_gen(daughter.pt(), daughter.eta(), daughter.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector temp_p(daughter.ptSmeared(), daughter.etaSmeared(), daughter.phiSmeared(), o2::constants::physics::MassElectron); + pEleGen = temp_p_gen; + pEleRec = temp_p; + weight = daughter.weight(); + effEle = daughter.efficiency(); + dcaEle = daughter.dca(); + nEle++; + continue; } + if (temp_pdg == -11) { + ROOT::Math::PtEtaPhiMVector temp_p_gen(daughter.pt(), daughter.eta(), daughter.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector temp_p(daughter.ptSmeared(), daughter.etaSmeared(), daughter.phiSmeared(), o2::constants::physics::MassElectron); + pPosGen = temp_p_gen; + pPosRec = temp_p; + effPos = daughter.efficiency(); + dcaPos = daughter.dca(); + nPos++; + continue; + } + other_daughter_pdg = abs(other_daughter_pdg * temp_pdg); + } + if (!(((nEle == 1) && (nPos == 1)) || ((nEle == 2) && (nPos == 2)))) { + LOG(error) << "Found decay with wrong number of electrons in decay of meson with pdg " << pdg << ": nElectrons = " << nEle << ", nPositrons = " << nPos; + continue; } - if (!good) { - LOGP(error, "Could not open photon parametrization {}/{} from file {}", dirname.Data(), funcname.Data(), filename.Data()); + if ((nEle == 2) && (nPos == 2) && (other_daughter_pdg == -1)) { + other_daughter_pdg = -2; + weight = 2 * weight; } - fFile->Close(); - } else if (filename.EndsWith(".json")) { // read from JSON file - std::ifstream fFile(filename.Data()); - if (!fFile) { - LOGP(error, "Could not open photon parametrization from file {}", filename.Data()); - return; + auto this_meson_decays = mesons[pdg].decayModes; + if (std::find(this_meson_decays.begin(), this_meson_decays.end(), other_daughter_pdg) == this_meson_decays.end()) { + LOG(error) << "Found decay with code = " << other_daughter_pdg << " that is not in list of decays of meson with pdg " << pdg; + continue; } - nlohmann::json paramfile = nlohmann::json::parse(fFile); - if (paramfile.contains(dirname.Data())) { - nlohmann::json dir = paramfile[dirname.Data()]; - if (dir.contains(funcname.Data())) { - std::string formula = dir[funcname.Data()]; - ffVPHpT = new TF1(TString(funcname.Data()), TString(formula), 0, 100); - if (ffVPHpT) { - ffVPHpT->SetNpx(10000); - return; + + for (int s = 0; s < kNRecLevels; s++) { // s=0: gen, s=1: rec + + ROOT::Math::PtEtaPhiMVector pEle, pPos; + float pairWeight(1.), weightEle(1.), weightPos(1.); + bool acceptedEle(true), acceptedPos(true), acceptedPair(true); + + if (s == kGen) { + pEle = pEleGen; + pPos = pPosGen; + pairWeight = weight; + weightEle = weight; + weightPos = weight; + acceptedEle = true; + acceptedPos = true; + acceptedPair = true; + } else if (s == kRec) { + pEle = pEleRec; + pPos = pPosRec; + pairWeight = weight * effEle * effPos; + weightEle = weight * effEle; + weightPos = weight * effPos; + acceptedEle = isAcceptedSingle(pEle); + acceptedPos = isAcceptedSingle(pPos); + acceptedPair = isAcceptedPair(pEle, pPos); + } + + // single track histograms + if (acceptedEle) + fillHistogram1D("Pt", s, pdg, other_daughter_pdg, pEle.Pt(), weightEle); + if (acceptedPos) + fillHistogram1D("Pt", s, pdg, other_daughter_pdg, pPos.Pt(), weightPos); + + if (acceptedEle) + fillHistogram1D("Eta", s, pdg, other_daughter_pdg, pEle.Eta(), weightEle); + if (acceptedPos) + fillHistogram1D("Eta", s, pdg, other_daughter_pdg, pPos.Eta(), weightPos); + + if (acceptedEle) + fillHistogram1D("Phi", s, pdg, other_daughter_pdg, pEle.Phi(), weightEle); + if (acceptedPos) + fillHistogram1D("Phi", s, pdg, other_daughter_pdg, pPos.Phi(), weightPos); + + if (s == kRec) { // dca only at rec. level + if (acceptedEle) { + fillHistogram1D("Dca", s, pdg, other_daughter_pdg, dcaEle, weightEle); + fillHistogram2D("DcaVsPt", s, pdg, other_daughter_pdg, dcaEle, pEle.Pt(), weightEle); + } + if (acceptedPos) { + fillHistogram1D("Dca", s, pdg, other_daughter_pdg, dcaPos, weightPos); + fillHistogram2D("DcaVsPt", s, pdg, other_daughter_pdg, dcaPos, pPos.Pt(), weightPos); + } + } + + // mother histograms + if (s == kGen) { // only at gen. level + fillHistogram1D_mother("Mother_Pt", pdg, particle.pt(), weight); + fillHistogram1D_mother("Mother_Eta", pdg, particle.eta(), weight); + fillHistogram1D_mother("Mother_Phi", pdg, particle.phi(), weight); + } + + // pair historams + if (acceptedPair) { + ROOT::Math::PtEtaPhiMVector p12 = pEle + pPos; + float mee = p12.M(); + float ptee = p12.Pt(); + float phiV = o2::aod::pwgem::dilepton::utils::pairutil::getOpeningAngle(pPos.Px(), pPos.Py(), pPos.Pz(), pEle.Px(), pEle.Py(), pEle.Pz()); + float opAng = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pPos.Px(), pPos.Py(), pPos.Pz(), pEle.Px(), pEle.Py(), pEle.Pz(), 1, -1, 1); + float dcaee = sqrt((pow(dcaEle, 2) + pow(dcaPos, 2)) / 2); + fillHistogram2D("MeeVsPtee", s, pdg, other_daughter_pdg, mee, ptee, pairWeight); + fillHistogram1D("Mee", s, pdg, other_daughter_pdg, mee, pairWeight); + fillHistogram1D("Ptee", s, pdg, other_daughter_pdg, ptee, pairWeight); + fillHistogram1D("PhiV", s, pdg, other_daughter_pdg, phiV, pairWeight); + fillHistogram1D("OpAng", s, pdg, other_daughter_pdg, opAng, pairWeight); + if (s == kRec) { // dca only at rec. level + fillHistogram1D("Dcaee", s, pdg, other_daughter_pdg, dcaee, pairWeight); + fillHistogram2D("DcaeeVsPtee", s, pdg, other_daughter_pdg, dcaee, ptee, pairWeight); + fillHistogram2D("DcaeeVsMee", s, pdg, other_daughter_pdg, dcaee, mee, pairWeight); } } } - LOGP(error, "Could not open photon parametrization {}/{} from file {}", dirname.Data(), funcname.Data(), filename.Data()); - return; - } else { // neither ROOT nor JSON - LOGP(error, "Not compatible file format for {}", filename.Data()); - } + + } // end particle loop } + PROCESS_SWITCH(lmeelfcocktail, processCocktail, "Process cocktail", true); + + // ULS and LS spectra + Preslice perCollision = aod::mcparticle::mcCollisionId; + Partition Electrons = (aod::mcparticle::pdgCode == 11); + Partition Positrons = (aod::mcparticle::pdgCode == -11); - void fillKrollWada() + void processPairing(aod::McCollisions const& mcCollisions, McParticlesSmeared const& mcParticles) { - // Build Kroll-wada for virtual photon mass parametrization: - Double_t KWmass = 0.; - Int_t KWnbins = 10000; - Float_t KWmin = 2. * eMass; - Double_t KWbinwidth = (fConfigKWMax - KWmin) / (Double_t)KWnbins; - fhKW = new TH1F("fhKW", "fhKW", KWnbins, KWmin, fConfigKWMax); - for (Int_t ibin = 1; ibin <= KWnbins; ibin++) { - KWmass = KWmin + (Double_t)(ibin - 1) * KWbinwidth + KWbinwidth / 2.0; - fhKW->AddBinContent(ibin, 2. * (1. / 137.03599911) / 3. / 3.14159265359 / KWmass * sqrt(1. - 4. * eMass * eMass / KWmass / KWmass) * (1. + 2. * eMass * eMass / KWmass / KWmass)); + + for (auto const& mcCollision : mcCollisions) { + auto const electronsGrouped = Electrons->sliceBy(perCollision, mcCollision.globalIndex()); + auto const positronsGrouped = Positrons->sliceBy(perCollision, mcCollision.globalIndex()); + + // ULS spectrum + for (auto const& [p1, p2] : combinations(o2::soa::CombinationsFullIndexPolicy(electronsGrouped, positronsGrouped))) { + if (!(from_primary(p1, mcParticles) && from_primary(p2, mcParticles))) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1_gen(p1.pt(), p1.eta(), p1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2_gen(p2.pt(), p2.eta(), p2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12_gen = v1_gen + v2_gen; + registry.fill(HIST("gen/ULS"), v12_gen.M(), v12_gen.Pt(), p1.weight() * p2.weight()); + if (isAcceptedPair(p1, p2)) { + ROOT::Math::PtEtaPhiMVector v1(p1.ptSmeared(), p1.etaSmeared(), p1.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(p2.ptSmeared(), p2.etaSmeared(), p2.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + registry.fill(HIST("rec/ULS"), v12.M(), v12.Pt(), p1.weight() * p2.weight() * p1.efficiency() * p2.efficiency()); + } + } + // LS spectra + for (auto& [p1, p2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(electronsGrouped, electronsGrouped))) { + if (!(from_primary(p1, mcParticles) && from_primary(p2, mcParticles))) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1_gen(p1.pt(), p1.eta(), p1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2_gen(p2.pt(), p2.eta(), p2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12_gen = v1_gen + v2_gen; + registry.fill(HIST("gen/LSmm"), v12_gen.M(), v12_gen.Pt(), p1.weight() * p2.weight()); + if (isAcceptedPair(p1, p2)) { + ROOT::Math::PtEtaPhiMVector v1(p1.ptSmeared(), p1.etaSmeared(), p1.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(p2.ptSmeared(), p2.etaSmeared(), p2.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + registry.fill(HIST("rec/LSmm"), v12.M(), v12.Pt(), p1.weight() * p2.weight() * p1.efficiency() * p2.efficiency()); + } + } + for (auto& [p1, p2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(positronsGrouped, positronsGrouped))) { + if (!(from_primary(p1, mcParticles) && from_primary(p2, mcParticles))) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1_gen(p1.pt(), p1.eta(), p1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2_gen(p2.pt(), p2.eta(), p2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12_gen = v1_gen + v2_gen; + registry.fill(HIST("gen/LSpp"), v12_gen.M(), v12_gen.Pt(), p1.weight() * p2.weight()); + if (isAcceptedPair(p1, p2)) { + ROOT::Math::PtEtaPhiMVector v1(p1.ptSmeared(), p1.etaSmeared(), p1.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(p2.ptSmeared(), p2.etaSmeared(), p2.phiSmeared(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + registry.fill(HIST("rec/LSpp"), v12.M(), v12.Pt(), p1.weight() * p2.weight() * p1.efficiency() * p2.efficiency()); + } + } } } + PROCESS_SWITCH(lmeelfcocktail, processPairing, "Process ULS and LS pairing", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec specs; - std::vector inputs; - inputs.emplace_back("mctracks", "MC", "MCTRACKS", 0., Lifetime::Timeframe); - DataProcessorSpec dSpec = adaptAnalysisTask(cfgc, TaskName{"em-lmee-lf-cocktail"}); - dSpec.inputs = inputs; - specs.emplace_back(dSpec); - return specs; + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName("em-lmee-lf-cocktail"))}; } diff --git a/PWGEM/Dilepton/Tasks/singleElectronQC.cxx b/PWGEM/Dilepton/Tasks/singleElectronQC.cxx new file mode 100644 index 00000000000..4a687e82217 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/singleElectronQC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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. +// +// ======================== +// +// Analysis task for single electron QC +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/SingleTrackQC.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"single-electron-qc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx b/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx new file mode 100644 index 00000000000..da2617158ec --- /dev/null +++ b/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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. +// +// ======================== +// +// Analysis task for single electron QC in MC +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/SingleTrackQCMC.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"single-electron-qc-mc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/singleMuonQC.cxx b/PWGEM/Dilepton/Tasks/singleMuonQC.cxx new file mode 100644 index 00000000000..b9ccb722ea3 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/singleMuonQC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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. +// +// ======================== +// +// Analysis task for single muon QC +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/SingleTrackQC.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"single-muon-qc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx b/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx new file mode 100644 index 00000000000..7b7176238c1 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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. +// +// ======================== +// +// Analysis task for single muon QC in MC +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "PWGEM/Dilepton/Core/SingleTrackQCMC.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"single-muon-qc-mc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/smearing.cxx b/PWGEM/Dilepton/Tasks/smearing.cxx index 1c5eda15739..655cedac2e7 100644 --- a/PWGEM/Dilepton/Tasks/smearing.cxx +++ b/PWGEM/Dilepton/Tasks/smearing.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. // // -// Analysis task to produce smeared pt,eta,phi for electrons/muons in dilepton analysis +// Analysis task to produce smeared pt, eta, phi for electrons/muons in dilepton analysis // Please write to: daiki.sekihata@cern.ch #include @@ -22,8 +22,9 @@ #include "Framework/ASoA.h" #include "Framework/DataTypes.h" #include "Framework/HistogramRegistry.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" // remove this later, because 2 data tables (covariant matrix) in this header confilict against EM tables. #include "PWGEM/Dilepton/Utils/MomentumSmearer.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" using namespace o2; using namespace o2::framework; @@ -31,47 +32,125 @@ using namespace o2::framework::expressions; using namespace o2::aod; struct ApplySmearing { - Produces smearedtrack; - - // Run for electrons or muons (For the moment the task is not designed for both at the same time) - Configurable fPdgCode{"cfgPdgCode", 11, "Set the type of particle to be smeared"}; - // Maps - Configurable fConfigResFileName{"cfgResFileName", "", "name of resolution file"}; - Configurable fConfigResPtHistName{"cfgResPtHistName", "RelPtResArrCocktail", "histogram name for pt in resolution file"}; - Configurable fConfigResEtaHistName{"cfgResEtaHistName", "EtaResArr", "histogram name for eta in resolution file"}; - Configurable fConfigResPhiPosHistName{"cfgResPhiPosHistName", "PhiPosResArr", "histogram name for phi pos in resolution file"}; - Configurable fConfigResPhiNegHistName{"cfgResPhiNegHistName", "PhiEleResArr", "hisogram for phi neg in resolution file"}; - Configurable fConfigEffFileName{"cfgEffFileName", "", "name of efficiency file"}; - Configurable fConfigEffHistName{"cfgEffHistName", "fhwEffpT", "name of efficiency histogram"}; + Produces smearedelectron; + Produces smearedmuon; + Configurable fFromCcdb{"cfgFromCcdb", false, "get resolution and efficiency histos from CCDB"}; - Configurable fConfigCcdbPathRes{"cfgCcdbPathRes", "", "path to the ccdb object for resolution"}; - Configurable fConfigCcdbPathEff{"cfgCcdbPahtEff", "", "path to the ccdb object for efficiency"}; Configurable fConfigCcdbUrl{"cfgCcdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbNoLaterThan{"cfgCcdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable fTimestamp{"cfgCcdbTimestamp", 10, "valid timestamp of CCDB object"}; + + struct : ConfigurableGroup { + std::string prefix = "electron_filename_group"; + Configurable fConfigResFileName{"cfgResFileName", "", "name of resolution file"}; + Configurable fConfigResPtHistName{"cfgResPtHistName", "RelPtResArrCocktail", "histogram name for pt in resolution file"}; + Configurable fConfigResEtaHistName{"cfgResEtaHistName", "EtaResArr", "histogram name for eta in resolution file"}; + Configurable fConfigResPhiPosHistName{"cfgResPhiPosHistName", "PhiPosResArr", "histogram name for phi pos in resolution file"}; + Configurable fConfigResPhiNegHistName{"cfgResPhiNegHistName", "PhiEleResArr", "hisogram for phi neg in resolution file"}; + Configurable fConfigEffFileName{"cfgEffFileName", "", "name of efficiency file"}; + Configurable fConfigEffHistName{"cfgEffHistName", "fhwEffpT", "name of efficiency histogram"}; + Configurable fConfigDCAFileName{"cfgDCAFileName", "", "name of DCA template file"}; + Configurable fConfigDCAHistName{"cfgDCAHistName", "fh_DCAtempaltes", "histogram name of the DCA templates"}; + Configurable fConfigCcdbPathRes{"cfgCcdbPathRes", "", "path to the ccdb object for resolution"}; + Configurable fConfigCcdbPathEff{"cfgCcdbPahtEff", "", "path to the ccdb object for efficiency"}; + Configurable fConfigCcdbPathDCA{"cfgCcdbPahtDCA", "", "path to the ccdb object for dca"}; + } electron_filenames; + + struct : ConfigurableGroup { + std::string prefix = "sa_muon_filename_group"; + Configurable fConfigResFileName{"cfgResFileName", "", "name of resolution file"}; + Configurable fConfigResPtHistName{"cfgResPtHistName", "RelPtResArrCocktail", "histogram name for pt in resolution file"}; + Configurable fConfigResEtaHistName{"cfgResEtaHistName", "EtaResArr", "histogram name for eta in resolution file"}; + Configurable fConfigResPhiPosHistName{"cfgResPhiPosHistName", "PhiPosResArr", "histogram name for phi pos in resolution file"}; + Configurable fConfigResPhiNegHistName{"cfgResPhiNegHistName", "PhiEleResArr", "hisogram for phi neg in resolution file"}; + Configurable fConfigEffFileName{"cfgEffFileName", "", "name of efficiency file"}; + Configurable fConfigEffHistName{"cfgEffHistName", "fhwEffpT", "name of efficiency histogram"}; + Configurable fConfigDCAFileName{"cfgDCAFileName", "", "name of DCA template file"}; + Configurable fConfigDCAHistName{"cfgDCAHistName", "fh_DCAtempaltes", "histogram name of the DCA templates"}; + Configurable fConfigCcdbPathRes{"cfgCcdbPathRes", "", "path to the ccdb object for resolution"}; + Configurable fConfigCcdbPathEff{"cfgCcdbPahtEff", "", "path to the ccdb object for efficiency"}; + Configurable fConfigCcdbPathDCA{"cfgCcdbPahtDCA", "", "path to the ccdb object for dca"}; + } sa_muon_filenames; + + struct : ConfigurableGroup { + std::string prefix = "gl_muon_filename_group"; + Configurable fConfigResFileName{"cfgResFileName", "", "name of resolution file"}; + Configurable fConfigResPtHistName{"cfgResPtHistName", "RelPtResArrCocktail", "histogram name for pt in resolution file"}; + Configurable fConfigResEtaHistName{"cfgResEtaHistName", "EtaResArr", "histogram name for eta in resolution file"}; + Configurable fConfigResPhiPosHistName{"cfgResPhiPosHistName", "PhiPosResArr", "histogram name for phi pos in resolution file"}; + Configurable fConfigResPhiNegHistName{"cfgResPhiNegHistName", "PhiEleResArr", "hisogram for phi neg in resolution file"}; + Configurable fConfigEffFileName{"cfgEffFileName", "", "name of efficiency file"}; + Configurable fConfigEffHistName{"cfgEffHistName", "fhwEffpT", "name of efficiency histogram"}; + Configurable fConfigDCAFileName{"cfgDCAFileName", "", "name of DCA template file"}; + Configurable fConfigDCAHistName{"cfgDCAHistName", "fh_DCAtempaltes", "histogram name of the DCA templates"}; + Configurable fConfigCcdbPathRes{"cfgCcdbPathRes", "", "path to the ccdb object for resolution"}; + Configurable fConfigCcdbPathEff{"cfgCcdbPahtEff", "", "path to the ccdb object for efficiency"}; + Configurable fConfigCcdbPathDCA{"cfgCcdbPahtDCA", "", "path to the ccdb object for dca"}; + } gl_muon_filenames; - MomentumSmearer smearer; + MomentumSmearer smearer_Electron; + MomentumSmearer smearer_StandaloneMuon; + MomentumSmearer smearer_GlobalMuon; Service ccdb; void init(InitContext&) { - smearer.setResFileName(TString(fConfigResFileName)); - smearer.setResPtHistName(TString(fConfigResPtHistName)); - smearer.setResEtaHistName(TString(fConfigResEtaHistName)); - smearer.setResPhiPosHistName(TString(fConfigResPhiPosHistName)); - smearer.setResPhiNegHistName(TString(fConfigResPhiNegHistName)); - smearer.setEffFileName(TString(fConfigEffFileName)); - smearer.setEffHistName(TString(fConfigEffHistName)); + smearer_Electron.setResFileName(TString(electron_filenames.fConfigResFileName)); + smearer_Electron.setResPtHistName(TString(electron_filenames.fConfigResPtHistName)); + smearer_Electron.setResEtaHistName(TString(electron_filenames.fConfigResEtaHistName)); + smearer_Electron.setResPhiPosHistName(TString(electron_filenames.fConfigResPhiPosHistName)); + smearer_Electron.setResPhiNegHistName(TString(electron_filenames.fConfigResPhiNegHistName)); + smearer_Electron.setEffFileName(TString(electron_filenames.fConfigEffFileName)); + smearer_Electron.setEffHistName(TString(electron_filenames.fConfigEffHistName)); + smearer_Electron.setDCAFileName(TString(electron_filenames.fConfigDCAFileName)); + smearer_Electron.setDCAHistName(TString(electron_filenames.fConfigDCAHistName)); + + smearer_StandaloneMuon.setResFileName(TString(sa_muon_filenames.fConfigResFileName)); + smearer_StandaloneMuon.setResPtHistName(TString(sa_muon_filenames.fConfigResPtHistName)); + smearer_StandaloneMuon.setResEtaHistName(TString(sa_muon_filenames.fConfigResEtaHistName)); + smearer_StandaloneMuon.setResPhiPosHistName(TString(sa_muon_filenames.fConfigResPhiPosHistName)); + smearer_StandaloneMuon.setResPhiNegHistName(TString(sa_muon_filenames.fConfigResPhiNegHistName)); + smearer_StandaloneMuon.setEffFileName(TString(sa_muon_filenames.fConfigEffFileName)); + smearer_StandaloneMuon.setEffHistName(TString(sa_muon_filenames.fConfigEffHistName)); + smearer_StandaloneMuon.setDCAFileName(TString(sa_muon_filenames.fConfigDCAFileName)); + smearer_StandaloneMuon.setDCAHistName(TString(sa_muon_filenames.fConfigDCAHistName)); + + smearer_GlobalMuon.setResFileName(TString(gl_muon_filenames.fConfigResFileName)); + smearer_GlobalMuon.setResPtHistName(TString(gl_muon_filenames.fConfigResPtHistName)); + smearer_GlobalMuon.setResEtaHistName(TString(gl_muon_filenames.fConfigResEtaHistName)); + smearer_GlobalMuon.setResPhiPosHistName(TString(gl_muon_filenames.fConfigResPhiPosHistName)); + smearer_GlobalMuon.setResPhiNegHistName(TString(gl_muon_filenames.fConfigResPhiNegHistName)); + smearer_GlobalMuon.setEffFileName(TString(gl_muon_filenames.fConfigEffFileName)); + smearer_GlobalMuon.setEffHistName(TString(gl_muon_filenames.fConfigEffHistName)); + smearer_GlobalMuon.setDCAFileName(TString(gl_muon_filenames.fConfigDCAFileName)); + smearer_GlobalMuon.setDCAHistName(TString(gl_muon_filenames.fConfigDCAHistName)); + if (fFromCcdb) { ccdb->setURL(fConfigCcdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - ccdb->setCreatedNotAfter(fConfigCcdbNoLaterThan); - smearer.setCcdbPathRes(TString(fConfigCcdbPathRes)); - smearer.setCcdbPathEff(TString(fConfigCcdbPathEff)); - smearer.setTimestamp(fConfigCcdbNoLaterThan); - smearer.setCcdb(ccdb); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); // now + + smearer_Electron.setCcdbPathRes(TString(electron_filenames.fConfigCcdbPathRes)); + smearer_Electron.setCcdbPathEff(TString(electron_filenames.fConfigCcdbPathEff)); + smearer_Electron.setCcdbPathDCA(TString(electron_filenames.fConfigCcdbPathDCA)); + smearer_Electron.setTimestamp(fTimestamp); + smearer_Electron.setCcdb(ccdb); + + smearer_StandaloneMuon.setCcdbPathRes(TString(sa_muon_filenames.fConfigCcdbPathRes)); + smearer_StandaloneMuon.setCcdbPathEff(TString(sa_muon_filenames.fConfigCcdbPathEff)); + smearer_StandaloneMuon.setCcdbPathDCA(TString(sa_muon_filenames.fConfigCcdbPathDCA)); + smearer_StandaloneMuon.setTimestamp(fTimestamp); + smearer_StandaloneMuon.setCcdb(ccdb); + + smearer_GlobalMuon.setCcdbPathRes(TString(gl_muon_filenames.fConfigCcdbPathRes)); + smearer_GlobalMuon.setCcdbPathEff(TString(gl_muon_filenames.fConfigCcdbPathEff)); + smearer_GlobalMuon.setCcdbPathDCA(TString(gl_muon_filenames.fConfigCcdbPathDCA)); + smearer_GlobalMuon.setTimestamp(fTimestamp); + smearer_GlobalMuon.setCcdb(ccdb); } - smearer.init(); + smearer_Electron.init(); + smearer_StandaloneMuon.init(); + smearer_GlobalMuon.init(); } template @@ -82,27 +161,57 @@ struct ApplySmearing { float etagen = mctrack.eta(); float phigen = mctrack.phi(); float efficiency = 1.; + float dca = 0.; int pdgCode = mctrack.pdgCode(); - if (abs(pdgCode) == fPdgCode) { + if (abs(pdgCode) == 11) { int ch = -1; if (pdgCode < 0) { ch = 1; } // apply smearing for electrons or muons. float ptsmeared, etasmeared, phismeared; - smearer.applySmearing(ch, ptgen, etagen, phigen, ptsmeared, etasmeared, phismeared); + smearer_Electron.applySmearing(ch, ptgen, etagen, phigen, ptsmeared, etasmeared, phismeared); // get the efficiency - efficiency = smearer.getEfficiency(ptgen, etagen, phigen); - smearedtrack(ptsmeared, etasmeared, phismeared, efficiency); + efficiency = smearer_Electron.getEfficiency(ptgen, etagen, phigen); + // get DCA + dca = smearer_Electron.getDCA(ptsmeared); + // fill the table + smearedelectron(ptsmeared, etasmeared, phismeared, efficiency, dca); + smearedmuon(ptgen, etagen, phigen, 1.f, 0.f, ptgen, etagen, phigen, 1.f, 0.f); + } else if (abs(pdgCode) == 13) { + int ch = -1; + if (pdgCode < 0) { + ch = 1; + } + // apply smearing for muons based on resolution map of standalone muons + float ptsmeared_sa = 0.f, etasmeared_sa = 0.f, phismeared_sa = 0.f, efficiency_sa = 1.f, dca_sa = 0.f; + smearer_StandaloneMuon.applySmearing(ch, ptgen, etagen, phigen, ptsmeared_sa, etasmeared_sa, phismeared_sa); + efficiency_sa = smearer_StandaloneMuon.getEfficiency(ptgen, etagen, phigen); + dca_sa = smearer_StandaloneMuon.getDCA(ptsmeared_sa); + + float ptsmeared_gl = 0.f, etasmeared_gl = 0.f, phismeared_gl = 0.f, efficiency_gl = 1.f, dca_gl = 0.f; + // apply smearing for muons based on resolution map of global muons + smearer_GlobalMuon.applySmearing(ch, ptgen, etagen, phigen, ptsmeared_gl, etasmeared_gl, phismeared_gl); + efficiency_gl = smearer_GlobalMuon.getEfficiency(ptgen, etagen, phigen); + dca_gl = smearer_GlobalMuon.getDCA(ptsmeared_gl); + smearedmuon(ptsmeared_sa, etasmeared_sa, phismeared_sa, efficiency_sa, dca_sa, ptsmeared_gl, etasmeared_gl, phismeared_gl, efficiency_gl, dca_gl); + + smearedelectron(ptgen, etagen, phigen, 1.f, 0.f); } else { // don't apply smearing - smearedtrack(ptgen, etagen, phigen, efficiency); + smearedelectron(ptgen, etagen, phigen, efficiency, dca); + smearedmuon(ptgen, etagen, phigen, efficiency, dca, ptgen, etagen, phigen, efficiency, dca); } } } - void processMCanalysis(ReducedMCTracks const& tracksMC) + void processMCanalysisEM(aod::EMMCParticles const& tracksMC) + { + applySmearing(tracksMC); + } + + void processMCanalysisDQ(ReducedMCTracks const& tracksMC) { applySmearing(tracksMC); } @@ -116,15 +225,17 @@ struct ApplySmearing { void processDummyMCanalysis(ReducedMCTracks const&) {} - PROCESS_SWITCH(ApplySmearing, processMCanalysis, "Run for MC analysis", false); + PROCESS_SWITCH(ApplySmearing, processMCanalysisEM, "Run for MC analysis which uses skimmed EM data format", false); + PROCESS_SWITCH(ApplySmearing, processMCanalysisDQ, "Run for MC analysis which uses skimmed DQ data format", false); PROCESS_SWITCH(ApplySmearing, processCocktail, "Run for cocktail analysis", false); PROCESS_SWITCH(ApplySmearing, processDummyMCanalysis, "Dummy process function", false); PROCESS_SWITCH(ApplySmearing, processDummyCocktail, "Dummy process function", true); }; struct CheckSmearing { - using MyReducedTracks = soa::Join; - using MyCocktailTracks = soa::Join; + using EMMCParticlesWithSmearing = soa::Join; // this is only for electrons + using MyReducedTracks = soa::Join; // this is only for electrons + using MyCocktailTracks = soa::Join; // this is only for electrons // Run for electrons or muons Configurable fPdgCode{"cfgPdgCode", 11, "Set the type of particle to be checked"}; @@ -137,30 +248,30 @@ struct CheckSmearing { ConfigurableAxis deltaetaResBins{"deltaetaResBins", {500, -0.5f, 0.5f}, "DeltaEta binning for resolution"}; ConfigurableAxis deltaphiResBins{"deltaphiResBins", {500, -0.5f, 0.5f}, "DeltaPhi binning for resolution"}; - HistogramRegistry registry{"HistoAnalysisTrackSelection", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry{"output", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { - registry.add("hCorrelation_Pt", "pT correlation", {HistType::kTH2F, {{1000, 0.0f, 10.0f}, {1000, 0.0f, 10.0f}}}); - registry.add("hCorrelation_Eta", "eta correlation", {HistType::kTH2F, {{200, -1.0f, +1.0f}, {200, -1.0f, +1.0f}}}); - registry.add("hCorrelation_Phi", "phi correlation", {HistType::kTH2F, {{100, 0.0f, TMath::TwoPi()}, {100, 0.0f, TMath::TwoPi()}}}); + registry.add("hCorrelation_Pt", "pT correlation;p_{T,l}^{gen} (GeV/c);p_{T,l}^{smeared} (GeV/c)", {HistType::kTH2F, {{1000, 0.0f, 10.0f}, {1000, 0.0f, 10.0f}}}); + registry.add("hCorrelation_Eta", "eta correlation;#eta_{l}^{gen};#eta_{l}^{smeared}", {HistType::kTH2F, {{200, -1.0f, +1.0f}, {200, -1.0f, +1.0f}}}); + registry.add("hCorrelation_Phi", "phi correlation;#varphi_{l}^{gen} (rad.);#varphi_{l}^{smeared} (rad.)", {HistType::kTH2F, {{100, 0.0f, TMath::TwoPi()}, {100, 0.0f, TMath::TwoPi()}}}); // Binning for resolution - AxisSpec axisPtRes{ptResBins, "#it{p}^{gen}_{T,e} (GeV/#it{c})"}; + AxisSpec axisPtRes{ptResBins, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}; AxisSpec axisDeltaptRes{deltaptResBins, "(p^{gen}_{T} - p^{rec}_{T}) / p^{gen}_{T}"}; AxisSpec axisDeltaetaRes{deltaetaResBins, "#eta^{gen} - #eta^{rec}"}; - AxisSpec axisDeltaphiRes{deltaphiResBins, "#varphi^{gen} - #varphi^{rec} (rad)"}; + AxisSpec axisDeltaphiRes{deltaphiResBins, "#varphi^{gen} - #varphi^{rec} (rad.)"}; if (!fConfigUsePtVecRes) { registry.add("PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {axisPtRes, axisDeltaptRes}, true); registry.add("PtGen_DeltaEta", "", HistType::kTH2D, {axisPtRes, axisDeltaetaRes}, true); - registry.add("PtGen_DeltaPhi_Ele", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); + registry.add("PtGen_DeltaPhi_Neg", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); registry.add("PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); } else { - registry.add("PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,e} (GeV/#it{c})"}, axisDeltaptRes}, true); - registry.add("PtGen_DeltaEta", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,e} (GeV/#it{c})"}, axisDeltaetaRes}, true); - registry.add("PtGen_DeltaPhi_Ele", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,e} (GeV/#it{c})"}, axisDeltaphiRes}, true); - registry.add("PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,e} (GeV/#it{c})"}, axisDeltaphiRes}, true); + registry.add("PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaptRes}, true); + registry.add("PtGen_DeltaEta", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaetaRes}, true); + registry.add("PtGen_DeltaPhi_Neg", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaphiRes}, true); + registry.add("PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaphiRes}, true); } } @@ -180,7 +291,7 @@ struct CheckSmearing { registry.fill(HIST("PtGen_DeltaPtOverPtGen"), mctrack.pt(), deltaptoverpt); registry.fill(HIST("PtGen_DeltaEta"), mctrack.pt(), deltaeta); if (mctrack.pdgCode() < 0) { - registry.fill(HIST("PtGen_DeltaPhi_Ele"), mctrack.pt(), deltaphi); + registry.fill(HIST("PtGen_DeltaPhi_Neg"), mctrack.pt(), deltaphi); } else { registry.fill(HIST("PtGen_DeltaPhi_Pos"), mctrack.pt(), deltaphi); } @@ -190,7 +301,12 @@ struct CheckSmearing { } // end of mctrack loop } - void processCheckMCanalysis(MyReducedTracks const& tracksMC) + void processCheckMCanalysisEM(EMMCParticlesWithSmearing const& tracksMC) + { + Check(tracksMC); + } + + void processCheckMCanalysisDQ(MyReducedTracks const& tracksMC) { Check(tracksMC); } @@ -200,12 +316,15 @@ struct CheckSmearing { Check(tracksMC); } - void processDummyMCanalysis(ReducedMCTracks const&) {} + void processDummyMCanalysisEM(aod::EMMCParticles const&) {} + void processDummyMCanalysisDQ(ReducedMCTracks const&) {} void processDummyCocktail(aod::McParticles const&) {} - PROCESS_SWITCH(CheckSmearing, processCheckMCanalysis, "Run for MC analysis", false); + PROCESS_SWITCH(CheckSmearing, processCheckMCanalysisEM, "Run for MC analysis", false); + PROCESS_SWITCH(CheckSmearing, processCheckMCanalysisDQ, "Run for MC analysis", false); PROCESS_SWITCH(CheckSmearing, processCheckCocktail, "Run for cocktail analysis", false); - PROCESS_SWITCH(CheckSmearing, processDummyMCanalysis, "Dummy process function", false); + PROCESS_SWITCH(CheckSmearing, processDummyMCanalysisEM, "Dummy process function", false); + PROCESS_SWITCH(CheckSmearing, processDummyMCanalysisDQ, "Dummy process function", false); PROCESS_SWITCH(CheckSmearing, processDummyCocktail, "Dummy process function", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx b/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx new file mode 100644 index 00000000000..227e070baca --- /dev/null +++ b/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx @@ -0,0 +1,1264 @@ +// Copyright 2019-2020 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. +// +// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +// +#include +#include +#include +#include +#include +#include +#include +#include +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/MixingHandler.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/MixingLibrary.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "Field/MagneticField.h" +#include "TGeoGlobalMagField.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "ITSMFTBase/DPLAlpideParam.h" +#include "Common/CCDB/EventSelectionParams.h" + +using std::cout; +using std::endl; +using std::string; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +// Some definitions +namespace o2::aod +{ + +namespace dqanalysisflags +{ +// TODO: the barrel amd muon selection columns are bit maps so unsigned types should be used, however, for now this is not supported in Filter expressions +// TODO: For now in the tasks we just statically convert from unsigned int to int, which should be fine as long as we do +// not use a large number of bits (>=30) +// Bcandidate columns for ML analysis of B->Jpsi+K +DECLARE_SOA_COLUMN(MixingHash, mixingHash, int); +DECLARE_SOA_COLUMN(IsEventSelected, isEventSelected, int); +DECLARE_SOA_COLUMN(IsBarrelSelected, isBarrelSelected, int); +DECLARE_SOA_COLUMN(IsBarrelSelectedPrefilter, isBarrelSelectedPrefilter, int); +DECLARE_SOA_COLUMN(IsPrefilterVetoed, isPrefilterVetoed, int); +} // namespace dqanalysisflags + +DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); +DECLARE_SOA_TABLE(MixingHashes, "AOD", "DQANAMIXHASH", dqanalysisflags::MixingHash); +DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected, dqanalysisflags::IsBarrelSelectedPrefilter); +DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsPrefilterVetoed); +} // namespace o2::aod + +// Declarations of various short names +using MyEvents = soa::Join; +using MyEventsSelected = soa::Join; +using MyEventsHashSelected = soa::Join; +using MyEventsVtxCov = soa::Join; +using MyEventsVtxCovSelected = soa::Join; +using MyEventsVtxCovSelectedQvector = soa::Join; +// using MyEventsVtxCovSelectedQvectorCentr = soa::Join; +using MyEventsQvector = soa::Join; +using MyEventsQvectorMultExtra = soa::Join; +using MyEventsQvectorCentr = soa::Join; +using MyEventsQvectorCentrMultExtra = soa::Join; +using MyEventsHashSelectedQvector = soa::Join; +// using MyEventsHashSelectedQvectorCentr = soa::Join; + +using MyBarrelTracks = soa::Join; +using MyBarrelTracksWithCov = soa::Join; +using MyBarrelTracksSelected = soa::Join; +using MyBarrelTracksSelectedWithPrefilter = soa::Join; +using MyBarrelTracksSelectedWithCov = soa::Join; +using MyBarrelTracksSelectedWithColl = soa::Join; + +// bit maps used for the Fill functions of the VarManager +constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; +constexpr static uint32_t gkEventFillMapWithCov = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov; +constexpr static uint32_t gkEventFillMapWithQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventQvector; +constexpr static uint32_t gkEventFillMapWithQvectorMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventQvector | VarManager::ObjTypes::ReducedEventMultExtra; +constexpr static uint32_t gkEventFillMapWithQvectorCentr = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::CollisionQvect; +constexpr static uint32_t gkEventFillMapWithQvectorCentrMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::CollisionQvect | VarManager::ObjTypes::ReducedEventMultExtra; +constexpr static uint32_t gkEventFillMapWithCovQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector; +// constexpr static uint32_t gkEventFillMapWithCovQvectorCentr = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::CollisionQvect; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t gkTrackFillMapWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; + +constexpr static int pairTypeEE = VarManager::kDecayToEE; + +// Global function used to define needed histogram classes +void DefineHistograms(HistogramManager* histMan, TString histClasses, Configurable configVar); // defines histograms for all tasks + +struct AnalysisEventSelection { + Produces eventSel; + Produces hash; + OutputObj fOutputList{"output"}; + // TODO: Provide the mixing variables and binning directly via configurables (e.g. vectors of float) + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; + Configurable fConfigITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + AnalysisCompositeCut* fEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgCentFT0CMin{"cfgCentralityMin", -1000000000.f, "min. centrality"}; + Configurable cfgCentFT0CMax{"cfgCentralityMax", 1000000000.f, "max. centrality"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1000000000, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + } eventcuts; + + HistogramManager* fHistMan = nullptr; + MixingHandler* fMixHandler = nullptr; + int fLastRun; + + Service fCCDB; + + void init(o2::framework::InitContext&) + { + fEventCut = new AnalysisCompositeCut(true); + fEventCut->AddCut(GetEventCut()); + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + + VarManager::SetDefaultVarNames(); + if (fConfigQA) { + fHistMan = new HistogramManager("analysisHistos", "", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;", fConfigAddEventHistogram); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + TString mixVarsString = fConfigMixingVariables.value; + std::unique_ptr objArray(mixVarsString.Tokenize(",")); + if (objArray->GetEntries() > 0) { + fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); + fMixHandler->Init(); + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + + // CCDB configuration + fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + // Not later than now objects + // fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + + fLastRun = -1; + } + + template + void runEventSelection(TEvent const& event) + { + if (event.runNumber() != fLastRun) { + auto alppar = fCCDB->getForTimeStamp>("ITS/Config/AlpideParam", event.timestamp()); + EventSelectionParams* par = fCCDB->getForTimeStamp("EventSelection/EventSelectionParams", event.timestamp()); + int itsROFrameStartBorderMargin = fConfigITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : fConfigITSROFrameStartBorderMargin; + int itsROFrameEndBorderMargin = fConfigITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : fConfigITSROFrameEndBorderMargin; + VarManager::SetITSROFBorderselection(alppar->roFrameBiasInBC, alppar->roFrameLengthInBC, itsROFrameStartBorderMargin, itsROFrameEndBorderMargin); + fLastRun = event.runNumber(); + } + + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + + VarManager::FillEvent(event); + // TODO: make this condition at compile time + if (fConfigQA) { + fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event + } + if (fEventCut->IsSelected(VarManager::fgValues)) { + if (fConfigQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + } + eventSel(1); + } else { + eventSel(0); + } + + if (fMixHandler != nullptr) { + int hh = fMixHandler->FindEventCategory(VarManager::fgValues); + hash(hh); + } + } + + AnalysisCut* GetEventCut() + { + AnalysisCut* cut = new AnalysisCut("eventcut", "eventcut"); + cut->AddCut(VarManager::kVtxZ, -eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + if (eventcuts.cfgRequireSel8) + cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + if (eventcuts.cfgRequireNoTFB) + cut->AddCut(VarManager::kIsNoTFBorder, 0.5, 1.5); + if (eventcuts.cfgRequireNoITSROFB) + cut->AddCut(VarManager::kIsNoITSROFBorder, 0.5, 1.5); + if (eventcuts.cfgRequireNoSameBunchPileup) + cut->AddCut(VarManager::kIsNoSameBunch, 0.5, 1.5); + if (eventcuts.cfgRequireGoodZvtxFT0vsPV) + cut->AddCut(VarManager::kIsGoodZvtxFT0vsPV, 0.5, 1.5); + cut->AddCut(VarManager::kCentFT0C, eventcuts.cfgCentFT0CMin, eventcuts.cfgCentFT0CMax); + cut->AddCut(VarManager::kTrackOccupancyInTimeRange, eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + return cut; + } + + void processSkimmed(MyEvents::iterator const& event) + { + runEventSelection(event); + } + void processSkimmedQVector(MyEventsQvector::iterator const& event) + { + runEventSelection(event); + } + void processSkimmedQVectorCentr(MyEventsQvectorCentr::iterator const& event) + { + runEventSelection(event); + } + void processSkimmedQVectorMultExtra(MyEventsQvectorMultExtra::iterator const& event) + { + runEventSelection(event); + } + void processSkimmedQVectorCentrMultExtra(MyEventsQvectorCentrMultExtra::iterator const& event) + { + runEventSelection(event); + } + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisEventSelection, processSkimmed, "Run event selection on DQ skimmed events", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedQVector, "Run event selection on DQ skimmed events with Q vector from GFW", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedQVectorCentr, "Run event selection on DQ skimmed events with Q vector from CFW", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedQVectorMultExtra, "Run event selection on DQ skimmed events with Q vector from GFW and MultPV", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedQVectorCentrMultExtra, "Run event selection on DQ skimmed events with Q vector from CFW and MultPV", false); + PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", false); + // TODO: Add process functions subscribing to Framework Collision +}; + +struct AnalysisTrackSelection { + Produces trackSel; + OutputObj fOutputList{"output"}; + // The list of cuts should contain all the track cuts needed later in analysis, including + // for candidate electron selection (+ eventual prefilter cuts) and other needs like quarkonium - hadron correlations + // The user must ensure using them properly in the tasks downstream + // NOTE: For now, the candidate electron cuts must be provided first, then followed by any other needed selections + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigQAIfSelEvt{"cfgQAIfSelEvt", true, "If true, fill QA only for selected events"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigPrefilterCutId{"cfgPrefilterCutId", 32, "Id of the Prefilter track cut (starting at 0)"}; // In order to create another column prefilter (should be temporary before improving cut selection in configurables, then displaced to AnalysisPrefilterSelection) + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; + Configurable fConfigRunPeriods{"cfgRunPeriods", "LHC22f", "run periods for used data"}; + Configurable fConfigDummyRunlist{"cfgDummyRunlist", false, "If true, use dummy runlist"}; + Configurable fConfigInitRunNumber{"cfgInitRunNumber", 543215, "Initial run number used in run by run checks"}; + Configurable fConfigNbTrackCut{"cfgNbTrackCut", 1, "Number of cuts including prefilter cut, need to be below 30"}; + + std::vector fTrackCuts; + struct : ConfigurableGroup { + std::string prefix = "trackingcut_group"; + Configurable> cfgEtaMax{"cfgEtaMax", {0.8f}, "Comma separated list of eta ranges"}; + Configurable> cfgPtMin{"cfgPtMin", {0.2f}, "Comma separated list of pt min"}; + Configurable> cfgPtMax{"cfgPtMax", {20.f}, "Comma separated list of pt max"}; + Configurable> cfgDCAxyMax{"cfgDCAxyMax", {3.f}, "Comma separated list of dcaxy max"}; + Configurable> cfgDCAzMax{"cfgDCAzMax", {1.f}, "Comma separated list of dcaz max"}; + Configurable> cfgIsSPDfirst{"cfgIsSPDfirst", {1}, "Comma separated list of if one requires one hit in the first ITS layer"}; + Configurable> cfgIsSPDany{"cfgIsSPDany", {-1}, "Comma separated list of if one requires one hit in the first two ITS layers"}; + Configurable> cfgIsITSibAny{"cfgIsITSibAny", {-1}, "Comma separated list of if one requires one hit in the first three ITS layers"}; + Configurable> cfgITSchi2Max{"cfgITSchi2Max", {5.f}, "Comma separated list of its chi2 max"}; + Configurable> cfgITSnclsMin{"cfgITSnclsMin", {4.5f}, "Comma separated list of min number of ITS clusters"}; + Configurable> cfgITSnclsMax{"cfgITSnclsMax", {7.5f}, "Comma separated list of max number of ITS clusters"}; + Configurable> cfgTPCchi2Max{"cfgTPCchi2Max", {4.f}, "Comma separated list of tpc chi2 max"}; + Configurable> cfgTPCnclsMin{"cfgTPCnclsMin", {90.f}, "Comma separated list of min number of TPC clusters"}; + Configurable> cfgTPCnclsMax{"cfgTPCnclsMax", {170.f}, "Comma separated list of max number of TPC clusters"}; + Configurable> cfgTPCnclsCRMin{"cfgTPCnclsCRMin", {80.f}, "Comma separated list of min number of TPC crossed rows"}; + Configurable> cfgTPCnclsCRMax{"cfgTPCnclsCRMax", {170.f}, "Comma separated list of max number of TPC crossed rows"}; + Configurable> cfgIsDalitzLeg{"cfgIsDalitzLeg", {-1}, "Comma separated list of if one requires hit for prefilter done during skimming, should be between 1 and 8"}; + } trackcuts; + + struct : ConfigurableGroup { + std::string prefix = "pidcut_group"; + Configurable> cfgPIDmode{"cfgPIDmode", {1}, "List of PID mode: 1 TPChadrrejection, 2 TOFreq, 3 OR between both"}; + Configurable> cfgRejBadTOF{"cfgRejBadTOF", {1}, "List of reject bad TOF: 1 yes, 0 no"}; + Configurable> cfgTPCNSigmaElMin{"cfgTPCNSigmaElMin", {-1.f}, "Comma separated list of min TPC nsigma e for inclusion"}; + Configurable> cfgTPCNSigmaElMax{"cfgTPCNSigmaElMax", {3.f}, "Comma separated list of max TPC nsigma e for inclusion"}; + Configurable> cfgTPCNSigmaPiMin{"cfgTPCNSigmaPiMin", {-3.f}, "Comma separated list of min TPC nsigma pion for exclusion"}; + Configurable> cfgTPCNSigmaPiMax{"cfgTPCNSigmaPiMax", {4.f}, "Comma separated list of max TPC nsigma pion for exclusion"}; + Configurable> cfgTPCNSigmaPrMin{"cfgTPCNSigmaPrMin", {-3.f}, "Comma separated list of min TPC nsigma proton for exclusion"}; + Configurable> cfgTPCNSigmaPrMax{"cfgTPCNSigmaPrMax", {4.f}, "Comma separated list of max TPC nsigma proton for exclusion"}; + Configurable> cfgTPCNSigmaKaMin{"cfgTPCNSigmaKaMin", {-3.f}, "Comma separated list of min TPC nsigma kaon for exclusion"}; + Configurable> cfgTPCNSigmaKaMax{"cfgTPCNSigmaKaMax", {4.f}, "Comma separated list of max TPC nsigma kaon for exclusion"}; + Configurable> cfgTPCNSigmaMuMin{"cfgTPCNSigmaMuMin", {0.f}, "Comma separated list of min TPC nsigma muon for exclusion"}; + Configurable> cfgTPCNSigmaMuMax{"cfgTPCNSigmaMuMax", {0.f}, "Comma separated list of max TPC nsigma muon for exclusion"}; + Configurable> cfgTOFNSigmaElMin{"cfgTOFNSigmaElMin", {-3.f}, "Comma separated list of min TOF nsigma e for inclusion"}; + Configurable> cfgTOFNSigmaElMax{"cfgTOFNSigmaElMax", {2.f}, "Comma separated list of max TOF nsigma e for inclusion"}; + } pidcuts; + + Service fCCDB; + + HistogramManager* fHistMan; + + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + + void init(o2::framework::InitContext&) + { + fCurrentRun = 0; + + int nbofcuts = fConfigNbTrackCut; + if (nbofcuts > 0 && CheckSize()) { + for (unsigned int icut = 0; icut < nbofcuts; ++icut) { + AnalysisCompositeCut* cut = new AnalysisCompositeCut(Form("trackcut%d", icut), Form("trackcut%d", icut)); + cut->AddCut(GetTrackCut(icut)); + cut->AddCut(GetPIDCut(icut)); + fTrackCuts.push_back(*cut); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + + if (fConfigQA) { + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // set one histogram directory for each defined track cut + TString histDirNames = "TrackBarrel_BeforeCuts;"; + for (auto& cut : fTrackCuts) { + histDirNames += Form("TrackBarrel_%s;", cut.GetName()); + } + + DefineHistograms(fHistMan, histDirNames.Data(), fConfigAddTrackHistogram); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + if (fConfigDummyRunlist) { + VarManager::SetDummyRunlist(fConfigInitRunNumber); + } + if (fConfigComputeTPCpostCalib) { + // CCDB configuration + fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + // Not later than now objects + fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + } + } + + bool CheckSize() + { + auto veceta = (std::vector)trackcuts.cfgEtaMax; + auto vecptmin = (std::vector)trackcuts.cfgPtMin; + auto vecptmax = (std::vector)trackcuts.cfgPtMax; + auto vecDCAxymax = (std::vector)trackcuts.cfgDCAxyMax; + auto vecDCAzmax = (std::vector)trackcuts.cfgDCAzMax; + auto vecIsSPDfirst = (std::vector)trackcuts.cfgIsSPDfirst; + auto vecIsSPDany = (std::vector)trackcuts.cfgIsSPDany; + auto vecIsITSibAny = (std::vector)trackcuts.cfgIsITSibAny; + auto vecITSchi2max = (std::vector)trackcuts.cfgITSchi2Max; + auto vecITSnclsmin = (std::vector)trackcuts.cfgITSnclsMin; + auto vecITSnclsmax = (std::vector)trackcuts.cfgITSnclsMax; + auto vecTPCchi2max = (std::vector)trackcuts.cfgTPCchi2Max; + auto vecTPCnclsmin = (std::vector)trackcuts.cfgTPCnclsMin; + auto vecTPCnclsmax = (std::vector)trackcuts.cfgTPCnclsMax; + auto vecTPCnclsCRmin = (std::vector)trackcuts.cfgTPCnclsCRMin; + auto vecTPCnclsCRmax = (std::vector)trackcuts.cfgTPCnclsCRMax; + auto vecIsDalitzLeg = (std::vector)trackcuts.cfgIsDalitzLeg; + auto vecPIDmode = (std::vector)pidcuts.cfgPIDmode; + auto vecrejbadtof = (std::vector)pidcuts.cfgRejBadTOF; + auto vecTPCnsigmaelmin = (std::vector)pidcuts.cfgTPCNSigmaElMin; + auto vecTPCnsigmaelmax = (std::vector)pidcuts.cfgTPCNSigmaElMax; + auto vecTPCnsigmapimin = (std::vector)pidcuts.cfgTPCNSigmaPiMin; + auto vecTPCnsigmapimax = (std::vector)pidcuts.cfgTPCNSigmaPiMax; + auto vecTPCnsigmaprmin = (std::vector)pidcuts.cfgTPCNSigmaPrMin; + auto vecTPCnsigmaprmax = (std::vector)pidcuts.cfgTPCNSigmaPrMax; + auto vecTPCnsigmakamin = (std::vector)pidcuts.cfgTPCNSigmaKaMin; + auto vecTPCnsigmakamax = (std::vector)pidcuts.cfgTPCNSigmaKaMax; + auto vecTPCnsigmamumin = (std::vector)pidcuts.cfgTPCNSigmaMuMin; + auto vecTPCnsigmamumax = (std::vector)pidcuts.cfgTPCNSigmaMuMax; + auto vecTOFnsigmaelmin = (std::vector)pidcuts.cfgTOFNSigmaElMin; + auto vecTOFnsigmaelmax = (std::vector)pidcuts.cfgTOFNSigmaElMax; + + if (veceta.size() != fConfigNbTrackCut) + return false; + if (vecptmin.size() != fConfigNbTrackCut) + return false; + if (vecptmax.size() != fConfigNbTrackCut) + return false; + if (vecDCAxymax.size() != fConfigNbTrackCut) + return false; + if (vecDCAzmax.size() != fConfigNbTrackCut) + return false; + if (vecIsSPDfirst.size() != fConfigNbTrackCut) + return false; + if (vecIsSPDany.size() != fConfigNbTrackCut) + return false; + if (vecIsITSibAny.size() != fConfigNbTrackCut) + return false; + if (vecITSchi2max.size() != fConfigNbTrackCut) + return false; + if (vecITSnclsmin.size() != fConfigNbTrackCut) + return false; + if (vecITSnclsmax.size() != fConfigNbTrackCut) + return false; + if (vecTPCchi2max.size() != fConfigNbTrackCut) + return false; + if (vecTPCnclsmin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnclsmax.size() != fConfigNbTrackCut) + return false; + if (vecTPCnclsCRmin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnclsCRmax.size() != fConfigNbTrackCut) + return false; + if (vecIsDalitzLeg.size() != fConfigNbTrackCut) + return false; + if (vecPIDmode.size() != fConfigNbTrackCut) + return false; + if (vecrejbadtof.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmaelmin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmaelmax.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmapimin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmapimax.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmaprmin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmaprmax.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmakamin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmakamax.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmamumin.size() != fConfigNbTrackCut) + return false; + if (vecTPCnsigmamumax.size() != fConfigNbTrackCut) + return false; + if (vecTOFnsigmaelmin.size() != fConfigNbTrackCut) + return false; + if (vecTOFnsigmaelmax.size() != fConfigNbTrackCut) + return false; + return true; + } + + AnalysisCompositeCut* GetPIDCut(unsigned int i) + { + auto vecPIDmode = (std::vector)pidcuts.cfgPIDmode; + auto vecrejbadtof = (std::vector)pidcuts.cfgRejBadTOF; + auto vecTPCnsigmaelmin = (std::vector)pidcuts.cfgTPCNSigmaElMin; + auto vecTPCnsigmaelmax = (std::vector)pidcuts.cfgTPCNSigmaElMax; + auto vecTPCnsigmapimin = (std::vector)pidcuts.cfgTPCNSigmaPiMin; + auto vecTPCnsigmapimax = (std::vector)pidcuts.cfgTPCNSigmaPiMax; + auto vecTPCnsigmaprmin = (std::vector)pidcuts.cfgTPCNSigmaPrMin; + auto vecTPCnsigmaprmax = (std::vector)pidcuts.cfgTPCNSigmaPrMax; + auto vecTPCnsigmakamin = (std::vector)pidcuts.cfgTPCNSigmaKaMin; + auto vecTPCnsigmakamax = (std::vector)pidcuts.cfgTPCNSigmaKaMax; + auto vecTPCnsigmamumin = (std::vector)pidcuts.cfgTPCNSigmaMuMin; + auto vecTPCnsigmamumax = (std::vector)pidcuts.cfgTPCNSigmaMuMax; + auto vecTOFnsigmaelmin = (std::vector)pidcuts.cfgTOFNSigmaElMin; + auto vecTOFnsigmaelmax = (std::vector)pidcuts.cfgTOFNSigmaElMax; + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut(Form("pid_TPCnSigma_%d", i), Form("pid_TPCnSigma_%d", i), kTRUE); + AnalysisCut* cuttpc = new AnalysisCut(Form("pidcuttpc_%d", i), Form("pidcuttpc_%d", i)); + if (!fConfigComputeTPCpostCalib) { + cuttpc->AddCut(VarManager::kTPCnSigmaEl, vecTPCnsigmaelmin.at(i), vecTPCnsigmaelmax.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaPi, vecTPCnsigmapimin.at(i), vecTPCnsigmapimax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaKa, vecTPCnsigmakamin.at(i), vecTPCnsigmakamax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaPr, vecTPCnsigmaprmin.at(i), vecTPCnsigmaprmax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaMu, vecTPCnsigmamumin.at(i), vecTPCnsigmamumax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } else { + cuttpc->AddCut(VarManager::kTPCnSigmaEl_Corr, vecTPCnsigmaelmin.at(i), vecTPCnsigmaelmax.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaPi_Corr, vecTPCnsigmapimin.at(i), vecTPCnsigmapimax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaKa, vecTPCnsigmakamin.at(i), vecTPCnsigmakamax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaPr_Corr, vecTPCnsigmaprmin.at(i), vecTPCnsigmaprmax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTPCnSigmaMu, vecTPCnsigmamumin.at(i), vecTPCnsigmamumax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } + + if (vecrejbadtof.at(i) > 0) { + cuttpc->AddCut(VarManager::kTOFbeta, 0., 0.985, true, VarManager::kPin, 0.0, 1e+10, false); + cuttpc->AddCut(VarManager::kTOFbeta, 1.015, 999999999., true, VarManager::kPin, 0.0, 1e+10, false); + } + cut_tpc_nSigma->AddCut(cuttpc); + + if (vecPIDmode.at(i) == 1) + return cut_tpc_nSigma; + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut(Form("pid_TOFnSigma_%d", i), Form("pid_TOFnSigma_%d", i), kTRUE); + AnalysisCut* cuttof = new AnalysisCut(Form("pidcuttof_%d", i), Form("pidcuttof_%d", i)); + if (!fConfigComputeTPCpostCalib) { + cuttof->AddCut(VarManager::kTPCnSigmaEl, vecTPCnsigmaelmin.at(i), vecTPCnsigmaelmax.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cuttof->AddCut(VarManager::kTPCnSigmaPi, vecTPCnsigmapimin.at(i), vecTPCnsigmapimax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } else { + cuttof->AddCut(VarManager::kTPCnSigmaEl_Corr, vecTPCnsigmaelmin.at(i), vecTPCnsigmaelmax.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cuttof->AddCut(VarManager::kTPCnSigmaPi_Corr, vecTPCnsigmapimin.at(i), vecTPCnsigmapimax.at(i), true, VarManager::kPin, 0.0, 1e+10, false); + } + cuttof->AddCut(VarManager::kTOFnSigmaEl, vecTOFnsigmaelmin.at(i), vecTOFnsigmaelmax.at(i), false, VarManager::kPin, 0.0, 1e+10, false); + cut_tof_nSigma->AddCut(cuttof); + + if (vecPIDmode.at(i) == 2) + return cut_tof_nSigma; + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut(Form("e_NSigma_%d", i), Form("e_NSigma_%d", i), kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + return cut_pid_OR; + } + + AnalysisCut* GetTrackCut(unsigned int i) + { + auto veceta = (std::vector)trackcuts.cfgEtaMax; + auto vecptmin = (std::vector)trackcuts.cfgPtMin; + auto vecptmax = (std::vector)trackcuts.cfgPtMax; + + auto vecDCAxymax = (std::vector)trackcuts.cfgDCAxyMax; + auto vecDCAzmax = (std::vector)trackcuts.cfgDCAzMax; + + auto vecIsSPDfirst = (std::vector)trackcuts.cfgIsSPDfirst; + auto vecIsSPDany = (std::vector)trackcuts.cfgIsSPDany; + auto vecIsITSibAny = (std::vector)trackcuts.cfgIsITSibAny; + + auto vecITSchi2max = (std::vector)trackcuts.cfgITSchi2Max; + auto vecITSnclsmin = (std::vector)trackcuts.cfgITSnclsMin; + auto vecITSnclsmax = (std::vector)trackcuts.cfgITSnclsMax; + + auto vecTPCchi2max = (std::vector)trackcuts.cfgTPCchi2Max; + auto vecTPCnclsmin = (std::vector)trackcuts.cfgTPCnclsMin; + auto vecTPCnclsmax = (std::vector)trackcuts.cfgTPCnclsMax; + auto vecTPCnclsCRmin = (std::vector)trackcuts.cfgTPCnclsCRMin; + auto vecTPCnclsCRmax = (std::vector)trackcuts.cfgTPCnclsCRMax; + + auto vecIsDalitzLeg = (std::vector)trackcuts.cfgIsDalitzLeg; + + AnalysisCut* cut = new AnalysisCut(Form("tracksel%d", i), Form("tracksel%d", i)); + cut->AddCut(VarManager::kPt, vecptmin.at(i), vecptmax.at(i)); + cut->AddCut(VarManager::kEta, -veceta.at(i), veceta.at(i)); + + cut->AddCut(VarManager::kTrackDCAxy, -vecDCAxymax.at(i), vecDCAxymax.at(i)); + cut->AddCut(VarManager::kTrackDCAz, -vecDCAzmax.at(i), vecDCAzmax.at(i)); + + if (vecIsSPDfirst.at(i) > 0) + cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); + if (vecIsSPDany.at(i) > 0) + cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); + if (vecIsITSibAny.at(i) > 0) + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + + cut->AddCut(VarManager::kITSchi2, 0.0, vecITSchi2max.at(i)); + cut->AddCut(VarManager::kITSncls, vecITSnclsmin.at(i), vecITSnclsmax.at(i)); + + cut->AddCut(VarManager::kTPCchi2, 0.0, vecTPCchi2max.at(i)); + cut->AddCut(VarManager::kTPCnclsCR, vecTPCnclsCRmin.at(i), vecTPCnclsCRmax.at(i)); + cut->AddCut(VarManager::kTPCncls, vecTPCnclsmin.at(i), vecTPCnclsmax.at(i)); + + if (vecIsDalitzLeg.at(i) > 0 && vecIsDalitzLeg.at(i) <= 8) + cut->AddCut(VarManager::kIsDalitzLeg + vecIsDalitzLeg.at(i) - 1, 0.5, 1.5); + return cut; + } + + template + void runTrackSelection(TEvent const& event, TTracks const& tracks) + { + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + // fill event information which might be needed in histograms/cuts that combine track and event properties + VarManager::FillEvent(event); + + // check whether the run changed, and if so, update calibrations in the VarManager + // TODO: Here, for the run number and timestamp we assume the function runs with the + // DQ skimmed model. However, we need a compile time check so to make this compatible + // also with the full data model. + if (fConfigComputeTPCpostCalib && fCurrentRun != event.runNumber()) { + auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, event.timestamp()); + VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + fCurrentRun = event.runNumber(); + } + + trackSel.reserve(tracks.size()); + uint32_t filterMap = 0; + bool prefilterSelected = false; + int iCut = 0; + + for (auto& track : tracks) { + filterMap = 0; + prefilterSelected = false; + VarManager::FillTrack(track); + if (fConfigQA) { // TODO: make this compile time + if (fConfigQAIfSelEvt) { + if (event.isEventSelected()) { + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); + } + } else { + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); + } + } + iCut = 0; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, iCut++) { + if ((*cut).IsSelected(VarManager::fgValues)) { + if (iCut != fConfigPrefilterCutId) { + filterMap |= (uint32_t(1) << iCut); + } + if (iCut == fConfigPrefilterCutId) { + prefilterSelected = true; + } + if (fConfigQA) { // TODO: make this compile time + if (fConfigQAIfSelEvt) { + if (event.isEventSelected()) { + fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), VarManager::fgValues); + } + } else { + fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), VarManager::fgValues); + } + } + } + } + + trackSel(static_cast(filterMap), static_cast(prefilterSelected)); + } // end loop over tracks + } + + void processSkimmed(MyEventsSelected::iterator const& event, MyBarrelTracks const& tracks) + { + runTrackSelection(event, tracks); + } + void processSkimmedWithCov(MyEventsVtxCovSelected::iterator const& event, MyBarrelTracksWithCov const& tracks) + { + runTrackSelection(event, tracks); + } + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisTrackSelection, processSkimmed, "Run barrel track selection on DQ skimmed tracks", false); + PROCESS_SWITCH(AnalysisTrackSelection, processSkimmedWithCov, "Run barrel track selection on DQ skimmed tracks w/ cov matrix", false); + PROCESS_SWITCH(AnalysisTrackSelection, processDummy, "Dummy function", false); +}; + +struct AnalysisPrefilterSelection { + SliceCache cache; + Produces prefilter; + Preslice perCollision = aod::reducedtrack::reducedeventId; + + // Configurables + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + + Service ccdb; + + o2::parameters::GRPMagField* grpmag = nullptr; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + + Filter barrelTracksSelectedPrefilter = aod::dqanalysisflags::isBarrelSelectedPrefilter > 0; + + Partition> barrelTracksSelected = aod::dqanalysisflags::isBarrelSelected > 0; + + std::map fPrefiltermap; + AnalysisCompositeCut* fPairCut; + struct : ConfigurableGroup { + std::string prefix = "pairprecut_group"; + Configurable cfgMassMax{"cfgMassMax", 0.05f, "max. mass"}; + Configurable cfgOpAngMax{"cfgOpAngMax", 0.05f, "max. opening angle"}; + Configurable cfgPhiVMin{"cfgPhiVMin", 2.f, "min. phiv"}; + + } pairprecuts; + + AnalysisCut* GetPairPreCut() + { + AnalysisCut* cut = new AnalysisCut("PairPre", "PairPre"); + cut->AddCut(VarManager::kMass, 0.0, pairprecuts.cfgMassMax); + cut->AddCut(VarManager::kOpeningAngle, 0.0, pairprecuts.cfgOpAngMax); + cut->AddCut(VarManager::kPairPhiv, pairprecuts.cfgPhiVMin, 3.2); + return cut; + } + + void init(o2::framework::InitContext&) + { + fCurrentRun = 0; + + ccdb->setURL(ccdburl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + fPairCut = new AnalysisCompositeCut(true); + fPairCut->AddCut(GetPairPreCut()); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetDefaultVarNames(); + } + + template + void runPrefilterPairing(TTracks1 const& tracks1, TTracks2 const& tracks2) + { + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (track1.sign() * track2.sign() > 0) { + continue; + } + + // pairing + VarManager::FillPair(track1, track2); + + if (fPairCut->IsSelected(VarManager::fgValues)) { + fPrefiltermap[track1.globalIndex()] = true; + fPrefiltermap[track2.globalIndex()] = true; + } + } + } + + void processBarrelSkimmed(MyEventsSelected const& events, soa::Filtered const& filteredTracks, MyBarrelTracks const& tracks) + { + const int pairType = VarManager::kDecayToEE; + fPrefiltermap.clear(); + + if (events.size() > 0 && fCurrentRun != events.begin().runNumber()) { + grpmag = ccdb->getForTimeStamp(grpmagPath, events.begin().timestamp()); + if (grpmag != nullptr) { + VarManager::SetMagneticField(grpmag->getNominalL3Field()); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", events.begin().timestamp()); + } + fCurrentRun = events.begin().runNumber(); + } + + for (auto& event : events) { + if (event.isEventSelected()) { + auto groupedPrefilterCandidates = filteredTracks.sliceBy(perCollision, event.globalIndex()); + auto groupedBarrelCandidates = barrelTracksSelected->sliceByCached(aod::reducedtrack::reducedeventId, event.globalIndex(), cache); + runPrefilterPairing(groupedPrefilterCandidates, groupedBarrelCandidates); + } + } // end loop events + + // Fill Prefilter bits for all tracks to have something joinable to MyBarrelTracksSelected + for (auto& track : tracks) { + prefilter(static_cast(fPrefiltermap[track.globalIndex()])); + } + } + + void processDummy(MyEvents&) + { + } + + PROCESS_SWITCH(AnalysisPrefilterSelection, processBarrelSkimmed, "Run Prefilter selection on reduced tracks", false); + PROCESS_SWITCH(AnalysisPrefilterSelection, processDummy, "Do nothing", false); +}; + +struct AnalysisEventMixing { + OutputObj fOutputList{"output"}; + // Here one should provide the list of electron and muon candidate cuts in the same order as specified in the above + // single particle selection tasks to preserve the correspondence between the track cut name and its + // bit position in the cuts bitmap + // TODO: Create a configurable to specify exactly on which of the bits one should run the event mixing + Configurable fConfigNbTrackCut{"cfgNbTrackCut", 1, "Number of cuts without prefilter cut, need to be consistent with the track selection"}; + Configurable fConfigMixingDepth{"cfgMixingDepth", 100, "Number of Events stored for event mixing"}; + Configurable fConfigAddEventMixingHistogram{"cfgAddEventMixingHistogram", "", "Comma separated list of histograms"}; + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + + Service ccdb; + + o2::parameters::GRPMagField* grpmag = nullptr; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + + Filter filterEventSelected = aod::dqanalysisflags::isEventSelected == 1; + Filter filterTrackSelected = aod::dqanalysisflags::isBarrelSelected > 0; + + HistogramManager* fHistMan; + // NOTE: The bit mask is required to run pairing just based on the desired electron/muon candidate cuts + uint32_t fTwoTrackFilterMask = 0; + std::vector> fTrackHistNames; + + NoBinningPolicy hashBin; + + void init(o2::framework::InitContext& /*context*/) + { + fCurrentRun = 0; + + ccdb->setURL(ccdburl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Keep track of all the histogram class names to avoid composing strings in the event mixing pairing + TString histNames = ""; + if (fConfigNbTrackCut > 0 && fConfigNbTrackCut < 31) { + for (int icut = 0; icut < fConfigNbTrackCut; ++icut) { + std::vector names = { + Form("PairsBarrelMEPM_trackcut%d", icut), + Form("PairsBarrelMEPP_trackcut%d", icut), + Form("PairsBarrelMEMM_trackcut%d", icut)}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + fTrackHistNames.push_back(names); + fTwoTrackFilterMask |= (uint32_t(1) << icut); + } + } + + DefineHistograms(fHistMan, histNames.Data(), fConfigAddEventMixingHistogram); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + template + void runMixedPairing(TTracks1 const& tracks1, TTracks2 const& tracks2) + { + + unsigned int ncuts = fTrackHistNames.size(); + std::vector> histNames = fTrackHistNames; + + uint32_t twoTrackFilter = 0; + for (auto& track1 : tracks1) { + for (auto& track2 : tracks2) { + twoTrackFilter = uint32_t(track1.isBarrelSelected()) & uint32_t(track2.isBarrelSelected()) & fTwoTrackFilterMask; + + if (!twoTrackFilter) { // the tracks must have at least one filter bit in common to continue + continue; + } + VarManager::FillPairME(track1, track2); + + constexpr bool eventHasQvector = (VarManager::ObjTypes::ReducedEventQvector > 0); + if constexpr (eventHasQvector) { + VarManager::FillPairVn(track1, track2); + } + constexpr bool eventHasQvectorCentr = (VarManager::ObjTypes::CollisionQvect > 0); + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(track1, track2); + } + + for (unsigned int icut = 0; icut < ncuts; icut++) { + if (twoTrackFilter & (uint32_t(1) << icut)) { + if (track1.sign() * track2.sign() < 0) { + fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); + } else { + if (track1.sign() > 0) { + fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); + } + } + } // end if (filter bits) + } // end for (cuts) + } // end for (track2) + } // end for (track1) + } + + // barrel-barrel and muon-muon event mixing + template + void runSameSide(TEvents& events, TTracks const& tracks, Preslice& preSlice) + { + if (events.size() > 0 && fCurrentRun != events.begin().runNumber()) { + grpmag = ccdb->getForTimeStamp(grpmagPath, events.begin().timestamp()); + if (grpmag != nullptr) { + VarManager::SetMagneticField(grpmag->getNominalL3Field()); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", events.begin().timestamp()); + } + fCurrentRun = events.begin().runNumber(); + } + + events.bindExternalIndices(&tracks); + int mixingDepth = fConfigMixingDepth.value; + for (auto& [event1, event2] : selfCombinations(hashBin, mixingDepth, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1, VarManager::fgValues); + + auto tracks1 = tracks.sliceBy(preSlice, event1.globalIndex()); + tracks1.bindExternalIndices(&events); + + auto tracks2 = tracks.sliceBy(preSlice, event2.globalIndex()); + tracks2.bindExternalIndices(&events); + + VarManager::FillTwoMixEvents(event1, event2, tracks1, tracks2); + runMixedPairing(tracks1, tracks2); + } // end event loop + } + + Preslice> perEventsSelectedT = aod::reducedtrack::reducedeventId; + + void processBarrelSkimmed(soa::Filtered& events, soa::Filtered const& tracks) + { + runSameSide(events, tracks, perEventsSelectedT); + } + void processBarrelVnSkimmed(soa::Filtered& events, soa::Filtered const& tracks) + { + runSameSide(events, tracks, perEventsSelectedT); + } + // TODO: This is a dummy process function for the case when the user does not want to run any of the process functions (no event mixing) + // If there is no process function enabled, the workflow hangs + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisEventMixing, processBarrelSkimmed, "Run barrel-barrel mixing on skimmed tracks", false); + PROCESS_SWITCH(AnalysisEventMixing, processBarrelVnSkimmed, "Run barrel-barrel vn mixing on skimmed tracks", false); + PROCESS_SWITCH(AnalysisEventMixing, processDummy, "Dummy function", false); +}; + +struct AnalysisSameEventPairing { + + float mMagField = 0.0; + o2::parameters::GRPMagField* grpmag = nullptr; + o2::base::MatLayerCylSet* lut = nullptr; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + + OutputObj fOutputList{"output"}; + Configurable fConfigNbTrackCut{"cfgNbTrackCut", 1, "Number of track cuts without prefilter cut, need to be consistent with the track selection"}; + Configurable fConfigNbPairCut{"cfgNbPairCut", 1, "Number of pair cuts, need to be below 4 right now"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPath{"ccdb-path", "Users/lm", "base path to the ccdb object"}; + Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fCollisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; + Configurable fCenterMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; + + Service ccdb; + Filter filterEventSelected = aod::dqanalysisflags::isEventSelected == 1; + // NOTE: the barrel filter map contains decisions for both electrons and hadrons used in the correlation task + Filter filterBarrelTrackSelected = aod::dqanalysisflags::isBarrelSelected > 0; + Filter prefilter = aod::dqanalysisflags::isPrefilterVetoed == 0; + + HistogramManager* fHistMan; + + // NOTE: The track filter produced by the barrel track selection contain a number of electron cut decisions and one last cut for hadrons used in the + // dilepton - hadron task downstream. So the bit mask is required to select pairs just based on the electron cuts + // TODO: provide as Configurable the list and names of the cuts which should be used in pairing + uint32_t fTwoTrackFilterMask = 0; + std::vector> fTrackHistNames; + std::vector fPairCuts; + struct : ConfigurableGroup { + std::string prefix = "paircut_group"; + Configurable> cfgRej{"cfgRej", {1}, "max. mass"}; + Configurable> cfgMassMax{"cfgMassMax", {0.1f}, "max. mass"}; + Configurable> cfgMassMin{"cfgMassMin", {0.f}, "min. mass"}; + Configurable> cfgOpAngMax{"cfgOpAngMax", {-1.f}, "max. opening angle"}; + Configurable> cfgPhiVMin{"cfgPhiVMin", {2.f}, "min. phiv"}; + + } paircuts; + + bool CheckSize() + { + auto vecRej = (std::vector)paircuts.cfgRej; + auto vecmassmin = (std::vector)paircuts.cfgMassMin; + auto vecmassmax = (std::vector)paircuts.cfgMassMax; + auto vecopamax = (std::vector)paircuts.cfgOpAngMax; + auto vecphivmin = (std::vector)paircuts.cfgPhiVMin; + + if (vecRej.size() != fConfigNbPairCut) + return false; + if (vecmassmin.size() != fConfigNbPairCut) + return false; + if (vecmassmax.size() != fConfigNbPairCut) + return false; + if (vecopamax.size() != fConfigNbPairCut) + return false; + if (vecphivmin.size() != fConfigNbPairCut) + return false; + return true; + } + + AnalysisCompositeCut* GetPairCut(unsigned int i) + { + auto vecRej = (std::vector)paircuts.cfgRej; + auto vecmassmin = (std::vector)paircuts.cfgMassMin; + auto vecmassmax = (std::vector)paircuts.cfgMassMax; + auto vecopamax = (std::vector)paircuts.cfgOpAngMax; + auto vecphivmin = (std::vector)paircuts.cfgPhiVMin; + + if (vecRej.at(i)) { + AnalysisCompositeCut* cut_pair = new AnalysisCompositeCut(Form("cut_pair_%d", i), Form("cut_pair_%d", i), kFALSE); + if (vecphivmin.at(i) > 0) { + AnalysisCut* cutphiv = new AnalysisCut(Form("phiv_%d", i), Form("phiv_%d", i)); + cutphiv->AddCut(VarManager::kPairPhiv, vecphivmin.at(i), 3.2, true); + cut_pair->AddCut(cutphiv); + } + if (vecmassmin.at(i) < vecmassmax.at(i)) { + AnalysisCut* cutmass = new AnalysisCut(Form("mass_%d", i), Form("mass_%d", i)); + cutmass->AddCut(VarManager::kMass, vecmassmin.at(i), vecmassmax.at(i), true); + cut_pair->AddCut(cutmass); + } + if (vecopamax.at(i) > 0) { + AnalysisCut* cutopa = new AnalysisCut(Form("opa_%d", i), Form("opa_%d", i)); + cutopa->AddCut(VarManager::kOpeningAngle, 0.0, vecopamax.at(i), true); + cut_pair->AddCut(cutopa); + } + return cut_pair; + } else { + AnalysisCompositeCut* cut_pair = new AnalysisCompositeCut(Form("cut_pair_%d", i), Form("cut_pair_%d", i), kTRUE); + if (vecphivmin.at(i) > 0) { + AnalysisCut* cutphiv = new AnalysisCut(Form("phiv_%d", i), Form("phiv_%d", i)); + cutphiv->AddCut(VarManager::kPairPhiv, vecphivmin.at(i), 3.2); + cut_pair->AddCut(cutphiv); + } + if (vecmassmin.at(i) < vecmassmax.at(i)) { + AnalysisCut* cutmass = new AnalysisCut(Form("mass_%d", i), Form("mass_%d", i)); + cutmass->AddCut(VarManager::kMass, vecmassmin.at(i), vecmassmax.at(i)); + cut_pair->AddCut(cutmass); + } + if (vecopamax.at(i) > 0) { + AnalysisCut* cutopa = new AnalysisCut(Form("opa_%d", i), Form("opa_%d", i)); + cutopa->AddCut(VarManager::kOpeningAngle, 0.0, vecopamax.at(i)); + cut_pair->AddCut(cutopa); + } + return cut_pair; + } + } + + void init(o2::framework::InitContext& /*context*/) + { + fCurrentRun = 0; + + ccdb->setURL(ccdburl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Keep track of all the histogram class names to avoid composing strings in the event mixing pairing + TString histNames = ""; + std::vector names; + + if (fConfigNbPairCut > 0 && CheckSize()) { + for (int icut = 0; icut < fConfigNbPairCut; ++icut) { + fPairCuts.push_back(*GetPairCut(icut)); + } + } + + if (fConfigNbTrackCut > 0 && fConfigNbTrackCut < 31) { // if track cuts + for (int icut = 0; icut < fConfigNbTrackCut; ++icut) { // loop over track cuts + fTwoTrackFilterMask |= (uint32_t(1) << icut); + // no pair cuts + names = { + Form("PairsBarrelSEPM_trackcut%d", icut), + Form("PairsBarrelSEPP_trackcut%d", icut), + Form("PairsBarrelSEMM_trackcut%d", icut)}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + fTrackHistNames.push_back(names); + + unsigned int npaircuts = fPairCuts.size(); + for (int iPairCut = 0; iPairCut < npaircuts; ++iPairCut) { // loop over pair cuts + names = { + Form("PairsBarrelSEPM_trackcut%d_paircut%d", icut, iPairCut), + Form("PairsBarrelSEPP_trackcut%d_paircut%d", icut, iPairCut), + Form("PairsBarrelSEMM_trackcut%d_paircut%d", icut, iPairCut)}; + + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + + fTrackHistNames.push_back(names); + } // end loop (pair cuts) + } // end loop (track cuts) + } // end if (track cuts) + + VarManager::SetCollisionSystem((TString)fCollisionSystem, fCenterMassEnergy); // set collision system and center of mass energy + + DefineHistograms(fHistMan, histNames.Data(), fConfigAddSEPHistogram); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) + template + void runSameEventPairing(TEvent const& event, TTracks1 const& tracks1, TTracks2 const& tracks2) + { + if (fCurrentRun != event.runNumber()) { + grpmag = ccdb->getForTimeStamp(grpmagPath, event.timestamp()); + if (grpmag != nullptr) { + mMagField = grpmag->getNominalL3Field(); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", event.timestamp()); + } + VarManager::SetMagneticField(mMagField); + fCurrentRun = event.runNumber(); + } + + std::vector> histNames = fTrackHistNames; + uint32_t twoTrackFilter = 0; + + for (auto& [t1, t2] : combinations(tracks1, tracks2)) { + twoTrackFilter = uint32_t(t1.isBarrelSelected()) & uint32_t(t2.isBarrelSelected()) & fTwoTrackFilterMask; + + if (!twoTrackFilter) { // the tracks must have at least one filter bit in common to continue + continue; + } + constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); + constexpr bool eventHasQvectorCentr = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); + + // TODO: FillPair functions need to provide a template argument to discriminate between cases when cov matrix is available or not + VarManager::FillPair(t1, t2); + if constexpr (eventHasQvector) { + VarManager::FillPairVn(t1, t2); + } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } + + int iCut = 0; + for (int icut = 0; icut < fConfigNbTrackCut; icut++) { + if (twoTrackFilter & (uint32_t(1) << icut)) { + if (t1.sign() * t2.sign() < 0) { + fHistMan->FillHistClass(histNames[iCut][0].Data(), VarManager::fgValues); + } else { + if (t1.sign() > 0) { + fHistMan->FillHistClass(histNames[iCut][1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNames[iCut][2].Data(), VarManager::fgValues); + } + } + iCut++; + for (unsigned int iPairCut = 0; iPairCut < fPairCuts.size(); iPairCut++, iCut++) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!(cut.IsSelected(VarManager::fgValues))) // apply pair cuts + continue; + if (t1.sign() * t2.sign() < 0) { + fHistMan->FillHistClass(histNames[iCut][0].Data(), VarManager::fgValues); + } else { + if (t1.sign() > 0) { + fHistMan->FillHistClass(histNames[iCut][1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNames[iCut][2].Data(), VarManager::fgValues); + } + } + } // end loop (pair cuts) + } else { // end if (filter bits) + iCut = iCut + 1 + fPairCuts.size(); + } + } // end loop (cuts) + } // end loop over pairs + } + + void processDecayToEESkimmed(soa::Filtered::iterator const& event, soa::Filtered const& tracks) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, tracks, tracks); + } + void processDecayToEESkimmedWithCov(soa::Filtered::iterator const& event, soa::Filtered const& tracks) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, tracks, tracks); + } + void processDecayToEEPrefilterSkimmed(soa::Filtered::iterator const& event, soa::Filtered const& tracks) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, tracks, tracks); + } + void processDecayToEESkimmedWithColl(soa::Filtered::iterator const& event, soa::Filtered const& tracks) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, tracks, tracks); + } + void processVnDecayToEESkimmed(soa::Filtered::iterator const& event, soa::Filtered const& tracks) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, tracks, tracks); + } + // TODO: dummy function for the case when no process function is enabled + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEESkimmed, "Run electron-electron pairing, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEESkimmedWithCov, "Run electron-electron pairing, with skimmed covariant tracks", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEEPrefilterSkimmed, "Run electron-electron pairing, with skimmed tracks and prefilter from AnalysisPrefilterSelection", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEESkimmedWithColl, "Run electron-electron pairing, with skimmed tracks and with collision information", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processVnDecayToEESkimmed, "Run electron-electron pairing, with skimmed tracks for vn", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} + +void DefineHistograms(HistogramManager* histMan, TString histClasses, Configurable configVar) +{ + // + // Define here the histograms for all the classes required in analysis. + // The histogram classes are provided in the histClasses string, separated by semicolon ";" + // The histogram classes and their components histograms are defined below depending on the name of the histogram class + // + std::unique_ptr objArray(histClasses.Tokenize(";")); + for (Int_t iclass = 0; iclass < objArray->GetEntries(); ++iclass) { + TString classStr = objArray->At(iclass)->GetName(); + histMan->AddHistClass(classStr.Data()); + + TString histName = configVar.value; + // NOTE: The level of detail for histogramming can be controlled via configurables + if (classStr.Contains("Event")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "event", histName); + } + + if (classStr.Contains("Track") && !classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + } + + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + } // end loop over histogram classes +} diff --git a/PWGEM/Dilepton/Tasks/vpPairQC.cxx b/PWGEM/Dilepton/Tasks/vpPairQC.cxx new file mode 100644 index 00000000000..162fe333430 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/vpPairQC.cxx @@ -0,0 +1,512 @@ +// Copyright 2019-2020 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 ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; + +struct vpPairQC { + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 0.01, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.9, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.9, "max pair rapidity"}; + Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + Configurable cfg_apply_phiv_meedep{"cfg_apply_phiv_meedep", false, "flag to apply mee-dependent phiv cut"}; + Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.9, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.9, "max eta for single track"}; + Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1e+10, "max DCA 3D in sigma"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.2, "max p to apply ITS cluster size cut"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTOFif), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -0.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +0.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -0.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +0.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber; + float d_bz; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + + void init(InitContext& /*context*/) + { + DefineEMEventCut(); + DefineDielectronCut(); + addhistograms(); + + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = collision.runNumber(); + } + + ~vpPairQC() + { + if (eid_bdt) { + delete eid_bdt; + } + } + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms(&fRegistry); + + const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; + const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; + const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; + const AxisSpec axis_dca{{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA_{e}^{3D} (#sigma)"}; + fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); + fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/positive/hPResolution", "p resolution;p (GeV/c);#Deltap/p", kTH2F, {{1000, 0.0f, 10.0f}, {100, 0.0f, 0.1f}}, false); + fRegistry.add("Track/positive/hPtResolution", "p_{T} resolution;p (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0.0f, 10.0f}, {100, 0.0f, 0.1f}}, false); + fRegistry.add("Track/positive/hThetaResolution", "#theta resolution;p (GeV/c);#Delta#theta (rad.)", kTH2F, {{1000, 0.0f, 10.0f}, {100, 0.0f, 0.01f}}, false); + fRegistry.add("Track/positive/hEtaResolution", "#eta resolution;p (GeV/c);#Delta#eta", kTH2F, {{1000, 0.0f, 10.0f}, {100, 0.0f, 0.01f}}, false); + fRegistry.add("Track/positive/hPhiResolution", "#varphi resolution;p (GeV/c);#Delta#varphi (rad.)", kTH2F, {{1000, 0.0f, 10.0f}, {100, 0.0f, 0.01f}}, false); + fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {200, 0., 400}}, false); + fRegistry.add("Track/positive/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/positive/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); + fRegistry.add("Track/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.addClone("Track/positive/", "Track/negative/"); + + const AxisSpec axis_mass{50, 0, 0.05, "m_{ee} (GeV/c^{2})"}; + const AxisSpec axis_pair_pt{200, 0, 2, "p_{T,ee} (GeV/c)"}; + const AxisSpec axis_pair_dca_3d{100, 0, 10, "DCA_{ee}^{3D} (#sigma)"}; + const AxisSpec axis_pair_dca_xy{100, 0, 10, "DCA_{ee}^{XY} (#sigma)"}; + const AxisSpec axis_phiv{90, 0, M_PI, "#varphi_{V} (rad.)"}; + // for pair + fRegistry.add("Pair/hMvsPt", "m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {axis_mass, axis_pair_pt}, true); + fRegistry.add("Pair/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {axis_phiv, axis_mass}, true); + fRegistry.add("Pair/hDCA3DvsPhiV", "DCA_{ee}^{3D} vs. #varphi_{V};#varphi_{V} (rad.);DCA_{ee}^{3D} (#sigma)", kTH2F, {axis_phiv, axis_pair_dca_3d}, true); + fRegistry.add("Pair/hDCAXYvsPhiV", "DCA_{ee}^{XY} vs. #varphi_{V};#varphi_{V} (rad.);DCA_{ee}^{XY} (#sigma)", kTH2F, {axis_phiv, axis_pair_dca_xy}, true); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for pair + fDielectronCut.SetMeeRange(dielectroncuts.cfg_min_mass, dielectroncuts.cfg_max_mass); + fDielectronCut.SetPairPtRange(dielectroncuts.cfg_min_pair_pt, dielectroncuts.cfg_max_pair_pt); + fDielectronCut.SetPairYRange(dielectroncuts.cfg_min_pair_y, dielectroncuts.cfg_max_pair_y); + fDielectronCut.SetPairDCARange(dielectroncuts.cfg_min_pair_dca3d, dielectroncuts.cfg_max_pair_dca3d); // in sigma + if (dielectroncuts.cfg_apply_phiv_meedep) { + fDielectronCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dielectroncuts.cfg_phiv_intercept) / dielectroncuts.cfg_phiv_slope; }); + } else { + fDielectronCut.SetPhivPairRange(0.f, dielectroncuts.cfg_max_phiv); + } + fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); + fDielectronCut.ApplyPrefilter(dielectroncuts.cfg_apply_pf); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackDca3DRange(0.f, dielectroncuts.cfg_max_dca3dsigma_track); // in sigma + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + fDielectronCut.SetMaxPinForPionRejectionTPC(dielectroncuts.cfg_max_pin_pirejTPC); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + template + bool fillPairInfo(TCollision const&, TTrack1 const& t1, TTrack2 const& t2) + { + // if (t1.trackId() == t2.trackId()) { // this is protection against pairing identical 2 tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + // return false; + // } + + if (!fDielectronCut.IsSelectedTrack(t1) || !fDielectronCut.IsSelectedTrack(t2)) { + return false; + } + + if (!fDielectronCut.IsSelectedPair(t1, t2, d_bz)) { + return false; + } + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + + float dca_t1 = dca3DinSigma(t1); + float dca_t2 = dca3DinSigma(t2); + float pair_dca_3d = std::sqrt((dca_t1 * dca_t1 + dca_t2 * dca_t2) / 2.); + float pair_dca_xy = std::sqrt((std::pow(t1.dcaXY() / std::sqrt(t1.cYY()), 2) + std::pow(t2.dcaXY() / std::sqrt(t2.cYY()), 2)) / 2.); + + fRegistry.fill(HIST("Pair/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/hDCA3DvsPhiV"), phiv, pair_dca_3d); + fRegistry.fill(HIST("Pair/hDCAXYvsPhiV"), phiv, pair_dca_xy); + + if (std::find(used_trackIds.begin(), used_trackIds.end(), t1.globalIndex()) == used_trackIds.end()) { + used_trackIds.emplace_back(t1.globalIndex()); + fillTrackInfo(t1); + } + if (std::find(used_trackIds.begin(), used_trackIds.end(), t2.globalIndex()) == used_trackIds.end()) { + used_trackIds.emplace_back(t2.globalIndex()); + fillTrackInfo(t2); + } + + return true; + } + + template + void fillTrackInfo(TTrack const& track) + { + float weight = 1.f; + float dca_3d = dca3DinSigma(track); + if (track.sign() > 0) { + fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca_3d, weight); + fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/positive/hPResolution"), track.p(), sigmaP(track) / track.p()); + fRegistry.fill(HIST("Track/positive/hPtResolution"), track.p(), sigmaPt(track) / track.pt()); + fRegistry.fill(HIST("Track/positive/hThetaResolution"), track.p(), sigmaTheta(track)); + fRegistry.fill(HIST("Track/positive/hEtaResolution"), track.p(), sigmaEta(track)); + fRegistry.fill(HIST("Track/positive/hPhiResolution"), track.p(), sigmaPhi(track)); + fRegistry.fill(HIST("Track/positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/positive/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/positive/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/positive/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/positive/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/positive/hITSClusterMap"), track.itsClusterMap()); + + fRegistry.fill(HIST("Track/positive/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/positive/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/positive/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + } else { + fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_3d, weight); + fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/negative/hPResolution"), track.p(), sigmaP(track) / track.p()); + fRegistry.fill(HIST("Track/negative/hPtResolution"), track.p(), sigmaPt(track) / track.pt()); + fRegistry.fill(HIST("Track/negative/hThetaResolution"), track.p(), sigmaTheta(track)); + fRegistry.fill(HIST("Track/negative/hEtaResolution"), track.p(), sigmaEta(track)); + fRegistry.fill(HIST("Track/negative/hPhiResolution"), track.p(), sigmaPhi(track)); + fRegistry.fill(HIST("Track/negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/negative/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/negative/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/negative/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/negative/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/negative/hITSClusterMap"), track.itsClusterMap()); + + fRegistry.fill(HIST("Track/negative/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/negative/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + fRegistry.fill(HIST("Track/negative/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + fRegistry.fill(HIST("Track/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + } + } + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + using FilteredMyCollisions = soa::Filtered; + + SliceCache cache; + Preslice perCollision_track = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + using FilteredMyTracks = soa::Filtered; + + Partition posTracks = o2::aod::emprimaryelectron::sign > int8_t(0); + Partition negTracks = o2::aod::emprimaryelectron::sign < int8_t(0); + + std::vector used_trackIds; + void processQC(FilteredMyCollisions const& collisions, FilteredMyTracks const& /*tracks*/) + { + for (auto& collision : collisions) { + initCCDB(collision); + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); + + for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + fillPairInfo(collision, pos, ele); + } + } // end of collision loop + + used_trackIds.clear(); + used_trackIds.shrink_to_fit(); + + } // end of process + PROCESS_SWITCH(vpPairQC, processQC, "run vp pair QC", true); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(vpPairQC, processDummy, "Dummy function", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"vp-pair-qc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx b/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx new file mode 100644 index 00000000000..d036e6dee6a --- /dev/null +++ b/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx @@ -0,0 +1,625 @@ +// Copyright 2019-2020 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 ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/RecoDecay.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCTracks = soa::Join; +using MyMCTrack = MyMCTracks::iterator; + +struct vpPairQCMC { + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "dielectroncut_group"; + Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + Configurable cfg_max_mass{"cfg_max_mass", 0.01, "max mass"}; + Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.9, "min pair rapidity"}; + Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.9, "max pair rapidity"}; + Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.9, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.9, "max eta for single track"}; + Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1e+10, "max DCA 3D in sigma"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTOFif), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -0.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +0.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -0.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +0.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -0.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +0.0, "max. TOF n sigma for electron inclusion"}; + Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + // CCDB configuration for PID ML + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } dielectroncuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber; + float d_bz; + + struct : ConfigurableGroup { + std::string prefix = "mctrackcut_group"; + Configurable min_mcPt{"min_mcPt", 0.05, "min. MC pT"}; + Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT"}; + Configurable max_mcEta{"max_mcEta", 0.9, "max. MC eta"}; + } mctrackcuts; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + + ~vpPairQCMC() {} + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms(&fRegistry); + + std::vector ptbins; + std::vector massbins; + + for (int i = 0; i < 51; i++) { + massbins.emplace_back(0.01 * (i - 0) + 0.0); // every 0.01 GeV/c2 from 0.0 to 0.5 GeV/c2 + } + const AxisSpec axis_mass{massbins, "m_{ee} (GeV/c^{2})"}; + + for (int i = 0; i < 50; i++) { + ptbins.emplace_back(0.1 * (i - 0) + 0.0); // every 0.1 GeV/c from 0.0 to 5.0 GeV/c + } + for (int i = 50; i < 61; i++) { + ptbins.emplace_back(0.5 * (i - 50) + 5.0); // every 0.5 GeV/c from 5.0 to 10 GeV/c + } + const AxisSpec axis_pt{ptbins, "p_{T,ee} (GeV/c)"}; + + // generated info + fRegistry.add("Generated/sm/Pi0/hMvsPt", "m_{ee} vs. p_{T,ee} ULS", kTH2F, {axis_mass, axis_pt}, true); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Eta/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/EtaPrime/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Rho/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Omega/"); + fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Phi/"); + + // reconstructed pair info + fRegistry.add("Pair/sm/Photon/hMvsPt", "m_{ee} vs. p_{T,ee} ULS", kTH2F, {axis_mass, axis_pt}, true); + fRegistry.add("Pair/sm/Photon/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, false); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Pi0/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Eta/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/EtaPrime/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Rho/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Omega/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Phi/"); + + // track info + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); + } + + void init(InitContext&) + { + DefineEMEventCut(); + DefineDielectronCut(); + addhistograms(); + + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = collision.runNumber(); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + } + + o2::ml::OnnxModel* eid_bdt = nullptr; + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for pair + fDielectronCut.SetMeeRange(dielectroncuts.cfg_min_mass, dielectroncuts.cfg_max_mass); + fDielectronCut.SetPairPtRange(dielectroncuts.cfg_min_pair_pt, dielectroncuts.cfg_max_pair_pt); + fDielectronCut.SetPairYRange(dielectroncuts.cfg_min_pair_y, dielectroncuts.cfg_max_pair_y); + fDielectronCut.SetPairDCARange(dielectroncuts.cfg_min_pair_dca3d, dielectroncuts.cfg_max_pair_dca3d); // in sigma + fDielectronCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dielectroncuts.cfg_phiv_intercept) / dielectroncuts.cfg_phiv_slope; }); + fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); + fDielectronCut.ApplyPrefilter(dielectroncuts.cfg_apply_pf); + fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f); + fDielectronCut.SetTrackEtaRange(-dielectroncuts.cfg_max_eta_track, +dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackDca3DRange(0.f, dielectroncuts.cfg_max_dca3dsigma_track); // in sigma + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(0, 16); + fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + fDielectronCut.SetTPCNsigmaMuRange(dielectroncuts.cfg_min_TPCNsigmaMu, dielectroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(dielectroncuts.cfg_min_TPCNsigmaPi, dielectroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(dielectroncuts.cfg_min_TPCNsigmaKa, dielectroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(dielectroncuts.cfg_min_TPCNsigmaPr, dielectroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(dielectroncuts.cfg_min_TOFNsigmaEl, dielectroncuts.cfg_max_TOFNsigmaEl); + fDielectronCut.SetMaxPinForPionRejectionTPC(dielectroncuts.cfg_max_pin_pirejTPC); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDielectronCut + // o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); + eid_bdt = new o2::ml::OnnxModel(); + if (dielectroncuts.loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + std::map metadata; + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dielectroncuts.BDTPathCCDB.value, ".", metadata, dielectroncuts.timestampCCDB.value, false, dielectroncuts.BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + eid_bdt->initModel(dielectroncuts.BDTLocalPathGamma.value, dielectroncuts.enableOptimizations.value); + } + + fDielectronCut.SetPIDModel(eid_bdt); + } // end of PID ML + } + + template + int FindLF(TTrack const& posmc, TTrack const& elemc, TMCParticles const& mcparticles) + { + int arr[] = { + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 111, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 221, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 331, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 113, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 223, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 333, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 443, mcparticles), + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 100443, mcparticles)}; + int size = sizeof(arr) / sizeof(*arr); + int max = *std::max_element(arr, arr + size); + return max; + } + + template + bool isInAcceptance(T const& t1) + { + if ((mctrackcuts.min_mcPt < t1.pt() && t1.pt() < mctrackcuts.max_mcPt) && abs(t1.eta()) < mctrackcuts.max_mcEta) { + return true; + } else { + return false; + } + } + + template + bool fillTruePairInfo(TCollision const&, TTrack1 const& t1, TTrack2 const& t2, TMCParticles const& mcparticles) + { + if (!fDielectronCut.IsSelectedTrack(t1) || !fDielectronCut.IsSelectedTrack(t2)) { + return false; + } + + if (!fDielectronCut.IsSelectedPair(t1, t2, d_bz)) { + return false; + } + + auto t1mc = t1.template emmcparticle_as(); + auto t2mc = t2.template emmcparticle_as(); + + int mother_id = FindLF(t1mc, t2mc, mcparticles); + int hfee_type = IsHF(t1mc, t2mc, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + return false; + } + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + if (abs(v12.Rapidity()) > maxY) { + return false; + } + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + + if (mother_id > -1 && t1mc.pdgCode() * t2mc.pdgCode() < 0) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { + if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + switch (abs(mcmother.pdgCode())) { + case 111: + fRegistry.fill(HIST("Pair/sm/Pi0/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/Pi0/hMvsPhiV"), phiv, v12.M()); + break; + case 221: + fRegistry.fill(HIST("Pair/sm/Eta/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/Eta/hMvsPhiV"), phiv, v12.M()); + break; + case 331: + fRegistry.fill(HIST("Pair/sm/EtaPrime/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/EtaPrime/hMvsPhiV"), phiv, v12.M()); + break; + case 113: + fRegistry.fill(HIST("Pair/sm/Rho/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/Rho/hMvsPhiV"), phiv, v12.M()); + break; + case 223: + fRegistry.fill(HIST("Pair/sm/Omega/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/Omega/hMvsPhiV"), phiv, v12.M()); + break; + case 333: + fRegistry.fill(HIST("Pair/sm/Phi/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/Phi/hMvsPhiV"), phiv, v12.M()); + break; + default: + break; + } + } else if (!(t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && !(t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + switch (abs(mcmother.pdgCode())) { + case 22: + fRegistry.fill(HIST("Pair/sm/Photon/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/sm/Photon/hMvsPhiV"), phiv, v12.M()); + break; + default: + break; + } + } // end of primary/secondary selection + } // end of primary selection for same mother + } + + // fill track info that belong to true pairs. + if (t1.sign() > 0) { + if (std::find(used_trackIds.begin(), used_trackIds.end(), t1.globalIndex()) == used_trackIds.end()) { + used_trackIds.emplace_back(t1.globalIndex()); + fillTrackInfo(t1); + } + } else { + if (std::find(used_trackIds.begin(), used_trackIds.end(), t1.globalIndex()) == used_trackIds.end()) { + used_trackIds.emplace_back(t1.globalIndex()); + fillTrackInfo(t1); + } + } + if (t2.sign() > 0) { + if (std::find(used_trackIds.begin(), used_trackIds.end(), t1.globalIndex()) == used_trackIds.end()) { + used_trackIds.emplace_back(t1.globalIndex()); + fillTrackInfo(t2); + } + } else { + if (std::find(used_trackIds.begin(), used_trackIds.end(), t2.globalIndex()) == used_trackIds.end()) { + used_trackIds.emplace_back(t2.globalIndex()); + fillTrackInfo(t2); + } + } + + return true; + } + + template + void fillTrackInfo(TTrack const& track) + { + fRegistry.fill(HIST("Track/hPt"), track.pt()); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); + fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + } + + std::vector used_trackIds; + SliceCache cache; + Preslice perCollision_track = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + + using FilteredMyMCTracks = soa::Filtered; + Partition posTracks = o2::aod::emprimaryelectron::sign > int8_t(0); + Partition negTracks = o2::aod::emprimaryelectron::sign < int8_t(0); + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + using FilteredMyCollisions = soa::Filtered; + + void processQCMC(FilteredMyCollisions const& collisions, FilteredMyMCTracks const& tracks, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const&) + { + used_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + initCCDB(collision); + + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); + + for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + fillTruePairInfo(collision, pos, ele, mcparticles); + } // end of ULS pair loop + + } // end of collision loop + + used_trackIds.clear(); + used_trackIds.shrink_to_fit(); + } // end of process + PROCESS_SWITCH(vpPairQCMC, processQCMC, "run Dalitz QC", true); + + Partition posTracksMC = o2::aod::mcparticle::pdgCode == -11; // e+ + Partition negTracksMC = o2::aod::mcparticle::pdgCode == +11; // e- + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + void processGen(MyCollisions const& collisions, aod::EMMCEvents const&, aod::EMMCParticles const& mcparticles) + { + // loop over mc stack and fill histograms for pure MC truth signals + // all MC tracks which belong to the MC event corresponding to the current reconstructed event + + for (auto& collision : collisions) { + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + auto mccollision = collision.emmcevent_as(); + + auto posTracks_per_coll = posTracksMC->sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); + auto negTracks_per_coll = negTracksMC->sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); + + for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); + + if (!isInAcceptance(t1) || !isInAcceptance(t2)) { + continue; + } + + if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { + continue; + } + if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { + continue; + } + + int mother_id = FindLF(t1, t2, mcparticles); + int hfee_type = IsHF(t1, t2, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if (abs(v12.Rapidity()) > maxY) { + continue; + } + + if (mother_id > -1) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { + + switch (abs(mcmother.pdgCode())) { + case 111: + fRegistry.fill(HIST("Generated/sm/Pi0/hMvsPt"), v12.M(), v12.Pt()); + break; + case 221: + fRegistry.fill(HIST("Generated/sm/Eta/hMvsPt"), v12.M(), v12.Pt()); + break; + case 331: + fRegistry.fill(HIST("Generated/sm/EtaPrime/hMvsPt"), v12.M(), v12.Pt()); + break; + case 113: + fRegistry.fill(HIST("Generated/sm/Rho/hMvsPt"), v12.M(), v12.Pt()); + break; + case 223: + fRegistry.fill(HIST("Generated/sm/Omega/hMvsPt"), v12.M(), v12.Pt()); + break; + case 333: + fRegistry.fill(HIST("Generated/sm/Phi/hMvsPt"), v12.M(), v12.Pt()); + break; + default: + break; + } + } + } + } // end of true ULS pair loop + } // end of collision loop + } + PROCESS_SWITCH(vpPairQCMC, processGen, "run genrated info", true); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(vpPairQCMC, processDummy, "Dummy function", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"vp-pair-qc-mc"})}; +} diff --git a/PWGEM/PhotonMeson/Utils/EMFwdTrack.h b/PWGEM/Dilepton/Utils/EMFwdTrack.h similarity index 77% rename from PWGEM/PhotonMeson/Utils/EMFwdTrack.h rename to PWGEM/Dilepton/Utils/EMFwdTrack.h index ed2755e9d13..0aa590c6fb2 100644 --- a/PWGEM/PhotonMeson/Utils/EMFwdTrack.h +++ b/PWGEM/Dilepton/Utils/EMFwdTrack.h @@ -12,18 +12,19 @@ /// \class to store minimal fwdtrack info /// \author daiki.sekihata@cern.ch -#ifndef PWGEM_PHOTONMESON_UTILS_EMFWDTRACK_H_ -#define PWGEM_PHOTONMESON_UTILS_EMFWDTRACK_H_ +#ifndef PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ +#define PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ #include -namespace o2::aod::pwgem::photonmeson::utils::emfwdtrack +namespace o2::aod::pwgem::dilepton::utils { class EMFwdTrack { public: - EMFwdTrack(int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaX = 0.f, float dcaY = 0.f, std::vector amb_muon_self_ids = {}) + EMFwdTrack(int dfId, int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaX = 0.f, float dcaY = 0.f, std::vector amb_muon_self_ids = {}) { + fDFId = dfId; fGlobalId = globalId; fCollisionId = collisionId; fTrackId = trackId; @@ -34,6 +35,7 @@ class EMFwdTrack fCharge = charge; fDCAx = dcaX; fDCAy = dcaY; + fPairDCAXYinSigmaOTF = 0; fAmbMuonSelfIds = amb_muon_self_ids; if (fAmbMuonSelfIds.size() > 0) { @@ -45,6 +47,7 @@ class EMFwdTrack ~EMFwdTrack() {} + int dfId() const { return fDFId; } int globalIndex() const { return fGlobalId; } int collisionId() const { return fCollisionId; } int fwdtrackId() const { return fTrackId; } @@ -56,6 +59,7 @@ class EMFwdTrack float fwdDcaX() const { return fDCAx; } float fwdDcaY() const { return fDCAy; } float fwdDcaXY() const { return std::sqrt(std::pow(fDCAx, 2) + std::pow(fDCAy, 2)); } + float p() const { return fPt * std::cosh(fEta); } float px() const { return fPt * std::cos(fPhi); } float py() const { return fPt * std::sin(fPhi); } float pz() const { return fPt * std::sinh(fEta); } @@ -63,7 +67,11 @@ class EMFwdTrack std::vector ambiguousMuonsIds() const { return fAmbMuonSelfIds; } float signed1Pt() const { return fCharge * 1.f / fPt; } + float pairDcaXYinSigmaOTF() const { return fPairDCAXYinSigmaOTF; } + void setPairDcaXYinSigmaOTF(float dca) { fPairDCAXYinSigmaOTF = dca; } + protected: + int fDFId; int fGlobalId; int fCollisionId; int fTrackId; @@ -74,6 +82,7 @@ class EMFwdTrack int8_t fCharge; float fDCAx; float fDCAy; + float fPairDCAXYinSigmaOTF; bool fIsAmbiguous; std::vector fAmbMuonSelfIds; }; @@ -81,12 +90,12 @@ class EMFwdTrack class EMFwdTrackWithCov : public EMFwdTrack { public: - EMFwdTrackWithCov(int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaX = 0.f, float dcaY = 0.f, std::vector amb_muon_self_ids = {}, + EMFwdTrackWithCov(int dfId, int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaX = 0.f, float dcaY = 0.f, std::vector amb_muon_self_ids = {}, float X = 0.f, float Y = 0.f, float Z = 0.f, float Tgl = 0.f, float CXX = 0.f, float CXY = 0.f, float CYY = 0.f, float CPhiX = 0.f, float CPhiY = 0.f, float CPhiPhi = 0.f, float CTglX = 0.f, float CTglY = 0.f, float CTglPhi = 0.f, float CTglTgl = 0.f, - float C1PtX = 0.f, float C1PtY = 0.f, float C1PtPhi = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f, float chi2 = 0.f) : EMFwdTrack(globalId, collisionId, trackId, pt, eta, phi, mass, charge, dcaX, dcaY, amb_muon_self_ids) + float C1PtX = 0.f, float C1PtY = 0.f, float C1PtPhi = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f, float chi2 = 0.f) : EMFwdTrack(dfId, globalId, collisionId, trackId, pt, eta, phi, mass, charge, dcaX, dcaY, amb_muon_self_ids) { fX = X; fY = Y; @@ -131,6 +140,10 @@ class EMFwdTrackWithCov : public EMFwdTrack float c1Pt21Pt2() const { return fC1Pt21Pt2; } float chi2() const { return fChi2; } + void setCXX(float cXX) { fCXX = cXX; } + void setCXY(float cXY) { fCXY = cXY; } + void setCYY(float cYY) { fCYY = cYY; } + protected: float fX; float fY; @@ -154,5 +167,5 @@ class EMFwdTrackWithCov : public EMFwdTrack float fChi2; }; -} // namespace o2::aod::pwgem::photonmeson::utils::emfwdtrack -#endif // PWGEM_PHOTONMESON_UTILS_EMFWDTRACK_H_ +} // namespace o2::aod::pwgem::dilepton::utils +#endif // PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ diff --git a/PWGEM/PhotonMeson/Utils/EMTrack.h b/PWGEM/Dilepton/Utils/EMTrack.h similarity index 54% rename from PWGEM/PhotonMeson/Utils/EMTrack.h rename to PWGEM/Dilepton/Utils/EMTrack.h index 48f4b66eee2..0f894d5b4dc 100644 --- a/PWGEM/PhotonMeson/Utils/EMTrack.h +++ b/PWGEM/Dilepton/Utils/EMTrack.h @@ -12,18 +12,20 @@ /// \class to store minimal track info /// \author daiki.sekihata@cern.ch -#ifndef PWGEM_PHOTONMESON_UTILS_EMTRACK_H_ -#define PWGEM_PHOTONMESON_UTILS_EMTRACK_H_ +#ifndef PWGEM_DILEPTON_UTILS_EMTRACK_H_ +#define PWGEM_DILEPTON_UTILS_EMTRACK_H_ #include +#include "Math/Vector4D.h" -namespace o2::aod::pwgem::photonmeson::utils::emtrack +namespace o2::aod::pwgem::dilepton::utils { class EMTrack { public: - EMTrack(int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, std::vector amb_ele_self_ids = {}) + EMTrack(int dfId, int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, std::vector amb_ele_self_ids = {}) { + fDFId = dfId; fGlobalId = globalId; fCollisionId = collisionId; fTrackId = trackId; @@ -34,6 +36,7 @@ class EMTrack fCharge = charge; fDCAxy = dcaXY; fDCAz = dcaZ; + fPairDCA3DinSigmaOTF = 0; fAmbEleSelfIds = amb_ele_self_ids; if (fAmbEleSelfIds.size() > 0) { @@ -41,10 +44,30 @@ class EMTrack } else { fIsAmbiguous = false; } + fVx = 0.f; + fVy = 0.f; + fVz = 0.f; + fVPos = ROOT::Math::PtEtaPhiMVector(0, 0, 0, 0); + fVNeg = ROOT::Math::PtEtaPhiMVector(0, 0, 0, 0); + fAmbPosLegSelfIds.clear(); + fAmbNegLegSelfIds.clear(); + fAmbPosLegSelfIds.shrink_to_fit(); + fAmbNegLegSelfIds.shrink_to_fit(); + fGlobalPosId = 0; + fGlobalNegId = 0; } - ~EMTrack() {} + ~EMTrack() + { + fAmbEleSelfIds.clear(); + fAmbEleSelfIds.shrink_to_fit(); + fAmbPosLegSelfIds.clear(); + fAmbNegLegSelfIds.clear(); + fAmbPosLegSelfIds.shrink_to_fit(); + fAmbNegLegSelfIds.shrink_to_fit(); + } + int dfId() const { return fDFId; } int globalIndex() const { return fGlobalId; } int collisionId() const { return fCollisionId; } int trackId() const { return fTrackId; } @@ -55,6 +78,7 @@ class EMTrack int8_t sign() const { return fCharge; } float dcaXY() const { return fDCAxy; } float dcaZ() const { return fDCAz; } + float p() const { return fPt * std::cosh(fEta); } float px() const { return fPt * std::cos(fPhi); } float py() const { return fPt * std::sin(fPhi); } float pz() const { return fPt * std::sinh(fEta); } @@ -62,7 +86,52 @@ class EMTrack std::vector ambiguousElectronsIds() const { return fAmbEleSelfIds; } float signed1Pt() const { return fCharge * 1.f / fPt; } + float pairDca3DinSigmaOTF() const { return fPairDCA3DinSigmaOTF; } + void setPairDca3DinSigmaOTF(float dca) { fPairDCA3DinSigmaOTF = dca; } + + void setConversionPointXYZ(float x, float y, float z) + { + fVx = x; + fVy = y; + fVz = z; + } + float vx() const { return fVx; } + float vy() const { return fVy; } + float vz() const { return fVz; } + float v0radius() const { return std::sqrt(std::pow(fVx, 2) + std::pow(fVy, 2)); } + float eta_cp() const { return std::atanh(fVz / sqrt(pow(fVx, 2) + pow(fVy, 2) + pow(fVz, 2))); } + float phi_cp() const { return std::atan2(fVy, fVx); } + + void setPositiveLegPtEtaPhiM(float pt, float eta, float phi, float m) + { + fVPos.SetPt(pt); + fVPos.SetEta(eta); + fVPos.SetPhi(phi); + fVPos.SetM(m); + } + void setNegativeLegPtEtaPhiM(float pt, float eta, float phi, float m) + { + fVNeg.SetPt(pt); + fVNeg.SetEta(eta); + fVNeg.SetPhi(phi); + fVNeg.SetM(m); + } + + ROOT::Math::PtEtaPhiMVector getPositiveLeg() const { return fVPos; } + ROOT::Math::PtEtaPhiMVector getNegativeLeg() const { return fVNeg; } + + void setGlobalPosId(int id) { fGlobalPosId = id; } + void setGlobalNegId(int id) { fGlobalNegId = id; } + int globalIndexPos() const { return fGlobalPosId; } + int globalIndexNeg() const { return fGlobalNegId; } + + void setAmbPosLegSelfIds(std::vector selfIds) { fAmbPosLegSelfIds = selfIds; } + void setAmbNegLegSelfIds(std::vector selfIds) { fAmbNegLegSelfIds = selfIds; } + std::vector ambiguousPosLegIds() const { return fAmbPosLegSelfIds; } + std::vector ambiguousNegLegIds() const { return fAmbNegLegSelfIds; } + protected: + int fDFId; int fGlobalId; int fCollisionId; int fTrackId; @@ -73,19 +142,32 @@ class EMTrack int8_t fCharge; float fDCAxy; float fDCAz; + float fPairDCA3DinSigmaOTF; bool fIsAmbiguous; std::vector fAmbEleSelfIds; + + int fGlobalPosId; + int fGlobalNegId; + ROOT::Math::PtEtaPhiMVector fVPos; + ROOT::Math::PtEtaPhiMVector fVNeg; + std::vector fAmbPosLegSelfIds; // for dileptons + std::vector fAmbNegLegSelfIds; // for dileptons + + // only for photon conversion point + float fVx; + float fVy; + float fVz; }; class EMTrackWithCov : public EMTrack { public: - EMTrackWithCov(int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, std::vector amb_ele_self_ids = {}, + EMTrackWithCov(int dfId, int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, std::vector amb_ele_self_ids = {}, float X = 0.f, float Y = 0.f, float Z = 0.f, float Alpha = 0.f, float Snp = 0.f, float Tgl = 0.f, float CYY = 0.f, float CZY = 0.f, float CZZ = 0.f, float CSnpY = 0.f, float CSnpZ = 0.f, float CSnpSnp = 0.f, float CTglY = 0.f, float CTglZ = 0.f, float CTglSnp = 0.f, float CTglTgl = 0.f, - float C1PtY = 0.f, float C1PtZ = 0.f, float C1PtSnp = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f) : EMTrack(globalId, collisionId, trackId, pt, eta, phi, mass, charge, dcaXY, dcaZ, amb_ele_self_ids) + float C1PtY = 0.f, float C1PtZ = 0.f, float C1PtSnp = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f) : EMTrack(dfId, globalId, collisionId, trackId, pt, eta, phi, mass, charge, dcaXY, dcaZ, amb_ele_self_ids) { fX = X; fY = Y; @@ -133,6 +215,10 @@ class EMTrackWithCov : public EMTrack float c1PtTgl() const { return fC1PtTgl; } float c1Pt21Pt2() const { return fC1Pt21Pt2; } + void setCYY(float cYY) { fCYY = cYY; } + void setCZY(float cZY) { fCZY = cZY; } + void setCZZ(float cZZ) { fCZZ = cZZ; } + protected: float fX; float fY; @@ -157,5 +243,5 @@ class EMTrackWithCov : public EMTrack float fC1Pt21Pt2; }; -} // namespace o2::aod::pwgem::photonmeson::utils::emtrack -#endif // PWGEM_PHOTONMESON_UTILS_EMTRACK_H_ +} // namespace o2::aod::pwgem::dilepton::utils +#endif // PWGEM_DILEPTON_UTILS_EMTRACK_H_ diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index 67830f4eee0..9e817a59630 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -56,6 +56,36 @@ float fwdDcaXYinSigma(T const& track) } } //_______________________________________________________________________ +template +float sigmaPt(T const& track) +{ + return std::sqrt(track.c1Pt21Pt2()) / std::pow(track.signed1Pt(), 2); // pT resolution +} +//_______________________________________________________________________ +template +float sigmaPhi(T const& track) +{ + return std::sqrt(track.cSnpSnp()) / std::sqrt(1.f - std::pow(track.snp(), 2)); // phi resolution +} +//_______________________________________________________________________ +template +float sigmaTheta(T const& track) +{ + return std::sqrt(track.cTglTgl()) / (1.f + std::pow(track.tgl(), 2)); // theta resolution = lambda resolution. // lambda = pi/2 - theta. theta is polar angle. +} +//_______________________________________________________________________ +template +float sigmaEta(T const& track) +{ + return std::sqrt(track.cTglTgl()) / std::sqrt(1.f + std::pow(track.tgl(), 2)); +} +//_______________________________________________________________________ +template +float sigmaP(T const& track) +{ + // p = 1/1/pT x 1/cos(lambda); + return std::sqrt(std::pow(1.f / track.signed1Pt(), 4) * ((1.f + std::pow(track.tgl(), 2)) * track.c1Pt21Pt2() + 1.f / (1.f + std::pow(track.tgl(), 2)) * std::pow(track.signed1Pt() * track.tgl(), 2) * track.cTglTgl() - 2.f * track.signed1Pt() * track.tgl() * track.c1PtTgl())); +} //_______________________________________________________________________ } // namespace o2::aod::pwgem::dilepton::utils::emtrackutil #endif // PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ diff --git a/PWGEM/Dilepton/Utils/EventHistograms.h b/PWGEM/Dilepton/Utils/EventHistograms.h new file mode 100644 index 00000000000..410cf65120e --- /dev/null +++ b/PWGEM/Dilepton/Utils/EventHistograms.h @@ -0,0 +1,329 @@ +// Copyright 2019-2020 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. + +/// \header file for histograms +/// \author daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ +#define PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ +using namespace o2::framework; + +namespace o2::aod::pwgem::dilepton::utils::eventhistogram +{ +const int nbin_ev = 14; +template +void addEventHistograms(HistogramRegistry* fRegistry) +{ + // event info + auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{nbin_ev, 0.5, nbin_ev + 0.5}}, false); + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "FT0AND"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "No TF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "No ITS ROF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "No Same Bunch Pileup"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "Is Vertex ITS-TPC"); + hCollisionCounter->GetXaxis()->SetBinLabel(8, "Is Vertex ITS-TPC-TRD"); + hCollisionCounter->GetXaxis()->SetBinLabel(9, "Is Vertex ITS-TPC-TOF"); + hCollisionCounter->GetXaxis()->SetBinLabel(10, "sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(11, "|Z_{vtx}| < 10 cm"); + hCollisionCounter->GetXaxis()->SetBinLabel(12, "NoCollInTimeRangeStandard"); + hCollisionCounter->GetXaxis()->SetBinLabel(13, "Calibrated Q vector"); + hCollisionCounter->GetXaxis()->SetBinLabel(14, "accepted"); + + fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); + fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0A_HMpp", "hCentFT0A for HM pp;centrality FT0A (%)", kTH1F, {{100, 0, 1}}, false); + fRegistry->add("Event/before/hCentFT0C_HMpp", "hCentFT0C for HM pp;centrality FT0C (%)", kTH1F, {{100, 0, 1}}, false); + fRegistry->add("Event/before/hCentFT0M_HMpp", "hCentFT0M for HM pp;centrality FT0M (%)", kTH1F, {{100, 0, 1}}, false); + fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); + fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); + fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{60, 0, 60000}, {200, 0, 20000}}, false); + fRegistry->add("Event/before/hNTracksPVvsOccupancy", "hNTracksPVvsOccupancy;N_{track} to PV;N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); + fRegistry->add("Event/before/hSpherocity", "hSpherocity;spherocity", kTH1F, {{100, 0, 1}}, false); + + if constexpr (nmod == 2) { // Q2 + fRegistry->add("Event/before/hQ2xFT0M_CentFT0C", "hQ2xFT0M_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0M}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFT0M_CentFT0C", "hQ2yFT0M_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0M}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xFT0A_CentFT0C", "hQ2xFT0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0A}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFT0A_CentFT0C", "hQ2yFT0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0A}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xFT0C_CentFT0C", "hQ2xFT0C_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0C}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFT0C_CentFT0C", "hQ2yFT0C_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0C}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xBPos_CentFT0C", "hQ2xBPos_CentFT0C;centrality FT0C (%);Q_{2,x}^{BPos}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yBPos_CentFT0C", "hQ2yBPos_CentFT0C;centrality FT0C (%);Q_{2,y}^{BPos}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xBNeg_CentFT0C", "hQ2xBNeg_CentFT0C;centrality FT0C (%);Q_{2,x}^{BNeg}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yBNeg_CentFT0C", "hQ2yBNeg_CentFT0C;centrality FT0C (%);Q_{2,y}^{BNeg}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xBTot_CentFT0C", "hQ2xBTot_CentFT0C;centrality FT0C (%);Q_{2,x}^{BTot}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yBTot_CentFT0C", "hQ2yBTot_CentFT0C;centrality FT0C (%);Q_{2,y}^{BTot}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + + fRegistry->add("Event/before/hEP2FT0M_CentFT0C", "2nd harmonics event plane FT0M;centrality FT0C (%);#Psi_{2}^{FT0M} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2FT0A_CentFT0C", "2nd harmonics event plane FT0A;centrality FT0C (%);#Psi_{2}^{FT0A} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2FT0C_CentFT0C", "2nd harmonics event plane FT0C;centrality FT0C (%);#Psi_{2}^{FT0C} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2BPos_CentFT0C", "2nd harmonics event plane BPos;centrality FT0C (%);#Psi_{2}^{BPos} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2BNeg_CentFT0C", "2nd harmonics event plane BNeg;centrality FT0C (%);#Psi_{2}^{BNeg} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2BTot_CentFT0C", "2nd harmonics event plane BTot;centrality FT0C (%);#Psi_{2}^{BTot} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + + fRegistry->add("Event/before/hPrfQ2FT0MQ2BPos_CentFT0C", "Q_{2}^{FT0M} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0M} #upoint Q_{2}^{BPos}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0MQ2BNeg_CentFT0C", "Q_{2}^{FT0M} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FT0M} #upoint Q_{2}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2BPosQ2BNeg_CentFT0C", "Q_{2}^{BPos} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{BPos} #upoint Q_{2}^{BNeg}", kTProfile, {{100, 0, 100}}, false); // this is common for FT0M, FT0A, FT0C, FV0A resolution. + fRegistry->add("Event/before/hPrfQ2FT0CQ2BPos_CentFT0C", "Q_{2}^{FT0C} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0C} #upoint Q_{2}^{BPos}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0CQ2BNeg_CentFT0C", "Q_{2}^{FT0C} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FT0C} #upoint Q_{2}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0CQ2BTot_CentFT0C", "Q_{2}^{FT0C} #upoint Q_{2}^{BTot};centrality FT0C (%);Q_{2}^{FT0C} #upoint Q_{2}^{BTot}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0AQ2BPos_CentFT0C", "Q_{2}^{FT0A} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0A} #upoint Q_{2}^{BPos}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0AQ2BNeg_CentFT0C", "Q_{2}^{FT0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FT0A} #upoint Q_{2}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0AQ2BTot_CentFT0C", "Q_{2}^{FT0A} #upoint Q_{2}^{BTot};centrality FT0C (%);Q_{2}^{FT0A} #upoint Q_{2}^{BTot}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FT0AQ2FT0C_CentFT0C", "Q_{2}^{FT0A} #upoint Q_{2}^{FT0C};centrality FT0C (%);Q_{2}^{FT0A} #upoint Q_{2}^{FT0C}", kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + } else if constexpr (nmod == 3) { // Q3 + fRegistry->add("Event/before/hQ3xFT0M_CentFT0C", "hQ3xFT0M_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0M}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFT0M_CentFT0C", "hQ3yFT0M_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0M}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xFT0A_CentFT0C", "hQ3xFT0A_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0A}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFT0A_CentFT0C", "hQ3yFT0A_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0A}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xFT0C_CentFT0C", "hQ3xFT0C_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0C}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFT0C_CentFT0C", "hQ3yFT0C_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0C}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xBPos_CentFT0C", "hQ3xBPos_CentFT0C;centrality FT0C (%);Q_{3,x}^{BPos}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yBPos_CentFT0C", "hQ3yBPos_CentFT0C;centrality FT0C (%);Q_{3,y}^{BPos}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xBNeg_CentFT0C", "hQ3xBNeg_CentFT0C;centrality FT0C (%);Q_{3,x}^{BNeg}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yBNeg_CentFT0C", "hQ3yBNeg_CentFT0C;centrality FT0C (%);Q_{3,y}^{BNeg}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xBTot_CentFT0C", "hQ3xBTot_CentFT0C;centrality FT0C (%);Q_{3,x}^{BTot}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yBTot_CentFT0C", "hQ3yBTot_CentFT0C;centrality FT0C (%);Q_{3,y}^{BTot}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + + fRegistry->add("Event/before/hEP3FT0M_CentFT0C", "3rd harmonics event plane FT0M;centrality FT0C (%);#Psi_{3}^{FT0M} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3FT0A_CentFT0C", "3rd harmonics event plane FT0A;centrality FT0C (%);#Psi_{3}^{FT0A} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3FT0C_CentFT0C", "3rd harmonics event plane FT0C;centrality FT0C (%);#Psi_{3}^{FT0C} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3BPos_CentFT0C", "3rd harmonics event plane BPos;centrality FT0C (%);#Psi_{3}^{BPos} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3BNeg_CentFT0C", "3rd harmonics event plane BNeg;centrality FT0C (%);#Psi_{3}^{BNeg} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3BTot_CentFT0C", "3rd harmonics event plane BTot;centrality FT0C (%);#Psi_{3}^{BTot} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + + fRegistry->add("Event/before/hPrfQ3FT0MQ3BPos_CentFT0C", "Q_{3}^{FT0M} #upoint Q_{3}^{BPos};centrality FT0C (%);Q_{3}^{FT0M} #upoint Q_{3}^{BPos}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0MQ3BNeg_CentFT0C", "Q_{3}^{FT0M} #upoint Q_{3}^{BNeg};centrality FT0C (%);Q_{3}^{FT0M} #upoint Q_{3}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3BPosQ3BNeg_CentFT0C", "Q_{3}^{BPos} #upoint Q_{3}^{BNeg};centrality FT0C (%);Q_{3}^{BPos} #upoint Q_{3}^{BNeg}", kTProfile, {{100, 0, 100}}, false); // this is common for FT0M, FT0A, FT0C, FV0A resolution. + fRegistry->add("Event/before/hPrfQ3FT0CQ3BPos_CentFT0C", "Q_{3}^{FT0C} #upoint Q_{3}^{BPos};centrality FT0C (%);Q_{3}^{FT0C} #upoint Q_{3}^{BPos}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0CQ3BNeg_CentFT0C", "Q_{3}^{FT0C} #upoint Q_{3}^{BNeg};centrality FT0C (%);Q_{3}^{FT0C} #upoint Q_{3}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0CQ3BTot_CentFT0C", "Q_{3}^{FT0C} #upoint Q_{3}^{BTot};centrality FT0C (%);Q_{3}^{FT0C} #upoint Q_{3}^{BTot}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0AQ3BPos_CentFT0C", "Q_{3}^{FT0A} #upoint Q_{3}^{BPos};centrality FT0C (%);Q_{3}^{FT0A} #upoint Q_{3}^{BPos}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0AQ3BNeg_CentFT0C", "Q_{3}^{FT0A} #upoint Q_{3}^{BNeg};centrality FT0C (%);Q_{3}^{FT0A} #upoint Q_{3}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0AQ3BTot_CentFT0C", "Q_{3}^{FT0A} #upoint Q_{3}^{BTot};centrality FT0C (%);Q_{3}^{FT0A} #upoint Q_{3}^{BTot}", kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FT0AQ3FT0C_CentFT0C", "Q_{3}^{FT0A} #upoint Q_{3}^{FT0C};centrality FT0C (%);Q_{3}^{FT0A} #upoint Q_{3}^{FT0C}", kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + } + // else if constexpr (nmod == 4) { // Q4 + // fRegistry->add("Event/before/hQ4xFT0M_CentFT0C", "hQ4xFT0M_CentFT0C;centrality FT0C (%);Q_{4,x}^{FT0M}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4yFT0M_CentFT0C", "hQ4yFT0M_CentFT0C;centrality FT0C (%);Q_{4,y}^{FT0M}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4xFT0A_CentFT0C", "hQ4xFT0A_CentFT0C;centrality FT0C (%);Q_{4,x}^{FT0A}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4yFT0A_CentFT0C", "hQ4yFT0A_CentFT0C;centrality FT0C (%);Q_{4,y}^{FT0A}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4xFT0C_CentFT0C", "hQ4xFT0C_CentFT0C;centrality FT0C (%);Q_{4,x}^{FT0C}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4yFT0C_CentFT0C", "hQ4yFT0C_CentFT0C;centrality FT0C (%);Q_{4,y}^{FT0C}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4xBPos_CentFT0C", "hQ4xBPos_CentFT0C;centrality FT0C (%);Q_{4,x}^{BPos}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4yBPos_CentFT0C", "hQ4yBPos_CentFT0C;centrality FT0C (%);Q_{4,y}^{BPos}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4xBNeg_CentFT0C", "hQ4xBNeg_CentFT0C;centrality FT0C (%);Q_{4,x}^{BNeg}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4yBNeg_CentFT0C", "hQ4yBNeg_CentFT0C;centrality FT0C (%);Q_{4,y}^{BNeg}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4xBTot_CentFT0C", "hQ4xBTot_CentFT0C;centrality FT0C (%);Q_{4,x}^{BTot}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + // fRegistry->add("Event/before/hQ4yBTot_CentFT0C", "hQ4yBTot_CentFT0C;centrality FT0C (%);Q_{4,y}^{BTot}", kTH2F, {{100, 0, 100}, {200, -10, +10}}, false); + + // fRegistry->add("Event/before/hEP4FT0M_CentFT0C", "4rd harmonics event plane FT0M;centrality FT0C (%);#Psi_{4}^{FT0M} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + // fRegistry->add("Event/before/hEP4FT0A_CentFT0C", "4rd harmonics event plane FT0A;centrality FT0C (%);#Psi_{4}^{FT0A} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + // fRegistry->add("Event/before/hEP4FT0C_CentFT0C", "4rd harmonics event plane FT0C;centrality FT0C (%);#Psi_{4}^{FT0C} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + // fRegistry->add("Event/before/hEP4BPos_CentFT0C", "4rd harmonics event plane BPos;centrality FT0C (%);#Psi_{4}^{BPos} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + // fRegistry->add("Event/before/hEP4BNeg_CentFT0C", "4rd harmonics event plane BNeg;centrality FT0C (%);#Psi_{4}^{BNeg} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + // fRegistry->add("Event/before/hEP4BTot_CentFT0C", "4rd harmonics event plane BTot;centrality FT0C (%);#Psi_{4}^{BTot} (rad.)", kTH2F, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + + // fRegistry->add("Event/before/hPrfQ4FT0MQ4BPos_CentFT0C", "Q_{4}^{FT0M} #upoint Q_{4}^{BPos};centrality FT0C (%);Q_{4}^{FT0M} #upoint Q_{4}^{BPos}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0MQ4BNeg_CentFT0C", "Q_{4}^{FT0M} #upoint Q_{4}^{BNeg};centrality FT0C (%);Q_{4}^{FT0M} #upoint Q_{4}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4BPosQ4BNeg_CentFT0C", "Q_{4}^{BPos} #upoint Q_{4}^{BNeg};centrality FT0C (%);Q_{4}^{BPos} #upoint Q_{4}^{BNeg}", kTProfile, {{100, 0, 100}}, false); // this is common for FT0M, FT0A, FT0C, FV0A resolution. + // fRegistry->add("Event/before/hPrfQ4FT0CQ4BPos_CentFT0C", "Q_{4}^{FT0C} #upoint Q_{4}^{BPos};centrality FT0C (%);Q_{4}^{FT0C} #upoint Q_{4}^{BPos}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0CQ4BNeg_CentFT0C", "Q_{4}^{FT0C} #upoint Q_{4}^{BNeg};centrality FT0C (%);Q_{4}^{FT0C} #upoint Q_{4}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0CQ4BTot_CentFT0C", "Q_{4}^{FT0C} #upoint Q_{4}^{BTot};centrality FT0C (%);Q_{4}^{FT0C} #upoint Q_{4}^{BTot}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0AQ4BPos_CentFT0C", "Q_{4}^{FT0A} #upoint Q_{4}^{BPos};centrality FT0C (%);Q_{4}^{FT0A} #upoint Q_{4}^{BPos}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0AQ4BNeg_CentFT0C", "Q_{4}^{FT0A} #upoint Q_{4}^{BNeg};centrality FT0C (%);Q_{4}^{FT0A} #upoint Q_{4}^{BNeg}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0AQ4BTot_CentFT0C", "Q_{4}^{FT0A} #upoint Q_{4}^{BTot};centrality FT0C (%);Q_{4}^{FT0A} #upoint Q_{4}^{BTot}", kTProfile, {{100, 0, 100}}, false); + // fRegistry->add("Event/before/hPrfQ4FT0AQ4FT0C_CentFT0C", "Q_{4}^{FT0A} #upoint Q_{4}^{FT0C};centrality FT0C (%);Q_{4}^{FT0A} #upoint Q_{4}^{FT0C}", kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + // } + fRegistry->addClone("Event/before/", "Event/after/"); +} + +template +void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, const float /*weight*/ = 1.f) +{ + static constexpr std::string_view event_types[2] = {"before/", "after/"}; + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 10.0); + } + if (abs(collision.posZ()) < 10.0) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 12.0); + } + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C"), collision.centFT0C()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M"), collision.centFT0M()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A_HMpp"), collision.centFT0A()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C_HMpp"), collision.centFT0C()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M_HMpp"), collision.centFT0M()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hNTracksPVvsOccupancy"), collision.multNTracksPV(), collision.trackOccupancyInTimeRange()); + + if constexpr (nmod == 2) { // Q2 + std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; + std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; + std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; + std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; + std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFT0M_CentFT0C"), collision.centFT0C(), collision.q2xft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFT0M_CentFT0C"), collision.centFT0C(), collision.q2yft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFT0A_CentFT0C"), collision.centFT0C(), collision.q2xft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFT0A_CentFT0C"), collision.centFT0C(), collision.q2yft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFT0C_CentFT0C"), collision.centFT0C(), collision.q2xft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFT0C_CentFT0C"), collision.centFT0C(), collision.q2yft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xBPos_CentFT0C"), collision.centFT0C(), collision.q2xbpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yBPos_CentFT0C"), collision.centFT0C(), collision.q2ybpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xBNeg_CentFT0C"), collision.centFT0C(), collision.q2xbneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yBNeg_CentFT0C"), collision.centFT0C(), collision.q2ybneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xBTot_CentFT0C"), collision.centFT0C(), collision.q2xbtot()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yBTot_CentFT0C"), collision.centFT0C(), collision.q2ybtot()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FT0M_CentFT0C"), collision.centFT0C(), collision.ep2ft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FT0A_CentFT0C"), collision.centFT0C(), collision.ep2ft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FT0C_CentFT0C"), collision.centFT0C(), collision.ep2ft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2BPos_CentFT0C"), collision.centFT0C(), collision.ep2bpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2BNeg_CentFT0C"), collision.centFT0C(), collision.ep2bneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2BTot_CentFT0C"), collision.centFT0C(), collision.ep2btot()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0MQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0m, q2bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0MQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0m, q2bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2BPosQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2bpos, q2bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0AQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0a, q2bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0AQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0a, q2bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0AQ2BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0a, q2btot)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0CQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0c, q2bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0CQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0c, q2bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0CQ2BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0c, q2btot)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ2FT0AQ2FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0a, q2ft0c)); + } else if constexpr (nmod == 3) { // Q3 + std::array q3ft0m = {collision.q3xft0m(), collision.q3yft0m()}; + std::array q3ft0a = {collision.q3xft0a(), collision.q3yft0a()}; + std::array q3ft0c = {collision.q3xft0c(), collision.q3yft0c()}; + std::array q3bpos = {collision.q3xbpos(), collision.q3ybpos()}; + std::array q3bneg = {collision.q3xbneg(), collision.q3ybneg()}; + std::array q3btot = {collision.q3xbtot(), collision.q3ybtot()}; + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3xFT0M_CentFT0C"), collision.centFT0C(), collision.q3xft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3yFT0M_CentFT0C"), collision.centFT0C(), collision.q3yft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3xFT0A_CentFT0C"), collision.centFT0C(), collision.q3xft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3yFT0A_CentFT0C"), collision.centFT0C(), collision.q3yft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3xFT0C_CentFT0C"), collision.centFT0C(), collision.q3xft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3yFT0C_CentFT0C"), collision.centFT0C(), collision.q3yft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3xBPos_CentFT0C"), collision.centFT0C(), collision.q3xbpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3yBPos_CentFT0C"), collision.centFT0C(), collision.q3ybpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3xBNeg_CentFT0C"), collision.centFT0C(), collision.q3xbneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3yBNeg_CentFT0C"), collision.centFT0C(), collision.q3ybneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3xBTot_CentFT0C"), collision.centFT0C(), collision.q3xbtot()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ3yBTot_CentFT0C"), collision.centFT0C(), collision.q3ybtot()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP3FT0M_CentFT0C"), collision.centFT0C(), collision.ep3ft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP3FT0A_CentFT0C"), collision.centFT0C(), collision.ep3ft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP3FT0C_CentFT0C"), collision.centFT0C(), collision.ep3ft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP3BPos_CentFT0C"), collision.centFT0C(), collision.ep3bpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP3BNeg_CentFT0C"), collision.centFT0C(), collision.ep3bneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP3BTot_CentFT0C"), collision.centFT0C(), collision.ep3btot()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0MQ3BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0m, q3bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0MQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0m, q3bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3BPosQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3bpos, q3bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0AQ3BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0a, q3bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0AQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0a, q3bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0AQ3BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0a, q3btot)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0CQ3BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0c, q3bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0CQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0c, q3bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0CQ3BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0c, q3btot)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0AQ3FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0a, q3ft0c)); + } else if constexpr (nmod == 4) { // Q4 + std::array q4ft0m = {collision.q4xft0m(), collision.q4yft0m()}; + std::array q4ft0a = {collision.q4xft0a(), collision.q4yft0a()}; + std::array q4ft0c = {collision.q4xft0c(), collision.q4yft0c()}; + std::array q4bpos = {collision.q4xbpos(), collision.q4ybpos()}; + std::array q4bneg = {collision.q4xbneg(), collision.q4ybneg()}; + std::array q4btot = {collision.q4xbtot(), collision.q4ybtot()}; + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0M_CentFT0C"), collision.centFT0C(), collision.q4xft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0M_CentFT0C"), collision.centFT0C(), collision.q4yft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0A_CentFT0C"), collision.centFT0C(), collision.q4xft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0A_CentFT0C"), collision.centFT0C(), collision.q4yft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0C_CentFT0C"), collision.centFT0C(), collision.q4xft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0C_CentFT0C"), collision.centFT0C(), collision.q4yft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBPos_CentFT0C"), collision.centFT0C(), collision.q4xbpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBPos_CentFT0C"), collision.centFT0C(), collision.q4ybpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBNeg_CentFT0C"), collision.centFT0C(), collision.q4xbneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBNeg_CentFT0C"), collision.centFT0C(), collision.q4ybneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBTot_CentFT0C"), collision.centFT0C(), collision.q4xbtot()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBTot_CentFT0C"), collision.centFT0C(), collision.q4ybtot()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0M_CentFT0C"), collision.centFT0C(), collision.ep4ft0m()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0A_CentFT0C"), collision.centFT0C(), collision.ep4ft0a()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0C_CentFT0C"), collision.centFT0C(), collision.ep4ft0c()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BPos_CentFT0C"), collision.centFT0C(), collision.ep4bpos()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BNeg_CentFT0C"), collision.centFT0C(), collision.ep4bneg()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BTot_CentFT0C"), collision.centFT0C(), collision.ep4btot()); + + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0MQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0m, q4bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0MQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0m, q4bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4BPosQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4bpos, q4bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4btot)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4bpos)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4bneg)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4btot)); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4ft0c)); + } +} + +} // namespace o2::aod::pwgem::dilepton::utils::eventhistogram + +#endif // PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ diff --git a/PWGEM/PhotonMeson/Utils/EventMixingHandler.h b/PWGEM/Dilepton/Utils/EventMixingHandler.h similarity index 90% rename from PWGEM/PhotonMeson/Utils/EventMixingHandler.h rename to PWGEM/Dilepton/Utils/EventMixingHandler.h index ff5c800d61b..1fa83c60240 100644 --- a/PWGEM/PhotonMeson/Utils/EventMixingHandler.h +++ b/PWGEM/Dilepton/Utils/EventMixingHandler.h @@ -12,14 +12,14 @@ /// \event mixing handler /// \author daiki.sekihata@cern.ch -#ifndef PWGEM_PHOTONMESON_UTILS_EVENTMIXINGHANDLER_H_ -#define PWGEM_PHOTONMESON_UTILS_EVENTMIXINGHANDLER_H_ +#ifndef PWGEM_DILEPTON_UTILS_EVENTMIXINGHANDLER_H_ +#define PWGEM_DILEPTON_UTILS_EVENTMIXINGHANDLER_H_ #include #include #include -namespace o2::aod::pwgem::photonmeson::utils +namespace o2::aod::pwgem::dilepton::utils { template class EventMixingHandler @@ -73,5 +73,5 @@ class EventMixingHandler std::map> fMapMixBins; // map : e.g. -> pair std::map> fMap_Tracks_per_collision; // map : e.g. pair -> track array }; -} // namespace o2::aod::pwgem::photonmeson::utils -#endif // PWGEM_PHOTONMESON_UTILS_EVENTMIXINGHANDLER_H_ +} // namespace o2::aod::pwgem::dilepton::utils +#endif // PWGEM_DILEPTON_UTILS_EVENTMIXINGHANDLER_H_ diff --git a/PWGEM/Dilepton/Utils/MCUtilities.h b/PWGEM/Dilepton/Utils/MCUtilities.h index 6e1467d21c3..668f1056e75 100644 --- a/PWGEM/Dilepton/Utils/MCUtilities.h +++ b/PWGEM/Dilepton/Utils/MCUtilities.h @@ -20,7 +20,7 @@ #include //_______________________________________________________________________ -namespace o2::aod::pwgem::dilepton::mcutil +namespace o2::aod::pwgem::dilepton::utils::mcutil { enum class EM_HFeeType : int { kUndef = -1, @@ -31,6 +31,160 @@ enum class EM_HFeeType : int { kBCe_Be_DiffB = 4, // LS }; +//_______________________________________________________________________ +template +int FindCommonMotherFrom2ProngsWithoutPDG(TMCParticle1 const& p1, TMCParticle2 const& p2) +{ + if (p1.globalIndex() == p2.globalIndex()) + return -1; // mc particle p1 and p2 is identical. reject. + + if (!p1.has_mothers()) + return -1; + if (!p2.has_mothers()) + return -1; + + // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); + + int motherid1 = p1.mothersIds()[0]; + int motherid2 = p2.mothersIds()[0]; + + // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); + + if (motherid1 != motherid2) + return -1; + return motherid1; +} +//_______________________________________________________________________ +template +int FindCommonMotherFrom3ProngsWithoutPDG(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticle3 const& p3) +{ + if (p1.globalIndex() == p2.globalIndex()) + return -1; // mc particle p1 and p2 are identical. reject. + if (p2.globalIndex() == p3.globalIndex()) + return -1; // mc particle p2 and p3 are identical. reject. + if (p3.globalIndex() == p1.globalIndex()) + return -1; // mc particle p3 and p1 are identical. reject. + + if (!p1.has_mothers()) + return -1; + if (!p2.has_mothers()) + return -1; + if (!p3.has_mothers()) + return -1; + + // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); + + int motherid1 = p1.mothersIds()[0]; + int motherid2 = p2.mothersIds()[0]; + int motherid3 = p3.mothersIds()[0]; + + // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); + + if (motherid1 != motherid2) + return -1; + if (motherid2 != motherid3) + return -1; + if (motherid3 != motherid1) + return -1; + return motherid1; +} +//_______________________________________________________________________ +template +int FindCommonMotherFrom2Prongs(TMCParticle1 const& p1, TMCParticle2 const& p2, const int expected_pdg1, const int expected_pdg2, const int expected_mother_pdg, TMCParticles const& mcparticles) +{ + if (p1.globalIndex() == p2.globalIndex()) + return -1; // mc particle p1 and p2 is identical. reject. + + if (p1.pdgCode() != expected_pdg1) + return -1; + if (p2.pdgCode() != expected_pdg2) + return -1; + + if (!p1.has_mothers()) + return -1; + if (!p2.has_mothers()) + return -1; + + // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); + + int motherid1 = p1.mothersIds()[0]; + auto mother1 = mcparticles.iteratorAt(motherid1); + int mother1_pdg = mother1.pdgCode(); + + int motherid2 = p2.mothersIds()[0]; + auto mother2 = mcparticles.iteratorAt(motherid2); + int mother2_pdg = mother2.pdgCode(); + + // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); + + if (motherid1 != motherid2) + return -1; + if (mother1_pdg != mother2_pdg) + return -1; + if (mother1_pdg != expected_mother_pdg) + return -1; + return motherid1; +} +//_______________________________________________________________________ +template +int FindCommonMotherFrom3Prongs(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticle3 const& p3, const int expected_pdg1, const int expected_pdg2, const int expected_pdg3, const int expected_mother_pdg, TMCParticles const& mcparticles) +{ + if (p1.globalIndex() == p2.globalIndex()) + return -1; // mc particle p1 and p2 are identical. reject. + if (p2.globalIndex() == p3.globalIndex()) + return -1; // mc particle p2 and p3 are identical. reject. + if (p3.globalIndex() == p1.globalIndex()) + return -1; // mc particle p3 and p1 are identical. reject. + + if (p1.pdgCode() != expected_pdg1) + return -1; + if (p2.pdgCode() != expected_pdg2) + return -1; + if (p3.pdgCode() != expected_pdg3) + return -1; + + if (!p1.has_mothers()) + return -1; + if (!p2.has_mothers()) + return -1; + if (!p3.has_mothers()) + return -1; + + // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); + + int motherid1 = p1.mothersIds()[0]; + auto mother1 = mcparticles.iteratorAt(motherid1); + int mother1_pdg = mother1.pdgCode(); + + int motherid2 = p2.mothersIds()[0]; + auto mother2 = mcparticles.iteratorAt(motherid2); + int mother2_pdg = mother2.pdgCode(); + + int motherid3 = p3.mothersIds()[0]; + auto mother3 = mcparticles.iteratorAt(motherid3); + int mother3_pdg = mother3.pdgCode(); + + // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); + + if (motherid1 != motherid2) + return -1; + if (motherid2 != motherid3) + return -1; + if (motherid3 != motherid1) + return -1; + + if (mother1_pdg != mother2_pdg) + return -1; + if (mother2_pdg != mother3_pdg) + return -1; + if (mother3_pdg != mother1_pdg) + return -1; + + if (mother1_pdg != expected_mother_pdg) + return -1; + return motherid1; +} +//_______________________________________________________________________ template int IsFromBeauty(TMCParticle const& p, TMCParticles const& mcparticles) { @@ -39,6 +193,11 @@ int IsFromBeauty(TMCParticle const& p, TMCParticles const& mcparticles) } int motherid = p.mothersIds()[0]; // first mother index + auto mp_tmp = mcparticles.iteratorAt(motherid); + if (abs(mp_tmp.pdgCode()) < 1e+9 && (std::to_string(abs(mp_tmp.pdgCode()))[std::to_string(abs(mp_tmp.pdgCode())).length() - 2] == '5' && std::to_string(abs(mp_tmp.pdgCode()))[std::to_string(abs(mp_tmp.pdgCode())).length() - 3] == '5') && abs(mp_tmp.pdgCode()) % 2 == 1) { + return -999; // reject bottomonia + } + while (motherid > -1) { if (motherid < mcparticles.size()) { // protect against bad mother indices. why is this needed? auto mp = mcparticles.iteratorAt(motherid); @@ -66,6 +225,10 @@ int IsFromCharm(TMCParticle const& p, TMCParticles const& mcparticles) } int motherid = p.mothersIds()[0]; // first mother index + auto mp_tmp = mcparticles.iteratorAt(motherid); + if (abs(mp_tmp.pdgCode()) < 1e+9 && (std::to_string(abs(mp_tmp.pdgCode()))[std::to_string(abs(mp_tmp.pdgCode())).length() - 2] == '4' && std::to_string(abs(mp_tmp.pdgCode()))[std::to_string(abs(mp_tmp.pdgCode())).length() - 3] == '4') && abs(mp_tmp.pdgCode()) % 2 == 1) { + return -999; // reject bottomonia + } while (motherid > -1) { if (motherid < mcparticles.size()) { // protect against bad mother indices. why is this needed? auto mp = mcparticles.iteratorAt(motherid); @@ -136,14 +299,14 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp } } - bool is_direct_from_b1 = abs(mothers_pdg1[0]) < 1e+9 && (std::to_string(mothers_pdg1[0])[std::to_string(mothers_pdg1[0]).length() - 3] == '5' || std::to_string(mothers_pdg1[0])[std::to_string(mothers_pdg1[0]).length() - 4] == '5'); - bool is_direct_from_b2 = abs(mothers_pdg2[0]) < 1e+9 && (std::to_string(mothers_pdg2[0])[std::to_string(mothers_pdg2[0]).length() - 3] == '5' || std::to_string(mothers_pdg2[0])[std::to_string(mothers_pdg2[0]).length() - 4] == '5'); - bool is_prompt_c1 = abs(mothers_pdg1[0]) < 1e+9 && (std::to_string(mothers_pdg1[0])[std::to_string(mothers_pdg1[0]).length() - 3] == '4' || std::to_string(mothers_pdg1[0])[std::to_string(mothers_pdg1[0]).length() - 4] == '4') && IsFromBeauty(p1, mcparticles) < 0; - bool is_prompt_c2 = abs(mothers_pdg2[0]) < 1e+9 && (std::to_string(mothers_pdg2[0])[std::to_string(mothers_pdg2[0]).length() - 3] == '4' || std::to_string(mothers_pdg2[0])[std::to_string(mothers_pdg2[0]).length() - 4] == '4') && IsFromBeauty(p2, mcparticles) < 0; - bool is_c_from_b1 = abs(mothers_pdg1[0]) < 1e+9 && (std::to_string(mothers_pdg1[0])[std::to_string(mothers_pdg1[0]).length() - 3] == '4' || std::to_string(mothers_pdg1[0])[std::to_string(mothers_pdg1[0]).length() - 4] == '4') && IsFromBeauty(p1, mcparticles) > 0; - bool is_c_from_b2 = abs(mothers_pdg2[0]) < 1e+9 && (std::to_string(mothers_pdg2[0])[std::to_string(mothers_pdg2[0]).length() - 3] == '4' || std::to_string(mothers_pdg2[0])[std::to_string(mothers_pdg2[0]).length() - 4] == '4') && IsFromBeauty(p2, mcparticles) > 0; + bool is_direct_from_b1 = IsFromBeauty(p1, mcparticles) > 0 && IsFromCharm(p1, mcparticles) < 0; + bool is_direct_from_b2 = IsFromBeauty(p2, mcparticles) > 0 && IsFromCharm(p2, mcparticles) < 0; + bool is_prompt_c1 = IsFromBeauty(p1, mcparticles) < 0 && IsFromCharm(p1, mcparticles) > 0; + bool is_prompt_c2 = IsFromBeauty(p2, mcparticles) < 0 && IsFromCharm(p2, mcparticles) > 0; + bool is_c_from_b1 = IsFromBeauty(p1, mcparticles) > 0 && IsFromCharm(p1, mcparticles) > 0; + bool is_c_from_b2 = IsFromBeauty(p2, mcparticles) > 0 && IsFromCharm(p2, mcparticles) > 0; - if (is_prompt_c1 && is_prompt_c2 && p1.pdgCode() * p2.pdgCode() < 0) { + if (is_direct_from_b1 && is_direct_from_b2 && p1.pdgCode() * p2.pdgCode() < 0) { mothers_id1.clear(); mothers_pdg1.clear(); mothers_id2.clear(); @@ -152,8 +315,9 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp mothers_pdg1.shrink_to_fit(); mothers_id2.shrink_to_fit(); mothers_pdg2.shrink_to_fit(); - return static_cast(EM_HFeeType::kCe_Ce); // cc->ee, decay type = 0 - } else if (is_direct_from_b1 && is_direct_from_b2 && p1.pdgCode() * p2.pdgCode() < 0) { + return static_cast(EM_HFeeType::kBe_Be); // bb->ee, decay type = 2 + } + if (is_prompt_c1 && is_prompt_c2 && p1.pdgCode() * p2.pdgCode() < 0) { mothers_id1.clear(); mothers_pdg1.clear(); mothers_id2.clear(); @@ -162,8 +326,9 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp mothers_pdg1.shrink_to_fit(); mothers_id2.shrink_to_fit(); mothers_pdg2.shrink_to_fit(); - return static_cast(EM_HFeeType::kBe_Be); // bb->ee, decay type = 2 - } else if (is_c_from_b1 && is_c_from_b2 && p1.pdgCode() * p2.pdgCode() < 0) { + return static_cast(EM_HFeeType::kCe_Ce); // cc->ee, decay type = 0 + } + if (is_c_from_b1 && is_c_from_b2 && p1.pdgCode() * p2.pdgCode() < 0) { mothers_id1.clear(); mothers_pdg1.clear(); mothers_id2.clear(); @@ -173,7 +338,8 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp mothers_id2.shrink_to_fit(); mothers_pdg2.shrink_to_fit(); return static_cast(EM_HFeeType::kBCe_BCe); // b->c->e and b->c->e, decay type = 1 - } else if ((is_direct_from_b1 && is_c_from_b2) || (is_direct_from_b2 && is_c_from_b1)) { + } + if ((is_direct_from_b1 && is_c_from_b2) || (is_direct_from_b2 && is_c_from_b1)) { if (p1.pdgCode() * p2.pdgCode() < 0) { // ULS for (auto& mid1 : mothers_id1) { for (auto& mid2 : mothers_id2) { @@ -374,5 +540,5 @@ bool isBeautyBaryon(T const& track) } //_______________________________________________________________________ //_______________________________________________________________________ -} // namespace o2::aod::pwgem::dilepton::mcutil +} // namespace o2::aod::pwgem::dilepton::utils::mcutil #endif // PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ diff --git a/PWGEM/Dilepton/Utils/MomentumSmearer.h b/PWGEM/Dilepton/Utils/MomentumSmearer.h index 2dc3c979529..002e7d6d247 100644 --- a/PWGEM/Dilepton/Utils/MomentumSmearer.h +++ b/PWGEM/Dilepton/Utils/MomentumSmearer.h @@ -18,10 +18,10 @@ #include #include #include -#include #include #include #include +#include #include "Framework/Logger.h" using namespace o2::framework; @@ -41,8 +41,10 @@ class MomentumSmearer setResEtaHistName(resEtaHistName); setResPhiPosHistName(resPhiPosHistName); setResPhiNegHistName(resPhiNegHistName); - setResPhiNegHistName(""); - setResPhiNegHistName(""); + setEffFileName(""); + setEffHistName(""); + setDCAFileName(""); + setDCAHistName(""); init(); } @@ -54,8 +56,25 @@ class MomentumSmearer setResEtaHistName(resEtaHistName); setResPhiPosHistName(resPhiPosHistName); setResPhiNegHistName(resPhiNegHistName); + setEffFileName(effFileName); + setEffHistName(effHistName); + setDCAFileName(""); + setDCAHistName(""); + init(); + } + + /// Constructor with resolution histograms and efficiency and dca + MomentumSmearer(TString resFileName, TString resPtHistName, TString resEtaHistName, TString resPhiPosHistName, TString resPhiNegHistName, TString effFileName, TString effHistName, TString dcaFileName, TString dcaHistName) + { + setResFileName(resFileName); + setResPtHistName(resPtHistName); + setResEtaHistName(resEtaHistName); + setResPhiPosHistName(resPhiPosHistName); setResPhiNegHistName(resPhiNegHistName); - setResPhiNegHistName(resPhiNegHistName); + setEffFileName(effFileName); + setEffHistName(effHistName); + setDCAFileName(dcaFileName); + setDCAHistName(dcaHistName); init(); } @@ -66,38 +85,42 @@ class MomentumSmearer void getResolutionHistos(TList* list) { - fArrResoPt = reinterpret_cast(list->FindObject(fResPtHistName)); - if (!fArrResoPt) { + fResoPt = reinterpret_cast(list->FindObject(fResPtHistName)); + if (!fResoPt) { LOGP(fatal, "Could not open {} from file {}", fResPtHistName.Data(), fResFileName.Data()); } - fArrResoEta = reinterpret_cast(list->FindObject(fResEtaHistName)); - if (!fArrResoEta) { + fResoEta = reinterpret_cast(list->FindObject(fResEtaHistName)); + if (!fResoEta) { LOGP(fatal, "Could not open {} from file {}", fResEtaHistName.Data(), fResFileName.Data()); } - fArrResoPhi_Pos = reinterpret_cast(list->FindObject(fResPhiPosHistName)); - if (!fArrResoPhi_Pos) { + fResoPhi_Pos = reinterpret_cast(list->FindObject(fResPhiPosHistName)); + if (!fResoPhi_Pos) { LOGP(fatal, "Could not open {} from file {}", fResPhiPosHistName.Data(), fResFileName.Data()); } - fArrResoPhi_Neg = reinterpret_cast(list->FindObject(fResPhiNegHistName)); - if (!fArrResoPhi_Neg) { + fResoPhi_Neg = reinterpret_cast(list->FindObject(fResPhiNegHistName)); + if (!fResoPhi_Neg) { LOGP(fatal, "Could not open {} from file {}", fResPhiNegHistName.Data(), fResFileName.Data()); } } - /*template - void getEfficiencyHistos(T dir){ - - }*/ + void fillVecReso(TH2F* fReso, std::vector& fVecReso) + { + TAxis* axisPt = fReso->GetXaxis(); + int nBinsPt = axisPt->GetNbins(); + for (int i = 1; i <= nBinsPt; i++) { + fVecReso.push_back(reinterpret_cast(fReso->ProjectionY("", i, i))); + } + } void init() { if (fInitialized) return; - if ((fResFileName.BeginsWith("alien://") || fEffFileName.BeginsWith("alien://")) && (!fFromCcdb)) { + if ((fResFileName.BeginsWith("alien://") || fEffFileName.BeginsWith("alien://") || fDCAFileName.BeginsWith("alien://")) && (!fFromCcdb)) { TGrid::Connect("alien://"); } @@ -134,27 +157,33 @@ class MomentumSmearer } } if (fResType != 0) { - fArrResoPt = reinterpret_cast(listRes->FindObject(fResPtHistName)); - if (!fArrResoPt) { + fResoPt = reinterpret_cast(listRes->FindObject(fResPtHistName)); + if (!fResoPt) { LOGP(fatal, "Could not open {} from file {}", fResPtHistName.Data(), fResFileName.Data()); } - fArrResoEta = reinterpret_cast(listRes->FindObject(fResEtaHistName)); - if (!fArrResoEta) { + fResoEta = reinterpret_cast(listRes->FindObject(fResEtaHistName)); + if (!fResoEta) { LOGP(fatal, "Could not open {} from file {}", fResEtaHistName.Data(), fResFileName.Data()); } - fArrResoPhi_Pos = reinterpret_cast(listRes->FindObject(fResPhiPosHistName)); - if (!fArrResoPhi_Pos) { + fResoPhi_Pos = reinterpret_cast(listRes->FindObject(fResPhiPosHistName)); + if (!fResoPhi_Pos) { LOGP(fatal, "Could not open {} from file {}", fResPhiPosHistName.Data(), fResFileName.Data()); } - fArrResoPhi_Neg = reinterpret_cast(listRes->FindObject(fResPhiNegHistName)); - if (!fArrResoPhi_Neg) { + fResoPhi_Neg = reinterpret_cast(listRes->FindObject(fResPhiNegHistName)); + if (!fResoPhi_Neg) { LOGP(fatal, "Could not open {} from file {}", fResPhiNegHistName.Data(), fResFileName.Data()); } + fillVecReso(fResoPt, fVecResoPt); + fillVecReso(fResoEta, fVecResoEta); + fillVecReso(fResoPhi_Pos, fVecResoPhi_Pos); + fillVecReso(fResoPhi_Neg, fVecResoPhi_Neg); } - delete listRes; + + if (!fFromCcdb) + delete listRes; LOGP(info, "Set efficiency histos"); TList* listEff = new TList(); @@ -189,85 +218,107 @@ class MomentumSmearer } } if (fEffType != 0) { - fArrEff = reinterpret_cast(listEff->FindObject(fEffHistName)); - if (!fArrEff) { + fEff = reinterpret_cast(listEff->FindObject(fEffHistName)); + if (!fEff) { LOGP(fatal, "Could not open {} from file {}", fEffHistName.Data(), fEffFileName.Data()); } // check which type is used - if (dynamic_cast(fArrEff)) { + if (dynamic_cast(fEff)) { fEffType = 3; LOGP(info, "Use 3d efficiency histo (pt, eta, phi)"); - } else if (dynamic_cast(fArrEff)) { + } else if (dynamic_cast(fEff)) { fEffType = 2; LOGP(info, "Use 2d efficiency histo (pt, eta)"); - } else if (dynamic_cast(fArrEff)) { + } else if (dynamic_cast(fEff)) { fEffType = 1; LOGP(info, "Use 1d efficiency histo (pt)"); } else { LOGP(fatal, "Could not identify type of histogram {}", fEffHistName.Data()); } } - delete listEff; + + if (!fFromCcdb) + delete listEff; + + LOGP(info, "Set DCA histos"); + TList* listDCA = new TList(); + if (fFromCcdb) { + if (fCcdbPathDCA.CompareTo("") != 0) { + fDCAType = 1; + listDCA = fCcdb->getForTimeStamp(fCcdbPathDCA.Data(), fTimestamp); + if (!listDCA) { + LOGP(fatal, "Could not get DCA file from CCDB"); + return; + } + } + } else { + if (fDCAFileName.CompareTo("") != 0) { + fDCAType = 1; + TFile* fFile = TFile::Open(fDCAFileName); + if (!fFile) { + LOGP(fatal, "Could not open DCA file {}", fDCAFileName.Data()); + return; + } + if (fFile->GetListOfKeys()->Contains("ccdb_object")) { + listDCA = reinterpret_cast(fFile->Get("ccdb_object")); + } else { + for (TObject* keyAsObj : *(fFile->GetListOfKeys())) { + auto key = dynamic_cast(keyAsObj); + TObject* arr = nullptr; + fFile->GetObject(key->GetName(), arr); + listDCA->Add(arr); + } + } + fFile->Close(); + } + } + if (fDCAType != 0) { + fDCA = reinterpret_cast(listDCA->FindObject(fDCAHistName)); + if (!fDCA) { + LOGP(fatal, "Could not open {} from file {}", fDCAHistName.Data(), fDCAFileName.Data()); + } + fillVecReso(fDCA, fVecDCA); + } + + if (!fFromCcdb) + delete listDCA; fInitialized = true; } - void applySmearing(const int ch, const float ptgen, const float etagen, const float phigen, float& ptsmeared, float& etasmeared, float& phismeared) + void applySmearing(float ptgen, float vargen, float multiply, float& varsmeared, TH2F* fReso, std::vector& fVecReso) { - if (fResType == 0) { - ptsmeared = ptgen; - etasmeared = etagen; - phismeared = phigen; - return; - } - // smear pt - int ptbin = reinterpret_cast(fArrResoPt->At(0))->GetXaxis()->FindBin(ptgen); + TAxis* axisPt = fReso->GetXaxis(); + int nBinsPt = axisPt->GetNbins(); + int ptbin = axisPt->FindBin(ptgen); if (ptbin < 1) { ptbin = 1; } - if (ptbin > fArrResoPt->GetLast()) { - ptbin = fArrResoPt->GetLast(); + if (ptbin > nBinsPt) { + ptbin = nBinsPt; } float smearing = 0.; - TH1D* thisHist = reinterpret_cast(fArrResoPt->At(ptbin)); - if (thisHist->GetEntries() > 0) { - smearing = thisHist->GetRandom() * ptgen; - } - ptsmeared = ptgen - smearing; - - // smear eta - ptbin = reinterpret_cast(fArrResoEta->At(0))->GetXaxis()->FindBin(ptgen); - if (ptbin < 1) { - ptbin = 1; - } - if (ptbin > fArrResoEta->GetLast()) { - ptbin = fArrResoEta->GetLast(); - } - smearing = 0.; - thisHist = reinterpret_cast(fArrResoEta->At(ptbin)); - if (thisHist->GetEntries() > 0) { - smearing = thisHist->GetRandom(); + if (fVecReso[ptbin - 1]->GetEntries() > 0) { + smearing = fVecReso[ptbin - 1]->GetRandom() * multiply; } - etasmeared = etagen - smearing; + varsmeared = vargen - smearing; + } - // smear phi - ptbin = reinterpret_cast(fArrResoPhi_Pos->At(0))->GetXaxis()->FindBin(ptgen); - if (ptbin < 1) { - ptbin = 1; - } - if (ptbin > fArrResoPhi_Pos->GetLast()) { - ptbin = fArrResoPhi_Pos->GetLast(); + void applySmearing(const int ch, const float ptgen, const float etagen, const float phigen, float& ptsmeared, float& etasmeared, float& phismeared) + { + if (fResType == 0) { + ptsmeared = ptgen; + etasmeared = etagen; + phismeared = phigen; + return; } - smearing = 0.; - if (ch < 0) { - thisHist = reinterpret_cast(fArrResoPhi_Neg->At(ptbin)); + applySmearing(ptgen, ptgen, ptgen, ptsmeared, fResoPt, fVecResoPt); + applySmearing(ptgen, etagen, 1., etasmeared, fResoEta, fVecResoEta); + if (ch > 0) { + applySmearing(ptgen, phigen, 1., phismeared, fResoPhi_Pos, fVecResoPhi_Pos); } else { - thisHist = reinterpret_cast(fArrResoPhi_Pos->At(ptbin)); + applySmearing(ptgen, phigen, 1., phismeared, fResoPhi_Neg, fVecResoPhi_Neg); } - if (thisHist->GetEntries() > 0) { - smearing = thisHist->GetRandom(); - } - phismeared = phigen - smearing; } float getEfficiency(float pt, float eta, float phi) @@ -278,7 +329,7 @@ class MomentumSmearer } if (fEffType == 1) { - TH1F* hist = reinterpret_cast(fArrEff); + TH1F* hist = reinterpret_cast(fEff); int ptbin = hist->GetXaxis()->FindBin(pt); int ptbin_max = hist->GetXaxis()->GetNbins(); // make sure that no underflow or overflow bins are used @@ -290,7 +341,7 @@ class MomentumSmearer } if (fEffType == 2) { - TH2F* hist = reinterpret_cast(fArrEff); + TH2F* hist = reinterpret_cast(fEff); int ptbin = hist->GetXaxis()->FindBin(pt); int ptbin_max = hist->GetXaxis()->GetNbins(); int etabin = hist->GetYaxis()->FindBin(eta); @@ -308,7 +359,7 @@ class MomentumSmearer } if (fEffType == 3) { - TH3F* hist = reinterpret_cast(fArrEff); + TH3F* hist = reinterpret_cast(fEff); int ptbin = hist->GetXaxis()->FindBin(pt); int ptbin_max = hist->GetXaxis()->GetNbins(); int etabin = hist->GetYaxis()->FindBin(eta); @@ -334,6 +385,28 @@ class MomentumSmearer return 1.; } + float getDCA(float ptsmeared) + { + if (fDCAType == 0) { + return 0.; + } + + TAxis* axisPt = fDCA->GetXaxis(); + int nBinsPt = axisPt->GetNbins(); + int ptbin = axisPt->FindBin(ptsmeared); + if (ptbin < 1) { + ptbin = 1; + } + if (ptbin > nBinsPt) { + ptbin = nBinsPt; + } + float dca = 0.; + if (fVecDCA[ptbin - 1]->GetEntries() > 0) { + dca = fVecDCA[ptbin - 1]->GetRandom(); + } + return dca; + } + // setters void setResFileName(TString resFileName) { fResFileName = resFileName; } void setResPtHistName(TString resPtHistName) { fResPtHistName = resPtHistName; } @@ -342,8 +415,11 @@ class MomentumSmearer void setResPhiNegHistName(TString resPhiNegHistName) { fResPhiNegHistName = resPhiNegHistName; } void setEffFileName(TString effFileName) { fEffFileName = effFileName; } void setEffHistName(TString effHistName) { fEffHistName = effHistName; } + void setDCAFileName(TString dcaFileName) { fDCAFileName = dcaFileName; } + void setDCAHistName(TString dcaHistName) { fDCAHistName = dcaHistName; } void setCcdbPathRes(TString ccdbPathRes) { fCcdbPathRes = ccdbPathRes; } void setCcdbPathEff(TString ccdbPathEff) { fCcdbPathEff = ccdbPathEff; } + void setCcdbPathDCA(TString ccdbPathDCA) { fCcdbPathDCA = ccdbPathDCA; } void setCcdb(Service ccdb) { fCcdb = ccdb; @@ -359,13 +435,16 @@ class MomentumSmearer TString getResPhiNegHistName() { return fResPhiNegHistName; } TString getEffFileName() { return fEffFileName; } TString getEffHistName() { return fEffHistName; } - TObjArray* getArrResoPt() { return fArrResoPt; } - TObjArray* getArrResoEta() { return fArrResoEta; } - TObjArray* getArrResoPhiPos() { return fArrResoPhi_Pos; } - TObjArray* getArrResoPhiNeg() { return fArrResoPhi_Neg; } - TObject* getArrEff() { return fArrEff; } + TString getDCAFileName() { return fDCAFileName; } + TString getDCaHistName() { return fDCAHistName; } + TH2F* getHistResoPt() { return fResoPt; } + TH2F* getHistResoEta() { return fResoEta; } + TH2F* getHistResoPhiPos() { return fResoPhi_Pos; } + TH2F* getHistResoPhiNeg() { return fResoPhi_Neg; } + TObject* getHistEff() { return fEff; } TString getCcdbPathRes() { return fCcdbPathRes; } TString getCcdbPathEff() { return fCcdbPathEff; } + TString getCcdbPathDCA() { return fCcdbPathDCA; } private: bool fInitialized = false; @@ -376,15 +455,25 @@ class MomentumSmearer TString fResPhiNegHistName; TString fEffFileName; TString fEffHistName; + TString fDCAFileName; + TString fDCAHistName; TString fCcdbPathRes; TString fCcdbPathEff; + TString fCcdbPathDCA; int fEffType = 0; int fResType = 0; - TObjArray* fArrResoPt; - TObjArray* fArrResoEta; - TObjArray* fArrResoPhi_Pos; - TObjArray* fArrResoPhi_Neg; - TObject* fArrEff; + int fDCAType = 0; + TH2F* fResoPt; + TH2F* fResoEta; + TH2F* fResoPhi_Pos; + TH2F* fResoPhi_Neg; + std::vector fVecResoPt; + std::vector fVecResoEta; + std::vector fVecResoPhi_Pos; + std::vector fVecResoPhi_Neg; + TObject* fEff; + TH2F* fDCA; + std::vector fVecDCA; int64_t fTimestamp; bool fFromCcdb = false; Service fCcdb; diff --git a/PWGEM/Dilepton/Utils/PairUtilities.h b/PWGEM/Dilepton/Utils/PairUtilities.h index 75efafafc6b..77496d185c2 100644 --- a/PWGEM/Dilepton/Utils/PairUtilities.h +++ b/PWGEM/Dilepton/Utils/PairUtilities.h @@ -18,21 +18,115 @@ #include #include #include "Math/SMatrix.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" #include "Common/Core/RecoDecay.h" #include "ReconstructionDataFormats/TrackFwd.h" //_______________________________________________________________________ namespace o2::aod::pwgem::dilepton::utils::pairutil { + +enum class DileptonPairType : int { + kDielectron = 0, + kDimuon = 1, +}; +enum class DileptonAnalysisType : int { + kQC = 0, + kUPC = 1, + kFlowV2 = 2, + kFlowV3 = 3, + kPolarization = 4, + kVM = 5, + kHFll = 6, +}; + using SMatrix55 = ROOT::Math::SMatrix>; using SMatrix5 = ROOT::Math::SVector; +//_______________________________________________________________________ +template +void getAngleHX(TTrack1 const& t1, TTrack2 const& t2, const float m1, const float m2, const float beamE1, const float beamE2, const float beamP1, const float beamP2, float& cos_thetaHX, float& phiHX) +{ + ROOT::Math::PxPyPzEVector v1(t1.px(), t1.py(), t1.pz(), std::sqrt(std::pow(t1.p(), 2) + std::pow(m1, 2))); + ROOT::Math::PxPyPzEVector v2(t2.px(), t2.py(), t2.pz(), std::sqrt(std::pow(t2.p(), 2) + std::pow(m2, 2))); + ROOT::Math::PxPyPzEVector v12 = v1 + v2; + + ROOT::Math::PxPyPzEVector Beam1(0., 0., -beamP1, beamE1); + ROOT::Math::PxPyPzEVector Beam2(0., 0., beamP2, beamE2); + + // Boost to center of mass frame. i.e. rest frame of pair + ROOT::Math::Boost boostv12{v12.BoostToCM()}; + ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; + ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam1_CM{(boostv12(Beam1).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam2_CM{(boostv12(Beam2).Vect()).Unit()}; + // LOGF(info, "boostv12(v12).Vect().X() = %f, boostv12(v12).Vect().Y() = %f, boostv12(v12).Vect().Z() = %f", boostv12(v12).Vect().X(), boostv12(v12).Vect().Y(), boostv12(v12).Vect().Z()); // expected to be (0,0,0) + + // Helicity frame + ROOT::Math::XYZVectorF zaxis_HX{(v12.Vect()).Unit()}; + ROOT::Math::XYZVectorF yaxis_HX{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_HX{(yaxis_HX.Cross(zaxis_HX)).Unit()}; + + // pdgCode : 11 for electron, -11 for positron + // pdgCode : 13 for negative muon, -13 for positive muon + // LOGF(info, "zaxis_HX.Dot(v1_CM) = %f , zaxis_HX.Dot(v2_CM) = %f", zaxis_HX.Dot(v1_CM), zaxis_HX.Dot(v2_CM)); // absolute value is identical. only sign is opposite. + + if constexpr (isMC) { + cos_thetaHX = t1.pdgCode() < 0 ? zaxis_HX.Dot(v1_CM) : zaxis_HX.Dot(v2_CM); + phiHX = t1.pdgCode() < 0 ? std::atan2(yaxis_HX.Dot(v1_CM), xaxis_HX.Dot(v1_CM)) : std::atan2(yaxis_HX.Dot(v2_CM), xaxis_HX.Dot(v2_CM)); + } else { + cos_thetaHX = t1.sign() > 0 ? zaxis_HX.Dot(v1_CM) : zaxis_HX.Dot(v2_CM); + phiHX = t1.sign() > 0 ? std::atan2(yaxis_HX.Dot(v1_CM), xaxis_HX.Dot(v1_CM)) : std::atan2(yaxis_HX.Dot(v2_CM), xaxis_HX.Dot(v2_CM)); + } +} + +//_______________________________________________________________________ +//_______________________________________________________________________ +template +void getAngleCS(TTrack1 const& t1, TTrack2 const& t2, const float m1, const float m2, const float beamE1, const float beamE2, const float beamP1, const float beamP2, float& cos_thetaCS, float& phiCS) +{ + ROOT::Math::PxPyPzEVector v1(t1.px(), t1.py(), t1.pz(), std::sqrt(std::pow(t1.p(), 2) + std::pow(m1, 2))); + ROOT::Math::PxPyPzEVector v2(t2.px(), t2.py(), t2.pz(), std::sqrt(std::pow(t2.p(), 2) + std::pow(m2, 2))); + ROOT::Math::PxPyPzEVector v12 = v1 + v2; + + ROOT::Math::PxPyPzEVector Beam1(0., 0., -beamP1, beamE1); + ROOT::Math::PxPyPzEVector Beam2(0., 0., beamP2, beamE2); + + // Boost to center of mass frame. i.e. rest frame of pair + ROOT::Math::Boost boostv12{v12.BoostToCM()}; + ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; + ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam1_CM{(boostv12(Beam1).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam2_CM{(boostv12(Beam2).Vect()).Unit()}; + // LOGF(info, "boostv12(v12).Vect().X() = %f, boostv12(v12).Vect().Y() = %f, boostv12(v12).Vect().Z() = %f", boostv12(v12).Vect().X(), boostv12(v12).Vect().Y(), boostv12(v12).Vect().Z()); // expected to be (0,0,0) + + // Collins-Soper frame + ROOT::Math::XYZVectorF zaxis_CS{((Beam1_CM.Unit() - Beam2_CM.Unit()).Unit())}; + ROOT::Math::XYZVectorF yaxis_CS{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_CS{(yaxis_CS.Cross(zaxis_CS)).Unit()}; + + // pdgCode : 11 for electron, -11 for positron + // pdgCode : 13 for negative muon, -13 for positive muon + // LOGF(info, "zaxis_CS.Dot(v1_CM) = %f , zaxis_CS.Dot(v2_CM) = %f", zaxis_CS.Dot(v1_CM), zaxis_CS.Dot(v2_CM)); // absolute value is identical. only sign is opposite. + + if constexpr (isMC) { + cos_thetaCS = t1.pdgCode() < 0 ? zaxis_CS.Dot(v1_CM) : zaxis_CS.Dot(v2_CM); + phiCS = t1.pdgCode() < 0 ? std::atan2(yaxis_CS.Dot(v1_CM), xaxis_CS.Dot(v1_CM)) : std::atan2(yaxis_CS.Dot(v2_CM), xaxis_CS.Dot(v2_CM)); + } else { + cos_thetaCS = t1.sign() > 0 ? zaxis_CS.Dot(v1_CM) : zaxis_CS.Dot(v2_CM); + phiCS = t1.sign() > 0 ? std::atan2(yaxis_CS.Dot(v1_CM), xaxis_CS.Dot(v1_CM)) : std::atan2(yaxis_CS.Dot(v2_CM), xaxis_CS.Dot(v2_CM)); + } +} + +//_______________________________________________________________________ template -bool isSVFound(TDCAFitter fitter, TCollision const& collision, TTrack const& t1, TTrack const& t2, float& pca, float& lxy) +bool isSVFound(TDCAFitter fitter, TCollision const& collision, TTrack const& t1, TTrack const& t2, float& pca, float& lxy, float& cosPA) { std::array svpos = {0.}; // secondary vertex position - // std::array pvec0 = {0.}; - // std::array pvec1 = {0.}; + std::array pvec0 = {0.}; + std::array pvec1 = {0.}; auto pTrack = getTrackParCov(t1); auto nTrack = getTrackParCov(t2); @@ -43,21 +137,32 @@ bool isSVFound(TDCAFitter fitter, TCollision const& collision, TTrack const& t1, for (int i = 0; i < 3; i++) { svpos[i] = vtx[i]; } - // fitter.getTrack(0).getPxPyPzGlo(pvec0); // positive - // fitter.getTrack(1).getPxPyPzGlo(pvec1); // negative - // std::array pvxyz{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; + fitter.getTrack(0).getPxPyPzGlo(pvec0); // positive + fitter.getTrack(1).getPxPyPzGlo(pvec1); // negative + std::array pvxyz{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; // float pt = RecoDecay::sqrtSumOfSquares(pvxyz[0], pvxyz[1]); // LOGF(info, "pair pT = %f GeV/c at sv", pt); pca = std::sqrt(fitter.getChi2AtPCACandidate()); // distance between 2 legs. lxy = RecoDecay::sqrtSumOfSquares(svpos[0] - collision.posX(), svpos[1] - collision.posY()); + cosPA = RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, svpos, pvxyz); return true; } else { pca = 999.f; lxy = 999.f; + cosPA = 999.f; return false; } } + +//_______________________________________________________________________ +// function call without cosPA +template +bool isSVFound(TDCAFitter fitter, TCollision const& collision, TTrack const& t1, TTrack const& t2, float& pca, float& lxy) +{ + float cosPA = 999.f; + return isSVFound(fitter, collision, t1, t2, pca, lxy, cosPA); +} //_______________________________________________________________________ template bool isSVFoundFwd(TFwdDCAFitter fitter, TCollision const& collision, TTrack const& t1, TTrack const& t2, float& pca, float& lxy) @@ -110,6 +215,106 @@ bool isSVFoundFwd(TFwdDCAFitter fitter, TCollision const& collision, TTrack cons } } //_______________________________________________________________________ +inline float getPhivPair(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, int cpos, int cneg, float bz) +{ + // cos(phiv) = w*a /|w||a| + // with w = u x v + // and a = u x z / |u x z| , unit vector perpendicular to v12 and z-direction (magnetic field) + // u = v12 / |v12| , the unit vector of v12 + // v = v1 x v2 / |v1 x v2| , unit vector perpendicular to v1 and v2 + + // momentum of e+ and e- in (ax,ay,az) axis. Note that az=0 by definition. + // vector product of pep X pem + // std::array arr_pos{t1.GetPx(), t1.GetPy(), t1.GetPz()}; + // std::array arr_ele{t2.GetPx(), t2.GetPy(), t2.GetPz()}; + std::array arr_pos{pxpos, pypos, pzpos}; + std::array arr_ele{pxneg, pyneg, pzneg}; + std::array pos_x_ele{0, 0, 0}; + // LOGF(info, "Q1 = %d , Q2 = %d", cpos, cneg); + + if (cpos * cneg > 0) { // Like Sign + if (bz < 0) { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } else { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } + } else { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } else { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } + } + } else { // Unlike Sign + if (bz > 0) { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } else { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } + } else { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } else { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } + } + } + + // unit vector of pep X pem + float vx = pos_x_ele[0] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + float vy = pos_x_ele[1] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + float vz = pos_x_ele[2] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + + // unit vector of (pep+pem) + float ux = (pxpos + pxneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + float uy = (pypos + pyneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + float uz = (pzpos + pzneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + + float ax = uy / std::sqrt(ux * ux + uy * uy); + float ay = -ux / std::sqrt(ux * ux + uy * uy); + + // The third axis defined by vector product (ux,uy,uz)X(vx,vy,vz) + float wx = uy * vz - uz * vy; + float wy = uz * vx - ux * vz; + // by construction, (wx,wy,wz) must be a unit vector. Measure angle between (wx,wy,wz) and (ax,ay,0). + // The angle between them should be small if the pair is conversion. This function then returns values close to pi! + auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; + + // if (!std::isfinite(std::acos(wx * ax + wy * ay))) { + // LOGF(info, "pxpos = %f, pypos = %f, pzpos = %f", pxpos, pypos, pzpos); + // LOGF(info, "pxneg = %f, pyneg = %f, pzneg = %f", pxneg, pyneg, pzneg); + // LOGF(info, "pos_x_ele[0] = %f, pos_x_ele[1] = %f, pos_x_ele[2] = %f", pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + // LOGF(info, "ux = %f, uy = %f, uz = %f", ux, uy, uz); + // LOGF(info, "ax = %f, ay = %f", ax, ay); + // LOGF(info, "wx = %f, wy = %f", wx, wy); + // LOGF(info, "wx * ax + wy * ay = %f", wx * ax + wy * ay); + // LOGF(info, "std::acos(wx * ax + wy * ay) = %f", std::acos(wx * ax + wy * ay)); + // LOGF(info, "std::acos(clipToPM1(wx * ax + wy * ay)) = %f", std::acos(clipToPM1(wx * ax + wy * ay))); + // } + + return std::acos(clipToPM1(wx * ax + wy * ay)); // phiv in [0,pi] //cosPhiV = wx * ax + wy * ay; +} +//_______________________________________________________________________ +inline float getPsiPair(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) +{ + auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; + float ptot2 = RecoDecay::p2(pxpos, pypos, pzpos) * RecoDecay::p2(pxneg, pyneg, pzneg); + float argcos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); + float thetaPos = std::atan2(RecoDecay::sqrtSumOfSquares(pxpos, pypos), pzpos); + float thetaNeg = std::atan2(RecoDecay::sqrtSumOfSquares(pxneg, pyneg), pzneg); + float argsin = (thetaNeg - thetaPos) / std::acos(clipToPM1(argcos)); + return std::asin(clipToPM1(argsin)); +} +//_______________________________________________________________________ +inline float getOpeningAngle(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) +{ + auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; + float ptot2 = RecoDecay::p2(pxpos, pypos, pzpos) * RecoDecay::p2(pxneg, pyneg, pzneg); + float argcos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); + return std::acos(clipToPM1(argcos)); +} //_______________________________________________________________________ } // namespace o2::aod::pwgem::dilepton::utils::pairutil #endif // PWGEM_DILEPTON_UTILS_PAIRUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Core/CMakeLists.txt b/PWGEM/PhotonMeson/Core/CMakeLists.txt index 68f4a662047..72a17aa1497 100644 --- a/PWGEM/PhotonMeson/Core/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Core/CMakeLists.txt @@ -10,25 +10,23 @@ # or submit itself to any jurisdiction. o2physics_add_library(PWGEMPhotonMesonCore - SOURCES EMEventCut.cxx - V0PhotonCut.cxx + SOURCES V0PhotonCut.cxx PHOSPhotonCut.cxx DalitzEECut.cxx - DimuonCut.cxx EMCPhotonCut.cxx PairCut.cxx + EMPhotonEventCut.cxx CutsLibrary.cxx HistogramsLibrary.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore) + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore) o2physics_target_root_dictionary(PWGEMPhotonMesonCore - HEADERS EMEventCut.h - V0PhotonCut.h + HEADERS V0PhotonCut.h DalitzEECut.h - DimuonCut.h PHOSPhotonCut.h EMCPhotonCut.h PairCut.h + EMPhotonEventCut.h CutsLibrary.h HistogramsLibrary.h LINKDEF PWGEMPhotonMesonCoreLinkDef.h) diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx index ffb8b915778..c2f313e6e62 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx @@ -36,9 +36,9 @@ std::vector splitString(const std::string& str, char delimiter) return ret; } //_______________________________________________ -EMEventCut* o2::aod::pwgem::photon::eventcuts::GetCut(const char* cutName) +EMPhotonEventCut* o2::aod::pwgem::photon::eventcuts::GetCut(const char* cutName) { - EMEventCut* cut = new EMEventCut(cutName, cutName); + EMPhotonEventCut* cut = new EMPhotonEventCut(cutName, cutName); std::string nameStr = cutName; if (!nameStr.compare("nocut")) { @@ -284,198 +284,185 @@ DalitzEECut* o2::aod::pwgem::photon::dalitzeecuts::GetCut(const char* cutName) DalitzEECut* cut = new DalitzEECut(cutName, cutName); std::string nameStr = cutName; // cut name should be like this mee0_120_minpt200_maxeta09_dca20_100_tpchadronbandrej_lowB in unit of MeV. - - if (!nameStr.compare("nocut")) { - // apply kinetic cuts - cut->SetTrackPtRange(0.1, 1e+10f); - cut->SetTrackEtaRange(-0.9, +0.9); - - // for pair - cut->SetMeeRange(0, 1e+10); - cut->SetMaxPhivPairMeeDep([](float mee) { return (mee - -0.028) / 0.0185; }); - cut->ApplyPhiV(false); - cut->ApplyPrefilter(false); - - // for track cuts - cut->SetMinNCrossedRowsTPC(40); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); - cut->SetChi2PerClusterTPC(0.0, 4.0); - cut->SetChi2PerClusterITS(0.0, 5.0); - cut->SetNClustersITS(4, 7); - cut->SetMaxDcaXY(1.0); - cut->SetMaxDcaZ(1.0); - return cut; - } - - if (!nameStr.compare("pc_itsib")) { - // for pair - cut->ApplyPhiV(true); - cut->SelectPhotonConversion(true); - cut->SetMeeRange(0.f, 0.03f); - cut->SetMaxPhivPairMeeDep([](float mee) { - return (mee - -0.028) / 0.0185; - }); - - // for track - cut->SetTrackPtRange(0.05f, 1e10f); - cut->SetTrackEtaRange(-0.9, +0.9); - cut->SetMinNCrossedRowsTPC(40); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); - cut->SetChi2PerClusterTPC(0.0, 4.0); - cut->SetChi2PerClusterITS(0.0, 5.0); - cut->SetNClustersITS(2, 7); - cut->SetMaxDcaXY(1.0); - cut->SetMaxDcaZ(1.0); - - // for PID - cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPConly)); - cut->SetTOFbetaRange(true, 0.0, 0.95); - cut->SetTPCNsigmaElRange(-3, +3); - cut->SetTPCNsigmaPiRange(0, 0); - return cut; - } - - float min_mass = 0.0; - float max_mass = 1e+10; - float min_pt = 0.05; - float max_eta = 0.9; - float min_dca3d_pair = 0.0; - float max_dca3d_pair = 1e+10; - std::vector tmp = splitString(nameStr, '_'); - for (size_t i = 0; i < tmp.size(); i++) { - // printf("string = %s , num = %d\n", tmp[i].data(), customAtoi(tmp[i])); - if (tmp[i].find("mee") != std::string::npos || tmp[i].find("mmumu") != std::string::npos) { - min_mass = static_cast(customAtoi(tmp[i])) * 1e-3; // convert MeV to GeV - max_mass = static_cast(customAtoi(tmp[i + 1])) * 1e-3; // convert MeV to GeV - } - if (tmp[i].find("minpt") != std::string::npos) { - min_pt = static_cast(customAtoi(tmp[i])) * 1e-3; // convert MeV to GeV - } - if (tmp[i].find("maxeta") != std::string::npos) { - max_eta = static_cast(customAtoi(tmp[i])) * 0.1; - } - if (tmp[i].find("dca") != std::string::npos) { - min_dca3d_pair = static_cast(customAtoi(tmp[i])) * 0.1; // 3d dca in sigma - max_dca3d_pair = static_cast(customAtoi(tmp[i + 1])) * 0.1; // 3d dca in sigma - } - } // end of split string loop - - // apply kinetic cuts - cut->SetTrackPtRange(min_pt, 1e+10f); - cut->SetTrackEtaRange(-max_eta, +max_eta); - - // for pair - cut->SetMeeRange(min_mass, max_mass); - cut->SetMaxPhivPairMeeDep([](float mee) { return (mee - -0.028) / 0.0185; }); - cut->SetPairDCARange(min_dca3d_pair, max_dca3d_pair); // in sigma - - cut->ApplyPhiV(true); - if (nameStr.find("wophiv") != std::string::npos) { - cut->ApplyPhiV(false); - } else if (nameStr.find("wphiv") != std::string::npos) { - cut->ApplyPhiV(true); - } - - cut->ApplyPrefilter(false); - if (nameStr.find("wpf") != std::string::npos) { - cut->ApplyPrefilter(true); - } else if (nameStr.find("wopf") != std::string::npos) { - cut->ApplyPrefilter(false); - } - - // for track cuts - cut->SetMinNCrossedRowsTPC(100); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); - cut->SetChi2PerClusterTPC(0.0, 4.0); - cut->SetChi2PerClusterITS(0.0, 5.0); - cut->SetNClustersITS(5, 7); - cut->SetMeanClusterSizeITSob(0, 16); - cut->SetMaxDcaXY(1.0); - cut->SetMaxDcaZ(1.0); - - if (nameStr.find("lowB") != std::string::npos) { - cut->SetMinNCrossedRowsTPC(40); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); - cut->SetChi2PerClusterTPC(0.0, 4.0); - cut->SetChi2PerClusterITS(0.0, 5.0); - cut->SetNClustersITS(4, 7); - cut->SetMeanClusterSizeITSob(0, 16); - cut->SetMaxDcaXY(1.0); - cut->SetMaxDcaZ(1.0); - } else if (nameStr.find("nominalB") != std::string::npos) { - cut->SetMinNCrossedRowsTPC(100); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); - cut->SetChi2PerClusterTPC(0.0, 4.0); - cut->SetChi2PerClusterITS(0.0, 5.0); - cut->SetNClustersITS(5, 7); - cut->SetMeanClusterSizeITSob(0, 16); - cut->SetMaxDcaXY(1.0); - cut->SetMaxDcaZ(1.0); - } - - // long pid name should be top, because of if--else if conditions. - - if (nameStr.find("mee") != std::string::npos) { // for electron - if (nameStr.find("tpcmupikaprrejortofreq") != std::string::npos) { - cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq)); - cut->SetTOFbetaRange(true, 0.0, 0.95); - cut->SetTPCNsigmaElRange(-2, +3); - cut->SetTPCNsigmaPiRange(-3, +3); - cut->SetTPCNsigmaKaRange(-3, +3); - cut->SetTPCNsigmaPrRange(-3, +3); - cut->SetTOFNsigmaElRange(-3, +3); - cut->SetTPCNsigmaMuRange(-2, +2); - cut->SetMuonExclusionTPC(true); - return cut; - } else if (nameStr.find("tpcpikaprrejortofreq") != std::string::npos) { - cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq)); - cut->SetTOFbetaRange(true, 0.0, 0.95); - cut->SetTPCNsigmaElRange(-2, +3); - cut->SetTPCNsigmaPiRange(-3, +3); - cut->SetTPCNsigmaKaRange(-3, +3); - cut->SetTPCNsigmaPrRange(-3, +3); - cut->SetTOFNsigmaElRange(-3, +3); - return cut; - } else if (nameStr.find("tpconly") != std::string::npos) { - cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPConly)); - cut->SetTOFbetaRange(true, 0.0, 0.95); - cut->SetTPCNsigmaElRange(-2, +3); - cut->SetTPCNsigmaPiRange(-3, +3); - return cut; - } else if (nameStr.find("tpcelonly") != std::string::npos) { - cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPConly)); - cut->SetTOFbetaRange(true, 0.0, 0.95); - cut->SetTPCNsigmaElRange(-2, +3); - cut->SetTPCNsigmaPiRange(0, 0); - return cut; - } else if (nameStr.find("mleidlocal") != std::string::npos) { - // cut->EnableEIDML(false, "/Users/d/dsekihat/pidml/", false, -1, "eid_lightgbm.onnx"); - return cut; - } else if (nameStr.find("mleid") != std::string::npos) { - // cut->EnableEIDML(true, "/Users/d/dsekihat/pidml/", false, -1, "eid_lightgbm.onnx"); - return cut; - } else { // not match electron cut - LOGF(info, Form("Did not find electron ID cut %s", cutName)); - return cut; - } - } else if (nameStr.find("mmumu") != std::string::npos) { // for muon - if (nameStr.find("tpctof") != std::string::npos) { - // for PID - cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kMuon_lowB)); - cut->SetTPCNsigmaElRange(-2, +2); // exclusion - cut->SetTPCNsigmaMuRange(-3, +3); - cut->SetTPCNsigmaPiRange(-3, +1e+10); - cut->SetTOFNsigmaMuRange(-3, +3); - cut->SetTOFNsigmaPiRange(-3, +1e+10); - return cut; - } else { // not match muon cut - LOGF(info, Form("Did not find muon ID cut %s", cutName)); - return cut; - } - } else { // match neither electron nor electron - LOGF(info, Form("Did not find any pid cut %s", cutName)); - return cut; - } + return cut; + + // if (!nameStr.compare("nocut")) { + // // apply kinetic cuts + // cut->SetTrackPtRange(0.1, 1e+10f); + // cut->SetTrackEtaRange(-0.9, +0.9); + // + // // for pair + // cut->SetMeeRange(0, 1e+10); + // cut->SetMaxPhivPairMeeDep([](float mee) { return (mee - -0.028) / 0.0185; }); + // cut->ApplyPhiV(false); + // cut->ApplyPrefilter(false); + // + // // for track cuts + // cut->SetMinNCrossedRowsTPC(40); + // cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + // cut->SetChi2PerClusterTPC(0.0, 4.0); + // cut->SetChi2PerClusterITS(0.0, 5.0); + // cut->SetNClustersITS(4, 7); + // cut->SetMaxDcaXY(1.0); + // cut->SetMaxDcaZ(1.0); + // return cut; + // } + // + // if (!nameStr.compare("pc_itsib")) { + // // for pair + // cut->ApplyPhiV(true); + // cut->SelectPhotonConversion(true); + // cut->SetMeeRange(0.f, 0.03f); + // cut->SetMaxPhivPairMeeDep([](float mee) { + // return (mee - -0.028) / 0.0185; + // }); + // + // // for track + // cut->SetTrackPtRange(0.05f, 1e10f); + // cut->SetTrackEtaRange(-0.9, +0.9); + // cut->SetMinNCrossedRowsTPC(40); + // cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + // cut->SetChi2PerClusterTPC(0.0, 4.0); + // cut->SetChi2PerClusterITS(0.0, 5.0); + // cut->SetNClustersITS(2, 7); + // cut->SetMaxDcaXY(1.0); + // cut->SetMaxDcaZ(1.0); + // + // // for PID + // cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPConly)); + // cut->SetTOFbetaRange(true, 0.0, 0.95); + // cut->SetTPCNsigmaElRange(-3, +3); + // cut->SetTPCNsigmaPiRange(0, 0); + // return cut; + // } + // + // float min_mass = 0.0; + // float max_mass = 1e+10; + // float min_pt = 0.05; + // float max_eta = 0.9; + // float min_dca3d_pair = 0.0; + // float max_dca3d_pair = 1e+10; + // std::vector tmp = splitString(nameStr, '_'); + // for (size_t i = 0; i < tmp.size(); i++) { + // // printf("string = %s , num = %d\n", tmp[i].data(), customAtoi(tmp[i])); + // if (tmp[i].find("mee") != std::string::npos || tmp[i].find("mmumu") != std::string::npos) { + // min_mass = static_cast(customAtoi(tmp[i])) * 1e-3; // convert MeV to GeV + // max_mass = static_cast(customAtoi(tmp[i + 1])) * 1e-3; // convert MeV to GeV + // } + // if (tmp[i].find("minpt") != std::string::npos) { + // min_pt = static_cast(customAtoi(tmp[i])) * 1e-3; // convert MeV to GeV + // } + // if (tmp[i].find("maxeta") != std::string::npos) { + // max_eta = static_cast(customAtoi(tmp[i])) * 0.1; + // } + // if (tmp[i].find("dca") != std::string::npos) { + // min_dca3d_pair = static_cast(customAtoi(tmp[i])) * 0.1; // 3d dca in sigma + // max_dca3d_pair = static_cast(customAtoi(tmp[i + 1])) * 0.1; // 3d dca in sigma + // } + // } // end of split string loop + // + // // apply kinetic cuts + // cut->SetTrackPtRange(min_pt, 1e+10f); + // cut->SetTrackEtaRange(-max_eta, +max_eta); + // + // // for pair + // cut->SetMeeRange(min_mass, max_mass); + // cut->SetMaxPhivPairMeeDep([](float mee) { return (mee - -0.028) / 0.0185; }); + // cut->SetPairDCARange(min_dca3d_pair, max_dca3d_pair); // in sigma + // + // cut->ApplyPhiV(true); + // if (nameStr.find("wophiv") != std::string::npos) { + // cut->ApplyPhiV(false); + // } else if (nameStr.find("wphiv") != std::string::npos) { + // cut->ApplyPhiV(true); + // } + // + // cut->ApplyPrefilter(false); + // if (nameStr.find("wpf") != std::string::npos) { + // cut->ApplyPrefilter(true); + // } else if (nameStr.find("wopf") != std::string::npos) { + // cut->ApplyPrefilter(false); + // } + // + // // for track cuts + // cut->SetMinNCrossedRowsTPC(100); + // cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + // cut->SetChi2PerClusterTPC(0.0, 4.0); + // cut->SetChi2PerClusterITS(0.0, 5.0); + // cut->SetNClustersITS(5, 7); + // cut->SetMeanClusterSizeITSob(0, 16); + // cut->SetMaxDcaXY(1.0); + // cut->SetMaxDcaZ(1.0); + // + // if (nameStr.find("lowB") != std::string::npos) { + // cut->SetMinNCrossedRowsTPC(40); + // cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + // cut->SetChi2PerClusterTPC(0.0, 4.0); + // cut->SetChi2PerClusterITS(0.0, 5.0); + // cut->SetNClustersITS(4, 7); + // cut->SetMeanClusterSizeITSob(0, 16); + // cut->SetMaxDcaXY(1.0); + // cut->SetMaxDcaZ(1.0); + // } else if (nameStr.find("nominalB") != std::string::npos) { + // cut->SetMinNCrossedRowsTPC(100); + // cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + // cut->SetChi2PerClusterTPC(0.0, 4.0); + // cut->SetChi2PerClusterITS(0.0, 5.0); + // cut->SetNClustersITS(5, 7); + // cut->SetMeanClusterSizeITSob(0, 16); + // cut->SetMaxDcaXY(1.0); + // cut->SetMaxDcaZ(1.0); + // } + // + // // long pid name should be top, because of if--else if conditions. + // + // if (nameStr.find("mee") != std::string::npos) { // for electron + // if (nameStr.find("tpcmupikaprrejortofreq") != std::string::npos) { + // cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq)); + // cut->SetTOFbetaRange(true, 0.0, 0.95); + // cut->SetTPCNsigmaElRange(-2, +3); + // cut->SetTPCNsigmaPiRange(-3, +3); + // cut->SetTPCNsigmaKaRange(-3, +3); + // cut->SetTPCNsigmaPrRange(-3, +3); + // cut->SetTOFNsigmaElRange(-3, +3); + // cut->SetTPCNsigmaMuRange(-2, +2); + // cut->SetMuonExclusionTPC(true); + // return cut; + // } else if (nameStr.find("tpcpikaprrejortofreq") != std::string::npos) { + // cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq)); + // cut->SetTOFbetaRange(true, 0.0, 0.95); + // cut->SetTPCNsigmaElRange(-2, +3); + // cut->SetTPCNsigmaPiRange(-3, +3); + // cut->SetTPCNsigmaKaRange(-3, +3); + // cut->SetTPCNsigmaPrRange(-3, +3); + // cut->SetTOFNsigmaElRange(-3, +3); + // return cut; + // } else if (nameStr.find("tpconly") != std::string::npos) { + // cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPConly)); + // cut->SetTOFbetaRange(true, 0.0, 0.95); + // cut->SetTPCNsigmaElRange(-2, +3); + // cut->SetTPCNsigmaPiRange(-3, +3); + // return cut; + // } else if (nameStr.find("tpcelonly") != std::string::npos) { + // cut->SetPIDScheme(static_cast(DalitzEECut::PIDSchemes::kTPConly)); + // cut->SetTOFbetaRange(true, 0.0, 0.95); + // cut->SetTPCNsigmaElRange(-2, +3); + // cut->SetTPCNsigmaPiRange(0, 0); + // return cut; + // } else if (nameStr.find("mleidlocal") != std::string::npos) { + // // cut->EnableEIDML(false, "/Users/d/dsekihat/pidml/", false, -1, "eid_lightgbm.onnx"); + // return cut; + // } else if (nameStr.find("mleid") != std::string::npos) { + // // cut->EnableEIDML(true, "/Users/d/dsekihat/pidml/", false, -1, "eid_lightgbm.onnx"); + // return cut; + // } else { // not match electron cut + // LOGF(info, Form("Did not find electron ID cut %s", cutName)); + // return cut; + // } + // } else { // do not match mee + // LOGF(info, Form("Did not find any pid cut %s", cutName)); + // return cut; + // } } PHOSPhotonCut* o2::aod::pwgem::photon::phoscuts::GetCut(const char* cutName) diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.h b/PWGEM/PhotonMeson/Core/CutsLibrary.h index 60bb65bbdbb..bf4fcfe7037 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.h +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.h @@ -16,7 +16,7 @@ #define PWGEM_PHOTONMESON_CORE_CUTSLIBRARY_H_ #include -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" @@ -29,7 +29,7 @@ namespace pwgem::photon { namespace eventcuts { -EMEventCut* GetCut(const char* cutName); +EMPhotonEventCut* GetCut(const char* cutName); } // namespace eventcuts namespace pcmcuts diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx index 6b4c95a11c6..b82b7460dfc 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx @@ -18,7 +18,7 @@ ClassImp(DalitzEECut); -const char* DalitzEECut::mCutNames[static_cast(DalitzEECut::DalitzEECuts::kNCuts)] = {"Mee", "PairPtRange", "PairRapidityRange", "PairDCARange", "PhivPair", "TrackPtRange", "TrackEtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCNsigmaEl", "TPCNsigmaMu", "TPCNsigmaPi", "TPCNsigmaKa", "TPCNsigmaPr", "TOFNsigmaEl", "TOFNsigmaMu", "TOFNsigmaPi", "TOFNsigmaKa", "TOFNsigmaPr", "DCA3Dsigma", "DCAxy", "DCAz", "ITSNCls", "ITSChi2NDF", "ITSClusterSize", "Prefilter"}; +// const char* DalitzEECut::mCutNames[static_cast(DalitzEECut::DalitzEECuts::kNCuts)] = {"Mee", "PairPtRange", "PairRapidityRange", "PairDCARange", "PhivPair", "TrackPtRange", "TrackEtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCNsigmaEl", "TPCNsigmaMu", "TPCNsigmaPi", "TPCNsigmaKa", "TPCNsigmaPr", "TOFNsigmaEl", "TOFNsigmaMu", "TOFNsigmaPi", "TOFNsigmaKa", "TOFNsigmaPr", "DCA3Dsigma", "DCAxy", "DCAz", "ITSNCls", "ITSChi2NDF", "ITSClusterSize", "Prefilter"}; const std::pair> DalitzEECut::its_ib_any_Requirement = {1, {0, 1, 2}}; // hits on any ITS ib layers. const std::pair> DalitzEECut::its_ib_1st_Requirement = {1, {0}}; // hit on 1st ITS ib layers. @@ -35,12 +35,6 @@ void DalitzEECut::SetPairYRange(float minY, float maxY) mMaxPairY = maxY; LOG(info) << "DalitzEE Cut, set pair eta range: " << mMinPairY << " - " << mMaxPairY; } -void DalitzEECut::SetPairDCARange(float min, float max) -{ - mMinPairDCA3D = min; - mMaxPairDCA3D = max; - LOG(info) << "DalitzEE Cut, set pair 3d dca range: " << mMinPairDCA3D << " - " << mMaxPairDCA3D; -} void DalitzEECut::SetMeeRange(float min, float max) { mMinMee = min; @@ -103,18 +97,12 @@ void DalitzEECut::SetChi2PerClusterITS(float min, float max) mMaxChi2PerClusterITS = max; LOG(info) << "DalitzEE Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; } -void DalitzEECut::SetMeanClusterSizeITSob(float min, float max) +void DalitzEECut::SetMeanClusterSizeITS(float min, float max) { mMinMeanClusterSizeITS = min; mMaxMeanClusterSizeITS = max; LOG(info) << "DalitzEE Cut, set mean cluster size ITS range: " << mMinMeanClusterSizeITS << " - " << mMaxMeanClusterSizeITS; } -void DalitzEECut::SetDca3DRange(float min, float max) -{ - mMinDca3D = min; - mMaxDca3D = max; - LOG(info) << "DalitzEE Cut, set DCA 3D range in sigma: " << mMinDca3D << " - " << mMaxDca3D; -} void DalitzEECut::SetMaxDcaXY(float maxDcaXY) { mMaxDcaXY = maxDcaXY; @@ -136,36 +124,6 @@ void DalitzEECut::ApplyPhiV(bool flag) mApplyPhiV = flag; LOG(info) << "DalitzEE Cut, apply phiv cut: " << mApplyPhiV; } -void DalitzEECut::ApplyPrefilter(bool flag) -{ - mApplyPF = flag; - LOG(info) << "DalitzEE Cut, apply prefilter: " << mApplyPF; -} - -void DalitzEECut::SetPIDScheme(int scheme) -{ - mPIDScheme = scheme; - LOG(info) << "DalitzEE Cut, PID scheme: " << static_cast(mPIDScheme); -} -void DalitzEECut::SetMinPinTOF(float min) -{ - mMinPinTOF = min; - LOG(info) << "DalitzEE Cut, set min pin for TOF: " << mMinPinTOF; -} - -void DalitzEECut::SetMuonExclusionTPC(bool flag) -{ - mMuonExclusionTPC = flag; - LOG(info) << "DalitzEE Cut, set flag for muon exclusion in TPC: " << mMuonExclusionTPC; -} - -void DalitzEECut::SetTOFbetaRange(bool flag, float min, float max) -{ - mApplyTOFbeta = flag; - mMinTOFbeta = min; - mMaxTOFbeta = max; - LOG(info) << "DalitzEE Cut, set TOF beta rejection range: " << mMinTOFbeta << " - " << mMaxTOFbeta; -} void DalitzEECut::SetTPCNsigmaElRange(float min, float max) { @@ -173,66 +131,13 @@ void DalitzEECut::SetTPCNsigmaElRange(float min, float max) mMaxTPCNsigmaEl = max; LOG(info) << "DalitzEE Cut, set TPC n sigma El range: " << mMinTPCNsigmaEl << " - " << mMaxTPCNsigmaEl; } -void DalitzEECut::SetTPCNsigmaMuRange(float min, float max) -{ - mMinTPCNsigmaMu = min; - mMaxTPCNsigmaMu = max; - LOG(info) << "DalitzEE Cut, set TPC n sigma Mu range: " << mMinTPCNsigmaMu << " - " << mMaxTPCNsigmaMu; -} void DalitzEECut::SetTPCNsigmaPiRange(float min, float max) { mMinTPCNsigmaPi = min; mMaxTPCNsigmaPi = max; LOG(info) << "DalitzEE Cut, set TPC n sigma Pi range: " << mMinTPCNsigmaPi << " - " << mMaxTPCNsigmaPi; } -void DalitzEECut::SetTPCNsigmaKaRange(float min, float max) -{ - mMinTPCNsigmaKa = min; - mMaxTPCNsigmaKa = max; - LOG(info) << "DalitzEE Cut, set TPC n sigma Ka range: " << mMinTPCNsigmaKa << " - " << mMaxTPCNsigmaKa; -} -void DalitzEECut::SetTPCNsigmaPrRange(float min, float max) -{ - mMinTPCNsigmaPr = min; - mMaxTPCNsigmaPr = max; - LOG(info) << "DalitzEE Cut, set TPC n sigma Pr range: " << mMinTPCNsigmaPr << " - " << mMaxTPCNsigmaPr; -} -void DalitzEECut::SetTOFNsigmaElRange(float min, float max) -{ - mMinTOFNsigmaEl = min; - mMaxTOFNsigmaEl = max; - LOG(info) << "DalitzEE Cut, set TOF n sigma El range: " << mMinTOFNsigmaEl << " - " << mMaxTOFNsigmaEl; -} -void DalitzEECut::SetTOFNsigmaMuRange(float min, float max) -{ - mMinTOFNsigmaMu = min; - mMaxTOFNsigmaMu = max; - LOG(info) << "DalitzEE Cut, set TOF n sigma Mu range: " << mMinTOFNsigmaMu << " - " << mMaxTOFNsigmaMu; -} -void DalitzEECut::SetTOFNsigmaPiRange(float min, float max) -{ - mMinTOFNsigmaPi = min; - mMaxTOFNsigmaPi = max; - LOG(info) << "DalitzEE Cut, set TOF n sigma Pi range: " << mMinTOFNsigmaPi << " - " << mMaxTOFNsigmaPi; -} -void DalitzEECut::SetTOFNsigmaKaRange(float min, float max) -{ - mMinTOFNsigmaKa = min; - mMaxTOFNsigmaKa = max; - LOG(info) << "DalitzEE Cut, set TOF n sigma Ka range: " << mMinTOFNsigmaKa << " - " << mMaxTOFNsigmaKa; -} -void DalitzEECut::SetTOFNsigmaPrRange(float min, float max) -{ - mMinTOFNsigmaPr = min; - mMaxTOFNsigmaPr = max; - LOG(info) << "DalitzEE Cut, set TOF n sigma Pr range: " << mMinTOFNsigmaPr << " - " << mMaxTOFNsigmaPr; -} -void DalitzEECut::SetMaxPinMuonTPConly(float max) -{ - mMaxPinMuonTPConly = max; - LOG(info) << "DalitzEE Cut, set max pin for Muon ID with TPC only: " << mMaxPinMuonTPConly; -} void DalitzEECut::RequireITSibAny(bool flag) { mRequireITSibAny = flag; @@ -243,38 +148,43 @@ void DalitzEECut::RequireITSib1st(bool flag) mRequireITSib1st = flag; LOG(info) << "DalitzEE Cut, require ITS ib 1st: " << mRequireITSib1st; } - -void DalitzEECut::print() const +void DalitzEECut::SetPIDScheme(int scheme) { - LOG(info) << "Dalitz EE Cut:"; - for (int i = 0; i < static_cast(DalitzEECuts::kNCuts); i++) { - switch (static_cast(i)) { - case DalitzEECuts::kTrackPtRange: - LOG(info) << mCutNames[i] << " in [" << mMinTrackPt << ", " << mMaxTrackPt << "]"; - break; - case DalitzEECuts::kTrackEtaRange: - LOG(info) << mCutNames[i] << " in [" << mMinTrackEta << ", " << mMaxTrackEta << "]"; - break; - case DalitzEECuts::kTPCNCls: - LOG(info) << mCutNames[i] << " > " << mMinNClustersTPC; - break; - case DalitzEECuts::kTPCCrossedRows: - LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsTPC; - break; - case DalitzEECuts::kTPCCrossedRowsOverNCls: - LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsOverFindableClustersTPC; - break; - case DalitzEECuts::kTPCChi2NDF: - LOG(info) << mCutNames[i] << " < " << mMaxChi2PerClusterTPC; - break; - case DalitzEECuts::kDCAxy: - LOG(info) << mCutNames[i] << " < " << mMaxDcaXY; - break; - case DalitzEECuts::kDCAz: - LOG(info) << mCutNames[i] << " < " << mMaxDcaZ; - break; - default: - LOG(fatal) << "Cut unknown!"; - } - } + mPIDScheme = scheme; + LOG(info) << "DalitzEE Cut, PID scheme: " << static_cast(mPIDScheme); } + +// void DalitzEECut::print() const +//{ +// LOG(info) << "Dalitz EE Cut:"; +// for (int i = 0; i < static_cast(DalitzEECuts::kNCuts); i++) { +// switch (static_cast(i)) { +// case DalitzEECuts::kTrackPtRange: +// LOG(info) << mCutNames[i] << " in [" << mMinTrackPt << ", " << mMaxTrackPt << "]"; +// break; +// case DalitzEECuts::kTrackEtaRange: +// LOG(info) << mCutNames[i] << " in [" << mMinTrackEta << ", " << mMaxTrackEta << "]"; +// break; +// case DalitzEECuts::kTPCNCls: +// LOG(info) << mCutNames[i] << " > " << mMinNClustersTPC; +// break; +// case DalitzEECuts::kTPCCrossedRows: +// LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsTPC; +// break; +// case DalitzEECuts::kTPCCrossedRowsOverNCls: +// LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsOverFindableClustersTPC; +// break; +// case DalitzEECuts::kTPCChi2NDF: +// LOG(info) << mCutNames[i] << " < " << mMaxChi2PerClusterTPC; +// break; +// case DalitzEECuts::kDCAxy: +// LOG(info) << mCutNames[i] << " < " << mMaxDcaXY; +// break; +// case DalitzEECuts::kDCAz: +// LOG(info) << mCutNames[i] << " < " << mMaxDcaZ; +// break; +// default: +// LOG(fatal) << "Cut unknown!"; +// } +// } +// } diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.h b/PWGEM/PhotonMeson/Core/DalitzEECut.h index b544b5c1c86..5ac38396976 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.h +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.h @@ -30,7 +30,7 @@ #include "Framework/Logger.h" #include "Framework/DataTypes.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; @@ -46,7 +46,6 @@ class DalitzEECut : public TNamed kMee = 0, kPairPtRange, kPairYRange, - kPairDCARange, kPhiV, // track cut kTrackPtRange, @@ -56,34 +55,19 @@ class DalitzEECut : public TNamed kTPCCrossedRowsOverNCls, kTPCChi2NDF, kTPCNsigmaEl, - kTPCNsigmaMu, kTPCNsigmaPi, - kTPCNsigmaKa, - kTPCNsigmaPr, - kTOFNsigmaEl, - kTOFNsigmaMu, - kTOFNsigmaPi, - kTOFNsigmaKa, - kTOFNsigmaPr, - kDCA3Dsigma, kDCAxy, kDCAz, kITSNCls, kITSChi2NDF, kITSCluserSize, - kPrefilter, kNCuts }; static const char* mCutNames[static_cast(DalitzEECuts::kNCuts)]; enum class PIDSchemes : int { kUnDef = -1, - kTOFreq = 0, - kTPChadrej = 1, - kTPChadrejORTOFreq = 2, - kTPConly = 3, - kMuon_lowB = 4, - kPIDML = 5, + kTPConly = 0, }; template @@ -110,11 +94,7 @@ class DalitzEECut : public TNamed ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - float dca_t1_3d = dca3DinSigma(t1); - float dca_t2_3d = dca3DinSigma(t2); - float dca_ee_3d = std::sqrt((dca_t1_3d * dca_t1_3d + dca_t2_3d * dca_t2_3d) / 2.); - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), bz); if (v12.M() < mMinMee || mMaxMee < v12.M()) { return false; @@ -127,14 +107,11 @@ class DalitzEECut : public TNamed if (mApplyPhiV && ((phiv < mMinPhivPair || (mMaxPhivPairMeeDep ? mMaxPhivPairMeeDep(v12.M()) : mMaxPhivPair) < phiv) ^ mSelectPC)) { return false; } - if (dca_ee_3d < mMinPairDCA3D || mMaxPairDCA3D < dca_ee_3d) { // in sigma for pair - return false; - } return true; } template - bool IsSelectedTrack(TTrack const& track, TCollision const& collision = 0) const + bool IsSelectedTrack(TTrack const& track, TCollision const& = 0) const { if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track return false; @@ -146,9 +123,6 @@ class DalitzEECut : public TNamed if (!IsSelectedTrack(track, DalitzEECuts::kTrackEtaRange)) { return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kDCA3Dsigma)) { - return false; - } if (!IsSelectedTrack(track, DalitzEECuts::kDCAxy)) { return false; } @@ -195,68 +169,21 @@ class DalitzEECut : public TNamed return false; } - if (mApplyPF && !IsSelectedTrack(track, DalitzEECuts::kPrefilter)) { - return false; - } - - if (mApplyTOFbeta && (mMinTOFbeta < track.beta() && track.beta() < mMaxTOFbeta)) { - return false; - } - // PID cuts - if constexpr (isML) { - if (!PassPIDML(track, collision)) { - return false; - } - } else { - if (!PassPID(track)) { - return false; - } + if (!PassPID(track)) { + return false; } return true; } - template - bool PassPIDML(TTrack const& track, TCollision const& collision) const - { - std::vector inputFeatures{static_cast(collision.numContrib()), track.p(), track.tgl(), - track.tpcNSigmaEl(), /*track.tpcNSigmaMu(),*/ track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.tofNSigmaEl(), /*track.tofNSigmaMu(),*/ track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))}; - - // calculate classifier - float prob_ele = mPIDModel->evalModel(inputFeatures)[0]; - // LOGF(info, "prob_ele = %f", prob_ele); - if (prob_ele < 0.95) { - return false; - } else { - return true; - } - } - template bool PassPID(T const& track) const { switch (mPIDScheme) { - case static_cast(PIDSchemes::kTOFreq): - return PassTOFreq(track); - - case static_cast(PIDSchemes::kTPChadrej): - return PassTPChadrej(track); - - case static_cast(PIDSchemes::kTPChadrejORTOFreq): - return PassTPChadrej(track) || PassTOFreq(track); - case static_cast(PIDSchemes::kTPConly): return PassTPConly(track); - case static_cast(PIDSchemes::kMuon_lowB): - return PassMuon_lowB(track); - - case static_cast(PIDSchemes::kPIDML): - return true; // don't use kPIDML here. - case static_cast(PIDSchemes::kUnDef): return true; @@ -265,26 +192,6 @@ class DalitzEECut : public TNamed } } - template - bool PassTOFreq(T const& track) const - { - bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi(); - bool is_el_included_TOF = mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl; - return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; - } - - template - bool PassTPChadrej(T const& track) const - { - bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; - bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi(); - bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); - bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); - return is_el_included_TPC && is_mu_excluded_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC; - } - template bool PassTPConly(T const& track) const { @@ -293,27 +200,6 @@ class DalitzEECut : public TNamed return is_el_included_TPC && is_pi_excluded_TPC; } - template - bool PassMuon_lowB(T const& track) const - { - bool is_el_excluded_TPC = track.tpcNSigmaEl() < mMinTPCNsigmaEl || mMaxTPCNsigmaEl < track.tpcNSigmaEl(); - if (!is_el_excluded_TPC) { - return false; - } - if (track.hasTOF()) { - bool is_mu_included_TPC = mMinTPCNsigmaMu < track.tpcNSigmaMu() && track.tpcNSigmaMu() < mMaxTPCNsigmaMu; - bool is_mu_included_TOF = mMinTOFNsigmaMu < track.tofNSigmaMu() && track.tofNSigmaMu() < mMaxTOFNsigmaMu; - bool is_pi_excluded_TOF = track.tofNSigmaPi() < mMinTOFNsigmaPi; - return is_mu_included_TPC && is_mu_included_TOF && is_pi_excluded_TOF; - } else if (track.tpcInnerParam() < mMaxPinMuonTPConly) { - bool is_mu_included_TPC = mMinTPCNsigmaMu < track.tpcNSigmaMu() && track.tpcNSigmaMu() < mMaxTPCNsigmaMu; - bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi; - return is_mu_included_TPC && is_pi_excluded_TPC; - } else { - return false; - } - } - template bool IsSelectedTrack(T const& track, const DalitzEECuts& cut) const { @@ -336,9 +222,6 @@ class DalitzEECut : public TNamed case DalitzEECuts::kTPCChi2NDF: return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; - case DalitzEECuts::kDCA3Dsigma: - return mMinDca3D <= dca3DinSigma(track) && dca3DinSigma(track) <= mMaxDca3D; // in sigma for single leg - case DalitzEECuts::kDCAxy: return abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); @@ -352,10 +235,7 @@ class DalitzEECut : public TNamed return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; case DalitzEECuts::kITSCluserSize: - return mMinMeanClusterSizeITS < track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; - - case DalitzEECuts::kPrefilter: - return track.pfb() <= 0; + return mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; default: return false; @@ -365,7 +245,6 @@ class DalitzEECut : public TNamed // Setters void SetPairPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetPairYRange(float minY = -1e10f, float maxY = 1e10f); - void SetPairDCARange(float min = 0.f, float max = 1e10f); // 3D DCA in sigma void SetMeeRange(float min = 0.f, float max = 0.5); void SetMaxPhivPairMeeDep(std::function meeDepCut); void SelectPhotonConversion(bool flag); @@ -378,52 +257,33 @@ class DalitzEECut : public TNamed void SetChi2PerClusterTPC(float min, float max); void SetNClustersITS(int min, int max); void SetChi2PerClusterITS(float min, float max); - void SetMeanClusterSizeITSob(float min, float max); + void SetMeanClusterSizeITS(float min, float max); void SetPIDScheme(int scheme); - void SetMinPinTOF(float min); - void SetMuonExclusionTPC(bool flag); - void SetTOFbetaRange(bool flag, float min, float max); void SetTPCNsigmaElRange(float min = -1e+10, float max = 1e+10); - void SetTPCNsigmaMuRange(float min = -1e+10, float max = 1e+10); void SetTPCNsigmaPiRange(float min = -1e+10, float max = 1e+10); - void SetTPCNsigmaKaRange(float min = -1e+10, float max = 1e+10); - void SetTPCNsigmaPrRange(float min = -1e+10, float max = 1e+10); - void SetTOFNsigmaElRange(float min = -1e+10, float max = 1e+10); - void SetTOFNsigmaMuRange(float min = -1e+10, float max = 1e+10); - void SetTOFNsigmaPiRange(float min = -1e+10, float max = 1e+10); - void SetTOFNsigmaKaRange(float min = -1e+10, float max = 1e+10); - void SetTOFNsigmaPrRange(float min = -1e+10, float max = 1e+10); - void SetMaxPinMuonTPConly(float max); void RequireITSibAny(bool flag); void RequireITSib1st(bool flag); - void SetDca3DRange(float min, float max); // in sigma - void SetMaxDcaXY(float maxDcaXY); // in cm - void SetMaxDcaZ(float maxDcaZ); // in cm + void SetMaxDcaXY(float maxDcaXY); // in cm + void SetMaxDcaZ(float maxDcaZ); // in cm void SetMaxDcaXYPtDep(std::function ptDepCut); void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); - void SetPIDModel(o2::ml::OnnxModel* model) - { - mPIDModel = model; - } - // Getters bool IsPhotonConversionSelected() const { return mSelectPC; } /// @brief Print the track selection - void print() const; + // void print() const; private: static const std::pair> its_ib_any_Requirement; static const std::pair> its_ib_1st_Requirement; // pair cuts float mMinMee{0.f}, mMaxMee{1e10f}; - float mMinPairPt{0.f}, mMaxPairPt{1e10f}; // range in pT - float mMinPairY{-1e10f}, mMaxPairY{1e10f}; // range in rapidity - float mMinPairDCA3D{0.f}, mMaxPairDCA3D{1e10f}; // range in 3D DCA in sigma + float mMinPairPt{0.f}, mMaxPairPt{1e10f}; // range in pT + float mMinPairY{-1e10f}, mMaxPairY{1e10f}; // range in rapidity float mMinPhivPair{0.f}, mMaxPhivPair{+3.2}; std::function mMaxPhivPairMeeDep{}; // max phiv as a function of mee bool mSelectPC{false}; // flag to select photon conversion used in mMaxPhivPairMeeDep @@ -443,32 +303,17 @@ class DalitzEECut : public TNamed bool mRequireITSibAny{true}; bool mRequireITSib1st{false}; - float mMinDca3D{0.0f}; // min dca in 3D in units of sigma - float mMaxDca3D{1e+10}; // max dca in 3D in units of sigma float mMaxDcaXY{1.0f}; // max dca in xy plane float mMaxDcaZ{1.0f}; // max dca in z direction std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mApplyPhiV{true}; - bool mApplyPF{false}; float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) // pid cuts int mPIDScheme{-1}; - float mMinPinTOF{0.0f}; // min pin cut for TOF. - bool mMuonExclusionTPC{false}; // flag to reject muon in TPC for low B - bool mApplyTOFbeta{false}; // flag to reject hadron contamination with TOF - float mMinTOFbeta{0.0}, mMaxTOFbeta{0.96}; float mMinTPCNsigmaEl{-1e+10}, mMaxTPCNsigmaEl{+1e+10}; - float mMinTPCNsigmaMu{-1e+10}, mMaxTPCNsigmaMu{+1e+10}; float mMinTPCNsigmaPi{-1e+10}, mMaxTPCNsigmaPi{+1e+10}; - float mMinTPCNsigmaKa{-1e+10}, mMaxTPCNsigmaKa{+1e+10}; - float mMinTPCNsigmaPr{-1e+10}, mMaxTPCNsigmaPr{+1e+10}; - - float mMinTOFNsigmaEl{-1e+10}, mMaxTOFNsigmaEl{+1e+10}; - float mMinTOFNsigmaMu{-1e+10}, mMaxTOFNsigmaMu{+1e+10}; - float mMinTOFNsigmaPi{-1e+10}, mMaxTOFNsigmaPi{+1e+10}; - float mMinTOFNsigmaKa{-1e+10}, mMaxTOFNsigmaKa{+1e+10}; - float mMinTOFNsigmaPr{-1e+10}, mMaxTOFNsigmaPr{+1e+10}; + o2::ml::OnnxModel* mPIDModel{nullptr}; ClassDef(DalitzEECut, 1); diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h index 1a2e0f28b48..533beffa524 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h @@ -49,33 +49,30 @@ class EMCPhotonCut : public TNamed template bool IsSelected(Cluster const& cluster) const { - // auto track = cluster.template MatchedTrack_as(); - auto track = nullptr; - if (!IsSelectedEMCal(EMCPhotonCuts::kEnergy, cluster, track)) { + if (!IsSelectedEMCal(EMCPhotonCuts::kEnergy, cluster)) { return false; } - if (!IsSelectedEMCal(EMCPhotonCuts::kNCell, cluster, track)) { + if (!IsSelectedEMCal(EMCPhotonCuts::kNCell, cluster)) { return false; } - if (!IsSelectedEMCal(EMCPhotonCuts::kM02, cluster, track)) { + if (!IsSelectedEMCal(EMCPhotonCuts::kM02, cluster)) { return false; } - if (!IsSelectedEMCal(EMCPhotonCuts::kTiming, cluster, track)) { + if (!IsSelectedEMCal(EMCPhotonCuts::kTiming, cluster)) { return false; } - if (!IsSelectedEMCal(EMCPhotonCuts::kTM, cluster, track)) { + if (!IsSelectedEMCal(EMCPhotonCuts::kTM, cluster)) { return false; } - if (!IsSelectedEMCal(EMCPhotonCuts::kExotic, cluster, track)) { + if (!IsSelectedEMCal(EMCPhotonCuts::kExotic, cluster)) { return false; } return true; } - // Temporary function to check if cluster passes a given selection criteria. To be replaced by framework filters. // Returns true if a cluster survives the cuts! - template - bool IsSelectedEMCal(const EMCPhotonCuts& cut, Cluster const& cluster, Track const& /*track*/) const + template + bool IsSelectedEMCal(const EMCPhotonCuts& cut, Cluster const& cluster) const { switch (cut) { case EMCPhotonCuts::kEnergy: diff --git a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx new file mode 100644 index 00000000000..285bf50eba4 --- /dev/null +++ b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx @@ -0,0 +1,31 @@ +// Copyright 2019-2020 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. + +// +// Class for em photon event selection +// + +#include "Framework/Logger.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" + +ClassImp(EMPhotonEventCut); + +void EMPhotonEventCut::SetRequireEMCReadoutInMB(bool flag) +{ + mRequireEMCReadoutInMB = flag; + LOG(info) << "EM Photon Event Cut, require the EMC to be read out in an MB collision by checking kTVXinEMC: " << mRequireEMCReadoutInMB; +} + +void EMPhotonEventCut::SetRequireEMCHardwareTriggered(bool flag) +{ + mRequireEMCHardwareTriggered = flag; + LOG(info) << "EM Photon Event Cut, require the EMC to be triggered by requiring kEMC7 or kDMC7: " << mRequireEMCHardwareTriggered; +} diff --git a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h new file mode 100644 index 00000000000..3b134ce882e --- /dev/null +++ b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h @@ -0,0 +1,76 @@ +// Copyright 2019-2020 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. + +// +// Class for em photon event selection +// + +#ifndef PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ +#define PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ + +#include "PWGEM/Dilepton/Core/EMEventCut.h" + +using namespace std; + +class EMPhotonEventCut : public EMEventCut +{ + public: + EMPhotonEventCut() = default; + EMPhotonEventCut(const char* name, const char* title) : EMEventCut(name, title) {} + + enum class EMPhotonEventCuts : int { + kEMCReadoutInMB = 0, + kEMCHardwareTriggered, + kNCuts + }; + + template + bool IsSelected(T const& collision) const + { + if (!EMEventCut::IsSelected(collision)) { + return false; + } + if (mRequireEMCReadoutInMB && !IsSelected(collision, EMPhotonEventCuts::kEMCReadoutInMB)) { + return false; + } + if (mRequireEMCHardwareTriggered && !IsSelected(collision, EMPhotonEventCuts::kEMCHardwareTriggered)) { + return false; + } + return true; + } + + template + bool IsSelected(T const& collision, const EMPhotonEventCuts& cut) const + { + switch (cut) { + case EMPhotonEventCuts::kEMCReadoutInMB: + return (collision.alias_bit(kTVXinEMC)); + + case EMPhotonEventCuts::kEMCHardwareTriggered: + return (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7)); + + default: + return true; + } + } + + // Setters + void SetRequireEMCReadoutInMB(bool flag); + void SetRequireEMCHardwareTriggered(bool flag); + + private: + bool mRequireEMCReadoutInMB{false}; + bool mRequireEMCHardwareTriggered{false}; + + ClassDef(EMPhotonEventCut, 1); +}; + +#endif // PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ diff --git a/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h b/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h index f5ecfb66dce..ff03b41a75e 100644 --- a/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h +++ b/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h @@ -16,12 +16,11 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class EMEventCut + ; #pragma link C++ class V0PhotonCut + ; #pragma link C++ class DalitzEECut + ; -#pragma link C++ class DimuonCut + ; #pragma link C++ class PHOSPhotonCut + ; #pragma link C++ class EMCPhotonCut + ; +#pragma link C++ class EMPhotonEventCut + ; #pragma link C++ class PairCut + ; #endif // PWGEM_PHOTONMESON_CORE_PWGEMPHOTONMESONCORELINKDEF_H_ diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 19e582ba1f8..583be6a37b8 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -38,11 +38,10 @@ #include "Framework/ASoAHelpers.h" #include "DetectorsBase/GeometryManager.h" +#include "EMCALBase/Geometry.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Tools/ML/model.h" #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" @@ -50,12 +49,10 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/PairCut.h" -#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" -#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EMTrack.h" -#include "PWGEM/PhotonMeson/Utils/EventMixingHandler.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/NMHistograms.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" @@ -65,31 +62,26 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; +using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::photonmeson::utils::emtrack; +using namespace o2::aod::pwgem::dilepton::utils; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyPrimaryElectrons = soa::Join; +using MyPrimaryElectrons = soa::Join; using MyPrimaryElectron = MyPrimaryElectrons::iterator; -// using MyPrimaryMuons = soa::Join; -// using MyPrimaryMuon = MyPrimaryMuons::iterator; - using MyEMCClusters = soa::Join; using MyEMCCluster = MyEMCClusters::iterator; using MyPHOSClusters = soa::Join; using MyPHOSCluster = MyEMCClusters::iterator; -using MyEMH = o2::aod::pwgem::photonmeson::utils::EventMixingHandler, std::pair, EMTrack>; - template struct Pi0EtaToGammaGamma { Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -102,7 +94,6 @@ struct Pi0EtaToGammaGamma { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - Configurable cfgDoFlow{"cfgDoFlow", false, "flag to analyze vn"}; Configurable maxY{"maxY", 0.8, "maximum rapidity for reconstructed particles"}; Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; Configurable ndepth{"ndepth", 10, "depth for event mixing"}; @@ -111,7 +102,7 @@ struct Pi0EtaToGammaGamma { ConfigurableAxis ConfEPBins{"ConfEPBins", {VARIABLE_WIDTH, -M_PI / 2, -M_PI / 4, 0.0f, +M_PI / 4, +M_PI / 2}, "Mixing bins - event plane angle"}; ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; @@ -122,8 +113,11 @@ struct Pi0EtaToGammaGamma { Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgRequireEMCReadoutInMB{"cfgRequireEMCReadoutInMB", false, "require the EMC to be read out in an MB collision (kTVXinEMC)"}; + Configurable cfgRequireEMCHardwareTriggered{"cfgRequireEMCHardwareTriggered", false, "require the EMC to be hardware triggered (kEMC7 or kDMC7)"}; Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; } eventcuts; V0PhotonCut fV0PhotonCut; @@ -157,8 +151,6 @@ struct Pi0EtaToGammaGamma { std::string prefix = "dileptoncut_group"; Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; Configurable cfg_max_mass{"cfg_max_mass", 0.1, "max mass"}; - Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; @@ -176,33 +168,16 @@ struct Pi0EtaToGammaGamma { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPConly), "pid scheme [kTPConly : 0]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3.0, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - - // CCDB configuration for PID ML - Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; - - Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dileptoncuts; EMCPhotonCut fEMCCut; struct : ConfigurableGroup { std::string prefix = "emccut_group"; - Configurable requireCaloReadout{"requireCaloReadout", true, "Require calorimeters readout when analyzing EMCal/PHOS"}; Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; 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"}; @@ -253,14 +228,13 @@ struct Pi0EtaToGammaGamma { emh1 = new MyEMH(ndepth); emh2 = new MyEMH(ndepth); - std::string_view qvec_det_names[3] = {"FT0M", "FT0A", "FT0C"}; - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); if constexpr (pairtype == PairType::kPCMDalitzEE) { - o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, cfgDoFlow, false, "ee#gamma", qvec_det_names[cfgQvecEstimator].data()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, false, "ee#gamma"); } else if constexpr (pairtype == PairType::kPCMDalitzMuMu) { - o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, cfgDoFlow, false, "#mu#mu#gamma", qvec_det_names[cfgQvecEstimator].data()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, false, "#mu#mu#gamma"); } else { - o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, cfgDoFlow, false, "#gamma#gamma", qvec_det_names[cfgQvecEstimator].data()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, false, "#gamma#gamma"); } DefineEMEventCut(); DefinePCMCut(); @@ -270,6 +244,7 @@ struct Pi0EtaToGammaGamma { if constexpr (pairtype == kEMCEMC) { fRegistry.addClone("Pair/same/", "Pair/rotation/"); + o2::emcal::Geometry::GetInstanceFromRunNumber(300000); } mRunNumber = 0; @@ -335,7 +310,7 @@ struct Pi0EtaToGammaGamma { void DefineEMEventCut() { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); @@ -344,6 +319,8 @@ struct Pi0EtaToGammaGamma { fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireEMCReadoutInMB(eventcuts.cfgRequireEMCReadoutInMB); + fEMEventCut.SetRequireEMCHardwareTriggered(eventcuts.cfgRequireEMCHardwareTriggered); fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); } @@ -361,7 +338,7 @@ struct Pi0EtaToGammaGamma { fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); // for track - fV0PhotonCut.SetTrackPtRange(pcmcuts.cfg_min_pt_v0 * 0.4, 1e+10f); + fV0PhotonCut.SetTrackPtRange(pcmcuts.cfg_min_pt_v0 * 0.5, 1e+10f); fV0PhotonCut.SetTrackEtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); @@ -407,9 +384,7 @@ struct Pi0EtaToGammaGamma { // for pair fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.SetPairDCARange(dileptoncuts.cfg_min_pair_dca3d, dileptoncuts.cfg_max_pair_dca3d); // in sigma fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.ApplyPrefilter(dileptoncuts.cfg_apply_pf); fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); @@ -422,36 +397,13 @@ struct Pi0EtaToGammaGamma { fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMeanClusterSizeITSob(0, 16); fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaMuRange(dileptoncuts.cfg_min_TPCNsigmaMu, dileptoncuts.cfg_max_TPCNsigmaMu); fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTPCNsigmaKaRange(dileptoncuts.cfg_min_TPCNsigmaKa, dileptoncuts.cfg_max_TPCNsigmaKa); - fDileptonCut.SetTPCNsigmaPrRange(dileptoncuts.cfg_min_TPCNsigmaPr, dileptoncuts.cfg_max_TPCNsigmaPr); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut - o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); - if (dileptoncuts.loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - std::map metadata; - bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dileptoncuts.BDTPathCCDB.value, ".", metadata, dileptoncuts.timestampCCDB.value, false, dileptoncuts.BDTLocalPathGamma.value); - if (retrieveSuccessGamma) { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } else { - LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; - } - } else { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } - - fDileptonCut.SetPIDModel(eid_bdt); - } // end of PID ML } void DefineEMCCut() @@ -484,7 +436,7 @@ struct Pi0EtaToGammaGamma { /// \brief Calculate background (using rotation background method only for EMCal!) template - void RotationBackground(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photons_coll, unsigned int ig1, unsigned int ig2, EMCPhotonCut const& cut, aod::SkimEMCMTs const&) + void RotationBackground(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photons_coll, unsigned int ig1, unsigned int ig2, float eventWeight) { // if less than 3 clusters are present skip event since we need at least 3 clusters if (photons_coll.size() < 3) { @@ -501,9 +453,6 @@ struct Pi0EtaToGammaGamma { // only combine rotated photons with other photons continue; } - if (!cut.template IsSelected(photon)) { - continue; - } ROOT::Math::PtEtaPhiMVector photon3(photon.pt(), photon.eta(), photon.phi(), 0.); ROOT::Math::PtEtaPhiMVector mother1 = photon1 + photon3; @@ -512,11 +461,25 @@ struct Pi0EtaToGammaGamma { float openingAngle1 = std::acos(photon1.Vect().Dot(photon3.Vect()) / (photon1.P() * photon3.P())); float openingAngle2 = std::acos(photon2.Vect().Dot(photon3.Vect()) / (photon2.P() * photon3.P())); - if (openingAngle1 > emccuts.minOpenAngle && abs(mother1.Rapidity()) < maxY) { - fRegistry.fill(HIST("Pair/rotation/hMggPt"), mother1.M(), mother1.Pt()); + int iCellID_photon1 = 0; + int iCellID_photon2 = 0; + + try { + iCellID_photon1 = o2::emcal::Geometry::GetInstance()->GetAbsCellIdFromEtaPhi(photon1.Eta(), photon1.Phi()); + } catch (o2::emcal::InvalidPositionException& e) { + iCellID_photon1 = -1; } - if (openingAngle2 > emccuts.minOpenAngle && abs(mother2.Rapidity()) < maxY) { - fRegistry.fill(HIST("Pair/rotation/hMggPt"), mother2.M(), mother2.Pt()); + try { + iCellID_photon2 = o2::emcal::Geometry::GetInstance()->GetAbsCellIdFromEtaPhi(photon2.Eta(), photon2.Phi()); + } catch (o2::emcal::InvalidPositionException& e) { + iCellID_photon2 = -1; + } + + if (openingAngle1 > emccuts.minOpenAngle && abs(mother1.Rapidity()) < maxY && iCellID_photon1 > 0) { + fRegistry.fill(HIST("Pair/rotation/hs"), mother1.M(), mother1.Pt(), eventWeight); + } + if (openingAngle2 > emccuts.minOpenAngle && abs(mother2.Rapidity()) < maxY && iCellID_photon2 > 0) { + fRegistry.fill(HIST("Pair/rotation/hs"), mother2.M(), mother2.Pt(), eventWeight); } } } @@ -530,22 +493,18 @@ struct Pi0EtaToGammaGamma { Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl&& o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); - // Preslice perCollision_muon = aod::emprimarymuon::emeventId; - // Partition muons_pos = o2::aod::emprimarymuon::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaMu) < o2::aod::pidtpc::tpcNSigmaMu&& o2::aod::pidtpc::tpcNSigmaMu < static_cast(dileptoncuts.cfg_max_TPCNsigmaMu); - // Partition muons_neg = o2::aod::emprimarymuon::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaMu) < o2::aod::pidtpc::tpcNSigmaMu && o2::aod::pidtpc::tpcNSigmaMu < static_cast(dileptoncuts.cfg_max_TPCNsigmaMu); - + using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; MyEMH* emh1 = nullptr; MyEMH* emh2 = nullptr; std::vector> used_photonIds; // std::vector> used_dileptonIds; // - template + template void runPairing(TCollisions const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TSubInfos1 const& /*subinfos1*/, TSubInfos2 const& /*subinfos2*/, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, - TCut1 const& cut1, TCut2 const& cut2, - TTracksMatchedWithEMC const& tracks_emc, TTracksMatchedWithPHOS const& /*tracks_phos*/) + TCut1 const& cut1, TCut2 const& cut2) { for (auto& collision : collisions) { initCCDB(collision); @@ -553,7 +512,8 @@ struct Pi0EtaToGammaGamma { if ((pairtype == PairType::kPHOSPHOS || pairtype == PairType::kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { continue; } - if ((pairtype == PairType::kEMCEMC || pairtype == PairType::kPCMEMC) && ((!collision.alias_bit(triggerAliases::kTVXinEMC) && emccuts.requireCaloReadout) || collision.ncollsPerBC() != 1)) { + + if (eventcuts.onlyKeepWeightedEvents && fabs(collision.weight() - 1.) < 1E-10) { continue; } @@ -562,17 +522,13 @@ struct Pi0EtaToGammaGamma { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); if (!fEMEventCut.IsSelected(collision)) { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; - std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; - std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; - const std::array q2vector[3] = {q2ft0m, q2ft0a, q2ft0c}; + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; if (zbin < 0) { @@ -589,7 +545,7 @@ struct Pi0EtaToGammaGamma { centbin = static_cast(cent_bin_edges.size()) - 2; } - float ep2 = collision.ep2ft0c(); + float ep2 = collision.ep2btot(); int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; if (epbin < 0) { epbin = 0; @@ -625,26 +581,21 @@ struct Pi0EtaToGammaGamma { continue; } - if (cfgDoFlow) { - std::array u2_gg = {static_cast(std::cos(2 * v12.Phi())), static_cast(std::sin(2 * v12.Phi()))}; - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), RecoDecay::dotProd(u2_gg, q2vector[cfgQvecEstimator])); - } else { - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), 0.0); - } + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), collision.weight()); if constexpr (pairtype == PairType::kEMCEMC) { - RotationBackground(v12, v1, v2, photons2_per_collision, g1.globalIndex(), g2.globalIndex(), cut1, tracks_emc); + RotationBackground(v12, v1, v2, photons2_per_collision, g1.globalIndex(), g2.globalIndex(), collision.weight()); } std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); std::pair pair_tmp_id2 = std::make_pair(ndf, g2.globalIndex()); if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.globalIndex(), collision.globalIndex(), g1.globalIndex(), g1.pt(), g1.eta(), g1.phi(), 0)); + emh1->AddTrackToEventPool(key_df_collision, EMTrack(-1, g1.globalIndex(), collision.globalIndex(), g1.globalIndex(), g1.pt(), g1.eta(), g1.phi(), 0)); used_photonIds.emplace_back(pair_tmp_id1); } if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id2) == used_photonIds.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g2.globalIndex(), collision.globalIndex(), g2.globalIndex(), g2.pt(), g2.eta(), g2.phi(), 0)); + emh1->AddTrackToEventPool(key_df_collision, EMTrack(-1, g2.globalIndex(), collision.globalIndex(), g2.globalIndex(), g2.pt(), g2.eta(), g2.phi(), 0)); used_photonIds.emplace_back(pair_tmp_id2); } ndiphoton++; @@ -671,14 +622,8 @@ struct Pi0EtaToGammaGamma { continue; } - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { - if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { - continue; - } - } else { // cut-based - if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { - continue; - } + if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { + continue; } if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { @@ -692,26 +637,22 @@ struct Pi0EtaToGammaGamma { if (abs(veeg.Rapidity()) > maxY) { continue; } - if (cfgDoFlow) { - std::array u2_gg = {static_cast(std::cos(2 * veeg.Phi())), static_cast(std::sin(2 * veeg.Phi()))}; - fRegistry.fill(HIST("Pair/same/hs"), veeg.M(), veeg.Pt(), RecoDecay::dotProd(u2_gg, q2vector[cfgQvecEstimator])); - } else { - fRegistry.fill(HIST("Pair/same/hs"), veeg.M(), veeg.Pt(), 0.0); - } + + fRegistry.fill(HIST("Pair/same/hs"), veeg.M(), veeg.Pt(), collision.weight()); std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); std::tuple tuple_tmp_id2 = std::make_tuple(ndf, collision.globalIndex(), pos2.trackId(), ele2.trackId()); if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.globalIndex(), collision.globalIndex(), -1, g1.pt(), g1.eta(), g1.phi(), 0)); + emh1->AddTrackToEventPool(key_df_collision, EMTrack(-1, g1.globalIndex(), collision.globalIndex(), -1, g1.pt(), g1.eta(), g1.phi(), 0)); used_photonIds.emplace_back(pair_tmp_id1); } if (std::find(used_dileptonIds.begin(), used_dileptonIds.end(), tuple_tmp_id2) == used_dileptonIds.end()) { - emh2->AddTrackToEventPool(key_df_collision, EMTrack(-1, collision.globalIndex(), -1, v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); + emh2->AddTrackToEventPool(key_df_collision, EMTrack(-1, -1, collision.globalIndex(), -1, v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); used_dileptonIds.emplace_back(tuple_tmp_id2); } ndiphoton++; - } // end of dielectron loop - } // end of g1 loop + } // end of dielectron loop + } // end of g1 loop } else { // PCM-EMC, PCM-PHOS. Nightmare. don't run these pairs. auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); auto photons2_per_collision = photons2.sliceBy(perCollision2, collision.globalIndex()); @@ -726,26 +667,23 @@ struct Pi0EtaToGammaGamma { if (abs(v12.Rapidity()) > maxY) { continue; } - if (cfgDoFlow) { - std::array u2_gg = {static_cast(std::cos(2 * v12.Phi())), static_cast(std::sin(2 * v12.Phi()))}; - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), RecoDecay::dotProd(u2_gg, q2vector[cfgQvecEstimator])); - } else { - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), 0.0); - } + + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), collision.weight()); + std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); std::pair pair_tmp_id2 = std::make_pair(ndf, g2.globalIndex()); if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.globalIndex(), collision.globalIndex(), -1, g1.pt(), g1.eta(), g1.phi(), 0)); + emh1->AddTrackToEventPool(key_df_collision, EMTrack(-1, g1.globalIndex(), collision.globalIndex(), -1, g1.pt(), g1.eta(), g1.phi(), 0)); used_photonIds.emplace_back(pair_tmp_id1); } if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id2) == used_photonIds.end()) { - emh2->AddTrackToEventPool(key_df_collision, EMTrack(g2.globalIndex(), collision.globalIndex(), -1, g2.pt(), g2.eta(), g2.phi(), 0)); + emh2->AddTrackToEventPool(key_df_collision, EMTrack(-1, g2.globalIndex(), collision.globalIndex(), -1, g2.pt(), g2.eta(), g2.phi(), 0)); used_photonIds.emplace_back(pair_tmp_id2); } ndiphoton++; } // end of pairing loop - } // end of pairing in same event + } // end of pairing in same event // event mixing if (!cfgDoMix || !(ndiphoton > 0)) { @@ -779,17 +717,13 @@ struct Pi0EtaToGammaGamma { if (abs(v12.Rapidity()) > maxY) { continue; } - if (cfgDoFlow) { - std::array u2_gg = {static_cast(std::cos(2 * v12.Phi())), static_cast(std::sin(2 * v12.Phi()))}; - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), RecoDecay::dotProd(u2_gg, q2vector[cfgQvecEstimator])); - } else { - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), 0.0); - } + + fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), collision.weight()); } } } // end of loop over mixed event pool - } else { //[photon1 from event1, photon2 from event2] and [photon1 from event2, photon2 from event1] + } else { // [photon1 from event1, photon2 from event2] and [photon1 from event2, photon2 from event1] for (auto& mix_dfId_collisionId : collisionIds2_in_mixing_pool) { int mix_dfId = mix_dfId_collisionId.first; int64_t mix_collisionId = mix_dfId_collisionId.second; @@ -812,12 +746,7 @@ struct Pi0EtaToGammaGamma { if (abs(v12.Rapidity()) > maxY) { continue; } - if (cfgDoFlow) { - std::array u2_gg = {static_cast(std::cos(2 * v12.Phi())), static_cast(std::sin(2 * v12.Phi()))}; - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), RecoDecay::dotProd(u2_gg, q2vector[cfgQvecEstimator])); - } else { - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), 0.0); - } + fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), collision.weight()); } } } // end of loop over mixed event pool @@ -843,12 +772,7 @@ struct Pi0EtaToGammaGamma { if (abs(v12.Rapidity()) > maxY) { continue; } - if (cfgDoFlow) { - std::array u2_gg = {static_cast(std::cos(2 * v12.Phi())), static_cast(std::sin(2 * v12.Phi()))}; - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), RecoDecay::dotProd(u2_gg, q2vector[cfgQvecEstimator])); - } else { - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), 0.0); - } + fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), collision.weight()); } } } // end of loop over mixed event pool @@ -872,20 +796,19 @@ struct Pi0EtaToGammaGamma { if constexpr (pairtype == PairType::kPCMPCM) { auto v0photons = std::get<0>(std::tie(args...)); auto v0legs = std::get<1>(std::tie(args...)); - runPairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, nullptr, nullptr); + runPairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut); } else if constexpr (pairtype == PairType::kPCMDalitzEE) { auto v0photons = std::get<0>(std::tie(args...)); auto v0legs = std::get<1>(std::tie(args...)); auto emprimaryelectrons = std::get<2>(std::tie(args...)); // LOGF(info, "electrons.size() = %d, positrons.size() = %d", electrons.size(), positrons.size()); - runPairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, nullptr, nullptr); + runPairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut); } else if constexpr (pairtype == PairType::kEMCEMC) { auto emcclusters = std::get<0>(std::tie(args...)); - auto emcmatchedtracks = std::get<1>(std::tie(args...)); - runPairing(collisions, emcclusters, emcclusters, nullptr, nullptr, perCollision_emc, perCollision_emc, fEMCCut, fEMCCut, emcmatchedtracks, nullptr); + runPairing(collisions, emcclusters, emcclusters, nullptr, nullptr, perCollision_emc, perCollision_emc, fEMCCut, fEMCCut); } else if constexpr (pairtype == PairType::kPHOSPHOS) { auto phosclusters = std::get<0>(std::tie(args...)); - runPairing(collisions, phosclusters, phosclusters, nullptr, nullptr, perCollision_phos, perCollision_phos, fPHOSCut, fPHOSCut, nullptr, nullptr); + runPairing(collisions, phosclusters, phosclusters, nullptr, nullptr, perCollision_phos, perCollision_phos, fPHOSCut, fPHOSCut); } // else if constexpr (pairtype == PairType::kPCMEMC) { // auto v0photons = std::get<0>(std::tie(args...)); diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 6acaaa3d09c..a09f0d8691b 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -33,8 +33,6 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Tools/ML/model.h" #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" @@ -46,18 +44,19 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; -using namespace o2::aod::pwgem::mcutil; -using namespace o2::aod::pwgem::photon; +using namespace o2::aod::pwgem::photonmeson::photonpair; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; @@ -75,12 +74,9 @@ using MyPHOSCluster = MyEMCClusters::iterator; using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = soa::Join; using MyMCElectron = MyMCElectrons::iterator; -// using MyMCMuons = soa::Join; -// using MyMCMuon = MyMCMuons::iterator; - template struct Pi0EtaToGammaGammaMC { Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -93,11 +89,10 @@ struct Pi0EtaToGammaGammaMC { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - // Configurable cfgDoFlow{"cfgDoFlow", false, "flag to analyze vn"}; Configurable maxY_rec{"maxY_rec", 0.9, "maximum rapidity for reconstructed particles"}; Configurable fd_k0s_to_pi0{"fd_k0s_pi0", "1.0", "feed down correction to pi0"}; - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; @@ -108,8 +103,11 @@ struct Pi0EtaToGammaGammaMC { Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgRequireEMCReadoutInMB{"cfgRequireEMCReadoutInMB", false, "require the EMC to be read out in an MB collision (kTVXinEMC)"}; + Configurable cfgRequireEMCHardwareTriggered{"cfgRequireEMCHardwareTriggered", false, "require the EMC to be hardware triggered (kEMC7 or kDMC7)"}; Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; } eventcuts; V0PhotonCut fV0PhotonCut; @@ -143,8 +141,6 @@ struct Pi0EtaToGammaGammaMC { std::string prefix = "dileptoncut_group"; Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; Configurable cfg_max_mass{"cfg_max_mass", 0.1, "max mass"}; - Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; @@ -162,33 +158,16 @@ struct Pi0EtaToGammaGammaMC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPConly), "pid scheme [kTPConly : 0]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3.0, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - - // CCDB configuration for PID ML - Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; - - Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dileptoncuts; EMCPhotonCut fEMCCut; struct : ConfigurableGroup { std::string prefix = "emccut_group"; - Configurable requireCaloReadout{"requireCaloReadout", true, "Require calorimeters readout when analyzing EMCal/PHOS"}; Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; 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"}; @@ -223,16 +202,15 @@ struct Pi0EtaToGammaGammaMC { int mRunNumber; float d_bz; - bool cfgDoFlow = false; void init(InitContext&) { - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); if constexpr (pairtype == PairType::kPCMDalitzEE) { - o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, cfgDoFlow, true, "ee#gamma", ""); + o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, true, "ee#gamma"); } else if constexpr (pairtype == PairType::kPCMDalitzMuMu) { - o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, cfgDoFlow, true, "#mu#mu#gamma", ""); + o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, true, "#mu#mu#gamma"); } else { - o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, cfgDoFlow, true, "#gamma#gamma", ""); + o2::aod::pwgem::photonmeson::utils::nmhistogram::addNMHistograms(&fRegistry, true, "#gamma#gamma"); } DefineEMEventCut(); DefinePCMCut(); @@ -300,7 +278,7 @@ struct Pi0EtaToGammaGammaMC { void DefineEMEventCut() { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); @@ -309,6 +287,8 @@ struct Pi0EtaToGammaGammaMC { fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireEMCReadoutInMB(eventcuts.cfgRequireEMCReadoutInMB); + fEMEventCut.SetRequireEMCHardwareTriggered(eventcuts.cfgRequireEMCHardwareTriggered); fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); } @@ -371,9 +351,7 @@ struct Pi0EtaToGammaGammaMC { // for pair fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.SetPairDCARange(dileptoncuts.cfg_min_pair_dca3d, dileptoncuts.cfg_max_pair_dca3d); // in sigma fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.ApplyPrefilter(dileptoncuts.cfg_apply_pf); fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); @@ -386,36 +364,13 @@ struct Pi0EtaToGammaGammaMC { fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMeanClusterSizeITSob(0, 16); fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaMuRange(dileptoncuts.cfg_min_TPCNsigmaMu, dileptoncuts.cfg_max_TPCNsigmaMu); fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTPCNsigmaKaRange(dileptoncuts.cfg_min_TPCNsigmaKa, dileptoncuts.cfg_max_TPCNsigmaKa); - fDileptonCut.SetTPCNsigmaPrRange(dileptoncuts.cfg_min_TPCNsigmaPr, dileptoncuts.cfg_max_TPCNsigmaPr); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut - o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); - if (dileptoncuts.loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - std::map metadata; - bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dileptoncuts.BDTPathCCDB.value, ".", metadata, dileptoncuts.timestampCCDB.value, false, dileptoncuts.BDTLocalPathGamma.value); - if (retrieveSuccessGamma) { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } else { - LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; - } - } else { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } - - fDileptonCut.SetPIDModel(eid_bdt); - } // end of PID ML } void DefineEMCCut() @@ -459,13 +414,12 @@ struct Pi0EtaToGammaGammaMC { // Partition muons_pos = o2::aod::emprimarymuon::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaMu) < o2::aod::pidtpc::tpcNSigmaMu&& o2::aod::pidtpc::tpcNSigmaMu < static_cast(dileptoncuts.cfg_max_TPCNsigmaMu); // Partition muons_neg = o2::aod::emprimarymuon::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaMu) < o2::aod::pidtpc::tpcNSigmaMu && o2::aod::pidtpc::tpcNSigmaMu < static_cast(dileptoncuts.cfg_max_TPCNsigmaMu); - template + template void runTruePairing(TCollisions const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TSubInfos1 const& /*subinfos1*/, TSubInfos2 const& /*subinfos2*/, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCut1 const& cut1, TCut2 const& cut2, - TTracksMatchedWithEMC const& /*tracks_emc*/, TTracksMatchedWithPHOS const& /*tracks_phos*/, TMCCollisions const& mccollisions, TMCParticles const& mcparticles) { for (auto& collision : collisions) { @@ -474,7 +428,8 @@ struct Pi0EtaToGammaGammaMC { if ((pairtype == PairType::kPHOSPHOS || pairtype == PairType::kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { continue; } - if ((pairtype == PairType::kEMCEMC || pairtype == PairType::kPCMEMC) && ((!collision.alias_bit(triggerAliases::kTVXinEMC) && emccuts.requireCaloReadout) || collision.ncollsPerBC() != 1)) { + + if (eventcuts.onlyKeepWeightedEvents && fabs(collision.weight() - 1.) < 1E-10) { continue; } @@ -483,13 +438,13 @@ struct Pi0EtaToGammaGammaMC { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); if (!fEMEventCut.IsSelected(collision)) { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted int photonid1 = -1, photonid2 = -1, pi0id = -1, etaid = -1; if constexpr (pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC) { // same kinds pairing @@ -553,10 +508,10 @@ struct Pi0EtaToGammaGammaMC { if (pi0id > 0) { auto pi0mc = mcparticles.iteratorAt(pi0id); - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); } else if (etaid > 0) { auto etamc = mcparticles.iteratorAt(etaid); - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); } } // end of pairing loop } else if constexpr (pairtype == PairType::kPCMDalitzEE) { @@ -590,14 +545,8 @@ struct Pi0EtaToGammaGammaMC { continue; } - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { - if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { - continue; - } - } else { // cut-based - if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { - continue; - } + if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { + continue; } if (!cut2.template IsSelectedPair(pos2, ele2, d_bz)) { @@ -619,13 +568,13 @@ struct Pi0EtaToGammaGammaMC { } if (pi0id > 0) { auto pi0mc = mcparticles.iteratorAt(pi0id); - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); } else if (etaid > 0) { auto etamc = mcparticles.iteratorAt(etaid); - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); } - } // end of dielectron loop - } // end of pcm loop + } // end of dielectron loop + } // end of pcm loop } else { // PCM-EMC, PCM-PHOS. Nightmare. don't run these pairs. auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); auto photons2_per_collision = photons2.sliceBy(perCollision2, collision.globalIndex()); @@ -640,10 +589,16 @@ struct Pi0EtaToGammaGammaMC { if (abs(v12.Rapidity()) > maxY_rec) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillPairInfo<0, pairtype>(&fRegistry, collision, v12, cfgDoFlow); + // if (pi0id > 0) { + // auto pi0mc = mcparticles.iteratorAt(pi0id); + // o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); + // } else if (etaid > 0) { + // auto etamc = mcparticles.iteratorAt(etaid); + // o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); + // } } // end of pairing loop - } // end of pairing in same event - } // end of collision loop + } // end of pairing in same event + } // end of collision loop } template @@ -688,9 +643,6 @@ struct Pi0EtaToGammaGammaMC { if ((pairtype == kPHOSPHOS || pairtype == kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { continue; // I don't know why this is necessary in simulation. } - if ((pairtype == kEMCEMC || pairtype == kPCMEMC) && ((!collision.alias_bit(triggerAliases::kTVXinEMC) && emccuts.requireCaloReadout) || collision.ncollsPerBC() != 1)) { - continue; // I don't know why this is necessary in simulation. - } float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { @@ -704,8 +656,8 @@ struct Pi0EtaToGammaGammaMC { auto mccollision = collision.template emmcevent_as(); auto binned_data_pi0_gen = mccollision.generatedPi0(); auto binned_data_eta_gen = mccollision.generatedEta(); - fillBinnedData<0>(binned_data_pi0_gen, 1.f); - fillBinnedData<1>(binned_data_eta_gen, 1.f); + fillBinnedData<0>(binned_data_pi0_gen, collision.weight()); + fillBinnedData<1>(binned_data_eta_gen, collision.weight()); } // end of collision loop } @@ -717,19 +669,18 @@ struct Pi0EtaToGammaGammaMC { if constexpr (pairtype == PairType::kPCMPCM) { auto v0photons = std::get<0>(std::tie(args...)); auto v0legs = std::get<1>(std::tie(args...)); - runTruePairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, nullptr, nullptr, mccollisions, mcparticles); + runTruePairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, mccollisions, mcparticles); runGenInfo(collisions, mccollisions, mcparticles); } else if constexpr (pairtype == PairType::kPCMDalitzEE) { auto v0photons = std::get<0>(std::tie(args...)); auto v0legs = std::get<1>(std::tie(args...)); auto emprimaryelectrons = std::get<2>(std::tie(args...)); // LOGF(info, "electrons.size() = %d, positrons.size() = %d", electrons.size(), positrons.size()); - runTruePairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, nullptr, nullptr, mccollisions, mcparticles); + runTruePairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, mccollisions, mcparticles); runGenInfo(collisions, mccollisions, mcparticles); } else if constexpr (pairtype == PairType::kEMCEMC) { auto emcclusters = std::get<0>(std::tie(args...)); - auto emcmatchedtracks = std::get<1>(std::tie(args...)); - runTruePairing(collisions, emcclusters, emcclusters, nullptr, nullptr, perCollision_emc, perCollision_emc, fEMCCut, fEMCCut, emcmatchedtracks, nullptr, mccollisions, mcparticles); + runTruePairing(collisions, emcclusters, emcclusters, nullptr, nullptr, perCollision_emc, perCollision_emc, fEMCCut, fEMCCut, mccollisions, mcparticles); runGenInfo(collisions, mccollisions, mcparticles); } diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index cb4f71465fe..bceee717d76 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -224,6 +224,12 @@ void V0PhotonCut::SetRequireTPCTRDTOF(bool flag) LOG(info) << "V0 Photon Cut, require TPC-TOF track: " << mRequireTPCTRDTOF; } +void V0PhotonCut::SetDisableITSonly(bool flag) +{ + mDisableITSonly = flag; + LOG(info) << "V0 Photon Cut, disable ITS only track: " << mDisableITSonly; +} + void V0PhotonCut::print() const { LOG(info) << "V0 Photon Cut:"; diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index dff38d1ffd6..55e9718e156 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -61,7 +61,7 @@ class V0PhotonCut : public TNamed kDCAz, kITSNCls, kITSChi2NDF, - kITSCluserSize, + kITSClusterSize, kIsWithinBeamPipe, kRequireITSTPC, kRequireITSonly, @@ -144,6 +144,9 @@ class V0PhotonCut : public TNamed if (!track.hasITS() && !track.hasTPC()) { // track has to be ITSonly or TPConly or ITS-TPC return false; } + if (mDisableITSonly && isITSonlyTrack(track)) { + return false; + } if (mRejectITSib) { auto hits_ib = std::count_if(its_ib_Requirement.second.begin(), its_ib_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); @@ -205,7 +208,7 @@ class V0PhotonCut : public TNamed if (!IsSelectedTrack(track, V0PhotonCuts::kITSChi2NDF)) { return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kITSCluserSize)) { + if (!IsSelectedTrack(track, V0PhotonCuts::kITSClusterSize)) { return false; } return true; @@ -392,7 +395,7 @@ class V0PhotonCut : public TNamed case V0PhotonCuts::kITSChi2NDF: return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; - case V0PhotonCuts::kITSCluserSize: { + case V0PhotonCuts::kITSClusterSize: { if (!isITSonlyTrack(track)) { return true; } @@ -483,6 +486,7 @@ class V0PhotonCut : public TNamed void SetRequireTPCTRD(bool flag); void SetRequireTPCTOF(bool flag); void SetRequireTPCTRDTOF(bool flag); + void SetDisableITSonly(bool flag); /// @brief Print the track selection void print() const; @@ -534,6 +538,7 @@ class V0PhotonCut : public TNamed bool mRequireTPCTRD{false}; bool mRequireTPCTOF{false}; bool mRequireTPCTRDTOF{false}; + bool mDisableITSonly{false}; ClassDef(V0PhotonCut, 1); }; diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index 380b0d54581..9b91eb0864f 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -13,14 +13,10 @@ #include #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/CaloClusters.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Qvectors.h" + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + #include "PWGJE/DataModel/EMCALClusters.h" #ifndef PWGEM_PHOTONMESON_DATAMODEL_GAMMATABLES_H_ @@ -29,183 +25,6 @@ namespace o2::aod { -namespace emevent -{ -DECLARE_SOA_COLUMN(CollisionId, collisionId, int); -DECLARE_SOA_COLUMN(NgammaPCM, ngpcm, int); -DECLARE_SOA_COLUMN(NgammaPHOS, ngphos, int); -DECLARE_SOA_COLUMN(NgammaEMC, ngemc, int); -DECLARE_SOA_COLUMN(NeeULS, neeuls, int); -DECLARE_SOA_COLUMN(NeeLSpp, neelspp, int); -DECLARE_SOA_COLUMN(NeeLSmm, neelsmm, int); -DECLARE_SOA_COLUMN(NmumuULS, nmumuuls, int); -DECLARE_SOA_COLUMN(NmumuLSpp, nmumulspp, int); -DECLARE_SOA_COLUMN(NmumuLSmm, nmumulsmm, int); -DECLARE_SOA_COLUMN(NcollsPerBC, ncollsPerBC, int); -DECLARE_SOA_COLUMN(Bz, bz, float); //! kG -DECLARE_SOA_COLUMN(Q2xFT0M, q2xft0m, float); //! Qx for 2nd harmonics in FT0M (i.e. positive eta) -DECLARE_SOA_COLUMN(Q2yFT0M, q2yft0m, float); //! Qy for 2nd harmonics in FT0M (i.e. positive eta) -DECLARE_SOA_COLUMN(Q2xFT0A, q2xft0a, float); //! Qx for 2nd harmonics in FT0A (i.e. positive eta) -DECLARE_SOA_COLUMN(Q2yFT0A, q2yft0a, float); //! Qy for 2nd harmonics in FT0A (i.e. positive eta) -DECLARE_SOA_COLUMN(Q2xFT0C, q2xft0c, float); //! Qx for 2nd harmonics in FT0C (i.e. negative eta) -DECLARE_SOA_COLUMN(Q2yFT0C, q2yft0c, float); //! Qy for 2nd harmonics in FT0C (i.e. negative eta) -DECLARE_SOA_COLUMN(Q2xBPos, q2xbpos, float); //! Qx for 2nd harmonics in Barrel positive eta region -DECLARE_SOA_COLUMN(Q2yBPos, q2ybpos, float); //! Qy for 2nd harmonics in Barrel positive eta region -DECLARE_SOA_COLUMN(Q2xBNeg, q2xbneg, float); //! Qx for 2nd harmonics in Barrel negative eta region -DECLARE_SOA_COLUMN(Q2yBNeg, q2ybneg, float); //! Qy for 2nd harmonics in Barrel negative eta region -DECLARE_SOA_COLUMN(Q3xFT0M, q3xft0m, float); //! Qx for 3rd harmonics in FT0M (i.e. positive eta) -DECLARE_SOA_COLUMN(Q3yFT0M, q3yft0m, float); //! Qy for 3rd harmonics in FT0M (i.e. positive eta) -DECLARE_SOA_COLUMN(Q3xFT0A, q3xft0a, float); //! Qx for 3rd harmonics in FT0A (i.e. positive eta) -DECLARE_SOA_COLUMN(Q3yFT0A, q3yft0a, float); //! Qy for 3rd harmonics in FT0A (i.e. positive eta) -DECLARE_SOA_COLUMN(Q3xFT0C, q3xft0c, float); //! Qx for 3rd harmonics in FT0C (i.e. negative eta) -DECLARE_SOA_COLUMN(Q3yFT0C, q3yft0c, float); //! Qy for 3rd harmonics in FT0C (i.e. negative eta) -DECLARE_SOA_COLUMN(Q3xBPos, q3xbpos, float); //! Qx for 3rd harmonics in Barrel positive eta region -DECLARE_SOA_COLUMN(Q3yBPos, q3ybpos, float); //! Qy for 3rd harmonics in Barrel positive eta region -DECLARE_SOA_COLUMN(Q3xBNeg, q3xbneg, float); //! Qx for 3rd harmonics in Barrel negative eta region -DECLARE_SOA_COLUMN(Q3yBNeg, q3ybneg, float); //! Qy for 3rd harmonics in Barrel negative eta region - -DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0M, ep2ft0m, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0A, ep2ft0a, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0C, ep2ft0c, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP2BPos, ep2bpos, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP2BNeg, ep2bneg, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP3FT0M, ep3ft0m, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP3FT0A, ep3ft0a, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP3FT0C, ep3ft0c, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP3BPos, ep3bpos, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); -DECLARE_SOA_DYNAMIC_COLUMN(EP3BNeg, ep3bneg, [](float q3x, float q3y) -> float { return std::atan2(q3y, q3x) / 3.0; }); -} // namespace emevent -DECLARE_SOA_TABLE(EMEvents_000, "AOD", "EMEVENT", //! Main event information table - o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, evsel::Sel8, evsel::Alias, evsel::Selection, emevent::NcollsPerBC, - collision::PosX, collision::PosY, collision::PosZ, - collision::NumContrib, emevent::Bz); - -DECLARE_SOA_TABLE_VERSIONED(EMEvents_001, "AOD", "EMEVENT", 1, //! Main event information table - o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, bc::GlobalBC, evsel::Sel8, evsel::Alias, evsel::Selection, timestamp::Timestamp, emevent::NcollsPerBC, - collision::PosX, collision::PosY, collision::PosZ, - collision::NumContrib, evsel::NumTracksInTimeRange); - -using EMEvents = EMEvents_001; -using EMEvent = EMEvents::iterator; - -DECLARE_SOA_TABLE(EMEventsCov, "AOD", "EMEVENTCOV", //! joinable to EMEvents - collision::CovXX, collision::CovXY, collision::CovXZ, collision::CovYY, collision::CovYZ, collision::CovZZ, collision::Chi2); -using EMEventCov = EMEventsCov::iterator; - -DECLARE_SOA_TABLE(EMEventsBz, "AOD", "EMEVENTBZ", emevent::Bz); // joinable to EMEvents -using EMEventBz = EMEventsBz::iterator; - -DECLARE_SOA_TABLE(EMEventsMult, "AOD", "EMEVENTMULT", //! event multiplicity table, joinable to EMEvents - mult::MultFT0A, mult::MultFT0C, - mult::MultTPC, mult::MultNTracksPV, mult::MultNTracksPVeta1, mult::MultNTracksPVetaHalf, - mult::IsInelGt0, mult::IsInelGt1, mult::MultFT0M); -using EMEventMult = EMEventsMult::iterator; - -DECLARE_SOA_TABLE(EMEventsCent, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents - cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentNTPV); -using EMEventCent = EMEventsCent::iterator; - -DECLARE_SOA_TABLE(EMEventsQvec, "AOD", "EMEVENTQVEC", //! event q vector table, joinable to EMEvents - emevent::Q2xFT0M, emevent::Q2yFT0M, emevent::Q2xFT0A, emevent::Q2yFT0A, emevent::Q2xFT0C, emevent::Q2yFT0C, - emevent::Q2xBPos, emevent::Q2yBPos, emevent::Q2xBNeg, emevent::Q2yBNeg, - emevent::Q3xFT0M, emevent::Q3yFT0M, emevent::Q3xFT0A, emevent::Q3yFT0A, emevent::Q3xFT0C, emevent::Q3yFT0C, - emevent::Q3xBPos, emevent::Q3yBPos, emevent::Q3xBNeg, emevent::Q3yBNeg, - - // Dynamic columns - emevent::EP2FT0M, - emevent::EP2FT0A, - emevent::EP2FT0C, - emevent::EP2BPos, - emevent::EP2BNeg, - emevent::EP3FT0M, - emevent::EP3FT0A, - emevent::EP3FT0C, - emevent::EP3BPos, - emevent::EP3BNeg); -using EMEventQvec = EMEventsQvec::iterator; - -DECLARE_SOA_TABLE(EMEventsNgPCM, "AOD", "EMEVENTNGPCM", emevent::NgammaPCM); // joinable to EMEvents -using EMEventNgPCM = EMEventsNgPCM::iterator; - -DECLARE_SOA_TABLE(EMEventsNgPHOS, "AOD", "EMEVENTNGPHOS", emevent::NgammaPHOS); // joinable to EMEvents -using EMEventNgPHOS = EMEventsNgPHOS::iterator; - -DECLARE_SOA_TABLE(EMEventsNgEMC, "AOD", "EMEVENTNGEMC", emevent::NgammaEMC); // joinable to EMEvents -using EMEventNgEMC = EMEventsNgEMC::iterator; - -DECLARE_SOA_TABLE(EMEventsNee, "AOD", "EMEVENTNEE", emevent::NeeULS, emevent::NeeLSpp, emevent::NeeLSmm); // joinable to EMEvents -using EMEventNee = EMEventsNee::iterator; - -DECLARE_SOA_TABLE(EMEventsNmumu, "AOD", "EMEVENTNMUMU", emevent::NmumuULS, emevent::NmumuLSpp, emevent::NmumuLSmm); // joinable to EMEvents -using EMEventNmumu = EMEventsNmumu::iterator; - -namespace emmcevent -{ -DECLARE_SOA_COLUMN(McCollisionId, mcCollisionId, int); -} // namespace emmcevent - -DECLARE_SOA_TABLE(EMMCEvents, "AOD", "EMMCEVENT", //! MC event information table - o2::soa::Index<>, emmcevent::McCollisionId, mccollision::GeneratorsID, - mccollision::PosX, mccollision::PosY, mccollision::PosZ, - mccollision::T, mccollision::ImpactParameter, - - // dynamic column - mccollision::GetGeneratorId, - mccollision::GetSubGeneratorId, - mccollision::GetSourceId); - -using EMMCEvent = EMMCEvents::iterator; - -namespace emmceventlabel -{ -DECLARE_SOA_INDEX_COLUMN(EMMCEvent, emmcevent); //! MC collision -DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); //! Bit mask to indicate collision mismatches (bit ON means mismatch). Bit 15: indicates negative label -} // namespace emmceventlabel - -DECLARE_SOA_TABLE(EMMCEventLabels, "AOD", "EMMCEVENTLABEL", //! Table joined to the EMEvents table containing the MC index - emmceventlabel::EMMCEventId, emmceventlabel::McMask); -using EMMCEventLabel = EMMCEventLabels::iterator; - -namespace emmcparticle -{ -DECLARE_SOA_INDEX_COLUMN(EMMCEvent, emmcevent); -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) array. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return RecoDecay::phi(px, py); }); -DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); -DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! Particle rapidity - [](float pz, float e) -> float { - if ((e - pz) > static_cast(1e-7)) { - return 0.5f * std::log((e + pz) / (e - pz)); - } else { - return -999.0f; - } - }); -} // namespace emmcparticle - -// This table contains all MC truth tracks (both v0 and calos) -DECLARE_SOA_TABLE_FULL(EMMCParticles, "EMMCParticles", "AOD", "EMMCPARTICLE", //! MC track information (on disk) - o2::soa::Index<>, emmcparticle::EMMCEventId, - mcparticle::PdgCode, mcparticle::Flags, - emmcparticle::MothersIds, emmcparticle::DaughtersIds, - mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, - mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, - - // dynamic column - emmcparticle::Pt, - emmcparticle::Eta, - emmcparticle::Phi, - - emmcparticle::P, - emmcparticle::Y, - mcparticle::ProducedByGenerator, - mcparticle::FromBackgroundEvent, - mcparticle::IsPhysicalPrimary); - -using EMMCParticle = EMMCParticles::iterator; - namespace emmcbinnedgen { DECLARE_SOA_COLUMN(GeneratedGamma, generatedGamma, std::vector); //! gamma binned generated data @@ -218,38 +37,41 @@ DECLARE_SOA_COLUMN(GeneratedChargedKaon, generatedChargedKaon, std::vector); //! K0S binned generated data DECLARE_SOA_COLUMN(GeneratedLambda, generatedLambda, std::vector); //! Lambda binned generated data -DECLARE_SOA_COLUMN(GeneratedPi0_Acc_gg, generatedPi0_acc_gg, std::vector); //! pi0 -> gg binned generated data -DECLARE_SOA_COLUMN(GeneratedPi0_Acc_eeg, generatedPi0_acc_eeg, std::vector); //! pi0 -> eeg binned generated data -DECLARE_SOA_COLUMN(GeneratedEta_Acc_gg, generatedEta_acc_gg, std::vector); //! eta -> gg binned generated data -DECLARE_SOA_COLUMN(GeneratedEta_Acc_eeg, generatedEta_acc_eeg, std::vector); //! eta -> eeg binned generated data -DECLARE_SOA_COLUMN(GeneratedEta_Acc_mumug, generatedEta_acc_mumug, std::vector); //! eta -> mumug binned generated data -DECLARE_SOA_COLUMN(GeneratedEta_Acc_pipig, generatedEta_acc_pipig, std::vector); //! eta -> pipig binned generated data -DECLARE_SOA_COLUMN(GeneratedOmega_Acc_ee, generatedOmega_acc_ee, std::vector); //! omega(782) -> ee binned generated data -DECLARE_SOA_COLUMN(GeneratedPhi_Acc_ee, generatedPhi_acc_ee, std::vector); //! phi(1020) -> ee binned generated data +// DECLARE_SOA_COLUMN(GeneratedPi0_Acc_gg, generatedPi0_acc_gg, std::vector); //! pi0 -> gg binned generated data +// DECLARE_SOA_COLUMN(GeneratedPi0_Acc_eeg, generatedPi0_acc_eeg, std::vector); //! pi0 -> eeg binned generated data +// DECLARE_SOA_COLUMN(GeneratedEta_Acc_gg, generatedEta_acc_gg, std::vector); //! eta -> gg binned generated data +// DECLARE_SOA_COLUMN(GeneratedEta_Acc_eeg, generatedEta_acc_eeg, std::vector); //! eta -> eeg binned generated data +// DECLARE_SOA_COLUMN(GeneratedEta_Acc_mumug, generatedEta_acc_mumug, std::vector); //! eta -> mumug binned generated data +// DECLARE_SOA_COLUMN(GeneratedOmega_Acc_ee, generatedOmega_acc_ee, std::vector); //! omega(782) -> ee binned generated data +// DECLARE_SOA_COLUMN(GeneratedPhi_Acc_ee, generatedPhi_acc_ee, std::vector); //! phi(1020) -> ee binned generated data +// DECLARE_SOA_COLUMN(GeneratedOmega_Acc_mumu, generatedOmega_acc_mumu, std::vector); //! omega(782) -> mumu binned generated data +// DECLARE_SOA_COLUMN(GeneratedPhi_Acc_mumu, generatedPhi_acc_mumu, std::vector); //! phi(1020) -> mumu binned generated data } // namespace emmcbinnedgen DECLARE_SOA_TABLE(BinnedGenPts, "AOD", "BINNEDGENPT", // To be joined with EMMCEvents table at analysis level. emmcbinnedgen::GeneratedGamma, emmcbinnedgen::GeneratedPi0, - emmcbinnedgen::GeneratedEta, - emmcbinnedgen::GeneratedOmega, - emmcbinnedgen::GeneratedPhi, - emmcbinnedgen::GeneratedChargedPion, - emmcbinnedgen::GeneratedChargedKaon, - emmcbinnedgen::GeneratedK0S, - emmcbinnedgen::GeneratedLambda); + emmcbinnedgen::GeneratedEta + // emmcbinnedgen::GeneratedOmega, + // emmcbinnedgen::GeneratedPhi, + // emmcbinnedgen::GeneratedChargedPion, + // emmcbinnedgen::GeneratedChargedKaon, + // emmcbinnedgen::GeneratedK0S, + // emmcbinnedgen::GeneratedLambda +); using BinnedGenPt = BinnedGenPts::iterator; -DECLARE_SOA_TABLE(BinnedGenPtAccs, "AOD", "BINNEDGENPTACC", // To be joined with EMMCEvents table at analysis level. - emmcbinnedgen::GeneratedPi0_Acc_gg, - emmcbinnedgen::GeneratedPi0_Acc_eeg, - emmcbinnedgen::GeneratedEta_Acc_gg, - emmcbinnedgen::GeneratedEta_Acc_eeg, - emmcbinnedgen::GeneratedEta_Acc_mumug, - emmcbinnedgen::GeneratedEta_Acc_pipig, - emmcbinnedgen::GeneratedOmega_Acc_ee, - emmcbinnedgen::GeneratedPhi_Acc_ee); -using BinnedGenPtAcc = BinnedGenPtAccs::iterator; +// DECLARE_SOA_TABLE(BinnedGenPtAccs, "AOD", "BINNEDGENPTACC", // To be joined with EMMCEvents table at analysis level. +// emmcbinnedgen::GeneratedPi0_Acc_gg, +// emmcbinnedgen::GeneratedPi0_Acc_eeg, +// emmcbinnedgen::GeneratedEta_Acc_gg, +// emmcbinnedgen::GeneratedEta_Acc_eeg, +// emmcbinnedgen::GeneratedEta_Acc_mumug, +// emmcbinnedgen::GeneratedOmega_Acc_ee, +// emmcbinnedgen::GeneratedPhi_Acc_ee) +//// emmcbinnedgen::GeneratedOmega_Acc_mumu, +//// emmcbinnedgen::GeneratedPhi_Acc_mumu); +// using BinnedGenPtAcc = BinnedGenPtAccs::iterator; namespace v0legmclabel { @@ -262,28 +84,6 @@ DECLARE_SOA_TABLE(V0LegMCLabels, "AOD", "V0LEGMCLABEL", //! v0legmclabel::EMMCParticleId, v0legmclabel::McMask); using V0LegMCLabel = V0LegMCLabels::iterator; -namespace emprimaryelectronmclabel -{ -DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! -DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); -} // namespace emprimaryelectronmclabel - -// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with EMPrimaryElectrons table) -DECLARE_SOA_TABLE(EMPrimaryElectronMCLabels, "AOD", "EMPRMELMCLABEL", //! - emprimaryelectronmclabel::EMMCParticleId, emprimaryelectronmclabel::McMask); -using EMPrimaryElectronMCLabel = EMPrimaryElectronMCLabels::iterator; - -namespace emprimarymuonmclabel -{ -DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! -DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); -} // namespace emprimarymuonmclabel - -// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with EMPrimaryMuons table) -DECLARE_SOA_TABLE(EMPrimaryMuonMCLabels, "AOD", "EMPRMMUMCLABEL", //! - emprimarymuonmclabel::EMMCParticleId, emprimarymuonmclabel::McMask); -using EMPrimaryMuonMCLabel = EMPrimaryMuonMCLabels::iterator; - // * EMC cluster mc label tables: // 1. EMCALMCClusters in EMCalClusters.h: Vectors of global mc particle ids and energy fractions of the cluster // 2. EMCClusterMCLabels: Vector of global mc particle ids @@ -370,7 +170,7 @@ DECLARE_SOA_TABLE(V0Legs, "AOD", "V0LEG", //! o2::soa::Index<>, v0leg::CollisionId, v0leg::TrackId, v0leg::Sign, v0leg::Px, v0leg::Py, v0leg::Pz, track::DcaXY, track::DcaZ, - track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TPCChi2NCl, track::TPCInnerParam, track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, track::ITSClusterSizes, track::ITSChi2NCl, track::DetectorMap, @@ -385,6 +185,7 @@ DECLARE_SOA_TABLE(V0Legs, "AOD", "V0LEG", //! track::TPCNClsCrossedRows, track::TPCCrossedRowsOverFindableCls, track::TPCFoundOverFindableCls, + track::TPCFractionSharedCls, track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, @@ -395,10 +196,24 @@ DECLARE_SOA_TABLE(V0Legs, "AOD", "V0LEG", //! // iterators using V0Leg = V0Legs::iterator; +namespace emevent +{ +DECLARE_SOA_COLUMN(NgPCM, ngpcm, int); +DECLARE_SOA_COLUMN(Weight, weight, float); //! Weight of the event (e.g. for JJ MCs). Set to 1 for data and non-weighted MCs. +} // namespace emevent + +DECLARE_SOA_TABLE(EMEventsNgPCM, "AOD", "EMEVENTNGPCM", emevent::NgPCM); // joinable to EMEvents or aod::Collisions +using EMEventNgPCM = EMEventsNgPCM::iterator; + +DECLARE_SOA_TABLE(EMEventsWeight, "AOD", "EMEVENTWEIGHT", //! table contanint the weight for eache event (for JJ MCs), joinable to EMEvents + emevent::Weight); +using EMEventWeight = EMEventsWeight::iterator; + namespace v0photonkf { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(V0Id, v0Id, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, V0Legs, "_Pos"); //! DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, V0Legs, "_Neg"); //! DECLARE_SOA_COLUMN(Vx, vx, float); //! secondary vertex x @@ -415,6 +230,12 @@ DECLARE_SOA_COLUMN(PCA, pca, float); //! DECLARE_SOA_COLUMN(Alpha, alpha, float); //! DECLARE_SOA_COLUMN(QtArm, qtarm, float); //! DECLARE_SOA_COLUMN(ChiSquareNDF, chiSquareNDF, float); // Chi2 / NDF of the reconstructed V0 +DECLARE_SOA_COLUMN(SigmaPx2, sigmaPx2, float); //! error^2 of px in covariant matrix +DECLARE_SOA_COLUMN(SigmaPy2, sigmaPy2, float); //! error^2 of py in covariant matrix +DECLARE_SOA_COLUMN(SigmaPz2, sigmaPz2, float); //! error^2 of pz in covariant matrix +DECLARE_SOA_COLUMN(SigmaPxPy, sigmaPxPy, float); //! error of px x py in covariant matrix +DECLARE_SOA_COLUMN(SigmaPyPz, sigmaPyPz, float); //! error of py x pz in covariant matrix +DECLARE_SOA_COLUMN(SigmaPzPx, sigmaPzPx, float); //! error of pz x px in covariant matrix DECLARE_SOA_DYNAMIC_COLUMN(E, e, [](float px, float py, float pz, float m = 0) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz, m); }); //! energy of v0 photn, mass to be given as argument when getter is called! DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); @@ -424,7 +245,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) -> float { ret DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, [](float vx, float vy) -> float { return RecoDecay::sqrtSumOfSquares(vx, vy); }); } // namespace v0photonkf DECLARE_SOA_TABLE(V0PhotonsKF, "AOD", "V0PHOTONKF", //! - o2::soa::Index<>, v0photonkf::CollisionId, v0photonkf::PosTrackId, v0photonkf::NegTrackId, + o2::soa::Index<>, v0photonkf::CollisionId, v0photonkf::V0Id, v0photonkf::PosTrackId, v0photonkf::NegTrackId, v0photonkf::Vx, v0photonkf::Vy, v0photonkf::Vz, v0photonkf::Px, v0photonkf::Py, v0photonkf::Pz, v0photonkf::MGamma, @@ -447,75 +268,19 @@ DECLARE_SOA_TABLE(V0KFEMEventIds, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId) // iterators using V0KFEMEventId = V0KFEMEventIds::iterator; -namespace emprimaryelectron -{ -DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! -DECLARE_SOA_COLUMN(TrackId, trackId, int); //! -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousElectrons, ambiguousElectrons); -DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! -DECLARE_SOA_COLUMN(PrefilterBit, pfb, uint8_t); //! -DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); -DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); -DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); -DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); -DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { - int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 0; layer < 7; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; - if (cluster_size_per_layer > 0) { - nl++; - } - total_cluster_size += cluster_size_per_layer; - } - if (nl > 0) { - return static_cast(total_cluster_size) / static_cast(nl); - } else { - return 0; - } -}); -DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSib, meanClusterSizeITSib, [](uint32_t itsClusterSizes) -> float { - int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 0; layer < 3; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; - if (cluster_size_per_layer > 0) { - nl++; - } - total_cluster_size += cluster_size_per_layer; - } - if (nl > 0) { - return static_cast(total_cluster_size) / static_cast(nl); - } else { - return 0; - } -}); -DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32_t itsClusterSizes) -> float { - int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 3; layer < 7; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; - if (cluster_size_per_layer > 0) { - nl++; - } - total_cluster_size += cluster_size_per_layer; - } - if (nl > 0) { - return static_cast(total_cluster_size) / static_cast(nl); - } else { - return 0; - } -}); -} // namespace emprimaryelectron -DECLARE_SOA_TABLE(EMPrimaryElectrons, "AOD", "EMPRIMARYEL", //! +DECLARE_SOA_TABLE(V0PhotonsKFCov, "AOD", "V0PHOTONKFCOV", //! To be joined with V0PhotonsKF table at analysis level. + v0photonkf::SigmaPx2, v0photonkf::SigmaPy2, v0photonkf::SigmaPz2, v0photonkf::SigmaPxPy, v0photonkf::SigmaPyPz, v0photonkf::SigmaPzPx); +// iterators +using V0PhotonKFCov = V0PhotonsKFCov::iterator; + +DECLARE_SOA_TABLE(EMPrimaryElectronsFromDalitz, "AOD", "EMPRIMARYELDA", //! o2::soa::Index<>, emprimaryelectron::CollisionId, emprimaryelectron::TrackId, emprimaryelectron::Sign, track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCChi2NCl, track::TPCInnerParam, - track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, - pidtofbeta::Beta, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, - track::ITSClusterSizes, track::ITSChi2NCl, track::DetectorMap, - track::X, track::Alpha, track::Y, track::Z, track::Snp, track::Tgl, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, + track::ITSClusterSizes, track::ITSChi2NCl, track::DetectorMap, track::Tgl, // dynamic column track::TPCNClsFound, @@ -534,38 +299,7 @@ DECLARE_SOA_TABLE(EMPrimaryElectrons, "AOD", "EMPRIMARYEL", //! emprimaryelectron::MeanClusterSizeITSib, emprimaryelectron::MeanClusterSizeITSob); // iterators -using EMPrimaryElectron = EMPrimaryElectrons::iterator; - -DECLARE_SOA_TABLE(EMPrimaryElectronsCov, "AOD", "EMPRIMARYELCOV", //! - aod::track::CYY, - aod::track::CZY, - aod::track::CZZ, - aod::track::CSnpY, - aod::track::CSnpZ, - aod::track::CSnpSnp, - aod::track::CTglY, - aod::track::CTglZ, - aod::track::CTglSnp, - aod::track::CTglTgl, - aod::track::C1PtY, - aod::track::C1PtZ, - aod::track::C1PtSnp, - aod::track::C1PtTgl, - aod::track::C1Pt21Pt2); -// iterators -using EMPrimaryElectronCov = EMPrimaryElectronsCov::iterator; - -DECLARE_SOA_TABLE(EMPrimaryElectronEMEventIds, "AOD", "PRMELMEVENTID", emprimaryelectron::EMEventId); // To be joined with EMPrimaryElectrons table at analysis level. -// iterators -using EMPrimaryElectronEMEventId = EMPrimaryElectronEMEventIds::iterator; - -DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBit, "AOD", "PRMELPFB", emprimaryelectron::PrefilterBit); // To be joined with EMPrimaryElectrons table at analysis level. -// iterators -using EMPrimaryElectronPrefilterBit = EMPrimaryElectronsPrefilterBit::iterator; - -DECLARE_SOA_TABLE(EMAmbiguousElectronSelfIds, "AOD", "EMAMBELSELFID", emprimaryelectron::AmbiguousElectronsIds); // To be joined with EMPrimaryElectrons table at analysis level. -// iterators -using EMAmbiguousElectronSelfId = EMAmbiguousElectronSelfIds::iterator; +using EMPrimaryElectronFromDalitz = EMPrimaryElectronsFromDalitz::iterator; namespace dalitzee { @@ -595,94 +329,6 @@ DECLARE_SOA_TABLE(DalitzEEEMEventIds, "AOD", "EEEMEVENTID", dalitzee::EMEventId) // iterators using DalitzEEEMEventId = DalitzEEEMEventIds::iterator; -namespace emprimarymuon -{ -DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! -DECLARE_SOA_COLUMN(FwdTrackId, fwdtrackId, int); //! -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(MCHTrack, matchMCHTrack, int, "FwdTracks_MatchMCHTrack"); //! Index of matched MCH track for GlobalMuonTracks and GlobalForwardTracks -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousMuons, ambiguousMuons); -DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! -DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); -DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); -DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); -DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); -DECLARE_SOA_DYNAMIC_COLUMN(DcaXY, dcaXY, [](float dcaX, float dcaY) -> float { return std::sqrt(dcaX * dcaX + dcaY * dcaY); }); -DECLARE_SOA_DYNAMIC_COLUMN(NClustersMFT, nClustersMFT, //! Number of MFT clusters - [](uint64_t mftClusterSizesAndTrackFlags) -> uint8_t { - uint8_t nClusters = 0; - for (int layer = 0; layer < 10; layer++) { - if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3F) { - nClusters++; - } - } - return nClusters; - }); -DECLARE_SOA_DYNAMIC_COLUMN(MFTClusterMap, mftClusterMap, //! MFT cluster map, one bit per a layer, starting from the innermost - [](uint64_t mftClusterSizesAndTrackFlags) -> uint16_t { - uint16_t clmap = 0; - for (unsigned int layer = 0; layer < 10; layer++) { - if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3f) { - clmap |= (1 << layer); - } - } - return clmap; - }); -} // namespace emprimarymuon -DECLARE_SOA_TABLE(EMPrimaryMuons, "AOD", "EMPRIMARYMU", //! - o2::soa::Index<>, emprimarymuon::CollisionId, - emprimarymuon::FwdTrackId, fwdtrack::TrackType, - fwdtrack::Pt, fwdtrack::Eta, fwdtrack::Phi, emprimarymuon::Sign, - fwdtrack::FwdDcaX, fwdtrack::FwdDcaY, - fwdtrack::X, fwdtrack::Y, fwdtrack::Z, fwdtrack::Tgl, - - fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, - fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, - // fwdtrack::MatchScoreMCHMFT, fwdtrack::MFTTrackId, fwdtrack::MCHTrackId, - emprimarymuon::MCHTrackId, - fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, - fwdtrack::MFTClusterSizesAndTrackFlags, - - // dynamic column - emprimarymuon::Signed1Pt, - emprimarymuon::NClustersMFT, - emprimarymuon::MFTClusterMap, - emprimarymuon::P, - emprimarymuon::Px, - emprimarymuon::Py, - emprimarymuon::Pz, - emprimarymuon::DcaXY); -// iterators -using EMPrimaryMuon = EMPrimaryMuons::iterator; - -DECLARE_SOA_TABLE(EMPrimaryMuonsCov, "AOD", "EMPRIMARYMUCOV", //! - aod::fwdtrack::CXX, - aod::fwdtrack::CXY, - aod::fwdtrack::CYY, - aod::fwdtrack::CPhiX, - aod::fwdtrack::CPhiY, - aod::fwdtrack::CPhiPhi, - aod::fwdtrack::CTglX, - aod::fwdtrack::CTglY, - aod::fwdtrack::CTglPhi, - aod::fwdtrack::CTglTgl, - aod::fwdtrack::C1PtX, - aod::fwdtrack::C1PtY, - aod::fwdtrack::C1PtPhi, - aod::fwdtrack::C1PtTgl, - aod::fwdtrack::C1Pt21Pt2); -// iterators -using EMPrimaryMuonCov = EMPrimaryMuonsCov::iterator; - -DECLARE_SOA_TABLE(EMPrimaryMuonEMEventIds, "AOD", "PRMMUEMEVENTID", emprimarymuon::EMEventId); // To be joined with EMPrimaryMuons table at analysis level. -// iterators -using EMPrimaryMuonEMEventId = EMPrimaryMuonEMEventIds::iterator; - -DECLARE_SOA_TABLE(EMAmbiguousMuonSelfIds, "AOD", "EMAMBMUSELFID", emprimarymuon::AmbiguousMuonsIds); // To be joined with EMPrimaryMuons table at analysis level. -// iterators -using EMAmbiguousMuonSelfId = EMAmbiguousMuonSelfIds::iterator; - namespace pwgem::photon::swtinfo { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! @@ -784,8 +430,8 @@ DECLARE_SOA_TABLE(McGammasTrue, "AOD", "MCGATRUE", namespace skimmedcluster { -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! collisionID used as index for matched clusters -DECLARE_SOA_INDEX_COLUMN(BC, bc); //! bunch crossing ID used as index for ambiguous clusters +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(ID, id, int); //! cluster ID identifying cluster in event DECLARE_SOA_COLUMN(E, e, float); //! cluster energy (GeV) DECLARE_SOA_COLUMN(Eta, eta, float); //! cluster pseudorapidity (calculated using vertex) @@ -813,12 +459,9 @@ DECLARE_SOA_COLUMN(TrackPt, trackpt, std::vector); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float e, float eta, float m = 0) -> float { return sqrt(e * e - m * m) / cosh(eta); }); //! cluster pt, mass to be given as argument when getter is called! } // namespace emccluster DECLARE_SOA_TABLE(SkimEMCClusters, "AOD", "SKIMEMCCLUSTERS", //! table of skimmed EMCal clusters - o2::soa::Index<>, skimmedcluster::CollisionId, skimmedcluster::BCId, skimmedcluster::E, emccluster::CoreEnergy, - skimmedcluster::Eta, skimmedcluster::Phi, skimmedcluster::M02, skimmedcluster::M20, skimmedcluster::NCells, skimmedcluster::Time, - emccluster::IsExotic, skimmedcluster::DistanceToBadChannel, skimmedcluster::NLM, emccluster::Definition, - emccluster::TrackIds, emccluster::TrackEta, emccluster::TrackPhi, emccluster::TrackP, emccluster::TrackPt, - // dynamic column - emccluster::Pt); + o2::soa::Index<>, skimmedcluster::CollisionId, skimmedcluster::E, skimmedcluster::Eta, skimmedcluster::Phi, + skimmedcluster::M02, skimmedcluster::NCells, skimmedcluster::Time, emccluster::IsExotic, emccluster::TrackEta, + emccluster::TrackPhi, emccluster::TrackP, emccluster::TrackPt, emccluster::Pt); using SkimEMCCluster = SkimEMCClusters::iterator; DECLARE_SOA_TABLE(EMCEMEventIds, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index 8753de19d26..7d58cb0cb7c 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt @@ -9,8 +9,6 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -add_subdirectory(converters) - o2physics_add_dpl_workflow(skimmer-gamma-conversion SOURCES skimmerGammaConversion.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle @@ -23,7 +21,7 @@ o2physics_add_dpl_workflow(skimmer-gamma-conversion-truthonlymc o2physics_add_dpl_workflow(photon-conversion-builder SOURCES photonconversionbuilder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle + PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle O2Physics::TPCDriftManager COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(create-pcm @@ -31,13 +29,13 @@ o2physics_add_dpl_workflow(create-pcm PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(create-emevent - SOURCES createEMEvent.cxx +o2physics_add_dpl_workflow(create-emevent-photon + SOURCES createEMEventPhoton.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(associate-mc-info - SOURCES associateMCinfo.cxx +o2physics_add_dpl_workflow(associate-mc-info-photon + SOURCES associateMCinfoPhoton.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -51,16 +49,11 @@ o2physics_add_dpl_workflow(skimmer-phos PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::PHOSBase COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(skimmer-primary-electron - SOURCES skimmerPrimaryElectron.cxx +o2physics_add_dpl_workflow(skimmer-primary-electron-from-dalitzee + SOURCES skimmerPrimaryElectronFromDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(skimmer-primary-muon - SOURCES skimmerPrimaryMuon.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(skimmer-dalitz-ee SOURCES skimmerDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx b/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx deleted file mode 100644 index 9c980999a93..00000000000 --- a/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx +++ /dev/null @@ -1,768 +0,0 @@ -// Copyright 2019-2020 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 produces reduced events for photon analyses. -// Please write to: daiki.sekihata@cern.ch - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::mcutil; - -using MyCollisionsMC = soa::Join; -using TracksMC = soa::Join; -using MyEMCClusters = soa::Join; - -struct AssociateMCInfo { - enum SubSystem { - kPCM = 0x1, - kPHOS = 0x2, - kEMC = 0x4, - kDalitzEE = 0x8, - kDalitzMuMu = 0x10, - }; - - Produces mcevents; - Produces mceventlabels; - Produces emmcparticles; - Produces v0legmclabels; - Produces emprimaryelectronmclabels; - // Produces emprimarymuonmclabels; - Produces ememcclustermclabels; - - Produces binned_gen_pt; - // Produces binned_gen_pt_acc; - - Configurable max_rxy_gen{"max_rxy_gen", 100, "max rxy to store generated information"}; - Configurable max_Y_gen_primary{"max_Y_gen_primary", 1.2, "max rapidity Y to store generated information"}; // smearing might be applied at analysis stage. set wider value. - Configurable max_Y_gen_secondary{"max_Y_gen_secondary", 0.9, "max rapidity Y to store generated information"}; - Configurable margin_z_gen{"margin_z_gen", 15.f, "margin for Z of true photon conversion point to store generated information"}; - - HistogramRegistry registry{"EMMCEvent"}; - - void init(o2::framework::InitContext&) - { - auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{6, 0.5f, 6.5f}}); - hEventCounter->GetXaxis()->SetBinLabel(1, "all"); - hEventCounter->GetXaxis()->SetBinLabel(2, "has mc collision"); - registry.add("PCM/hXY", "hRxy;X (cm);Y (cm)", kTH2F, {{1000, -100, +100}, {1000, -100, +100}}); - registry.add("PCM/hRZ", "hRxy;R (cm);Z (cm)", kTH2F, {{1000, -100, +100}, {1000, 0, +100}}); - - // !!Don't change pt,eta,y binning. These binnings have to be consistent with binned data at analysis.!! - std::vector ptbins; - for (int i = 0; i < 2; i++) { - ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.1 GeV/c, every 0.05 GeV/c - } - for (int i = 2; i < 52; i++) { - ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 5 GeV/c, every 0.1 GeV/c - } - for (int i = 52; i < 62; i++) { - ptbins.emplace_back(0.5 * (i - 52) + 5.0); // from 5 to 10 GeV/c, evety 0.5 GeV/c - } - for (int i = 62; i < 73; i++) { - ptbins.emplace_back(1.0 * (i - 62) + 10.0); // from 10 to 20 GeV/c, evety 1 GeV/c - } - const AxisSpec axis_pt{ptbins, "p_{T} (GeV/c)"}; - const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y|"}; - - static constexpr std::string_view parnames[9] = { - "Gamma", "Pi0", "Eta", "Omega", "Phi", - "ChargedPion", "ChargedKaon", "K0S", "Lambda"}; - - for (int i = 0; i < 9; i++) { - registry.add(Form("Generated/h2PtY_%s", parnames[i].data()), Form("Generated %s", parnames[i].data()), kTH2F, {axis_pt, axis_rapidity}, true); - } - - // reserve space for generated vectors if that process enabled - auto hBinFinder = registry.get(HIST("Generated/h2PtY_Pi0")); - LOGF(info, "Binned generated processing enabled. Initialising with %i elements...", hBinFinder->GetNcells()); - genGamma.resize(hBinFinder->GetNcells(), 0); - genPi0.resize(hBinFinder->GetNcells(), 0); - genEta.resize(hBinFinder->GetNcells(), 0); - genOmega.resize(hBinFinder->GetNcells(), 0); - genPhi.resize(hBinFinder->GetNcells(), 0); - genChargedPion.resize(hBinFinder->GetNcells(), 0); - genChargedKaon.resize(hBinFinder->GetNcells(), 0); - genK0S.resize(hBinFinder->GetNcells(), 0); - genLambda.resize(hBinFinder->GetNcells(), 0); - - static constexpr std::string_view parnames_acc[8] = { - "Pi0_acc_gg", "Pi0_acc_eeg", - "Eta_acc_gg", "Eta_acc_eeg", "Eta_acc_mumug", "Eta_acc_pipig", - "Omega_acc_ee", - "Phi_acc_ee"}; - const AxisSpec axis_eta{{0.0, +0.8, +0.9}, "pseudo-rapidity |#eta|"}; - - for (int i = 0; i < 8; i++) { - registry.add(Form("Generated/hs_%s", parnames_acc[i].data()), Form("Generated %s", parnames_acc[i].data()), kTHnSparseF, {axis_pt, axis_rapidity, axis_eta, axis_eta, axis_eta}, true); - } - auto hBinFinder_acc = registry.get(HIST("Generated/hs_Pi0_acc_gg")); - int nbins_acc = 1; - for (int idim = 0; idim < hBinFinder_acc->GetNdimensions(); idim++) { - nbins_acc *= hBinFinder_acc->GetAxis(idim)->GetNbins(); // without over/underflow - } - - LOGF(info, "Binned generated processing enabled. Initialising with %i elements... for particles in acceptance", nbins_acc); - genPi0_acc_gg.resize(nbins_acc, 0); - genPi0_acc_eeg.resize(nbins_acc, 0); - genEta_acc_gg.resize(nbins_acc, 0); - genEta_acc_eeg.resize(nbins_acc, 0); - genEta_acc_mumug.resize(nbins_acc, 0); - genEta_acc_pipig.resize(nbins_acc, 0); - genOmega_acc_ee.resize(nbins_acc, 0); - genPhi_acc_ee.resize(nbins_acc, 0); - } - - template - bool isBeam(TMCParticle const& p) - { - if ((abs(p.pdgCode()) == 2212 || abs(p.pdgCode()) > 1e+9) && p.pt() < 1e-4 && p.pz() > 440.f && p.globalIndex() < 2 && !p.has_mothers()) { - return true; - } else { - return false; - } - } - - template - bool isQuarkOrGluon(TMCParticle const& p) - { - if ((1 <= abs(p.pdgCode()) && abs(p.pdgCode()) <= 6) || p.pdgCode() == 21) { - return true; - } else { - return false; - } - } - - Preslice perMcCollision = aod::mcparticle::mcCollisionId; - Preslice perCollision_pcm = aod::v0photonkf::collisionId; - Preslice perCollision_el = aod::emprimaryelectron::collisionId; - // Preslice perCollision_mu = aod::emprimarymuon::collisionId; - Preslice perCollision_phos = aod::skimmedcluster::collisionId; - Preslice perCollision_emc = aod::skimmedcluster::collisionId; - - std::vector genGamma; // primary, pt, y - std::vector genPi0; // primary, pt, y - std::vector genPi0_acc_gg; // primary, pt, y - std::vector genPi0_acc_eeg; // primary, pt, y - std::vector genEta; // primary, pt, y - std::vector genEta_acc_gg; // primary, pt, y - std::vector genEta_acc_eeg; // primary, pt, y - std::vector genEta_acc_mumug; // primary, pt, y - std::vector genEta_acc_pipig; // primary, pt, y - std::vector genOmega; // primary, pt, y - std::vector genOmega_acc_ee; // primary, pt, y - std::vector genPhi; // primary, pt, y - std::vector genPhi_acc_ee; // primary, pt, y - std::vector genChargedPion; // primary, pt, y - std::vector genChargedKaon; // primary, pt, y - std::vector genK0S; // primary, pt, y - std::vector genLambda; // primary, pt, y - - template - void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const&, aod::McParticles const& mcTracks, TTracks const& o2tracks, TPCMs const& v0photons, TPCMLegs const& /*v0legs*/, TPHOSs const& /*phosclusters*/, TEMCs const& emcclusters, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) - { - // temporary variables used for the indexing of the skimmed MC stack - std::map fNewLabels; - std::map fNewLabelsReversed; - // std::map fMCFlags; - std::map fEventIdx; - std::map fEventLabels; - int fCounters[2] = {0, 0}; //! [0] - particle counter, [1] - event counter - auto hBinFinder = registry.get(HIST("Generated/h2PtY_Gamma")); - - for (auto& collision : collisions) { - registry.fill(HIST("hEventCounter"), 1); - - // TODO: investigate the collisions without corresponding mcCollision - if (!collision.has_mcCollision()) { - continue; - } - registry.fill(HIST("hEventCounter"), 2); - - std::fill(genGamma.begin(), genGamma.end(), 0); - std::fill(genPi0.begin(), genPi0.end(), 0); - std::fill(genEta.begin(), genEta.end(), 0); - std::fill(genOmega.begin(), genOmega.end(), 0); - std::fill(genPhi.begin(), genPhi.end(), 0); - std::fill(genChargedPion.begin(), genChargedPion.end(), 0); - std::fill(genChargedKaon.begin(), genChargedKaon.end(), 0); - std::fill(genK0S.begin(), genK0S.end(), 0); - std::fill(genLambda.begin(), genLambda.end(), 0); - - std::fill(genPi0_acc_gg.begin(), genPi0_acc_gg.end(), 0); - std::fill(genPi0_acc_eeg.begin(), genPi0_acc_eeg.end(), 0); - std::fill(genEta_acc_gg.begin(), genEta_acc_gg.end(), 0); - std::fill(genEta_acc_eeg.begin(), genEta_acc_eeg.end(), 0); - std::fill(genEta_acc_mumug.begin(), genEta_acc_mumug.end(), 0); - std::fill(genEta_acc_pipig.begin(), genEta_acc_pipig.end(), 0); - std::fill(genOmega_acc_ee.begin(), genOmega_acc_ee.end(), 0); - std::fill(genPhi_acc_ee.begin(), genPhi_acc_ee.end(), 0); - - auto mcCollision = collision.mcCollision(); - // store mc particles - auto groupedMcTracks = mcTracks.sliceBy(perMcCollision, mcCollision.globalIndex()); - - for (auto& mctrack : groupedMcTracks) { // store necessary information for denominator of efficiency - if ((mctrack.isPhysicalPrimary() || mctrack.producedByGenerator()) && abs(mctrack.y()) < 0.9f && mctrack.pt() < 20.f) { - auto binNumber = hBinFinder->FindBin(mctrack.pt(), mctrack.y()); // caution: pack - switch (abs(mctrack.pdgCode())) { - case 22: - registry.fill(HIST("Generated/h2PtY_Gamma"), mctrack.pt(), mctrack.y()); - genGamma[binNumber]++; - break; - case 111: - registry.fill(HIST("Generated/h2PtY_Pi0"), mctrack.pt(), mctrack.y()); - genPi0[binNumber]++; - if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{22, 22}, -0.9, +0.9, 0, 2 * M_PI)) { - genPi0_acc_gg[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - registry.fill(HIST("Generated/hs_Pi0_acc_gg"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), 0.0); - } else if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{-11, 11, 22}, -0.9, +0.9, 0, 2 * M_PI)) { - genPi0_acc_eeg[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - auto dau3 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 2); - registry.fill(HIST("Generated/hs_Pi0_acc_eeg"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), abs(dau3.eta())); - } - break; - case 221: - registry.fill(HIST("Generated/h2PtY_Eta"), mctrack.pt(), mctrack.y()); - genEta[binNumber]++; - if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{22, 22}, -0.9, +0.9, 0, 2 * M_PI)) { - genEta_acc_gg[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - registry.fill(HIST("Generated/hs_Eta_acc_gg"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), 0.0); - } else if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{-11, 11, 22}, -0.9, +0.9, 0, 2 * M_PI)) { - genEta_acc_eeg[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - auto dau3 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 2); - registry.fill(HIST("Generated/hs_Eta_acc_eeg"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), abs(dau3.eta())); - } else if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{-13, 13, 22}, -0.9, +0.9, 0, 2 * M_PI)) { - genEta_acc_mumug[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - auto dau3 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 2); - registry.fill(HIST("Generated/hs_Eta_acc_mumug"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), abs(dau3.eta())); - } else if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{-211, 211, 22}, -0.9, +0.9, 0, 2 * M_PI)) { - genEta_acc_pipig[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - auto dau3 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 2); - registry.fill(HIST("Generated/hs_Eta_acc_pipig"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), abs(dau3.eta())); - } - break; - case 223: - registry.fill(HIST("Generated/h2PtY_Omega"), mctrack.pt(), mctrack.y()); - genOmega[binNumber]++; - if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{-11, 11}, -0.9, +0.9, 0, 2 * M_PI)) { - genOmega_acc_ee[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - registry.fill(HIST("Generated/hs_Omega_acc_ee"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), 0.f); - } - break; - case 333: - registry.fill(HIST("Generated/h2PtY_Phi"), mctrack.pt(), mctrack.y()); - genPhi[binNumber]++; - if (o2::aod::pwgem::mcutil::IsInAcceptanceNonDerived(mctrack, mcTracks, std::vector{-11, 11}, -0.9, +0.9, 0, 2 * M_PI)) { - genPhi_acc_ee[binNumber]++; - auto dau1 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 0); - auto dau2 = mcTracks.iteratorAt(mctrack.daughtersIds()[0] + 1); - registry.fill(HIST("Generated/hs_Phi_acc_ee"), mctrack.pt(), abs(mctrack.y()), abs(dau1.eta()), abs(dau2.eta()), 0.f); - } - break; - case 211: - registry.fill(HIST("Generated/h2PtY_ChargedPion"), mctrack.pt(), mctrack.y()); - genChargedPion[binNumber]++; - break; - case 321: - registry.fill(HIST("Generated/h2PtY_ChargedKaon"), mctrack.pt(), mctrack.y()); - genChargedKaon[binNumber]++; - break; - case 310: - registry.fill(HIST("Generated/h2PtY_K0S"), mctrack.pt(), mctrack.y()); - genK0S[binNumber]++; - break; - case 3122: - registry.fill(HIST("Generated/h2PtY_Lambda"), mctrack.pt(), mctrack.y()); - genLambda[binNumber]++; - break; - default: - break; - } - } - } // end of mc track loop - - // make an entry for this MC event only if it was not already added to the table - if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { - mcevents(mcCollision.globalIndex(), mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.t(), mcCollision.impactParameter()); - fEventLabels[mcCollision.globalIndex()] = fCounters[1]; - fCounters[1]++; - binned_gen_pt(genGamma, genPi0, genEta, genOmega, genPhi, genChargedPion, genChargedKaon, genK0S, genLambda); - // binned_gen_pt_acc( - // genPi0_acc_gg, genPi0_acc_eeg, - // genEta_acc_gg, genEta_acc_eeg, genEta_acc_mumug, genEta_acc_pipig, - // genOmega_acc_ee, - // genPhi_acc_ee); - } - - mceventlabels(fEventLabels.find(mcCollision.globalIndex())->second, collision.mcMask()); - - for (auto& mctrack : groupedMcTracks) { // store necessary information for denominator of efficiency - if (mctrack.pt() < 1e-3 || abs(mctrack.vz()) > 250 || sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2)) > max_rxy_gen) { - continue; - } - int pdg = mctrack.pdgCode(); - if (abs(pdg) > 1e+9) { - continue; - } - - // Note that pi0 from weak decay gives producedByGenerator() = false - if ( - abs(pdg) != 11 // electron - && (abs(pdg) != 13) // muon - ) { - continue; - } - // LOGF(info,"index = %d , mc track pdg = %d , producedByGenerator = %d , isPhysicalPrimary = %d", mctrack.index(), mctrack.pdgCode(), mctrack.producedByGenerator(), mctrack.isPhysicalPrimary()); - - if (abs(pdg) == 11 && !(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { // only for quick check, only secondary electrons should appear. - registry.fill(HIST("PCM/hXY"), mctrack.vx(), mctrack.vy()); - registry.fill(HIST("PCM/hRZ"), mctrack.vz(), sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2))); - } - - if (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator()) { // primary leptons - if (abs(mctrack.y()) < max_Y_gen_primary) { // primary leptons - if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { - fNewLabels[mctrack.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // fMCFlags[mctrack.globalIndex()] = mcflags; - fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - - int motherid = -999; // first mother index - if (mctrack.has_mothers()) { - motherid = mctrack.mothersIds()[0]; // first mother index - } - while (motherid > -1) { - if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcTracks.iteratorAt(motherid); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // fMCFlags[mp.globalIndex()] = mcflags; - fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index - } else { - motherid = -999; - } - } else { - motherid = -999; - } - } // end of mother chain loop - } - } else if (abs(pdg) == 11 && mctrack.has_mothers()) { // secondary electrons. i.e. ele/pos from photon conversions. - int motherid = mctrack.mothersIds()[0]; // first mother index - auto mp = mcTracks.iteratorAt(motherid); - - if (sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2)) < abs(mctrack.vz()) * std::tan(2 * std::atan(std::exp(-max_Y_gen_secondary))) - margin_z_gen) { - continue; - } - - if (mp.pdgCode() == 22 && (mp.isPhysicalPrimary() || mp.producedByGenerator()) && abs(mp.y()) < max_Y_gen_secondary) { - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { // store electron information. !!Not photon!! - fNewLabels[mctrack.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // fMCFlags[mctrack.globalIndex()] = mcflags; - fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { // store conversion photon - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // fMCFlags[mp.globalIndex()] = mcflags; - fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - } - } - } // end of mc track loop - - if constexpr (static_cast(system & kPCM)) { - auto groupedV0s = v0photons.sliceBy(perCollision_pcm, collision.globalIndex()); - for (auto& v0 : groupedV0s) { - auto ele = v0.template negTrack_as(); - auto pos = v0.template posTrack_as(); - - auto o2track_ele = o2tracks.iteratorAt(pos.trackId()); - auto o2track_pos = o2tracks.iteratorAt(ele.trackId()); - - if (!o2track_ele.has_mcParticle() || !o2track_pos.has_mcParticle()) { - continue; // If no MC particle is found, skip the v0 - } - - for (auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! - // auto o2track = leg.template track_as(); - auto o2track = o2tracks.iteratorAt(leg.trackId()); - auto mctrack = o2track.template mcParticle_as(); - // LOGF(info, "mctrack.globalIndex() = %d, mctrack.index() = %d", mctrack.globalIndex(), mctrack.index()); // these are exactly the same. - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { - fNewLabels[mctrack.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // fMCFlags[mctrack.globalIndex()] = mcflags; - fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - v0legmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); - - // Next, store mother-chain of this reconstructed track. - int motherid = -999; // first mother index - if (mctrack.has_mothers()) { - motherid = mctrack.mothersIds()[0]; // first mother index - } - while (motherid > -1) { - if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcTracks.iteratorAt(motherid); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // fMCFlags[mp.globalIndex()] = mcflags; - fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index - } else { - motherid = -999; - } - } else { - motherid = -999; - } - } // end of mother chain loop - } // end of leg loop - } // end of v0 loop - } - if constexpr (static_cast(system & kDalitzEE)) { - // for dalitz ee - auto emprimaryelectrons_coll = emprimaryelectrons.sliceBy(perCollision_el, collision.globalIndex()); - for (auto& emprimaryelectron : emprimaryelectrons_coll) { - auto o2track = o2tracks.iteratorAt(emprimaryelectron.trackId()); - if (!o2track.has_mcParticle()) { - continue; // If no MC particle is found, skip the dilepton - } - auto mctrack = o2track.template mcParticle_as(); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { - fNewLabels[mctrack.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // fMCFlags[mctrack.globalIndex()] = mcflags; - fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - emprimaryelectronmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); - - // Next, store mother-chain of this reconstructed track. - int motherid = -999; // first mother index - if (mctrack.has_mothers()) { - motherid = mctrack.mothersIds()[0]; // first mother index - } - while (motherid > -1) { - if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcTracks.iteratorAt(motherid); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // fMCFlags[mp.globalIndex()] = mcflags; - fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index - } else { - motherid = -999; - } - } else { - motherid = -999; - } - } // end of mother chain loop - - } // end of em primary track loop - } - // if constexpr (static_cast(system & kDalitzMuMu)) { - // // for dalitz mumu - // auto emprimarymuons_coll = emprimarymuons.sliceBy(perCollision_mu, collision.globalIndex()); - // for (auto& emprimarymuon : emprimarymuons_coll) { - // auto o2track = o2tracks.iteratorAt(emprimarymuon.trackId()); - // if (!o2track.has_mcParticle()) { - // continue; // If no MC particle is found, skip the dilepton - // } - // auto mctrack = o2track.template mcParticle_as(); - - // // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - // if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { - // fNewLabels[mctrack.globalIndex()] = fCounters[0]; - // fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // // fMCFlags[mctrack.globalIndex()] = mcflags; - // fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - // fCounters[0]++; - // } - // emprimarymuonmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); - - // // Next, store mother-chain of this reconstructed track. - // int motherid = -999; // first mother index - // if (mctrack.has_mothers()) { - // motherid = mctrack.mothersIds()[0]; // first mother index - // } - // while (motherid > -1) { - // if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - // auto mp = mcTracks.iteratorAt(motherid); - - // // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - // if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - // fNewLabels[mp.globalIndex()] = fCounters[0]; - // fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // // fMCFlags[mp.globalIndex()] = mcflags; - // fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - // fCounters[0]++; - // } - - // if (mp.has_mothers()) { - // motherid = mp.mothersIds()[0]; // first mother index - // } else { - // motherid = -999; - // } - // } else { - // motherid = -999; - // } - // } // end of mother chain loop - - // } // end of em primary track loop - // } - if constexpr (static_cast(system & kEMC)) { - // for emc photons - auto ememcclusters_coll = emcclusters.sliceBy(perCollision_emc, collision.globalIndex()); - for (auto& ememccluster : ememcclusters_coll) { - auto mcphoton = mcTracks.iteratorAt(ememccluster.emmcparticleIds()[0]); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mcphoton.globalIndex()) != fNewLabels.end())) { - fNewLabels[mcphoton.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mcphoton.globalIndex(); - fEventIdx[mcphoton.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - ememcclustermclabels(fNewLabels.find(mcphoton.index())->second); - - // Next, store mother-chain of this reconstructed track. - int motherid = -999; // first mother index - if (mcphoton.has_mothers()) { - motherid = mcphoton.mothersIds()[0]; // first mother index - } - while (motherid > -1) { - if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcTracks.iteratorAt(motherid); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; - fCounters[0]++; - } - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index - } else { - motherid = -999; - } - } else { - motherid = -999; - } - } // end of mother chain loop - - } // end of em emc cluster loop - } - } // end of collision loop - - // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack - for (const auto& [newLabel, oldLabel] : fNewLabelsReversed) { - auto mctrack = mcTracks.iteratorAt(oldLabel); - // uint16_t mcflags = fMCFlags.find(oldLabel)->second; - - std::vector mothers; - if (mctrack.has_mothers()) { - for (auto& m : mctrack.mothersIds()) { - if (m < mcTracks.size()) { // protect against bad mother indices - if (fNewLabels.find(m) != fNewLabels.end()) { - mothers.push_back(fNewLabels.find(m)->second); - } - } else { - std::cout << "Mother label (" << m << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; - std::cout << " Check the MC generator" << std::endl; - } - } - } - - // Note that not all daughters from the original table are preserved in the skimmed MC stack - std::vector daughters; - if (mctrack.has_daughters()) { - // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); - for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { - // TODO: remove this check as soon as issues with MC production are fixed - if (d < mcTracks.size()) { // protect against bad daughter indices - // auto dau_tmp = mcTracks.iteratorAt(d); - // LOGF(info, "daughter pdg = %d", dau_tmp.pdgCode()); - if (fNewLabels.find(d) != fNewLabels.end()) { - daughters.push_back(fNewLabels.find(d)->second); - } - } else { - std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; - std::cout << " Check the MC generator" << std::endl; - } - } - } - - emmcparticles(fEventIdx.find(oldLabel)->second, mctrack.pdgCode(), mctrack.flags(), - mothers, daughters, - mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), - mctrack.vx(), mctrack.vy(), mctrack.vz(), mctrack.vt()); - } // end loop over labels - - fNewLabels.clear(); - fNewLabelsReversed.clear(); - // fMCFlags.clear(); - fEventIdx.clear(); - fEventLabels.clear(); - fCounters[0] = 0; - fCounters[1] = 0; - } // end of skimmingMC - - void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) - { - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, nullptr, nullptr, nullptr); - } - void processMC_PCM_DalitzEE(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - const uint8_t sysflag = kPCM | kDalitzEE; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, nullptr, emprimaryelectrons, nullptr); - } - void processMC_DalitzEE(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - const uint8_t sysflag = kDalitzEE; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, nullptr, nullptr, emprimaryelectrons, nullptr); - } - - // void processMC_PCM_DalitzEE_DalitzMuMu(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) - // { - // const uint8_t sysflag = kPCM | kDalitzEE | kDalitzMuMu; - // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, nullptr, emprimaryelectrons, emprimarymuons); - // } - - void processMC_PHOS(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::PHOSClusters const& phosclusters) - { - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, phosclusters, nullptr, nullptr, nullptr); - } - void processMC_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, MyEMCClusters const& emcclusters) - { - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, nullptr, emcclusters, nullptr, nullptr); - } - void processMC_PCM_PHOS(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters) - { - const uint8_t sysflag = kPCM | kPHOS; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, nullptr, nullptr, nullptr); - } - void processMC_PCM_PHOS_DalitzEE(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - const uint8_t sysflag = kPCM | kPHOS | kDalitzEE; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, nullptr, emprimaryelectrons, nullptr); - } - void processMC_PCM_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, MyEMCClusters const& emcclusters) - { - const uint8_t sysflag = kPCM | kEMC; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, emcclusters, nullptr, nullptr); - } - void processMC_PCM_EMC_DalitzEE(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, MyEMCClusters const& emcclusters, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - const uint8_t sysflag = kPCM | kEMC | kDalitzEE; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, emcclusters, emprimaryelectrons, nullptr); - } - void processMC_PHOS_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::PHOSClusters const& phosclusters, MyEMCClusters const& emcclusters) - { - const uint8_t sysflag = kPHOS | kEMC; - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, phosclusters, emcclusters, nullptr, nullptr); - } - void processMC_PCM_PHOS_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, MyEMCClusters const& emcclusters) - { - const uint8_t sysflag = kPCM | kPHOS | kEMC; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, emcclusters, nullptr, nullptr); - } - void processMC_PCM_PHOS_EMC_DalitzEE(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, MyEMCClusters const& emcclusters, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - const uint8_t sysflag = kPCM | kPHOS | kEMC | kDalitzEE; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, emcclusters, emprimaryelectrons, nullptr); - } - - void processDummy(MyCollisionsMC const&) {} - - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM, "create em mc event table for PCM", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_DalitzEE, "create em mc event table for PCM, DalitzEE", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_DalitzEE, "create em mc event table for DalitzEE", false); - // PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_DalitzEE_DalitzMuMu, "create em mc event table for PCM, DalitzEE, DalitzMuMu", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PHOS, "create em mc event table for PHOS", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_EMC, "create em mc event table for EMCal", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_PHOS, "create em mc event table for PCM, PHOS", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_PHOS_DalitzEE, "create em mc event table for PCM, PHOS, DalitzEE", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_EMC, "create em mc event table for PCM, EMCal", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_EMC_DalitzEE, "create em mc event table for PCM, EMCal, DalitzEE", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PHOS_EMC, "create em mc event table for PHOS, EMCal", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_PHOS_EMC, "create em mc event table for PCM, PHOS, EMCal", false); - PROCESS_SWITCH(AssociateMCInfo, processMC_PCM_PHOS_EMC_DalitzEE, "create em mc event table for PCM, PHOS, EMCal, DalitzEE", false); - PROCESS_SWITCH(AssociateMCInfo, processDummy, "processDummy", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"associate-mc-info"})}; -} diff --git a/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx new file mode 100644 index 00000000000..257450cce99 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx @@ -0,0 +1,521 @@ +// Copyright 2019-2020 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 produces reduced events for photon analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; + +using MyCollisionsMC = soa::Join; +using TracksMC = soa::Join; +using FwdTracksMC = soa::Join; +using MyEMCClusters = soa::Join; + +struct AssociateMCInfoPhoton { + enum SubSystem { + kPCM = 0x1, + kPHOS = 0x2, + kEMC = 0x4, + kElectron = 0x8, + }; + + Produces mcevents; + Produces mceventlabels; + Produces emmcparticles; + Produces v0legmclabels; + Produces emprimaryelectronmclabels; + Produces ememcclustermclabels; + + Produces binned_gen_pt; + + Configurable applyEveSel_at_skimming{"applyEveSel_at_skimming", false, "flag to apply minimal event selection at the skimming level"}; + Configurable max_eta_gen_secondary{"max_eta_gen_secondary", 0.9, "max eta to store generated information"}; + Configurable margin_z_gen{"margin_z_gen", 15.f, "margin for Z of true photon conversion point to store generated information"}; + Configurable max_rxy_gen{"max_rxy_gen", 100, "max rxy to store generated information"}; + + HistogramRegistry registry{"EMMCEvent"}; + + void init(o2::framework::InitContext&) + { + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{6, 0.5f, 6.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + hEventCounter->GetXaxis()->SetBinLabel(2, "has mc collision"); + + // !!Don't change pt,eta,y binning. These binnings have to be consistent with binned data at analysis.!! + std::vector ptbins; + for (int i = 0; i < 2; i++) { + ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c + } + for (int i = 2; i < 51; i++) { + ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c + } + for (int i = 51; i < 61; i++) { + ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c + } + for (int i = 61; i < 72; i++) { + ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c + } + const AxisSpec axis_pt{ptbins, "p_{T} (GeV/c)"}; + const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y|"}; + + static constexpr std::string_view parnames[9] = { + "Gamma", "Pi0", "Eta", "Omega", "Phi", + "ChargedPion", "ChargedKaon", "K0S", "Lambda"}; + + for (int i = 0; i < 9; i++) { + registry.add(Form("Generated/h2PtY_%s", parnames[i].data()), Form("Generated %s", parnames[i].data()), kTH2F, {axis_pt, axis_rapidity}, true); + } + + // reserve space for generated vectors if that process enabled + auto hBinFinder = registry.get(HIST("Generated/h2PtY_Pi0")); + LOGF(info, "Binned generated processing enabled. Initialising with %i elements...", hBinFinder->GetNcells()); + genGamma.resize(hBinFinder->GetNcells(), 0); + genPi0.resize(hBinFinder->GetNcells(), 0); + genEta.resize(hBinFinder->GetNcells(), 0); + } + + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perCollision_pcm = aod::v0photonkf::collisionId; + Preslice perCollision_el = aod::emprimaryelectron::collisionId; + Preslice perCollision_phos = aod::skimmedcluster::collisionId; + Preslice perCollision_emc = aod::skimmedcluster::collisionId; + + std::vector genGamma; // primary, pt, y + std::vector genPi0; // primary, pt, y + std::vector genEta; // primary, pt, y + + template + void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const&, aod::McParticles const& mcTracks, TTracks const& o2tracks, TFwdTracks const&, TPCMs const& v0photons, TPCMLegs const& /*v0legs*/, TPHOSs const& /*phosclusters*/, TEMCs const& emcclusters, TEMPrimaryElectrons const& emprimaryelectrons) + { + // temporary variables used for the indexing of the skimmed MC stack + std::map fNewLabels; + std::map fNewLabelsReversed; + // std::map fMCFlags; + std::map fEventIdx; + std::map fEventLabels; + int fCounters[2] = {0, 0}; //! [0] - particle counter, [1] - event counter + auto hBinFinder = registry.get(HIST("Generated/h2PtY_Gamma")); + + for (auto& collision : collisions) { + registry.fill(HIST("hEventCounter"), 1); + + // TODO: investigate the collisions without corresponding mcCollision + if (!collision.has_mcCollision()) { + continue; + } + + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + + registry.fill(HIST("hEventCounter"), 2); + + std::fill(genGamma.begin(), genGamma.end(), 0); + std::fill(genPi0.begin(), genPi0.end(), 0); + std::fill(genEta.begin(), genEta.end(), 0); + + auto mcCollision = collision.mcCollision(); + // store mc particles + auto groupedMcTracks = mcTracks.sliceBy(perMcCollision, mcCollision.globalIndex()); + + for (auto& mctrack : groupedMcTracks) { // store necessary information for denominator of efficiency + if ((mctrack.isPhysicalPrimary() || mctrack.producedByGenerator()) && abs(mctrack.y()) < 0.9f && mctrack.pt() < 20.f) { + auto binNumber = hBinFinder->FindBin(mctrack.pt(), abs(mctrack.y())); // caution: pack + switch (abs(mctrack.pdgCode())) { + case 22: + registry.fill(HIST("Generated/h2PtY_Gamma"), mctrack.pt(), abs(mctrack.y())); + genGamma[binNumber]++; + break; + case 111: + registry.fill(HIST("Generated/h2PtY_Pi0"), mctrack.pt(), abs(mctrack.y())); + genPi0[binNumber]++; + break; + case 221: + registry.fill(HIST("Generated/h2PtY_Eta"), mctrack.pt(), abs(mctrack.y())); + genEta[binNumber]++; + break; + default: + break; + } + } + } // end of mc track loop + + // make an entry for this MC event only if it was not already added to the table + if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { + mcevents(mcCollision.globalIndex(), mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + fEventLabels[mcCollision.globalIndex()] = fCounters[1]; + fCounters[1]++; + binned_gen_pt(genGamma, genPi0, genEta); + } + + mceventlabels(fEventLabels.find(mcCollision.globalIndex())->second, collision.mcMask()); + + for (auto& mctrack : groupedMcTracks) { // store necessary information for denominator of efficiency + if (mctrack.pt() < 1e-3 || abs(mctrack.vz()) > 250 || sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2)) > max_rxy_gen) { + continue; + } + int pdg = mctrack.pdgCode(); + if (abs(pdg) > 1e+9) { + continue; + } + + // Note that pi0 from weak decay gives producedByGenerator() = false + // LOGF(info,"index = %d , mc track pdg = %d , producedByGenerator = %d , isPhysicalPrimary = %d", mctrack.index(), mctrack.pdgCode(), mctrack.producedByGenerator(), mctrack.isPhysicalPrimary()); + + if (abs(pdg) == 11 && mctrack.has_mothers() && !(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { // secondary electrons. i.e. ele/pos from photon conversions. + int motherid = mctrack.mothersIds()[0]; // first mother index + auto mp = mcTracks.iteratorAt(motherid); + + if (sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2)) < abs(mctrack.vz()) * std::tan(2 * std::atan(std::exp(-max_eta_gen_secondary))) - margin_z_gen) { + continue; + } + + if (mp.pdgCode() == 22 && (mp.isPhysicalPrimary() || mp.producedByGenerator()) && abs(mp.eta()) < max_eta_gen_secondary) { + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { // store electron information. !!Not photon!! + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { // store conversion photon + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + } + } + } // end of mc track loop + + } // end of rec. collision loop + + if constexpr (static_cast(system & kPCM)) { + for (auto& v0 : v0photons) { + auto collision_from_v0 = collisions.iteratorAt(v0.collisionId()); + if (!collision_from_v0.has_mcCollision()) { + continue; + } + auto mcCollision_from_v0 = collision_from_v0.mcCollision(); + + auto ele = v0.template negTrack_as(); + auto pos = v0.template posTrack_as(); + + auto o2track_ele = o2tracks.iteratorAt(pos.trackId()); + auto o2track_pos = o2tracks.iteratorAt(ele.trackId()); + + if (!o2track_ele.has_mcParticle() || !o2track_pos.has_mcParticle()) { + continue; // If no MC particle is found, skip the v0 + } + + for (auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! + auto o2track = o2tracks.iteratorAt(leg.trackId()); + auto mctrack = o2track.template mcParticle_as(); + // LOGF(info, "mctrack.globalIndex() = %d, mctrack.index() = %d", mctrack.globalIndex(), mctrack.index()); // these are exactly the same. + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision_from_v0.globalIndex())->second; + fCounters[0]++; + } + v0legmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision_from_v0.globalIndex())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + } // end of leg loop + } // end of v0 loop + } + + if constexpr (static_cast(system & kElectron)) { + // auto emprimaryelectrons_coll = emprimaryelectrons.sliceBy(perCollision_el, collision.globalIndex()); + for (auto& emprimaryelectron : emprimaryelectrons) { + auto collision_from_el = collisions.iteratorAt(emprimaryelectron.collisionId()); + if (!collision_from_el.has_mcCollision()) { + continue; + } + auto mcCollision_from_el = collision_from_el.mcCollision(); + + auto o2track = o2tracks.iteratorAt(emprimaryelectron.trackId()); + if (!o2track.has_mcParticle()) { + continue; // If no MC particle is found, skip the dilepton + } + auto mctrack = o2track.template mcParticle_as(); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision_from_el.globalIndex())->second; + fCounters[0]++; + } + emprimaryelectronmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mctrack.has_mothers()) { + motherid = mctrack.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // fMCFlags[mp.globalIndex()] = mcflags; + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision_from_el.globalIndex())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + + } // end of em primary electron loop + } + + if constexpr (static_cast(system & kEMC)) { // for emc photons + // auto ememcclusters_coll = emcclusters.sliceBy(perCollision_emc, collision.globalIndex()); + for (auto& emccluster : emcclusters) { + auto collision_from_emc = collisions.iteratorAt(emccluster.collisionId()); + if (!collision_from_emc.has_mcCollision()) { + continue; + } + auto mcCollision_from_emc = collision_from_emc.mcCollision(); + + auto mcphoton = mcTracks.iteratorAt(emccluster.emmcparticleIds()[0]); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mcphoton.globalIndex()) != fNewLabels.end())) { + fNewLabels[mcphoton.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mcphoton.globalIndex(); + fEventIdx[mcphoton.globalIndex()] = fEventLabels.find(mcCollision_from_emc.globalIndex())->second; + fCounters[0]++; + } + ememcclustermclabels(fNewLabels.find(mcphoton.index())->second); + + // Next, store mother-chain of this reconstructed track. + int motherid = -999; // first mother index + if (mcphoton.has_mothers()) { + motherid = mcphoton.mothersIds()[0]; // first mother index + } + while (motherid > -1) { + if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + auto mp = mcTracks.iteratorAt(motherid); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + fNewLabels[mp.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision_from_emc.globalIndex())->second; + fCounters[0]++; + } + + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } + } else { + motherid = -999; + } + } // end of mother chain loop + + } // end of em emc cluster loop + } + + // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack + for (const auto& [newLabel, oldLabel] : fNewLabelsReversed) { + auto mctrack = mcTracks.iteratorAt(oldLabel); + // uint16_t mcflags = fMCFlags.find(oldLabel)->second; + + std::vector mothers; + if (mctrack.has_mothers()) { + for (auto& m : mctrack.mothersIds()) { + if (m < mcTracks.size()) { // protect against bad mother indices + if (fNewLabels.find(m) != fNewLabels.end()) { + mothers.push_back(fNewLabels.find(m)->second); + } + } else { + std::cout << "Mother label (" << m << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + } + + // Note that not all daughters from the original table are preserved in the skimmed MC stack + std::vector daughters; + if (mctrack.has_daughters()) { + // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); + for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { + // TODO: remove this check as soon as issues with MC production are fixed + if (d < mcTracks.size()) { // protect against bad daughter indices + // auto dau_tmp = mcTracks.iteratorAt(d); + // LOGF(info, "daughter pdg = %d", dau_tmp.pdgCode()); + if (fNewLabels.find(d) != fNewLabels.end()) { + daughters.push_back(fNewLabels.find(d)->second); + } + } else { + std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + } + } + } + + emmcparticles(fEventIdx.find(oldLabel)->second, mctrack.pdgCode(), mctrack.flags(), + mothers, daughters, + mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), + mctrack.vx(), mctrack.vy(), mctrack.vz()); + } // end loop over labels + + fNewLabels.clear(); + fNewLabelsReversed.clear(); + // fMCFlags.clear(); + fEventIdx.clear(); + fEventLabels.clear(); + fCounters[0] = 0; + fCounters[1] = 0; + } // end of skimmingMC + + void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) + { + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, nullptr, nullptr, nullptr); + } + void processMC_PCM_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectronsFromDalitz const& emprimaryelectrons) + { + const uint8_t sysflag = kPCM | kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, nullptr, nullptr, emprimaryelectrons); + } + void processMC_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::EMPrimaryElectronsFromDalitz const& emprimaryelectrons) + { + const uint8_t sysflag = kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, nullptr, nullptr, nullptr, emprimaryelectrons); + } + void processMC_PHOS(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::PHOSClusters const& phosclusters) + { + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, nullptr, phosclusters, nullptr, nullptr); + } + void processMC_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, MyEMCClusters const& emcclusters) + { + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, nullptr, nullptr, emcclusters, nullptr); + } + void processMC_PCM_PHOS(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters) + { + const uint8_t sysflag = kPCM | kPHOS; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, phosclusters, nullptr, nullptr); + } + void processMC_PCM_PHOS_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, aod::EMPrimaryElectronsFromDalitz const& emprimaryelectrons) + { + const uint8_t sysflag = kPCM | kPHOS | kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, phosclusters, nullptr, emprimaryelectrons); + } + void processMC_PCM_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, MyEMCClusters const& emcclusters) + { + const uint8_t sysflag = kPCM | kEMC; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, nullptr, emcclusters, nullptr); + } + void processMC_PCM_EMC_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, MyEMCClusters const& emcclusters, aod::EMPrimaryElectronsFromDalitz const& emprimaryelectrons) + { + const uint8_t sysflag = kPCM | kEMC | kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, nullptr, emcclusters, emprimaryelectrons); + } + void processMC_PHOS_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::PHOSClusters const& phosclusters, MyEMCClusters const& emcclusters) + { + const uint8_t sysflag = kPHOS | kEMC; + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, nullptr, phosclusters, emcclusters, nullptr); + } + void processMC_PCM_PHOS_EMC(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, MyEMCClusters const& emcclusters) + { + const uint8_t sysflag = kPCM | kPHOS | kEMC; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, phosclusters, emcclusters, nullptr); + } + void processMC_PCM_PHOS_EMC_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, MyEMCClusters const& emcclusters, aod::EMPrimaryElectronsFromDalitz const& emprimaryelectrons) + { + const uint8_t sysflag = kPCM | kPHOS | kEMC | kElectron; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, v0photons, v0legs, phosclusters, emcclusters, emprimaryelectrons); + } + + void processDummy(MyCollisionsMC const&) {} + + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM, "create em mc event table for PCM", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_Electron, "create em mc event table for PCM, Electron", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_Electron, "create em mc event table for Electron", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PHOS, "create em mc event table for PHOS", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_EMC, "create em mc event table for EMCal", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_PHOS, "create em mc event table for PCM, PHOS", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_PHOS_Electron, "create em mc event table for PCM, PHOS, Electron", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_EMC, "create em mc event table for PCM, EMCal", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_EMC_Electron, "create em mc event table for PCM, EMCal, Electron", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PHOS_EMC, "create em mc event table for PHOS, EMCal", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_PHOS_EMC, "create em mc event table for PCM, PHOS, EMCal", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processMC_PCM_PHOS_EMC_Electron, "create em mc event table for PCM, PHOS, EMCal, Electron", false); + PROCESS_SWITCH(AssociateMCInfoPhoton, processDummy, "processDummy", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"associate-mc-info-photon"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/converters/ambElectronIdconverter.cxx b/PWGEM/PhotonMeson/TableProducer/converters/ambElectronIdconverter.cxx deleted file mode 100644 index 91c7702e252..00000000000 --- a/PWGEM/PhotonMeson/TableProducer/converters/ambElectronIdconverter.cxx +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2019-2020 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. - -/// \brief write relevant information for dalitz ee analysis to an AO2D.root file. This file is then the only necessary input to perform pcm analysis. -/// \author daiki.sekihata@cern.ch - -#include "vector" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - -using namespace o2; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; - -struct AmbiguousElectronIdConverter { - Produces em_amb_ele_ids; - - SliceCache cache; - PresliceUnsorted perTrack = o2::aod::emprimaryelectron::trackId; - std::vector ambele_self_Ids; - - void process(aod::EMPrimaryElectrons const& electrons) - { - for (auto& electron : electrons) { - auto electrons_with_same_trackId = electrons.sliceBy(perTrack, electron.trackId()); - ambele_self_Ids.reserve(electrons_with_same_trackId.size()); - for (auto& amp_ele : electrons_with_same_trackId) { - if (amp_ele.globalIndex() == electron.globalIndex()) { // don't store myself. - continue; - } - ambele_self_Ids.emplace_back(amp_ele.globalIndex()); - } - em_amb_ele_ids(ambele_self_Ids); - ambele_self_Ids.clear(); - ambele_self_Ids.shrink_to_fit(); - } - } -}; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"ambiguous-electronid-converter"})}; -} diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEvent.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx similarity index 65% rename from PWGEM/PhotonMeson/TableProducer/createEMEvent.cxx rename to PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index 87ecce12f7b..9e331503783 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEvent.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -33,14 +33,15 @@ using namespace o2::framework::expressions; using namespace o2::soa; using MyBCs = soa::Join; +using MyQvectors = soa::Join; using MyCollisions = soa::Join; using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. -using MyCollisions_Cent_Qvec = soa::Join; +using MyCollisions_Cent_Qvec = soa::Join; using MyCollisionsMC = soa::Join; using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. -using MyCollisionsMC_Cent_Qvec = soa::Join; +using MyCollisionsMC_Cent_Qvec = soa::Join; struct CreateEMEvent { Produces event; @@ -48,11 +49,13 @@ struct CreateEMEvent { Produces event_mult; Produces event_cent; Produces event_qvec; + Produces event_weights; enum class EMEventType : int { kEvent = 0, kEvent_Cent = 1, kEvent_Cent_Qvec = 2, + kEvent_JJ = 3, }; // CCDB options @@ -61,6 +64,7 @@ struct CreateEMEvent { Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; + Configurable applyEveSel_at_skimming{"applyEveSel_at_skimming", false, "flag to apply minimal event selection at the skimming level"}; HistogramRegistry registry{"registry"}; void init(o2::framework::InitContext&) @@ -116,7 +120,6 @@ struct CreateEMEvent { PresliceUnsorted preslice_collisions_per_bc = o2::aod::evsel::foundBCId; std::unordered_map map_ncolls_per_bc; - //! Please don't skip any event! template void skimEvent(TCollisions const& collisions, TBCs const& bcs) { @@ -137,6 +140,10 @@ struct CreateEMEvent { auto bc = collision.template foundBC_as(); initCCDB(bc); + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + // LOGF(info, "collision-loop | bc.globalIndex() = %d, ncolls_per_bc = %d", bc.globalIndex(), map_ncolls_per_bc[bc.globalIndex()]); registry.fill(HIST("hEventCounter"), 1); @@ -145,7 +152,7 @@ struct CreateEMEvent { } // uint64_t tag = collision.selection_raw(); - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.sel8(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), map_ncolls_per_bc[bc.globalIndex()], + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange()); @@ -153,43 +160,62 @@ struct CreateEMEvent { event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + if constexpr (eventype != EMEventType::kEvent_JJ) { + event_weights(1.f); + } + + float q2xft0m = 999.f, q2yft0m = 999.f, q2xft0a = 999.f, q2yft0a = 999.f, q2xft0c = 999.f, q2yft0c = 999.f, q2xbpos = 999.f, q2ybpos = 999.f, q2xbneg = 999.f, q2ybneg = 999.f, q2xbtot = 999.f, q2ybtot = 999.f; + float q3xft0m = 999.f, q3yft0m = 999.f, q3xft0a = 999.f, q3yft0a = 999.f, q3xft0c = 999.f, q3yft0c = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; + if constexpr (eventype == EMEventType::kEvent) { event_cent(105.f, 105.f, 105.f, 105.f); - event_qvec(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f); + event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else if constexpr (eventype == EMEventType::kEvent_Cent) { event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); - event_qvec(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f); + event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else if constexpr (eventype == EMEventType::kEvent_Cent_Qvec) { event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); - event_qvec(collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), - // collision.qvecFV0ARe(), collision.qvecFV0AIm(), - collision.qvecBPosRe(), collision.qvecBPosIm(), collision.qvecBNegRe(), collision.qvecBNegIm(), - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f); // as of 20240416, only 2nd harmonics is supported. + + if (collision.qvecFT0CReVec().size() >= 2) { // harmonics 2,3 + q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; + q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; + q3xft0m = collision.qvecFT0MReVec()[1], q3xft0a = collision.qvecFT0AReVec()[1], q3xft0c = collision.qvecFT0CReVec()[1], q3xbpos = collision.qvecBPosReVec()[1], q3xbneg = collision.qvecBNegReVec()[1], q3xbtot = collision.qvecBTotReVec()[1]; + q3yft0m = collision.qvecFT0MImVec()[1], q3yft0a = collision.qvecFT0AImVec()[1], q3yft0c = collision.qvecFT0CImVec()[1], q3ybpos = collision.qvecBPosImVec()[1], q3ybneg = collision.qvecBNegImVec()[1], q3ybtot = collision.qvecBTotImVec()[1]; + } else if (collision.qvecFT0CReVec().size() >= 1) { // harmonics 2 + q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; + q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; + } + event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else { event_cent(105.f, 105.f, 105.f, 105.f); - event_qvec(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - // 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f); + event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } } // end of collision loop map_ncolls_per_bc.clear(); } // end of skimEvent + void fillEventWeights(MyCollisionsMC const& collisions, aod::McCollisions const&, MyBCs const& bcs) + { + for (auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + auto mcCollision = collision.mcCollision(); + event_weights(mcCollision.weight()); + } + } + void processEvent(MyCollisions const& collisions, MyBCs const& bcs) { skimEvent(collisions, bcs); @@ -202,6 +228,13 @@ struct CreateEMEvent { } PROCESS_SWITCH(CreateEMEvent, processEventMC, "process event info", false); + void processEventJJMC(MyCollisionsMC const& collisions, aod::McCollisions const& mcCollisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + fillEventWeights(collisions, mcCollisions, bcs); + } + PROCESS_SWITCH(CreateEMEvent, processEventJJMC, "process event info", false); + void processEvent_Cent(MyCollisions_Cent const& collisions, MyBCs const& bcs) { skimEvent(collisions, bcs); @@ -236,57 +269,13 @@ struct AssociatePhotonToEMEvent { Produces phoseventid; Produces emceventid; - Produces event_ng_pcm; - Produces event_ng_phos; - Produces event_ng_emc; - Preslice perCollision_pcm = aod::v0photonkf::collisionId; - PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; + PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; PresliceUnsorted perCollision_mu = aod::emprimarymuon::collisionId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; - bool doPCM = false, doElectron = false, doFwdMuon = false, doPHOS = false, doEMC = false; - void init(o2::framework::InitContext& context) - { - if (context.mOptions.get("processPCM")) { - doPCM = true; - } - if (context.mOptions.get("processElectron")) { - doElectron = true; - } - if (context.mOptions.get("processFwdMuon")) { - doFwdMuon = true; - } - if (context.mOptions.get("processPHOS")) { - doPHOS = true; - } - if (context.mOptions.get("processEMC")) { - doEMC = true; - } - } - - template - void zero_padding(TCollisions const& collisions, TEventNg& event_ng) - { - int nc = collisions.size(); - for (int ic = 0; ic < nc; ic++) { - event_ng(0); - } // end of collision loop - } - - template - void fillEventId_Ng(TCollisions const& collisions, TPhotons const& photons, TEventIds& eventIds, TEventNg& event_ng, TPreslice const& perCollision) - { - for (auto& collision : collisions) { - auto photons_coll = photons.sliceBy(perCollision, collision.collisionId()); - int ng = photons_coll.size(); - for (int ig = 0; ig < ng; ig++) { - eventIds(collision.globalIndex()); - } // end of photon loop - event_ng(ng); - } // end of collision loop - } + void init(o2::framework::InitContext&) {} template void fillEventId(TCollisions const& collisions, TPhotons const& photons, TEventIds& eventIds, TPreslice const& perCollision) @@ -297,7 +286,7 @@ struct AssociatePhotonToEMEvent { for (int ig = 0; ig < ng; ig++) { eventIds(collision.globalIndex()); } // end of photon loop - } // end of collision loop + } // end of collision loop } // This struct is for both data and MC. @@ -305,53 +294,36 @@ struct AssociatePhotonToEMEvent { void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) { - fillEventId_Ng(collisions, photons, v0kfeventid, event_ng_pcm, perCollision_pcm); + fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); } - void processElectron(aod::EMEvents const& collisions, aod::EMPrimaryElectrons const& tracks) + void processElectronFromDalitz(aod::EMEvents const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) { fillEventId(collisions, tracks, prmeleventid, perCollision_el); } - void processFwdMuon(aod::EMEvents const& collisions, aod::EMPrimaryMuons const& tracks) - { - fillEventId(collisions, tracks, prmmueventid, perCollision_mu); - } - void processPHOS(aod::EMEvents const& collisions, aod::PHOSClusters const& photons) { - fillEventId_Ng(collisions, photons, phoseventid, event_ng_phos, perCollision_phos); + fillEventId(collisions, photons, phoseventid, perCollision_phos); } void processEMC(aod::EMEvents const& collisions, aod::SkimEMCClusters const& photons) { - fillEventId_Ng(collisions, photons, emceventid, event_ng_emc, perCollision_emc); + fillEventId(collisions, photons, emceventid, perCollision_emc); } - void processZeroPadding(aod::EMEvents const& collisions) - { - if (!doPCM) { - zero_padding(collisions, event_ng_pcm); - } - if (!doPHOS) { - zero_padding(collisions, event_ng_phos); - } - if (!doEMC) { - zero_padding(collisions, event_ng_emc); - } - } + void processDummy(aod::EMEvents const&) {} PROCESS_SWITCH(AssociatePhotonToEMEvent, processPCM, "process pcm-event indexing", false); - PROCESS_SWITCH(AssociatePhotonToEMEvent, processElectron, "process dalitzee-event indexing", false); - PROCESS_SWITCH(AssociatePhotonToEMEvent, processFwdMuon, "process forward muon indexing", false); + PROCESS_SWITCH(AssociatePhotonToEMEvent, processElectronFromDalitz, "process dalitzee-event indexing", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processPHOS, "process phos-event indexing", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processEMC, "process emc-event indexing", false); - PROCESS_SWITCH(AssociatePhotonToEMEvent, processZeroPadding, "process zero padding.", true); + PROCESS_SWITCH(AssociatePhotonToEMEvent, processDummy, "process dummy", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"create-emevent"}), + adaptAnalysisTask(cfgc, TaskName{"create-emevent-photon"}), adaptAnalysisTask(cfgc, TaskName{"associate-photon-to-emevent"}), }; } diff --git a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx index c65a5f46043..9786329b601 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -39,6 +39,8 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "Common/Core/TableHelper.h" +#include "Common/Core/TPCVDriftManager.h" #include "Tools/KFparticle/KFUtilities.h" @@ -54,7 +56,8 @@ using namespace o2::constants::physics; using namespace o2::pwgem::photonmeson; using std::array; -using MyCollisions = aod::Collisions; +using MyCollisions = soa::Join; +using MyCollisionsWithSWT = soa::Join; using MyCollisionsMC = soa::Join; using MyTracksIU = soa::Join; @@ -62,7 +65,9 @@ using MyTracksIUMC = soa::Join; struct PhotonConversionBuilder { Produces v0photonskf; + Produces v0photonskfcov; Produces v0legs; + Produces events_ngpcm; // CCDB options Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -71,23 +76,30 @@ struct PhotonConversionBuilder { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable inherit_from_emevent_photon{"inherit_from_emevent_photon", false, "flag to inherit task options from emevent-photon"}; // Operation and minimisation criteria Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; + Configurable applyEveSel_at_skimming{"applyEveSel_at_skimming", false, "flag to apply minimal event selection at the skimming level"}; // single track cuts - Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 10, "min crossed rows"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable mincrossedrows{"mincrossedrows", 40, "min crossed rows"}; + Configurable moveTPCTracks{"moveTPCTracks", true, "Move TPC-only tracks under the collision assumption"}; + Configurable disableITSonlyTracks{"disableITSonlyTracks", false, "disable ITSonly tracks in V0 legs"}; + Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max chi2/NclsTPC"}; // default 4.0 + 1.0 Configurable maxchi2its{"maxchi2its", 6.0, "max chi2/NclsITS"}; // default 5.0 + 1.0 Configurable maxpt_itsonly{"maxpt_itsonly", 0.15, "max pT for ITSonly tracks at SV"}; Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 4.0, "max. TPC n sigma for electron"}; + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -4.0, "min. TPC n sigma for electron"}; Configurable dcanegtopv{"dcanegtopv", 0.1, "DCA Neg To PV"}; Configurable dcapostopv{"dcapostopv", 0.1, "DCA Pos To PV"}; - Configurable min_pt_leg{"min_pt_leg", 0.04, "min pT for v0 legs at SV"}; + Configurable min_pt_leg_at_sv{"min_pt_leg_at_sv", 0.0, "min pT for v0 legs at SV"}; // this is obsolete. Configurable max_mean_its_cluster_size{"max_mean_its_cluster_size", 16.f, "max. x cos(lambda) for ITSonly tracks"}; // this is to suppress random combination for V0s with ITSonly tracks. default 3 + 1 for skimming. Configurable maxX{"maxX", 83.1, "max X for track IU"}; + Configurable min_pt_trackiu{"min_pt_trackiu", 0.05, "min pT for trackiu"}; // this comes from online processing. pT of track seed is above 50 MeV/c in B = 0.5 T, 20 MeV/c in B = 0.2 T. // v0 cuts Configurable min_v0cospa_tpconly{"min_v0cospa_tpconly", 0.99, "min V0 CosPA to V0s with TPConly tracks"}; // double -> N.B. dcos(x)/dx = 0 at x=0) @@ -103,7 +115,7 @@ struct PhotonConversionBuilder { Configurable margin_z{"margin_z", 7.0, "margin for z cut in cm"}; Configurable max_alpha_ap{"max_alpha_ap", 0.95, "max alpha for AP cut"}; Configurable max_qt_ap{"max_qt_ap", 0.01, "max qT for AP cut"}; - Configurable min_pt_v0{"min_pt_v0", 0.05, "min pT for v0 photons at PV"}; + Configurable min_pt_v0{"min_pt_v0", 0.1, "min pT for v0 photons at PV"}; Configurable max_pt_v0_itsonly{"max_pt_v0_itsonly", 0.3, "max pT for v0 photons wth 2 ITSonly tracks at PV"}; Configurable max_eta_v0{"max_eta_v0", 0.9, "max eta for v0 photons at PV"}; Configurable kfMassConstrain{"kfMassConstrain", -1.f, "mass constrain for the KFParticle mother particle"}; @@ -121,6 +133,7 @@ struct PhotonConversionBuilder { Service ccdb; o2::base::MatLayerCylSet* lut = nullptr; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + o2::aod::common::TPCVDriftManager mVDriftMgr; HistogramRegistry registry{ "registry", @@ -130,7 +143,7 @@ struct PhotonConversionBuilder { {"V0/hConversionPointXY", "conversion point in XY;X (cm);Y (cm)", {HistType::kTH2F, {{400, -100.0f, 100.0f}, {400, -100.f, 100.f}}}}, {"V0/hConversionPointRZ", "conversion point in RZ;Z (cm);R_{xy} (cm)", {HistType::kTH2F, {{200, -100.0f, 100.0f}, {200, 0.f, 100.f}}}}, {"V0/hPt", "pT of V0 at PV;p_{T,#gamma} (GeV/c)", {HistType::kTH1F, {{1000, 0.0f, 10.0f}}}}, - {"V0/hEtaPhi", "#eta vs. #varphi of V0 at PV;#varphi (rad.);#eta", {HistType::kTH2F, {{72, 0.0f, 2 * M_PI}, {400, -2, +2}}}}, + {"V0/hEtaPhi", "#eta vs. #varphi of V0 at PV;#varphi (rad.);#eta", {HistType::kTH2F, {{72, 0.0f, 2 * M_PI}, {200, -1, +1}}}}, {"V0/hCosPA", "cosine of pointing angle;cosine of pointing angle", {HistType::kTH1F, {{100, 0.9f, 1.f}}}}, {"V0/hCosPA_Rxy", "cosine of pointing angle;r_{xy} (cm);cosine of pointing angle", {HistType::kTH2F, {{200, 0, 100}, {100, 0.9f, 1.f}}}}, {"V0/hCosPAXY_Rxy", "cosine of pointing angle;r_{xy} (cm);cosine of pointing angle", {HistType::kTH2F, {{200, 0, 100}, {100, 0.9f, 1.f}}}}, @@ -147,14 +160,14 @@ struct PhotonConversionBuilder { {"V0/hRxy_minX_TPC_TPC", "min trackiu X vs. R_{xy};trackiu X (cm);min trackiu X - R_{xy} (cm)", {HistType::kTH2F, {{100, 0.0f, 100.f}, {100, -50.0, 50.0f}}}}, {"V0/hPCA_diffX", "PCA vs. trackiu X - R_{xy};distance btween 2 legs (cm);min trackiu X - R_{xy} (cm)", {HistType::kTH2F, {{500, 0.0f, 5.f}, {100, -50.0, 50.0f}}}}, {"V0Leg/hPt", "pT of leg at SV;p_{T,e} (GeV/c)", {HistType::kTH1F, {{1000, 0.0f, 10.0f}}}}, - {"V0Leg/hEtaPhi", "#eta vs. #varphi of leg at SV;#varphi (rad.);#eta", {HistType::kTH2F, {{72, 0.0f, 2 * M_PI}, {400, -2, +2}}}}, + {"V0Leg/hEtaPhi", "#eta vs. #varphi of leg at SV;#varphi (rad.);#eta", {HistType::kTH2F, {{72, 0.0f, 2 * M_PI}, {200, -1, +1}}}}, {"V0Leg/hDCAxyz", "DCA xy vs. z to PV;DCA_{xy} (cm);DCA_{z} (cm)", {HistType::kTH2F, {{200, -50.f, 50.f}, {200, -50.f, +50.f}}}}, {"V0Leg/hdEdx_Pin", "TPC dE/dx vs. p_{in};p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{1000, 0.f, 10.f}, {200, 0.f, 200.f}}}}, {"V0Leg/hTPCNsigmaEl", "TPC dE/dx vs. p_{in};p_{in} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, -5.f, +5.f}}}}, {"V0Leg/hXZ", "track iu x vs. z;z (cm);x (cm)", {HistType::kTH2F, {{200, -100.f, 100.f}, {200, 0.f, 100.f}}}}, }}; - void init(InitContext&) + void init(InitContext& initContext) { mRunNumber = 0; d_bz = 0; @@ -166,6 +179,10 @@ struct PhotonConversionBuilder { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + if (inherit_from_emevent_photon) { + getTaskOptionValue(initContext, "create-emevent-photon", "applyEveSel_at_skimming", applyEveSel_at_skimming.value, true); + } + if (useMatCorrType == 1) { LOGF(info, "TGeo correction requested, loading geometry"); if (!o2::base::GeometryManager::isGeometryLoaded()) { @@ -177,10 +194,12 @@ struct PhotonConversionBuilder { lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); } - if (useMatCorrType == 1) + if (useMatCorrType == 1) { matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - if (useMatCorrType == 2) + } + if (useMatCorrType == 2) { matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -202,18 +221,19 @@ struct PhotonConversionBuilder { } auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) + o2::parameters::GRPObject* grpo = nullptr; + o2::parameters::GRPMagField* grpmag = nullptr; + if (!skipGRPOquery) { grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { + } + if (grpo != nullptr) { o2::base::Propagator::initFieldFromGRP(grpo); // Fetch magnetic field from ccdb for current collision d_bz = grpo->getNominalL3Field(); LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; } else { grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { + if (grpmag == nullptr) { LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; } o2::base::Propagator::initFieldFromGRP(grpmag); @@ -228,8 +248,17 @@ struct PhotonConversionBuilder { o2::base::Propagator::Instance()->setMatLUT(lut); } /// Set magnetic field for KF vertexing - float magneticField = o2::base::Propagator::Instance()->getNominalBz(); + const float magneticField = o2::base::Propagator::Instance()->getNominalBz(); KFParticle::SetField(magneticField); + + mVDriftMgr.init(&ccdb->instance()); + } + + void updateCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + auto timestamp = bc.timestamp(); + + mVDriftMgr.update(timestamp); } std::pair> its_ib_Requirement = {0, {0, 1, 2}}; // no hit on 3 ITS ib layers. @@ -242,6 +271,10 @@ struct PhotonConversionBuilder { } } + if (disableITSonlyTracks && isITSonlyTrack(track)) { + return false; + } + if (track.x() > maxX) { return false; } @@ -261,7 +294,7 @@ struct PhotonConversionBuilder { if (track.tpcNClsCrossedRows() < mincrossedrows || track.tpcChi2NCl() > maxchi2tpc) { return false; } - if (abs(track.tpcNSigmaEl()) > maxTPCNsigmaEl) { + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { return false; } } @@ -333,30 +366,34 @@ struct PhotonConversionBuilder { return cospaRZ; } - template - void fillTrackTable(TTrack const& track, TKFParticle const& kfp, float dcaXY, float dcaZ) + template + void fillTrackTable(TTrack const& track, TShiftedTrack const& shiftedtrack, TKFParticle const& kfp, float dcaXY, float dcaZ) { v0legs(track.collisionId(), track.globalIndex(), track.sign(), kfp.GetPx(), kfp.GetPy(), kfp.GetPz(), dcaXY, dcaZ, - track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), - track.x(), track.y(), track.z(), track.tgl()); + shiftedtrack.getX(), shiftedtrack.getY(), shiftedtrack.getZ(), shiftedtrack.getTgl()); } - template + template void fillV0Table(TV0 const& v0, const bool filltable) { // Get tracks - auto pos = v0.template posTrack_as(); - auto ele = v0.template negTrack_as(); - auto collision = v0.template collision_as(); // collision where this v0 belongs to. + const auto& pos = v0.template posTrack_as(); + const auto& ele = v0.template negTrack_as(); + const auto& collision = v0.template collision_as(); // collision where this v0 belongs to. if (pos.sign() * ele.sign() > 0) { // reject same sign pair return; } + if (pos.pt() < min_pt_trackiu || ele.pt() < min_pt_trackiu) { + return; + } + if (pos.globalIndex() == ele.globalIndex()) { return; } @@ -364,6 +401,7 @@ struct PhotonConversionBuilder { if (isITSonlyTrack(pos) && !ele.hasITS()) { return; } + if (isITSonlyTrack(ele) && !pos.hasITS()) { return; } @@ -371,18 +409,31 @@ struct PhotonConversionBuilder { if (!checkV0leg(pos) || !checkV0leg(ele)) { return; } + // LOGF(info, "v0.collisionId() = %d , v0.posTrackId() = %d , v0.negTrackId() = %d", v0.collisionId(), v0.posTrackId(), v0.negTrackId()); // Calculate DCA with respect to the collision associated to the v0, not individual tracks gpu::gpustd::array dcaInfo; - auto pTrack = getTrackPar(pos); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, pTrack, 2.f, matCorr, &dcaInfo); + auto pTrack = getTrackParCov(pos); + if (moveTPCTracks && isTPConlyTrack(pos) && !mVDriftMgr.moveTPCTrack(collision, pos, pTrack)) { + LOGP(error, "failed correction for positive tpc track"); + return; + } + auto pTrackC = pTrack; + pTrackC.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, pTrackC, 2.f, matCorr, &dcaInfo); auto posdcaXY = dcaInfo[0]; auto posdcaZ = dcaInfo[1]; - auto nTrack = getTrackPar(ele); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, nTrack, 2.f, matCorr, &dcaInfo); + auto nTrack = getTrackParCov(ele); + if (moveTPCTracks && isTPConlyTrack(ele) && !mVDriftMgr.moveTPCTrack(collision, ele, nTrack)) { + LOGP(error, "failed correction for negative tpc track"); + return; + } + auto nTrackC = nTrack; + nTrackC.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, nTrackC, 2.f, matCorr, &dcaInfo); auto eledcaXY = dcaInfo[0]; auto eledcaZ = dcaInfo[1]; @@ -391,17 +442,17 @@ struct PhotonConversionBuilder { } float xyz[3] = {0.f, 0.f, 0.f}; - Vtx_recalculation(o2::base::Propagator::Instance(), pos, ele, xyz, matCorr); + Vtx_recalculationParCov(o2::base::Propagator::Instance(), pTrack, nTrack, xyz, matCorr); float rxy_tmp = RecoDecay::sqrtSumOfSquares(xyz[0], xyz[1]); if (rxy_tmp > maxX + margin_r_tpc) { return; } - if (rxy_tmp < abs(xyz[2]) * TMath::Tan(2 * TMath::ATan(TMath::Exp(-max_eta_v0))) - margin_z) { + if (rxy_tmp < fabs(xyz[2]) * std::tan(2 * std::atan(std::exp(-max_eta_v0))) - margin_z) { return; // RZ line cut } - KFPTrack kfp_track_pos = createKFPTrackFromTrack(pos); - KFPTrack kfp_track_ele = createKFPTrackFromTrack(ele); + KFPTrack kfp_track_pos = createKFPTrackFromTrackParCov(pTrack, pos.sign(), pos.tpcNClsFound(), pos.tpcChi2NCl()); + KFPTrack kfp_track_ele = createKFPTrackFromTrackParCov(nTrack, ele.sign(), ele.tpcNClsFound(), ele.tpcChi2NCl()); KFParticle kfp_pos(kfp_track_pos, -11); KFParticle kfp_ele(kfp_track_ele, 11); const KFParticle* GammaDaughters[2] = {&kfp_pos, &kfp_ele}; @@ -434,7 +485,7 @@ struct PhotonConversionBuilder { if (rxy > maxX + margin_r_tpc) { return; } - if (rxy < abs(gammaKF_DecayVtx.GetZ()) * TMath::Tan(2 * TMath::ATan(TMath::Exp(-max_eta_v0))) - margin_z) { + if (rxy < fabs(gammaKF_DecayVtx.GetZ()) * std::tan(2 * std::atan(std::exp(-max_eta_v0))) - margin_z) { return; // RZ line cut } if (rxy < min_v0radius) { @@ -443,30 +494,30 @@ struct PhotonConversionBuilder { if (!filltable) { if (isITSTPCTrack(pos) && isITSTPCTrack(ele)) { - registry.fill(HIST("V0/hRxy_minX_ITSTPC_ITSTPC"), std::min(pos.x(), ele.x()), std::min(pos.x(), ele.x()) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hRxy_minX_ITSTPC_ITSTPC"), std::min(pTrack.getX(), nTrack.getX()), std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive } else if (isITSonlyTrack(pos) && isITSonlyTrack(ele)) { - registry.fill(HIST("V0/hRxy_minX_ITSonly_ITSonly"), std::min(pos.x(), ele.x()), std::min(pos.x(), ele.x()) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hRxy_minX_ITSonly_ITSonly"), std::min(pTrack.getX(), nTrack.getX()), std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive } else if ((isITSTPCTrack(pos) && isITSonlyTrack(ele)) || (isITSTPCTrack(ele) && isITSonlyTrack(pos))) { - registry.fill(HIST("V0/hRxy_minX_ITSTPC_ITSonly"), std::min(pos.x(), ele.x()), std::min(pos.x(), ele.x()) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hRxy_minX_ITSTPC_ITSonly"), std::min(pTrack.getX(), nTrack.getX()), std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive } else if (isITSTPCTrack(pos) && !ele.hasITS()) { - registry.fill(HIST("V0/hRxy_minX_ITSTPC_TPC"), std::min(pos.x(), 83.f), std::min(pos.x(), 83.f) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hRxy_minX_ITSTPC_TPC"), std::min(pTrack.getX(), 83.f), std::min(pTrack.getX(), 83.f) - rxy); // trackiu.x() - rxy should be positive } else if (isITSTPCTrack(ele) && !pos.hasITS()) { - registry.fill(HIST("V0/hRxy_minX_ITSTPC_TPC"), std::min(ele.x(), 83.f), std::min(ele.x(), 83.f) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hRxy_minX_ITSTPC_TPC"), std::min(nTrack.getX(), 83.f), std::min(nTrack.getX(), 83.f) - rxy); // trackiu.x() - rxy should be positive } else { registry.fill(HIST("V0/hRxy_minX_TPC_TPC"), std::min(83.f, 83.f), std::min(83.f, 83.f) - rxy); // trackiu.x() - rxy should be positive } } if (pos.hasITS() && ele.hasITS()) { // ITSonly-ITSonly, ITSTPC-ITSTPC, ITSTPC-ITSonly - if (rxy > std::min(pos.x(), ele.x()) + margin_r_its) { + if (rxy > std::min(pTrack.getX(), nTrack.getX()) + margin_r_its) { return; } } else if (!pos.hasITS() && ele.hasITS()) { // ITSTPC-TPC - if (rxy > std::min(83.f, ele.x()) + margin_r_itstpc_tpc) { + if (rxy > std::min(83.f, nTrack.getX()) + margin_r_itstpc_tpc) { return; } } else if (pos.hasITS() && !ele.hasITS()) { // ITSTPC-TPC - if (rxy > std::min(pos.x(), 83.f) + margin_r_itstpc_tpc) { + if (rxy > std::min(pTrack.getX(), 83.f) + margin_r_itstpc_tpc) { return; } } else if (!pos.hasITS() && !ele.hasITS()) { // TPC-TPC @@ -535,7 +586,7 @@ struct PhotonConversionBuilder { float pos_pt = RecoDecay::sqrtSumOfSquares(kfp_pos_DecayVtx.GetPx(), kfp_pos_DecayVtx.GetPy()); float ele_pt = RecoDecay::sqrtSumOfSquares(kfp_ele_DecayVtx.GetPx(), kfp_ele_DecayVtx.GetPy()); - if (pos_pt < min_pt_leg || ele_pt < min_pt_leg) { + if (pos_pt < min_pt_leg_at_sv || ele_pt < min_pt_leg_at_sv) { return; } @@ -579,7 +630,7 @@ struct PhotonConversionBuilder { registry.fill(HIST("V0/hPCA_CosPA"), cospa_kf, pca_kf); registry.fill(HIST("V0/hPCA_Rxy"), rxy, pca_kf); registry.fill(HIST("V0/hDCAxyz"), dca_xy_v0_to_pv, dca_z_v0_to_pv); - registry.fill(HIST("V0/hPCA_diffX"), pca_kf, std::min(pos.x(), ele.x()) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hPCA_diffX"), pca_kf, std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive float cospaXY_kf = cospaXY_KF(gammaKF_DecayVtx, KFPV); float cospaRZ_kf = cospaRZ_KF(gammaKF_DecayVtx, KFPV); @@ -599,8 +650,9 @@ struct PhotonConversionBuilder { for (auto& leg : {pos, ele}) { registry.fill(HIST("V0Leg/hdEdx_Pin"), leg.tpcInnerParam(), leg.tpcSignal()); registry.fill(HIST("V0Leg/hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); - registry.fill(HIST("V0Leg/hXZ"), leg.z(), leg.x()); } // end of leg loop + registry.fill(HIST("V0Leg/hXZ"), pTrack.getZ(), pTrack.getX()); + registry.fill(HIST("V0Leg/hXZ"), nTrack.getZ(), nTrack.getX()); registry.fill(HIST("V0Leg/hDCAxyz"), posdcaXY, posdcaZ); registry.fill(HIST("V0Leg/hDCAxyz"), eledcaXY, eledcaZ); @@ -609,45 +661,70 @@ struct PhotonConversionBuilder { ROOT::Math::PxPyPzMVector v0_sv = vpos_sv + vele_sv; registry.fill(HIST("V0/hMeeSV_Rxy"), rxy, v0_sv.M()); - v0photonskf(collision.globalIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, + v0photonskf(collision.globalIndex(), v0.globalIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, gammaKF_DecayVtx.GetX(), gammaKF_DecayVtx.GetY(), gammaKF_DecayVtx.GetZ(), gammaKF_PV.GetPx(), gammaKF_PV.GetPy(), gammaKF_PV.GetPz(), v0_sv.M(), dca_xy_v0_to_pv, dca_z_v0_to_pv, cospa_kf, pca_kf, alpha, qt, chi2kf); - fillTrackTable(pos, kfp_pos_DecayVtx, posdcaXY, posdcaZ); // positive leg first - fillTrackTable(ele, kfp_ele_DecayVtx, eledcaXY, eledcaZ); // negative leg second - } // end of fill table + v0photonskfcov(gammaKF_PV.GetCovariance(9), gammaKF_PV.GetCovariance(14), gammaKF_PV.GetCovariance(20), gammaKF_PV.GetCovariance(13), gammaKF_PV.GetCovariance(19), gammaKF_PV.GetCovariance(18)); + + fillTrackTable(pos, pTrack, kfp_pos_DecayVtx, posdcaXY, posdcaZ); // positive leg first + fillTrackTable(ele, nTrack, kfp_ele_DecayVtx, eledcaXY, eledcaZ); // negative leg second + } // end of fill table } Preslice perCollision = o2::aod::v0::collisionId; - std::map, float> pca_map; //(v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex()) -> pca - std::map, float> cospa_map; //(v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex()) -> cospa - std::vector> stored_v0Ids; //(pos.globalIndex(), ele.globalIndex()) - - template - void build(TCollisions const& collisions, TV0s const& v0s, TTracks const& /*tracks*/, TBCs const&) + std::map, float> pca_map; // (v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex()) -> pca + std::map, float> cospa_map; // (v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex()) -> cospa + std::vector> stored_v0Ids; // (pos.globalIndex(), ele.globalIndex()) + std::vector> stored_fullv0Ids; // (v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex()) + std::unordered_map nv0_map; // map collisionId -> nv0 + + template + void build(TCollisions const& collisions, TV0s const& v0s, TTracks const&, TBCs const&) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { if constexpr (isMC) { if (!collision.has_mcCollision()) { continue; } } - auto bc = collision.template bc_as(); + if constexpr (enableFilter) { + if (!collision.isSelected()) { + continue; + } + } + + if constexpr (isTriggerAnalysis) { + if (collision.swtaliastmp_raw() == 0) { + continue; + } + } + + nv0_map[collision.globalIndex()] = 0; + + const auto& bc = collision.template bc_as(); initCCDB(bc); registry.fill(HIST("hCollisionCounter"), 1); - auto v0s_per_coll = v0s.sliceBy(perCollision, collision.globalIndex()); + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + + updateCCDB(bc); // delay update until is needed + + const auto& v0s_per_coll = v0s.sliceBy(perCollision, collision.globalIndex()); // LOGF(info, "n v0 = %d", v0s_per_coll.size()); - for (auto& v0 : v0s_per_coll) { + for (const auto& v0 : v0s_per_coll) { // LOGF(info, "collision.globalIndex() = %d, v0.globalIndex() = %d, v0.posTrackId() = %d, v0.negTrackId() = %d", collision.globalIndex(), v0.globalIndex(), v0.posTrackId() , v0.negTrackId()); - fillV0Table(v0, false); + fillV0Table(v0, false); } // end of v0 loop - } // end of collision loop + } // end of collision loop - stored_v0Ids.reserve(pca_map.size()); // number of photon candidates per DF + stored_v0Ids.reserve(pca_map.size()); // number of photon candidates per DF + stored_fullv0Ids.reserve(pca_map.size()); // number of photon candidates per DF // find minimal pca for (const auto& [key, value] : pca_map) { @@ -687,20 +764,55 @@ struct PhotonConversionBuilder { bool is_stored = std::find(stored_v0Ids.begin(), stored_v0Ids.end(), std::make_pair(posId, eleId)) != stored_v0Ids.end(); if (is_closest_v0 && is_most_aligned_v0 && !is_stored) { - auto v0 = v0s.rawIteratorAt(v0Id); + // auto v0 = v0s.rawIteratorAt(v0Id); // auto collision = collisions.rawIteratorAt(collisionId); // auto pos = tracks.rawIteratorAt(posId); // auto ele = tracks.rawIteratorAt(eleId); // LOGF(info, "!accept! | collision id = %d | v0id1 = %d , posid1 = %d , eleid1 = %d , pca1 = %f , cospa = %f", collisionId, v0Id, posId, eleId, v0pca, cospa); - fillV0Table(v0, true); + + // fillV0Table(v0, true); stored_v0Ids.emplace_back(std::make_pair(posId, eleId)); + stored_fullv0Ids.emplace_back(std::make_tuple(v0Id, collisionId, posId, eleId)); + nv0_map[collisionId]++; } } // end of pca_map loop // LOGF(info, "pca_map.size() = %d", pca_map.size()); + + for (auto& fullv0Id : stored_fullv0Ids) { + auto v0Id = std::get<0>(fullv0Id); + // auto collisionId = std::get<1>(fullv0Id); + // auto posId = std::get<2>(fullv0Id); + // auto eleId = std::get<3>(fullv0Id); + // LOGF(info, "!accept! | collision id = %d | v0id = %d , posid = %d , eleid = %d", collisionId, v0Id, posId, eleId); + + auto v0 = v0s.rawIteratorAt(v0Id); + if constexpr (enableFilter) { + auto collision_tmp = v0.template collision_as(); // collision where this v0 belongs. + if (!(collision_tmp.neeuls() >= 1 || collision_tmp.neeuls() + nv0_map[collision_tmp.globalIndex()] >= 2)) { + continue; + } + // LOGF(info, "collision_tmp.globalIndex() = %d, collision_tmp.neeuls() = %d, nv0_map = %d", collision_tmp.globalIndex(), collision_tmp.neeuls(), nv0_map[collision_tmp.globalIndex()]); + } + + fillV0Table(v0, true); + } // end of fullv0Id loop + + for (auto& collision : collisions) { + if constexpr (isMC) { + if (!collision.has_mcCollision()) { + continue; + } + } + events_ngpcm(nv0_map[collision.globalIndex()]); + } // end of collision loop + pca_map.clear(); cospa_map.clear(); + nv0_map.clear(); stored_v0Ids.clear(); stored_v0Ids.shrink_to_fit(); + stored_fullv0Ids.clear(); + stored_fullv0Ids.shrink_to_fit(); } // end of build //! type of V0. 0: built solely for cascades (does not pass standard V0 cuts), 1: standard 2, 3: photon-like with TPC-only use. Regular analysis should always use type 1 or 3. @@ -709,15 +821,33 @@ struct PhotonConversionBuilder { void processRec(MyCollisions const& collisions, filteredV0s const& v0s, MyTracksIU const& tracks, aod::BCsWithTimestamps const& bcs) { - build(collisions, v0s, tracks, bcs); + build(collisions, v0s, tracks, bcs); } PROCESS_SWITCH(PhotonConversionBuilder, processRec, "process reconstructed info for data", true); + void processRec_SWT(MyCollisionsWithSWT const& collisions, filteredV0s const& v0s, MyTracksIU const& tracks, aod::BCsWithTimestamps const& bcs) + { + build(collisions, v0s, tracks, bcs); + } + PROCESS_SWITCH(PhotonConversionBuilder, processRec_SWT, "process reconstructed info for data", false); + void processMC(MyCollisionsMC const& collisions, filteredV0s const& v0s, MyTracksIUMC const& tracks, aod::BCsWithTimestamps const& bcs) { - build(collisions, v0s, tracks, bcs); + build(collisions, v0s, tracks, bcs); } PROCESS_SWITCH(PhotonConversionBuilder, processMC, "process reconstructed info for MC", false); + + void processRec_OnlyIfDielectron(soa::Join const& collisions, filteredV0s const& v0s, MyTracksIU const& tracks, aod::BCsWithTimestamps const& bcs) + { + build(collisions, v0s, tracks, bcs); + } + PROCESS_SWITCH(PhotonConversionBuilder, processRec_OnlyIfDielectron, "process reconstructed info for data", false); + + void processRec_SWT_OnlyIfDielectron(soa::Join const& collisions, filteredV0s const& v0s, MyTracksIU const& tracks, aod::BCsWithTimestamps const& bcs) + { + build(collisions, v0s, tracks, bcs); + } + PROCESS_SWITCH(PhotonConversionBuilder, processRec_SWT_OnlyIfDielectron, "process reconstructed info for data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx index 0a5e0be452b..5eb1bfeb069 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -24,7 +24,7 @@ #include "Framework/AnalysisDataModel.h" #include "CommonConstants/PhysicsConstants.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" using namespace o2; using namespace o2::soa; @@ -273,8 +273,8 @@ struct skimmerDalitzEE { if (v12.M() > maxMee) { // don't store continue; } - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); - float opangle = getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + float opangle = o2::aod::pwgem::dilepton::utils::pairutil::getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); // if (!std::isfinite(phiv)) { // LOGF(info, "t1.px() = %f, t1.py() = %f, t1.pz() = %f, t2.px() = %f, t2.py() = %f, t2.pz() = %f", t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); @@ -302,8 +302,8 @@ struct skimmerDalitzEE { if (v12.M() > maxMee) { // don't store continue; } - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); - float opangle = getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + float opangle = o2::aod::pwgem::dilepton::utils::pairutil::getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); if constexpr (isCEFP) { dalitzees(collision.globalIndex(), t1.globalIndex(), t2.globalIndex(), v12.Pt(), v12.Eta(), v12.Phi() > 0 ? v12.Phi() : v12.Phi() + TMath::TwoPi(), v12.M(), v12.M(), phiv, opangle, static_cast(pairtype)); diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx index c3843080eaf..68e6d26ddfb 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx @@ -17,6 +17,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Common/Core/TableHelper.h" + // includes for the R recalculation #include "DetectorsBase/GeometryManager.h" #include "DataFormatsParameters/GRPObject.h" @@ -44,44 +46,56 @@ struct skimmerGammaCalo { Configurable maxTime{"maxTime", +200., "Maximum cluster time for time cut"}; Configurable minM02{"minM02", 0.0, "Minimum M02 for M02 cut"}; Configurable maxM02{"maxM02", 1.0, "Maximum M02 for M02 cut"}; + Configurable minE{"minE", 0.5, "Minimum energy for energy cut"}; Configurable hasPropagatedTracks{"hasPropagatedTracks", false, "temporary flag, only set to true when running over data which has the tracks propagated to EMCal/PHOS!"}; + Configurable applyEveSel_at_skimming{"applyEveSel_at_skimming", false, "flag to apply minimal event selection at the skimming level"}; + Configurable inherit_from_emevent_photon{"inherit_from_emevent_photon", false, "flag to inherit task options from emevent-photon"}; - HistogramRegistry historeg{ - "historeg", - {}, - OutputObjHandlingPolicy::QAObject, - false, - true}; + HistogramRegistry historeg{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& initContext) { historeg.add("hCaloClusterEIn", "hCaloClusterEIn", gHistoSpec_clusterE); historeg.add("hCaloClusterEOut", "hCaloClusterEOut", gHistoSpec_clusterE); - historeg.add("hMTEtaPhi", "hMTEtaPhi", gHistoSpec_EtaPhi); - auto hCaloClusterFilter = historeg.add("hCaloClusterFilter", "hCaloClusterFilter", kTH1I, {{4, 0, 4}}); + historeg.add("hMTEtaPhi", "hMTEtaPhi", gHistoSpec_clusterTM_dEtadPhi); + auto hCaloClusterFilter = historeg.add("hCaloClusterFilter", "hCaloClusterFilter", kTH1I, {{5, 0, 5}}); hCaloClusterFilter->GetXaxis()->SetBinLabel(1, "in"); - hCaloClusterFilter->GetXaxis()->SetBinLabel(2, "time cut"); - hCaloClusterFilter->GetXaxis()->SetBinLabel(3, "M02 cut"); - hCaloClusterFilter->GetXaxis()->SetBinLabel(4, "out"); + hCaloClusterFilter->GetXaxis()->SetBinLabel(2, "E cut"); + hCaloClusterFilter->GetXaxis()->SetBinLabel(3, "time cut"); + hCaloClusterFilter->GetXaxis()->SetBinLabel(4, "M02 cut"); + hCaloClusterFilter->GetXaxis()->SetBinLabel(5, "out"); + + if (inherit_from_emevent_photon) { + getTaskOptionValue(initContext, "create-emevent-photon", "applyEveSel_at_skimming", applyEveSel_at_skimming.value, true); // for EM users. + } - LOG(info) << "| Timing cut: " << minTime << " < t < " << maxTime << std::endl; - LOG(info) << "| M02 cut: " << minM02 << " < M02 < " << maxM02 << std::endl; + LOG(info) << "| Timing cut: " << minTime << " < t < " << maxTime; + LOG(info) << "| M02 cut: " << minM02 << " < M02 < " << maxM02; + LOG(info) << "| E cut: E > " << minE; } - void processRec(aod::Collision const&, aod::EMCALClusters const& emcclusters, aod::EMCALClusterCells const& emcclustercells, aod::EMCALMatchedTracks const& emcmatchedtracks, aod::FullTracks const&) + void processRec(soa::Join::iterator const& collision, aod::EMCALClusters const& emcclusters, aod::EMCALClusterCells const& emcclustercells, aod::EMCALMatchedTracks const& emcmatchedtracks, aod::FullTracks const&) { + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + return; + } for (const auto& emccluster : emcclusters) { historeg.fill(HIST("hCaloClusterEIn"), emccluster.energy()); historeg.fill(HIST("hCaloClusterFilter"), 0); + // Energy cut + if (emccluster.energy() < minE) { + historeg.fill(HIST("hCaloClusterFilter"), 1); + continue; + } // timing cut if (emccluster.time() > maxTime || emccluster.time() < minTime) { - historeg.fill(HIST("hCaloClusterFilter"), 1); + historeg.fill(HIST("hCaloClusterFilter"), 2); continue; } // M02 cut if (emccluster.nCells() > 1 && (emccluster.m02() > maxM02 || emccluster.m02() < minM02)) { - historeg.fill(HIST("hCaloClusterFilter"), 2); + historeg.fill(HIST("hCaloClusterFilter"), 3); continue; } @@ -126,28 +140,31 @@ struct skimmerGammaCalo { } historeg.fill(HIST("hCaloClusterEOut"), emccluster.energy()); - historeg.fill(HIST("hCaloClusterFilter"), 3); + historeg.fill(HIST("hCaloClusterFilter"), 4); - tableGammaEMCReco(emccluster.collisionId(), emccluster.id(), - emccluster.energy(), emccluster.coreEnergy(), emccluster.eta(), emccluster.phi(), emccluster.m02(), - emccluster.m20(), emccluster.nCells(), emccluster.time(), emccluster.isExotic(), emccluster.distanceToBadChannel(), emccluster.nlm(), - emccluster.definition(), vTrackIds, vEta, vPhi, vP, vPt); + tableGammaEMCReco(emccluster.collisionId(), emccluster.energy(), emccluster.eta(), emccluster.phi(), emccluster.m02(), + emccluster.nCells(), emccluster.time(), emccluster.isExotic(), vEta, vPhi, vP, vPt); } } - void processMC(aod::Collision const&, soa::Join const& emcclusters, aod::McParticles const&) + void processMC(soa::Join::iterator const& collision, soa::Join const& emcclusters, aod::McParticles const&) { + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + return; + } for (const auto& emccluster : emcclusters) { historeg.fill(HIST("hCaloClusterEIn"), emccluster.energy()); historeg.fill(HIST("hCaloClusterFilter"), 0); + // Energy cut + if (emccluster.energy() < minE) { + continue; + } // timing cut if (emccluster.time() > maxTime || emccluster.time() < minTime) { - historeg.fill(HIST("hCaloClusterFilter"), 1); continue; } // M02 cut if (emccluster.nCells() > 1 && (emccluster.m02() > maxM02 || emccluster.m02() < minM02)) { - historeg.fill(HIST("hCaloClusterFilter"), 2); continue; } std::vector mcLabels; diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx index 40334a036c0..bed52425fb5 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx @@ -181,7 +181,7 @@ struct skimmerGammaConversion { v0legs(theTrack.collisionId(), theTrack.globalIndex(), theTrack.sign(), kfp.GetPx(), kfp.GetPy(), kfp.GetPz(), theTrack.dcaXY(), theTrack.dcaZ(), - theTrack.tpcNClsFindable(), theTrack.tpcNClsFindableMinusFound(), theTrack.tpcNClsFindableMinusCrossedRows(), + theTrack.tpcNClsFindable(), theTrack.tpcNClsFindableMinusFound(), theTrack.tpcNClsFindableMinusCrossedRows(), theTrack.tpcNClsShared(), theTrack.tpcChi2NCl(), theTrack.tpcInnerParam(), theTrack.tpcSignal(), theTrack.tpcNSigmaEl(), theTrack.tpcNSigmaPi(), theTrack.itsClusterSizes(), theTrack.itsChi2NCl(), theTrack.detectorMap(), @@ -304,7 +304,7 @@ struct skimmerGammaConversion { float sign_tmp = dca_y_v0_to_pv > 0 ? +1 : -1; float dca_xy_v0_to_pv = RecoDecay::sqrtSumOfSquares(dca_x_v0_to_pv, dca_y_v0_to_pv) * sign_tmp; - v0photonskf(collision.globalIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, + v0photonskf(collision.globalIndex(), v0.globalIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, gammaKF_DecayVtx.GetX(), gammaKF_DecayVtx.GetY(), gammaKF_DecayVtx.GetZ(), gammaKF_DecayVtx.GetPx(), gammaKF_DecayVtx.GetPy(), gammaKF_DecayVtx.GetPz(), v0_sv.M(), dca_xy_v0_to_pv, dca_z_v0_to_pv, @@ -342,7 +342,7 @@ struct skimmerGammaConversion { fillV0KF(collision, v0); } // end of v0 loop - } // end of collision loop + } // end of collision loop } PROCESS_SWITCH(skimmerGammaConversion, processRec, "process reconstructed info only", true); diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx new file mode 100644 index 00000000000..a42f00e0374 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx @@ -0,0 +1,375 @@ +// Copyright 2019-2020 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. + +/// \brief write relevant information about primary electrons. +/// \author daiki.sekihata@cern.ch + +#include +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/trackUtilities.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::pwgem::photonmeson; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; +using MyTracksMC = soa::Join; +using MyTrackMC = MyTracksMC::iterator; + +struct skimmerPrimaryElectronFromDalitzEE { + + SliceCache cache; + Preslice perCol = o2::aod::track::collisionId; + Produces emprimaryelectrons; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + // Operation and minimisation criteria + Configurable applyEveSel_at_skimming{"applyEveSel_at_skimming", false, "flag to apply minimal event selection at the skimming level"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable minitsncls{"minitsncls", 4, "min. number of ITS clusters"}; + Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; + Configurable minpt{"minpt", 0.15, "min pt for track"}; + Configurable maxeta{"maxeta", 0.8, "eta acceptance"}; + Configurable dca_xy_max{"dca_xy_max", 0.1, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 0.1, "max DCAz in cm"}; + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.5, "max. TPC n sigma for pion exclusion"}; + Configurable minTPCNsigmaPi{"minTPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable maxMee_lowPtee{"maxMee_lowPtee", 0.02, "max. mee to store dalitz ee pairs for recovery"}; + Configurable maxMee_highPtee{"maxMee_highPtee", 0.04, "max. mee to store dalitz ee pairs for recovery"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + std::pair> itsRequirement = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. + + int mRunNumber; + float d_bz; + Service ccdb; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + void init(InitContext&) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxy_Pt", "DCA_{xy} vs. pT;p_{T} (GeV/c);DCA_{xy} (cm)", kTH2F, {{1000, 0, 10}, {200, -1, 1}}, false); + fRegistry.add("Track/hDCAz_Pt", "DCA_{z} vs. pT;p_{T} (GeV/c);DCA_{z} (cm)", kTH2F, {{1000, 0, 10}, {200, -1, 1}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Pair/hMeePtee_ULS", "mee vs. pTee for dalitz ee ULS;m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{100, 0, 0.1}, {100, 0, 10}}, false); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + } + + template + bool checkTrack(TCollision const&, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + + if (track.itsChi2NCl() > maxchi2its) { + return false; + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + if (track.itsNCls() < minitsncls) { + return false; + } + + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits < itsRequirement.first) { + return false; + } + + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (abs(track.dcaXY()) > dca_xy_max || abs(track.dcaZ()) > dca_z_max) { + return false; + } + + if (track.pt() < minpt || abs(track.eta()) > maxeta) { + return false; + } + + return true; + } + + template + bool isElectron(TTrack const& track) + { + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + return false; + } + if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi) { + return false; + } + return true; + } + + template + void fillTrackTable(TCollision const& collision, TTrack const& track) + { + if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::make_pair(collision.globalIndex(), track.globalIndex())) == stored_trackIds.end()) { + emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), + track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), + track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), track.tgl()); + + fRegistry.fill(HIST("Track/hPt"), track.pt()); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); + fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/hDCAxy_Pt"), track.pt(), track.dcaXY()); + fRegistry.fill(HIST("Track/hDCAz_Pt"), track.pt(), track.dcaZ()); + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + + stored_trackIds.emplace_back(std::make_pair(collision.globalIndex(), track.globalIndex())); + } + } + + template + void fillPairInfo(TCollision const& collision, TTracks1 const& tracks1, TTracks2 const& tracks2) + { + for (auto& t1 : tracks1) { + for (auto& t2 : tracks2) { + if (!checkTrack(collision, t1) || !checkTrack(collision, t2)) { + continue; + } + if (!isElectron(t1) || !isElectron(t2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if (v12.Pt() < 1.0) { // don't store + if (v12.M() > maxMee_lowPtee) { // don't store + continue; + } + } else { + if (v12.M() > maxMee_highPtee) { // don't store + continue; + } + } + fRegistry.fill(HIST("Pair/hMeePtee_ULS"), v12.M(), v12.Pt()); + fillTrackTable(collision, t1); + fillTrackTable(collision, t2); + } // end of t2 + } // end of t1 + } + + std::vector> stored_trackIds; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + using MyFilteredTracks = soa::Filtered; + Partition posTracks = o2::aod::track::signed1Pt > 0.f; + Partition negTracks = o2::aod::track::signed1Pt < 0.f; + + // ---------- for data ---------- + void processRec(Join const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryElectronFromDalitzEE, processRec, "process reconstructed info only", true); // standalone + + using MyFilteredTracksMC = soa::Filtered; + Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; + Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; + // ---------- for MC ---------- + void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + auto bc = collision.bc_as(); + initCCDB(bc); + if (applyEveSel_at_skimming && (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + + auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryElectronFromDalitzEE, processMC, "process reconstructed and MC info ", false); +}; + +// struct associateAmbiguousElectron { +// Produces em_amb_ele_ids; +// +// SliceCache cache; +// PresliceUnsorted perTrack = o2::aod::emprimaryelectron::trackId; +// std::vector ambele_self_Ids; +// +// void process(aod::EMPrimaryElectrons const& electrons) +// { +// for (auto& electron : electrons) { +// auto electrons_with_same_trackId = electrons.sliceBy(perTrack, electron.trackId()); +// ambele_self_Ids.reserve(electrons_with_same_trackId.size()); +// for (auto& amp_ele : electrons_with_same_trackId) { +// if (amp_ele.globalIndex() == electron.globalIndex()) { // don't store myself. +// continue; +// } +// ambele_self_Ids.emplace_back(amp_ele.globalIndex()); +// } +// em_amb_ele_ids(ambele_self_Ids); +// ambele_self_Ids.clear(); +// ambele_self_Ids.shrink_to_fit(); +// } +// } +// }; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-electron-from-dalitzee"}), + // adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-electron"}) + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 1302da226b9..187e3a1bc36 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -34,29 +34,14 @@ o2physics_add_dpl_workflow(pcm-qc-mc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(dielectron-qc - SOURCES dielectronQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore O2::DCAFitter - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(dielectron-qc-mc - SOURCES dielectronQCMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore O2::DCAFitter - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(dimuon-qc - SOURCES dimuonQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore O2::DCAFitter O2::GlobalTracking - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(dalitz-ee-qc SOURCES dalitzEEQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dalitz-ee-qc-mc SOURCES dalitzEEQCMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(emcal-qc @@ -119,11 +104,6 @@ o2physics_add_dpl_workflow(tagging-pi0-mc PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(photon-hbt - SOURCES PhotonHBT.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(tag-and-probe SOURCES TagAndProbe.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx index d7ce6b28678..b5c1a5d8fde 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx @@ -41,10 +41,10 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; +using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -62,7 +62,7 @@ struct MaterialBudget { Configurable fDoMixing{"DoMixing", false, "do event mixing"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; @@ -204,7 +204,7 @@ struct MaterialBudget { template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) { - return o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + return o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } template @@ -321,8 +321,6 @@ struct MaterialBudget { THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ndepth, -1, collisions, collisions)) { // internally, CombinationsStrictlyUpperIndexPolicy(collisions, collisions) is called. - // LOGF(info, "Mixed event globalIndex: (%d, %d) , ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", collision1.globalIndex(), collision2.globalIndex(), collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); - const float centralities1[3] = {collision1.centFT0M(), collision1.centFT0A(), collision1.centFT0C()}; const float centralities2[3] = {collision2.centFT0M(), collision2.centFT0A(), collision2.centFT0C()}; @@ -380,7 +378,6 @@ struct MaterialBudget { Partition grouped_collisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = o2::aod::emevent::ngpcm >= 2; using MyFilteredCollisions = soa::Filtered; // this goes to mixed event. void processMB(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx index 9eef10ead68..3fe51c1ff7c 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx @@ -36,17 +36,19 @@ #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; -using namespace o2::aod::pwgem::mcutil; +using namespace o2::aod::pwgem::photonmeson::photonpair; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -69,7 +71,7 @@ struct MaterialBudgetMC { Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; @@ -221,7 +223,7 @@ struct MaterialBudgetMC { template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& tagcut, TCut2 const& probecut) { - return o2::aod::photonpair::IsSelectedPair(g1, g2, tagcut, probecut); + return o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, tagcut, probecut); } template @@ -380,7 +382,6 @@ struct MaterialBudgetMC { Partition grouped_collisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = o2::aod::emevent::ngpcm >= 2; using MyFilteredCollisions = soa::Filtered; // this goes to same event pairing. void processMBMC(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) diff --git a/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx b/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx deleted file mode 100644 index 1806db09791..00000000000 --- a/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx +++ /dev/null @@ -1,805 +0,0 @@ -// Copyright 2019-2020 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 loops over v0 photons and makes pairs for photon HBT analysis. -// Please write to: daiki.sekihata@cern.ch - -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/GenVector/Boost.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -// #include "Tools/ML/MlResponse.h" -// #include "Tools/ML/model.h" - -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/PairCut.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 namespace o2::aod::photonpair; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -using MyDalitzEEs = soa::Join; -using MyDalitzEE = MyDalitzEEs::iterator; - -using MyPrimaryElectrons = soa::Join; -using MyPrimaryElectron = MyPrimaryElectrons::iterator; - -struct PhotonHBT { - // Configurables - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - - Configurable fConfigPCMCuts{"cfgPCMCuts", "qc", "Comma separated list of V0 photon cuts"}; - Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_all_tpchadrejortofreq_prompt", "Comma separated list of DalitzEE cuts"}; - Configurable fConfigPHOSCuts{"cfgPHOSCuts", "test02,test03", "Comma separated list of PHOS photon cuts"}; - Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; - Configurable fConfigDo3D{"cfgDo3D", false, "Flag to analyze 3D BE correlation"}; // it is very heavy. - Configurable maxY_dielectron{"maxY_dielectron", 0.9, "maximum rapidity for dielectron"}; - - Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; - static constexpr std::string_view event_types[2] = {"before", "after"}; - - OutputObj fOutputEvent{"Event"}; - OutputObj fOutputPair{"Pair"}; // 2-photon pair - THashList* fMainList = new THashList(); - - std::vector fPCMCuts; - std::vector fDalitzEECuts; - std::vector fPHOSCuts; - std::vector fPairCuts; - - std::vector fPairNames; - - Service ccdb; - int mRunNumber; - float d_bz; - - void init(InitContext& context) - { - if (context.mOptions.get("processPCMPCM")) { - fPairNames.push_back("PCMPCM"); - } - if (context.mOptions.get("processPCMDalitzEE")) { - fPairNames.push_back("PCMDalitzEE"); - } - if (context.mOptions.get("processDalitzEEDalitzEE")) { - fPairNames.push_back("DalitzEEDalitzEE"); - } - if (context.mOptions.get("processPHOSPHOS")) { - fPairNames.push_back("PHOSPHOS"); - } - if (context.mOptions.get("processPCMPHOS")) { - fPairNames.push_back("PCMPHOS"); - } - - DefinePCMCuts(); - DefineDalitzEECuts(); - DefinePHOSCuts(); - DefinePairCuts(); - addhistograms(); - TString ev_cut_name = fConfigEMEventCut.value; - fEMEventCut = *eventcuts::GetCut(ev_cut_name.Data()); - - fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); - fOutputPair.setObject(reinterpret_cast(fMainList->FindObject("Pair"))); - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - mRunNumber = collision.runNumber(); - return; - } - - auto run3grp_timestamp = collision.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = collision.runNumber(); - } - - template - void add_pair_histograms(THashList* list_pair, const std::string pairname, TCuts1 const& cuts1, TCuts2 const& cuts2, TCuts3 const& cuts3) - { - for (auto& cut1 : cuts1) { - for (auto& cut2 : cuts2) { - std::string cutname1 = cut1.GetName(); - std::string cutname2 = cut2.GetName(); - - if ((pairname == "PCMPCM" || pairname == "PHOSPHOS" || pairname == "EMCEMC" || pairname == "DalitzEEDalitzEE") && (cutname1 != cutname2)) { - continue; - } - - THashList* list_pair_subsys = reinterpret_cast(list_pair->FindObject(pairname.data())); - std::string photon_cut_name = cutname1 + "_" + cutname2; - o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys, photon_cut_name.data()); - THashList* list_pair_subsys_photoncut = reinterpret_cast(list_pair_subsys->FindObject(photon_cut_name.data())); - - for (auto& cut3 : cuts3) { - std::string pair_cut_name = cut3.GetName(); - o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys_photoncut, pair_cut_name.data()); - THashList* list_pair_subsys_paircut = reinterpret_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); - if (fConfigDo3D) { - o2::aod::pwgem::photon::histogram::DefineHistograms(list_pair_subsys_paircut, "photon_hbt", "3d"); - } else { - o2::aod::pwgem::photon::histogram::DefineHistograms(list_pair_subsys_paircut, "photon_hbt", "1d"); - } - } // end of pair cut3 loop - } // end of cut2 loop - } // end of cut1 loop - } - - static constexpr std::string_view pairnames[9] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitzEE", "PCMDalitzMuMu", "PHOSEMC", "DalitzEEDalitzEE"}; - void addhistograms() - { - fMainList->SetOwner(true); - fMainList->SetName("fMainList"); - - // create sub lists first. - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Event"); - THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); - - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Pair"); - THashList* list_pair = reinterpret_cast(fMainList->FindObject("Pair")); - - for (auto& pairname : fPairNames) { - LOGF(info, "Enabled pairs = %s", pairname.data()); - - THashList* list_ev_pair = reinterpret_cast(o2::aod::pwgem::photon::histogram::AddHistClass(list_ev, pairname.data())); - for (const auto& evtype : event_types) { - THashList* list_ev_type = reinterpret_cast(o2::aod::pwgem::photon::histogram::AddHistClass(list_ev_pair, evtype.data())); - o2::aod::pwgem::photon::histogram::DefineHistograms(list_ev_type, "Event", evtype.data()); - } - - o2::aod::pwgem::photon::histogram::AddHistClass(list_pair, pairname.data()); - - if (pairname == "PCMPCM") { - add_pair_histograms(list_pair, pairname, fPCMCuts, fPCMCuts, fPairCuts); - } - if (pairname == "PCMDalitzEE") { - add_pair_histograms(list_pair, pairname, fPCMCuts, fDalitzEECuts, fPairCuts); - } - if (pairname == "DalitzEEDalitzEE") { - add_pair_histograms(list_pair, pairname, fDalitzEECuts, fDalitzEECuts, fPairCuts); - } - if (pairname == "PHOSPHOS") { - add_pair_histograms(list_pair, pairname, fPHOSCuts, fPHOSCuts, fPairCuts); - } - if (pairname == "PCMPHOS") { - add_pair_histograms(list_pair, pairname, fPCMCuts, fPHOSCuts, fPairCuts); - } - - } // end of pair name loop - } - - void DefinePCMCuts() - { - TString cutNamesStr = fConfigPCMCuts.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); - fPCMCuts.push_back(*pcmcuts::GetCut(cutname)); - } - } - LOGF(info, "Number of PCM cuts = %d", fPCMCuts.size()); - } - - void DefineDalitzEECuts() - { - TString cutNamesStr = fConfigDalitzEECuts.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); - fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); - } - } - LOGF(info, "Number of DalitzEE cuts = %d", fDalitzEECuts.size()); - } - - void DefinePHOSCuts() - { - TString cutNamesStr = fConfigPHOSCuts.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); - fPHOSCuts.push_back(*phoscuts::GetCut(cutname)); - } - } - LOGF(info, "Number of PHOS cuts = %d", fPHOSCuts.size()); - } - - void DefinePairCuts() - { - TString cutNamesStr = fConfigPairCuts.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); - fPairCuts.push_back(*paircuts::GetCut(cutname)); - } - } - LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); - } - - template - bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) - { - bool is_selected_pair = false; - if constexpr (pairtype == PairType::kPCMPCM) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); - } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); - } else if constexpr (pairtype == PairType::kDalitzEEDalitzEE) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); - } else if constexpr (pairtype == PairType::kPHOSPHOS) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); // dummy, because track matching is not ready. - } else if constexpr (pairtype == PairType::kPCMPHOS) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); - } else { - is_selected_pair = true; - } - return is_selected_pair; - } - - template - void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& /*legs*/, TEMPrimaryElectrons const& /*emprimaryelectrons*/) - { - THashList* list_ev_pair_before = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[0].data())); - THashList* list_ev_pair_after = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[1].data())); - THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); - - for (auto& collision : collisions) { - initCCDB(collision); - - if ((pairtype == kPHOSPHOS || pairtype == kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { - continue; - } - - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - o2::aod::pwgem::photon::histogram::FillHistClass(list_ev_pair_before, "", collision); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photon::histogram::FillHistClass(list_ev_pair_after, "", collision); - reinterpret_cast(list_ev_pair_before->FindObject("hCollisionCounter"))->Fill("accepted", 1.f); - reinterpret_cast(list_ev_pair_after->FindObject("hCollisionCounter"))->Fill("accepted", 1.f); - - auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); - // LOGF(info, "photons1_coll.size() = %d, photons2_coll.size() = %d", photons1_coll.size(), photons2_coll.size()); - - float dca_pos1_3d = 999.f, dca_ele1_3d = 999.f, dca_ee1_3d = 999.f; - float dca_pos2_3d = 999.f, dca_ele2_3d = 999.f, dca_ee2_3d = 999.f; - - double values_1d[6] = {0.f}; - double values_3d[10] = {0.f}; - if constexpr (pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC || pairtype == PairType::kDalitzEEDalitzEE) { - for (auto& cut : cuts1) { - for (auto& paircut : paircuts) { - for (auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_coll, photons2_coll))) { - - if constexpr (pairtype == PairType::kDalitzEEDalitzEE) { - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - std::tuple pair1 = std::make_tuple(pos1, ele1, d_bz); - std::tuple pair2 = std::make_tuple(pos2, ele2, d_bz); - if (!IsSelectedPair(pair1, pair2, cut, cut)) { - continue; - } - } else { - if (!IsSelectedPair(g1, g2, cut, cut)) { - continue; - } - } - - if (!paircut.IsSelected(g1, g2)) { - continue; - } - - values_1d[0] = 0.0, values_1d[1] = 0.0, values_1d[2] = 0.0, values_1d[3] = 0.0; - values_3d[0] = 0.0, values_3d[1] = 0.0, values_3d[2] = 0.0, values_3d[3] = 0.0; - // center-of-mass system (CMS) - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - if constexpr (pairtype == PairType::kDalitzEEDalitzEE) { - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { - continue; - } - v1.SetM(g1.mass()); - v2.SetM(g2.mass()); - values_1d[0] = g1.mass(); - values_1d[1] = g2.mass(); - values_3d[0] = g1.mass(); - values_3d[1] = g2.mass(); - - dca_pos1_3d = dca3DinSigma(pos1); - dca_ele1_3d = dca3DinSigma(ele1); - dca_ee1_3d = std::sqrt((dca_pos1_3d * dca_pos1_3d + dca_ele1_3d * dca_ele1_3d) / 2.); - values_1d[2] = dca_ee1_3d; - values_3d[2] = dca_ee1_3d; - - dca_pos2_3d = dca3DinSigma(pos2); - dca_ele2_3d = dca3DinSigma(ele2); - dca_ee2_3d = std::sqrt((dca_pos2_3d * dca_pos2_3d + dca_ele2_3d * dca_ele2_3d) / 2.); - values_1d[3] = dca_ee2_3d; - values_3d[3] = dca_ee2_3d; - } - - ROOT::Math::PtEtaPhiMVector q12 = v1 - v2; - ROOT::Math::PtEtaPhiMVector k12 = 0.5 * (v1 + v2); - float qinv = -q12.M(); - float kt = k12.Pt(); - - values_1d[4] = kt; - values_1d[5] = qinv; - - if (fConfigDo3D) { - // float qt = q12.Pt(); - float qlong_cms = q12.Pz(); - - ROOT::Math::XYZVector q_3d = q12.Vect(); // 3D q vector - ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); // unit vector for out. i.e. parallel to kt - ROOT::Math::XYZVector uv_long(0, 0, 1); // unit vector for long, beam axis - ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); // unit vector for side - float qout_cms = q_3d.Dot(uv_out); - float qside_cms = q_3d.Dot(uv_side); - - // longitudinally co-moving system (LCMS) - ROOT::Math::PxPyPzEVector v1_cartesian(v1.Px(), v1.Py(), v1.Pz(), v1.E()); - ROOT::Math::PxPyPzEVector v2_cartesian(v2.Px(), v2.Py(), v2.Pz(), v2.E()); - ROOT::Math::PxPyPzEVector q12_cartesian = v1_cartesian - v2_cartesian; - float beta_z = (v1 + v2).Pz() / (v1 + v2).E(); - ROOT::Math::Boost bst_z(0, 0, -beta_z); // Boost supports only PxPyPzEVector - ROOT::Math::PxPyPzEVector q12_lcms = bst_z(q12_cartesian); - float qlong_lcms = q12_lcms.Pz(); - - // ROOT::Math::PxPyPzEVector v1_lcms_cartesian = bst_z(v1_cartesian); - // ROOT::Math::PxPyPzEVector v2_lcms_cartesian = bst_z(v2_cartesian); - // ROOT::Math::PxPyPzEVector q12_lcms_cartesian = bst_z(q12_cartesian); - // LOGF(info, "q12.Pz() = %f, q12_cartesian.Pz() = %f",q12.Pz(), q12_cartesian.Pz()); - // LOGF(info, "v1.Pz() = %f, v2.Pz() = %f",v1.Pz(), v2.Pz()); - // LOGF(info, "v1_lcms_cartesian.Pz() = %f, v2_lcms_cartesian.Pz() = %f",v1_lcms_cartesian.Pz(), v2_lcms_cartesian.Pz()); - // LOGF(info, "q12_lcms_cartesian.Pz() = %f", q12_lcms_cartesian.Pz()); - values_3d[4] = kt; - values_3d[5] = qinv; - values_3d[6] = qlong_cms; - values_3d[7] = qout_cms; - values_3d[8] = qside_cms; - values_3d[9] = qlong_lcms; - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hs_q_same"))->Fill(values_3d); - } else { - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hs_q_same"))->Fill(values_1d); - } - } // end of combination - } // end of pair cut loop - } // end of cut loop - } else { // different subsystem pairs - for (auto& cut1 : cuts1) { - for (auto& cut2 : cuts2) { - for (auto& paircut : paircuts) { - for (auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photons1_coll, photons2_coll))) { - - if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto pos_pv = g2.template posTrack_as(); - auto ele_pv = g2.template negTrack_as(); - std::tuple pair2 = std::make_tuple(pos_pv, ele_pv, d_bz); - if (!IsSelectedPair(g1, pair2, cut1, cut2)) { - continue; - } - } else { - if (!IsSelectedPair(g1, g2, cut1, cut2)) { - continue; - } - } - - if (!paircut.IsSelected(g1, g2)) { - continue; - } - - if constexpr (pairtype == PairType::kPCMPHOS) { - auto pos = g1.template posTrack_as(); - auto ele = g1.template negTrack_as(); - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.2) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.2)) { - continue; - } - } - - values_1d[0] = 0.0, values_1d[1] = 0.0, values_1d[2] = 0.0, values_1d[3] = 0.0; - values_3d[0] = 0.0, values_3d[1] = 0.0, values_3d[2] = 0.0, values_3d[3] = 0.0; - // center-of-mass system (CMS) - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - v2.SetM(g2.mass()); - values_1d[1] = g2.mass(); - values_3d[1] = g2.mass(); - dca_pos2_3d = dca3DinSigma(pos2); - dca_ele2_3d = dca3DinSigma(ele2); - dca_ee2_3d = std::sqrt((dca_pos2_3d * dca_pos2_3d + dca_ele2_3d * dca_ele2_3d) / 2.); - values_1d[3] = dca_ee2_3d; - values_3d[3] = dca_ee2_3d; - } - ROOT::Math::PtEtaPhiMVector q12 = v1 - v2; - ROOT::Math::PtEtaPhiMVector k12 = 0.5 * (v1 + v2); - float qinv = -q12.M(); - float kt = k12.Pt(); - - values_1d[4] = kt; - values_1d[5] = qinv; - - if (fConfigDo3D) { - // float qt = q12.Pt(); - float qlong_cms = q12.Pz(); - - ROOT::Math::XYZVector q_3d = q12.Vect(); // 3D q vector - ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); // unit vector for out. i.e. parallel to kt - ROOT::Math::XYZVector uv_long(0, 0, 1); // unit vector for long, beam axis - ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); // unit vector for side - float qout_cms = q_3d.Dot(uv_out); - float qside_cms = q_3d.Dot(uv_side); - - // longitudinally co-moving system (LCMS) - ROOT::Math::PxPyPzEVector v1_cartesian(v1.Px(), v1.Py(), v1.Pz(), v1.E()); - ROOT::Math::PxPyPzEVector v2_cartesian(v2.Px(), v2.Py(), v2.Pz(), v2.E()); - ROOT::Math::PxPyPzEVector q12_cartesian = v1_cartesian - v2_cartesian; - float beta_z = (v1 + v2).Pz() / (v1 + v2).E(); - ROOT::Math::Boost bst_z(0, 0, -beta_z); // Boost supports only PxPyPzEVector - ROOT::Math::PxPyPzEVector q12_lcms = bst_z(q12_cartesian); - float qlong_lcms = q12_lcms.Pz(); - values_3d[4] = kt; - values_3d[5] = qinv; - values_3d[6] = qlong_cms; - values_3d[7] = qout_cms; - values_3d[8] = qside_cms; - values_3d[9] = qlong_lcms; - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_q_same"))->Fill(values_3d); - } else { - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_q_same"))->Fill(values_1d); - } - } // end of combination - } // end of pair cut loop - } // end of cut2 loop - } // end of cut1 loop - } - } // end of collision loop - } - - Configurable ndepth{"ndepth", 10, "depth for event mixing"}; - ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 999.f}, "Mixing bins - centrality"}; - using BinningType_M = ColumnBinningPolicy; - using BinningType_A = ColumnBinningPolicy; - using BinningType_C = ColumnBinningPolicy; - BinningType_M colBinning_M{{ConfVtxBins, ConfCentBins}, true}; - BinningType_A colBinning_A{{ConfVtxBins, ConfCentBins}, true}; - BinningType_C colBinning_C{{ConfVtxBins, ConfCentBins}, true}; - - template - void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& /*legs*/, TEMPrimaryElectrons const& /*emprimaryelectrons*/, TMixedBinning const& colBinning) - { - THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); - // LOGF(info, "Number of collisions after filtering: %d", collisions.size()); - for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ndepth, -1, collisions, collisions)) { // internally, CombinationsStrictlyUpperIndexPolicy(collisions, collisions) is called. - // LOGF(info, "Mixed event globalIndex: (%d, %d) , counter = %d, ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", collision1.globalIndex(), collision2.globalIndex(), nev, collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); - - const float centralities1[3] = {collision1.centFT0M(), collision1.centFT0A(), collision1.centFT0C()}; - const float centralities2[3] = {collision2.centFT0M(), collision2.centFT0A(), collision2.centFT0C()}; - - if (centralities1[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities1[cfgCentEstimator]) { - continue; - } - if (centralities2[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities2[cfgCentEstimator]) { - continue; - } - if (!fEMEventCut.IsSelected(collision1) || !fEMEventCut.IsSelected(collision2)) { - continue; - } - - auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.globalIndex()); - auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.globalIndex()); - // LOGF(info, "collision1: posZ = %f, numContrib = %d , sel8 = %d | collision2: posZ = %f, numContrib = %d , sel8 = %d", collision1.posZ(), collision1.numContrib(), collision1.sel8(), collision2.posZ(), collision2.numContrib(), collision2.sel8()); - - float dca_pos1_3d = 999.f, dca_ele1_3d = 999.f, dca_ee1_3d = 999.f; - float dca_pos2_3d = 999.f, dca_ele2_3d = 999.f, dca_ee2_3d = 999.f; - double values_1d[6] = {0.f}; - double values_3d[10] = {0.f}; - for (auto& cut1 : cuts1) { - for (auto& cut2 : cuts2) { - for (auto& paircut : paircuts) { - for (auto& [g1, g2] : combinations(soa::CombinationsFullIndexPolicy(photons_coll1, photons_coll2))) { - // LOGF(info, "Mixed event photon pair: (%d, %d) from events (%d, %d), photon event: (%d, %d)", g1.index(), g2.index(), collision1.index(), collision2.index(), g1.globalIndex(), g2.globalIndex()); - - if ((pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC || pairtype == PairType::kDalitzEEDalitzEE) && (TString(cut1.GetName()) != TString(cut2.GetName()))) { - continue; - } - - if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - std::tuple pair2 = std::make_tuple(pos2, ele2, d_bz); - if (!IsSelectedPair(g1, pair2, cut1, cut2)) { - continue; - } - } else if constexpr (pairtype == PairType::kDalitzEEDalitzEE) { - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - std::tuple pair1 = std::make_tuple(pos1, ele1, d_bz); - std::tuple pair2 = std::make_tuple(pos2, ele2, d_bz); - if (!IsSelectedPair(pair1, pair2, cut1, cut2)) { - continue; - } - } else { - if (!IsSelectedPair(g1, g2, cut1, cut2)) { - continue; - } - } - - // if (!paircut.IsSelected(g1, g2)) { - // continue; - // } - - // center-of-mass system (CMS) - values_1d[0] = 0.0, values_1d[1] = 0.0, values_1d[2] = 0.0, values_1d[3] = 0.0; - values_3d[0] = 0.0, values_3d[1] = 0.0, values_3d[2] = 0.0, values_3d[3] = 0.0; - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - v2.SetM(g2.mass()); - values_1d[1] = g2.mass(); - values_3d[1] = g2.mass(); - dca_pos2_3d = dca3DinSigma(pos2); - dca_ele2_3d = dca3DinSigma(ele2); - dca_ee2_3d = std::sqrt((dca_pos2_3d * dca_pos2_3d + dca_ele2_3d * dca_ele2_3d) / 2.); - values_1d[3] = dca_ee2_3d; - values_3d[3] = dca_ee2_3d; - } else if constexpr (pairtype == PairType::kDalitzEEDalitzEE) { - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - v1.SetM(g1.mass()); - v2.SetM(g2.mass()); - values_1d[0] = g1.mass(); - values_1d[1] = g2.mass(); - values_3d[0] = g1.mass(); - values_3d[1] = g2.mass(); - - dca_pos1_3d = dca3DinSigma(pos1); - dca_ele1_3d = dca3DinSigma(ele1); - dca_ee1_3d = std::sqrt((dca_pos1_3d * dca_pos1_3d + dca_ele1_3d * dca_ele1_3d) / 2.); - values_1d[2] = dca_ee1_3d; - values_3d[2] = dca_ee1_3d; - - dca_pos2_3d = dca3DinSigma(pos2); - dca_ele2_3d = dca3DinSigma(ele2); - dca_ee2_3d = std::sqrt((dca_pos2_3d * dca_pos2_3d + dca_ele2_3d * dca_ele2_3d) / 2.); - values_1d[3] = dca_ee2_3d; - values_3d[3] = dca_ee2_3d; - } - ROOT::Math::PtEtaPhiMVector q12 = v1 - v2; - ROOT::Math::PtEtaPhiMVector k12 = 0.5 * (v1 + v2); - float qinv = -q12.M(); - float kt = k12.Pt(); - values_1d[4] = kt; - values_1d[5] = qinv; - - if (fConfigDo3D) { - // float qt = q12.Pt(); - float qlong_cms = q12.Pz(); - - ROOT::Math::XYZVector q_3d = q12.Vect(); // 3D q vector - ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); // unit vector for out. i.e. parallel to kt - ROOT::Math::XYZVector uv_long(0, 0, 1); // unit vector for long, beam axis - ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); // unit vector for side - float qout_cms = q_3d.Dot(uv_out); - float qside_cms = q_3d.Dot(uv_side); - - // longitudinally co-moving system (LCMS) - ROOT::Math::PxPyPzEVector v1_cartesian(v1.Px(), v1.Py(), v1.Pz(), v1.E()); - ROOT::Math::PxPyPzEVector v2_cartesian(v2.Px(), v2.Py(), v2.Pz(), v2.E()); - ROOT::Math::PxPyPzEVector q12_cartesian = v1_cartesian - v2_cartesian; - float beta_z = (v1 + v2).Pz() / (v1 + v2).E(); - ROOT::Math::Boost bst_z(0, 0, -beta_z); // Boost supports only PxPyPzEVector - ROOT::Math::PxPyPzEVector q12_lcms = bst_z(q12_cartesian); - float qlong_lcms = q12_lcms.Pz(); - - values_3d[4] = kt; - values_3d[5] = qinv; - values_3d[6] = qlong_cms; - values_3d[7] = qout_cms; - values_3d[8] = qside_cms; - values_3d[9] = qlong_lcms; - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_q_mix"))->Fill(values_3d); - } else { - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_q_mix"))->Fill(values_1d); - } - - } // end of different photon combinations - } // end of pair cut loop - } // end of cut2 loop - } // end of cut1 loop - } // end of different collision combinations - } - - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - Preslice perCollision_dalitzee = aod::dalitzee::emeventId; - Preslice perCollision_phos = aod::skimmedcluster::collisionId; - - Filter eeFilter = o2::aod::dalitzee::sign == 0 && nabs(o2::aod::dalitzee::rapidity) < maxY_dielectron; // analyze only uls - using filteredMyDalitzEEs = soa::Filtered; - - Partition grouped_collisions = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); // this goes to same event. - - Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) || (o2::aod::emevent::neeuls >= 1); - using MyFilteredCollisions = soa::Filtered; - - void processPCMPCM(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) - { - SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr); - if (cfgCentEstimator == 0) { - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr, colBinning_M); - } else if (cfgCentEstimator == 1) { - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr, colBinning_A); - } else if (cfgCentEstimator == 2) { - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr, colBinning_C); - } - } - - void processPCMDalitzEE(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs, filteredMyDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons) - { - SameEventPairing(grouped_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitzee, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimaryelectrons); - if (cfgCentEstimator == 0) { - MixedEventPairing(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitzee, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimaryelectrons, colBinning_M); - } else if (cfgCentEstimator == 1) { - MixedEventPairing(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitzee, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimaryelectrons, colBinning_A); - } else if (cfgCentEstimator == 2) { - MixedEventPairing(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitzee, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimaryelectrons, colBinning_C); - } - } - - void processDalitzEEDalitzEE(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, filteredMyDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons) - { - SameEventPairing(grouped_collisions, dielectrons, dielectrons, perCollision_dalitzee, perCollision_dalitzee, fDalitzEECuts, fDalitzEECuts, fPairCuts, nullptr, emprimaryelectrons); - if (cfgCentEstimator == 0) { - MixedEventPairing(filtered_collisions, dielectrons, dielectrons, perCollision_dalitzee, perCollision_dalitzee, fDalitzEECuts, fDalitzEECuts, fPairCuts, nullptr, emprimaryelectrons, colBinning_M); - } else if (cfgCentEstimator == 1) { - MixedEventPairing(filtered_collisions, dielectrons, dielectrons, perCollision_dalitzee, perCollision_dalitzee, fDalitzEECuts, fDalitzEECuts, fPairCuts, nullptr, emprimaryelectrons, colBinning_A); - } else if (cfgCentEstimator == 2) { - MixedEventPairing(filtered_collisions, dielectrons, dielectrons, perCollision_dalitzee, perCollision_dalitzee, fDalitzEECuts, fDalitzEECuts, fPairCuts, nullptr, emprimaryelectrons, colBinning_C); - } - } - - void processPHOSPHOS(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, aod::PHOSClusters const& phosclusters) - { - SameEventPairing(grouped_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fPHOSCuts, fPHOSCuts, fPairCuts, nullptr, nullptr); - MixedEventPairing(filtered_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fPHOSCuts, fPHOSCuts, fPairCuts, nullptr, nullptr, colBinning_C); - } - - void processPCMPHOS(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::PHOSClusters const& phosclusters, aod::V0Legs const& legs) - { - SameEventPairing(grouped_collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr); - MixedEventPairing(filtered_collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr, colBinning_C); - } - - void processDummy(MyCollisions const&) {} - - PROCESS_SWITCH(PhotonHBT, processPCMPCM, "pairing PCM-PCM", false); - PROCESS_SWITCH(PhotonHBT, processPCMDalitzEE, "pairing PCM-DalitzEE", false); - PROCESS_SWITCH(PhotonHBT, processDalitzEEDalitzEE, "pairing DalitzEE-DalitzEE", false); - PROCESS_SWITCH(PhotonHBT, processPHOSPHOS, "pairing PHOS-PHOS", false); - PROCESS_SWITCH(PhotonHBT, processPCMPHOS, "pairing PCM-PHOS", false); - PROCESS_SWITCH(PhotonHBT, processDummy, "Dummy function", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"photon-hbt"})}; -} diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaEMCEMC.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaEMCEMC.cxx index 30ab6b734f2..3b7893f7373 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaEMCEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaEMCEMC.cxx @@ -32,6 +32,6 @@ using MyEMCCluster = MyEMCClusters::iterator; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-emcemc"}), + adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-emcemc"}), }; } diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCEMCEMC.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCEMCEMC.cxx index 3de63aaad4a..7cd7ba3c492 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCEMCEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCEMCEMC.cxx @@ -32,6 +32,6 @@ using MyEMCCluster = MyEMCClusters::iterator; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-mc-emcemc"}), + adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-mc-emcemc"}), }; } diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx index 6184e2a9984..2d929f1a82a 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx @@ -26,14 +26,14 @@ using namespace o2; using namespace o2::aod; -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -using MyMCV0Legs = soa::Join; -using MyMCV0Leg = MyMCV0Legs::iterator; - -using MyMCElectrons = soa::Join; -using MyMCElectron = MyMCElectrons::iterator; +// using MyV0Photons = soa::Join; +// using MyV0Photon = MyV0Photons::iterator; +// +// using MyMCV0Legs = soa::Join; +// using MyMCV0Leg = MyMCV0Legs::iterator; +// +// using MyMCElectrons = soa::Join; +// using MyMCElectron = MyMCElectrons::iterator; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx index 7fd5b53d03e..15ccbe72bd4 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx @@ -27,12 +27,6 @@ using namespace o2; using namespace o2::aod; -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -using MyPrimaryElectrons = soa::Join; -using MyPrimaryElectron = MyPrimaryElectrons::iterator; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx index 638a756fba3..24557c828a7 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx @@ -26,8 +26,8 @@ using namespace o2; using namespace o2::aod; -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; +// using MyV0Photons = soa::Join; +// using MyV0Photon = MyV0Photons::iterator; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index bae378ab8ff..ddf61e9765e 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -82,7 +82,7 @@ struct SinglePhoton { Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index 65ced5c85a4..ccb33db7f3a 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -39,13 +39,15 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::pwgem::mcutil; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; using MyCollisions = soa::Join; @@ -88,7 +90,7 @@ struct SinglePhotonMC { // Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; diff --git a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx index d41c4d744da..2f91a62dc43 100644 --- a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx +++ b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx @@ -42,10 +42,10 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; +using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -69,7 +69,7 @@ struct TagAndProbe { Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; @@ -341,8 +341,6 @@ struct TagAndProbe { for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ndepth, -1, collisions, collisions)) { // internally, CombinationsStrictlyUpperIndexPolicy(collisions, collisions) is called. - // LOGF(info, "Mixed event globalIndex: (%d, %d) , ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", collision1.globalIndex(), collision2.globalIndex(), collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); - const float centralities1[3] = {collision1.centFT0M(), collision1.centFT0A(), collision1.centFT0C()}; const float centralities2[3] = {collision2.centFT0M(), collision2.centFT0A(), collision2.centFT0C()}; @@ -478,7 +476,6 @@ struct TagAndProbe { Partition grouped_collisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) || (o2::aod::emevent::ngphos >= 1) || (o2::aod::emevent::ngemc >= 1); using MyFilteredCollisions = soa::Filtered; // this goes to mixed event. void processPCMPCM(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx index d5e7687cdf0..f12cf270290 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx @@ -45,10 +45,10 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; +using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -57,7 +57,7 @@ using MyV0Photon = MyV0Photons::iterator; using MyDalitzEEs = soa::Join; using MyDalitzEE = MyDalitzEEs::iterator; -using MyPrimaryElectrons = soa::Join; +using MyPrimaryElectrons = soa::Join; using MyPrimaryElectron = MyPrimaryElectrons::iterator; struct TaggingPi0 { @@ -93,7 +93,7 @@ struct TaggingPi0 { Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; @@ -350,11 +350,11 @@ struct TaggingPi0 { { bool is_selected_pair = false; if constexpr (pairtype == PairType::kPCMPHOS) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + is_selected_pair = o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMEMC) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + is_selected_pair = o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + is_selected_pair = o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else { is_selected_pair = true; } @@ -419,11 +419,11 @@ struct TaggingPi0 { auto pos = g1.template posTrack_as(); auto ele = g1.template negTrack_as(); if constexpr (pairtype == PairType::kPCMPHOS) { - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.2) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.2)) { + if (o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.2) || o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.2)) { continue; } } else if constexpr (pairtype == PairType::kPCMEMC) { - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.5) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.5)) { + if (o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.5) || o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.5)) { continue; } } @@ -463,9 +463,6 @@ struct TaggingPi0 { // LOGF(info, "Number of collisions after filtering: %d", collisions.size()); for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ndepth, -1, collisions, collisions)) { // internally, CombinationsStrictlyUpperIndexPolicy(collisions, collisions) is called. - // LOGF(info, "Mixed event globalIndex: (%d, %d) , counter = %d, ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", - // collision1.globalIndex(), collision2.globalIndex(), nev, collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); - const float centralities1[3] = {collision1.centFT0M(), collision1.centFT0A(), collision1.centFT0C()}; const float centralities2[3] = {collision2.centFT0M(), collision2.centFT0A(), collision2.centFT0C()}; @@ -539,7 +536,6 @@ struct TaggingPi0 { Partition grouped_collisions = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) || (o2::aod::emevent::ngphos >= 1) || (o2::aod::emevent::ngemc >= 1) || (o2::aod::emevent::neeuls >= 1); using MyFilteredCollisions = soa::Filtered; Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx index 80e4afa1dc7..3cf8a46a2b0 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx @@ -41,14 +41,16 @@ #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::photonpair; -using namespace o2::aod::pwgem::mcutil; +using namespace o2::aod::pwgem::photonmeson::photonpair; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; using MyCollisions = soa::Join; @@ -62,7 +64,7 @@ using MyDalitzEE = MyDalitzEEs::iterator; struct TaggingPi0MC { using MyMCV0Legs = soa::Join; - using MyMCTracks = soa::Join; + using MyMCTracks = soa::Join; using MyMCTrack = MyMCTracks::iterator; // Configurables @@ -99,7 +101,7 @@ struct TaggingPi0MC { Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; static constexpr std::string_view event_types[2] = {"before", "after"}; OutputObj fOutputEvent{"Event"}; @@ -365,11 +367,11 @@ struct TaggingPi0MC { { bool is_selected_pair = false; if constexpr (pairtype == PairType::kPCMPHOS) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + is_selected_pair = o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMEMC) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + is_selected_pair = o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + is_selected_pair = o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else { is_selected_pair = true; } @@ -491,11 +493,11 @@ struct TaggingPi0MC { if constexpr (pairtype == PairType::kPCMPHOS || pairtype == PairType::kPCMEMC) { if constexpr (pairtype == PairType::kPCMPHOS) { - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos1, g2, 0.02, 0.4, 0.2) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele1, g2, 0.02, 0.4, 0.2)) { + if (o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(pos1, g2, 0.02, 0.4, 0.2) || o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(ele1, g2, 0.02, 0.4, 0.2)) { continue; } } else if constexpr (pairtype == PairType::kPCMEMC) { - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos1, g2, 0.02, 0.4, 0.5) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele1, g2, 0.02, 0.4, 0.5)) { + if (o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(pos1, g2, 0.02, 0.4, 0.5) || o2::aod::pwgem::photonmeson::photonpair::DoesV0LegMatchWithCluster(ele1, g2, 0.02, 0.4, 0.5)) { continue; } } diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx index 05ca9b95508..e20116bc99f 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -25,28 +25,24 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Tools/ML/model.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::pwgem::photon; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; struct DalitzEEQC { @@ -62,7 +58,7 @@ struct DalitzEEQC { Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; @@ -82,8 +78,6 @@ struct DalitzEEQC { std::string prefix = "dileptoncut_group"; Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; Configurable cfg_max_mass{"cfg_max_mass", 0.5, "max mass"}; - Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", true, "flag to require ITS ib any hits"}; @@ -101,26 +95,11 @@ struct DalitzEEQC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPConly), "pid scheme [kTPConly : 0]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - - // CCDB configuration for PID ML - Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; - Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dileptoncuts; o2::ccdb::CcdbApi ccdbApi; @@ -130,7 +109,6 @@ struct DalitzEEQC { HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; - bool cfgDoFlow = false; void init(InitContext& /*context*/) { @@ -191,7 +169,7 @@ struct DalitzEEQC { void addhistograms() { // event info - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); // pair info std::vector ptbins; @@ -210,44 +188,29 @@ struct DalitzEEQC { } const AxisSpec axis_pt{ptbins, "p_{T,ee} (GeV/c)"}; - fRegistry.add("Pair/same/uls/hMvsPt", "m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {axis_mass, axis_pt}, true); - fRegistry.add("Pair/same/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, true); - fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); - fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.add("Pair/same/hMvsPt", "m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {axis_mass, axis_pt}, true); + fRegistry.add("Pair/same/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, true); fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {100, 0., 1000}}, false); - fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {100, 0., 1000}}, false); fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFbeta", "TOF beta;p_{in} (GeV/c);TOF #beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); - fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); } void DefineEMEventCut() { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); @@ -266,9 +229,7 @@ struct DalitzEEQC { // for pair fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.SetPairDCARange(dileptoncuts.cfg_min_pair_dca3d, dileptoncuts.cfg_max_pair_dca3d); // in sigma fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.ApplyPrefilter(dileptoncuts.cfg_apply_pf); fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); @@ -281,53 +242,24 @@ struct DalitzEEQC { fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMeanClusterSizeITSob(0, 16); fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaMuRange(dileptoncuts.cfg_min_TPCNsigmaMu, dileptoncuts.cfg_max_TPCNsigmaMu); fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTPCNsigmaKaRange(dileptoncuts.cfg_min_TPCNsigmaKa, dileptoncuts.cfg_max_TPCNsigmaKa); - fDileptonCut.SetTPCNsigmaPrRange(dileptoncuts.cfg_min_TPCNsigmaPr, dileptoncuts.cfg_max_TPCNsigmaPr); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut - o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); - if (dileptoncuts.loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - std::map metadata; - bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dileptoncuts.BDTPathCCDB.value, ".", metadata, dileptoncuts.timestampCCDB.value, false, dileptoncuts.BDTLocalPathGamma.value); - if (retrieveSuccessGamma) { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } else { - LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; - } - } else { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } - - fDileptonCut.SetPIDModel(eid_bdt); - } // end of PID ML } template - bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2) + bool fillPairInfo(TCollision const&, TTrack1 const& t1, TTrack2 const& t2) { if (t1.trackId() == t2.trackId()) { // this is protection against pairing identical 2 tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. return false; } - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { - if (!fDileptonCut.IsSelectedTrack(t1, collision) || !fDileptonCut.IsSelectedTrack(t2, collision)) { - return false; - } - } else { // cut-based - if (!fDileptonCut.IsSelectedTrack(t1) || !fDileptonCut.IsSelectedTrack(t2)) { - return false; - } + if (!fDileptonCut.IsSelectedTrack(t1) || !fDileptonCut.IsSelectedTrack(t2)) { + return false; } if (!fDileptonCut.IsSelectedPair(t1, t2, d_bz)) { @@ -340,17 +272,11 @@ struct DalitzEEQC { if (abs(v12.Rapidity()) > maxY) { return false; } - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); if (t1.sign() * t2.sign() < 0) { // ULS - fRegistry.fill(HIST("Pair/same/uls/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/same/uls/hMvsPhiV"), phiv, v12.M()); - } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ - fRegistry.fill(HIST("Pair/same/lspp/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/same/lspp/hMvsPhiV"), phiv, v12.M()); - } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- - fRegistry.fill(HIST("Pair/same/lsmm/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/same/lsmm/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/same/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/same/hMvsPhiV"), phiv, v12.M()); } if (t1.sign() > 0) { @@ -385,9 +311,6 @@ struct DalitzEEQC { fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); @@ -396,19 +319,9 @@ struct DalitzEEQC { fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); - fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); } Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); @@ -432,13 +345,13 @@ struct DalitzEEQC { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); if (!fEMEventCut.IsSelected(collision)) { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); @@ -447,12 +360,6 @@ struct DalitzEEQC { for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS fillPairInfo(collision, pos, ele); } - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - fillPairInfo(collision, pos1, pos2); - } - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- - fillPairInfo(collision, ele1, ele2); - } } // end of collision loop used_trackIds.clear(); diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx index aebcaa0914c..afa1bca2bd7 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -24,31 +24,28 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Tools/ML/model.h" #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::pwgem::mcutil; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::mcutil; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyMCTracks = soa::Join; +using MyMCTracks = soa::Join; using MyMCTrack = MyMCTracks::iterator; struct DalitzEEQCMC { @@ -65,7 +62,7 @@ struct DalitzEEQCMC { Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; @@ -85,8 +82,6 @@ struct DalitzEEQCMC { std::string prefix = "dileptoncut_group"; Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; - Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", true, "flag to require ITS ib any hits"}; @@ -104,26 +99,11 @@ struct DalitzEEQCMC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPConly), "pid scheme [kTPConly : 0]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - - // CCDB configuration for PID ML - Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; - Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dileptoncuts; o2::ccdb::CcdbApi ccdbApi; @@ -146,7 +126,7 @@ struct DalitzEEQCMC { void addhistograms() { // event info - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); std::vector ptbins; std::vector massbins; @@ -187,24 +167,12 @@ struct DalitzEEQCMC { fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {100, 0., 1000}}, false); - fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {100, 0., 1000}}, false); fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFbeta", "TOF beta;p_{in} (GeV/c);TOF #beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); - fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); @@ -213,7 +181,6 @@ struct DalitzEEQCMC { fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); } - bool cfgDoFlow = false; void init(InitContext&) { DefineEMEventCut(); @@ -270,7 +237,7 @@ struct DalitzEEQCMC { void DefineEMEventCut() { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); @@ -289,9 +256,7 @@ struct DalitzEEQCMC { // for pair fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.SetPairDCARange(dileptoncuts.cfg_min_pair_dca3d, dileptoncuts.cfg_max_pair_dca3d); // in sigma fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.ApplyPrefilter(dileptoncuts.cfg_apply_pf); fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); @@ -304,36 +269,13 @@ struct DalitzEEQCMC { fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMeanClusterSizeITSob(0, 16); fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaMuRange(dileptoncuts.cfg_min_TPCNsigmaMu, dileptoncuts.cfg_max_TPCNsigmaMu); fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTPCNsigmaKaRange(dileptoncuts.cfg_min_TPCNsigmaKa, dileptoncuts.cfg_max_TPCNsigmaKa); - fDileptonCut.SetTPCNsigmaPrRange(dileptoncuts.cfg_min_TPCNsigmaPr, dileptoncuts.cfg_max_TPCNsigmaPr); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut - o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); - if (dileptoncuts.loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - std::map metadata; - bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dileptoncuts.BDTPathCCDB.value, ".", metadata, dileptoncuts.timestampCCDB.value, false, dileptoncuts.BDTLocalPathGamma.value); - if (retrieveSuccessGamma) { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } else { - LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; - } - } else { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } - - fDileptonCut.SetPIDModel(eid_bdt); - } // end of PID ML } template @@ -365,16 +307,10 @@ struct DalitzEEQCMC { } template - bool fillTruePairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TMCParticles const& mcparticles) + bool fillTruePairInfo(TCollision const&, TTrack1 const& t1, TTrack2 const& t2, TMCParticles const& mcparticles) { - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { - if (!fDileptonCut.IsSelectedTrack(t1, collision) || !fDileptonCut.IsSelectedTrack(t2, collision)) { - return false; - } - } else { // cut-based - if (!fDileptonCut.IsSelectedTrack(t1) || !fDileptonCut.IsSelectedTrack(t2)) { - return false; - } + if (!fDileptonCut.IsSelectedTrack(t1) || !fDileptonCut.IsSelectedTrack(t2)) { + return false; } if (!fDileptonCut.IsSelectedPair(t1, t2, d_bz)) { @@ -395,10 +331,7 @@ struct DalitzEEQCMC { if (abs(v12.Rapidity()) > maxY) { return false; } - float dca_t1_3d = dca3DinSigma(t1); - float dca_t2_3d = dca3DinSigma(t2); - float dca_ee_3d = std::sqrt((dca_t1_3d * dca_t1_3d + dca_t2_3d * dca_t2_3d) / 2.); - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); if (mother_id > -1 && t1mc.pdgCode() * t2mc.pdgCode() < 0) { auto mcmother = mcparticles.iteratorAt(mother_id); @@ -435,7 +368,7 @@ struct DalitzEEQCMC { } else if (!(t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && !(t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { switch (abs(mcmother.pdgCode())) { case 22: - fRegistry.fill(HIST("Pair/sm/Photon/hMvsPt"), v12.M(), v12.Pt(), dca_ee_3d); + fRegistry.fill(HIST("Pair/sm/Photon/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/sm/Photon/hMvsPhiV"), phiv, v12.M()); break; default: @@ -479,9 +412,6 @@ struct DalitzEEQCMC { fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); @@ -493,16 +423,7 @@ struct DalitzEEQCMC { fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); - fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); } std::vector used_trackIds; @@ -529,13 +450,13 @@ struct DalitzEEQCMC { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); if (!fEMEventCut.IsSelected(collision)) { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); diff --git a/PWGEM/PhotonMeson/Tasks/dielectronQC.cxx b/PWGEM/PhotonMeson/Tasks/dielectronQC.cxx deleted file mode 100644 index a2c904d84a7..00000000000 --- a/PWGEM/PhotonMeson/Tasks/dielectronQC.cxx +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright 2019-2020 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 dalitz ee table for dalitz QC. -// Please write to: daiki.sekihata@cern.ch - -#include -#include -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "DCAFitter/DCAFitterN.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Tools/ML/model.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EMTrack.h" -#include "PWGEM/PhotonMeson/Utils/EventMixingHandler.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::photonmeson::utils::emtrack; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; - -using MyEMH = o2::aod::pwgem::photonmeson::utils::EventMixingHandler, std::pair, EMTrackWithCov>; - -struct dielectronQC { - - // Configurables - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable cfgDoFlow{"cfgDoFlow", false, "flag to analyze vn"}; - Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - Configurable ndepth{"ndepth", 10, "depth for event mixing"}; - ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; - ConfigurableAxis ConfEPBins{"ConfEPBins", {VARIABLE_WIDTH, -M_PI / 2, -M_PI / 4, 0.0f, +M_PI / 4, +M_PI / 2}, "Mixing bins - event plane angle"}; - ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - - ConfigurableAxis ConfMeeBins{"ConfMeeBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00}, "mee bins for output histograms"}; - ConfigurableAxis ConfPteeBins{"ConfPteeBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.50, 6.00, 6.50, 7.00, 7.50, 8.00, 8.50, 9.00, 9.50, 10.00}, "pTee bins for output histograms"}; - ConfigurableAxis ConfDCAeeBins{"ConfDCAeeBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAee bins for output histograms"}; - ConfigurableAxis ConfPCAeeBins{"ConfPCAeeBins", {VARIABLE_WIDTH, 0.0, 0.5, 1, 1.5, 2, 3, 4, 5}, "PCAee bins for output histograms in mm"}; - - EMEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; - Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; - } eventcuts; - - DalitzEECut fDileptonCut; - struct : ConfigurableGroup { - std::string prefix = "dileptoncut_group"; - Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; - Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; - Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; - Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; - Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; - Configurable cfg_require_itsib_any{"cfg_require_itsib_any", true, "flag to require ITS ib any hits"}; - Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; - Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; - Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", 0.9, "max eta for single track"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 70, "min ncrossed rows"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; - Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; - Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - - // CCDB configuration for PID ML - Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; - Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; - } dileptoncuts; - - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; - int mRunNumber; - float d_bz; - o2::vertexing::DCAFitterN<2> fitter; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; - static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; - - std::vector cent_bin_edges; - std::vector zvtx_bin_edges; - std::vector ep_bin_edges; - std::vector occ_bin_edges; - - void init(InitContext& /*context*/) - { - zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); - zvtx_bin_edges.erase(zvtx_bin_edges.begin()); - - cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); - cent_bin_edges.erase(cent_bin_edges.begin()); - - ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); - ep_bin_edges.erase(ep_bin_edges.begin()); - - occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); - occ_bin_edges.erase(occ_bin_edges.begin()); - - emh_pos = new MyEMH(ndepth); - emh_ele = new MyEMH(ndepth); - - DefineEMEventCut(); - DefineDileptonCut(); - addhistograms(); - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - fitter.setPropagateToPCA(true); - fitter.setMaxR(5.f); - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(true); - fitter.setWeightedFinalPCA(false); - fitter.setMatCorrType(matCorr); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - mRunNumber = collision.runNumber(); - fitter.setBz(d_bz); - return; - } - - auto run3grp_timestamp = collision.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = collision.runNumber(); - fitter.setBz(d_bz); - } - - ~dielectronQC() - { - delete emh_pos; - emh_pos = 0x0; - delete emh_ele; - emh_ele = 0x0; - - used_trackIds.clear(); - used_trackIds.shrink_to_fit(); - } - - void addhistograms() - { - // event info - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); - - // pair info - const AxisSpec axis_mass{ConfMeeBins, "m_{ee} (GeV/c^{2})"}; - const AxisSpec axis_pt{ConfPteeBins, "p_{T,ee} (GeV/c)"}; - const AxisSpec axis_dca{ConfDCAeeBins, "DCA_{ee}^{3D} (#sigma)"}; - const AxisSpec axis_pca{ConfPCAeeBins, "PCA (mm)"}; // particle closest approach - - fRegistry.add("Pair/same/uls/hs", "dielectron", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_pca}, true); - fRegistry.add("Pair/same/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, true); - fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); - fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); - fRegistry.addClone("Pair/same/", "Pair/mix/"); - - // for track info - fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); - fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxy_Pt", "DCA_{xy} vs. pT;p_{T} (GeV/c);DCA_{xy} (cm)", kTH2F, {{1000, 0, 10}, {200, -1, 1}}, false); - fRegistry.add("Track/hDCAz_Pt", "DCA_{z} vs. pT;p_{T} (GeV/c);DCA_{z} (cm)", kTH2F, {{1000, 0, 10}, {200, -1, 1}}, false); - fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFbeta", "TOF beta;p_{in} (GeV/c);TOF #beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); - fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); - } - - void DefineEMEventCut() - { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); - } - - void DefineDileptonCut() - { - fDileptonCut = DalitzEECut("fDileptonCut", "fDileptonCut"); - - // for pair - fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); - fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.SetPairDCARange(dileptoncuts.cfg_min_pair_dca3d, dileptoncuts.cfg_max_pair_dca3d); // in sigma - fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.ApplyPrefilter(dileptoncuts.cfg_apply_pf); - fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); - fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); - - // for track - fDileptonCut.SetTrackPtRange(dileptoncuts.cfg_min_pt_track, 1e+10f); - fDileptonCut.SetTrackEtaRange(-dileptoncuts.cfg_max_eta_track, +dileptoncuts.cfg_max_eta_track); - fDileptonCut.SetMinNClustersTPC(dileptoncuts.cfg_min_ncluster_tpc); - fDileptonCut.SetMinNCrossedRowsTPC(dileptoncuts.cfg_min_ncrossedrows); - fDileptonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); - fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); - fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMeanClusterSizeITSob(0, 16); - fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); - fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); - - // for eID - fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); - fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaMuRange(dileptoncuts.cfg_min_TPCNsigmaMu, dileptoncuts.cfg_max_TPCNsigmaMu); - fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTPCNsigmaKaRange(dileptoncuts.cfg_min_TPCNsigmaKa, dileptoncuts.cfg_max_TPCNsigmaKa); - fDileptonCut.SetTPCNsigmaPrRange(dileptoncuts.cfg_min_TPCNsigmaPr, dileptoncuts.cfg_max_TPCNsigmaPr); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut - o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); - if (dileptoncuts.loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - std::map metadata; - bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dileptoncuts.BDTPathCCDB.value, ".", metadata, dileptoncuts.timestampCCDB.value, false, dileptoncuts.BDTLocalPathGamma.value); - if (retrieveSuccessGamma) { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } else { - LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; - } - } else { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } - - fDileptonCut.SetPIDModel(eid_bdt); - } // end of PID ML - } - - template - bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2) - { - if constexpr (ev_id == 1) { - if (t1.has_ambiguousElectrons() && t2.has_ambiguousElectrons()) { - for (auto& possible_id1 : t1.ambiguousElectronsIds()) { - for (auto& possible_id2 : t2.ambiguousElectronsIds()) { - if (possible_id1 == possible_id2) { - // LOGF(info, "event id = %d: same track is found. t1.trackId() = %d, t1.collisionId() = %d, t1.pt() = %f, t1.eta() = %f, t1.phi() = %f, t2.trackId() = %d, t2.collisionId() = %d, t2.pt() = %f, t2.eta() = %f, t2.phi() = %f", ev_id, t1.trackId(), t1.collisionId(), t1.pt(), t1.eta(), t1.phi(), t2.trackId(), t2.collisionId(), t2.pt(), t2.eta(), t2.phi()); - return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. - } - } - } - } - } - - if constexpr (ev_id == 0) { - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { - if (!fDileptonCut.IsSelectedTrack(t1, collision) || !fDileptonCut.IsSelectedTrack(t2, collision)) { - return false; - } - } else { // cut-based - if (!fDileptonCut.IsSelectedTrack(t1) || !fDileptonCut.IsSelectedTrack(t2)) { - return false; - } - } - } - - if (!fDileptonCut.IsSelectedPair(t1, t2, d_bz)) { - return false; - } - - float pca = 999.f, lxy = 999.f; // in unit of cm - o2::aod::pwgem::dilepton::utils::pairutil::isSVFound(fitter, collision, t1, t2, pca, lxy); - - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (abs(v12.Rapidity()) > maxY) { - return false; - } - - float dca_t1_3d = dca3DinSigma(t1); - float dca_t2_3d = dca3DinSigma(t2); - float dca_ee_3d = std::sqrt((dca_t1_3d * dca_t1_3d + dca_t2_3d * dca_t2_3d) / 2.); - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); - - if (t1.sign() * t2.sign() < 0) { // ULS - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca * 10); - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsPhiV"), phiv, v12.M()); - } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca * 10); - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsPhiV"), phiv, v12.M()); - } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca * 10); - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsPhiV"), phiv, v12.M()); - } - - // store tracks for event mixing without double counting - if constexpr (ev_id == 0) { - std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); - std::pair pair_tmp_id1 = std::make_pair(ndf, t1.globalIndex()); - std::pair pair_tmp_id2 = std::make_pair(ndf, t2.globalIndex()); - - std::vector possibleIds1; - std::vector possibleIds2; - std::copy(t1.ambiguousElectronsIds().begin(), t1.ambiguousElectronsIds().end(), std::back_inserter(possibleIds1)); - std::copy(t2.ambiguousElectronsIds().begin(), t2.ambiguousElectronsIds().end(), std::back_inserter(possibleIds2)); - - if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id1) == used_trackIds.end()) { - used_trackIds.emplace_back(pair_tmp_id1); - fillTrackInfo(t1); - if (cfgDoMix) { - if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrackWithCov(t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, - t1.x(), t1.y(), t1.z(), t1.alpha(), t1.snp(), t1.tgl(), t1.cYY(), t1.cZY(), t1.cZZ(), - t1.cSnpY(), t1.cSnpZ(), t1.cSnpSnp(), t1.cTglY(), t1.cTglZ(), t1.cTglSnp(), t1.cTglTgl(), t1.c1PtY(), t1.c1PtZ(), t1.c1PtSnp(), t1.c1PtTgl(), t1.c1Pt21Pt2())); - } else { - emh_ele->AddTrackToEventPool(key_df_collision, EMTrackWithCov(t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, - t1.x(), t1.y(), t1.z(), t1.alpha(), t1.snp(), t1.tgl(), t1.cYY(), t1.cZY(), t1.cZZ(), - t1.cSnpY(), t1.cSnpZ(), t1.cSnpSnp(), t1.cTglY(), t1.cTglZ(), t1.cTglSnp(), t1.cTglTgl(), t1.c1PtY(), t1.c1PtZ(), t1.c1PtSnp(), t1.c1PtTgl(), t1.c1Pt21Pt2())); - } - } - } - if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id2) == used_trackIds.end()) { - used_trackIds.emplace_back(pair_tmp_id2); - fillTrackInfo(t2); - if (cfgDoMix) { - if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrackWithCov(t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds1, - t2.x(), t2.y(), t2.z(), t2.alpha(), t2.snp(), t2.tgl(), t2.cYY(), t2.cZY(), t2.cZZ(), - t2.cSnpY(), t2.cSnpZ(), t2.cSnpSnp(), t2.cTglY(), t2.cTglZ(), t2.cTglSnp(), t2.cTglTgl(), t2.c1PtY(), t2.c1PtZ(), t2.c1PtSnp(), t2.c1PtTgl(), t2.c1Pt21Pt2())); - } else { - emh_ele->AddTrackToEventPool(key_df_collision, EMTrackWithCov(t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds1, - t2.x(), t2.y(), t2.z(), t2.alpha(), t2.snp(), t2.tgl(), t2.cYY(), t2.cZY(), t2.cZZ(), - t2.cSnpY(), t2.cSnpZ(), t2.cSnpSnp(), t2.cTglY(), t2.cTglZ(), t2.cTglSnp(), t2.cTglTgl(), t2.c1PtY(), t2.c1PtZ(), t2.c1PtSnp(), t2.c1PtTgl(), t2.c1Pt21Pt2())); - } - } - } - } - return true; - } - - template - void fillTrackInfo(TTrack const& track) - { - fRegistry.fill(HIST("Track/hPt"), track.pt()); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); - fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); - fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); - fRegistry.fill(HIST("Track/hDCAxy_Pt"), track.pt(), track.dcaXY()); - fRegistry.fill(HIST("Track/hDCAz_Pt"), track.pt(), track.dcaZ()); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); - fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); - fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); - fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); - fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); - fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); - fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); - fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); - } - - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - using FilteredMyCollisions = soa::Filtered; - - SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectron::emeventId; - Filter trackFilter = static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && o2::aod::track::tpcChi2NCl < static_cast(dileptoncuts.cfg_max_chi2tpc) && o2::aod::track::itsChi2NCl < static_cast(dileptoncuts.cfg_max_chi2its) && nabs(o2::aod::track::dcaXY) < static_cast(dileptoncuts.cfg_max_dcaxy) && nabs(o2::aod::track::dcaZ) < static_cast(dileptoncuts.cfg_max_dcaz); - Filter pidFilter = (static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl)) && (o2::aod::pidtpc::tpcNSigmaPi < static_cast(dileptoncuts.cfg_min_TPCNsigmaPi) || static_cast(dileptoncuts.cfg_max_TPCNsigmaPi) < o2::aod::pidtpc::tpcNSigmaPi) && ((0.96f < o2::aod::pidtofbeta::beta && o2::aod::pidtofbeta::beta < 1.04f) || o2::aod::pidtofbeta::beta < 0.f); - using FilteredMyTracks = soa::Filtered; - using FilteredMyTrack = FilteredMyTracks::iterator; - - MyEMH* emh_pos = nullptr; - MyEMH* emh_ele = nullptr; - - Partition posTracks = o2::aod::emprimaryelectron::sign > int8_t(0); - Partition negTracks = o2::aod::emprimaryelectron::sign < int8_t(0); - - std::vector> used_trackIds; - int ndf = 0; - void processQC(FilteredMyCollisions const& collisions, FilteredMyTracks const& /*tracks*/) - { - for (auto& collision : collisions) { - initCCDB(collision); - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - // LOGF(info, "collision.globalIndex() = %d , collision.posZ() = %f , collision.numContrib() = %d, centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", collision.globalIndex(), collision.posZ(), collision.numContrib(), centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); - - int nuls = 0, nlspp = 0, nlsmm = 0; - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - bool is_pair_ok = fillPairInfo<0>(collision, pos, ele); - if (is_pair_ok) { - nuls++; - } - } - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - bool is_pair_ok = fillPairInfo<0>(collision, pos1, pos2); - if (is_pair_ok) { - nlspp++; - } - } - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- - bool is_pair_ok = fillPairInfo<0>(collision, ele1, ele2); - if (is_pair_ok) { - nlsmm++; - } - } - - if (!cfgDoMix || !(nuls > 0 || nlspp > 0 || nlsmm > 0)) { - continue; - } - - // event mixing - int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; - if (zbin < 0) { - zbin = 0; - } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { - zbin = static_cast(zvtx_bin_edges.size()) - 2; - } - - float centrality = centralities[cfgCentEstimator]; - int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; - if (centbin < 0) { - centbin = 0; - } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { - centbin = static_cast(cent_bin_edges.size()) - 2; - } - - float ep2 = collision.ep2ft0c(); - int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; - if (epbin < 0) { - epbin = 0; - } else if (static_cast(ep_bin_edges.size()) - 2 < epbin) { - epbin = static_cast(ep_bin_edges.size()) - 2; - } - - int occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - if (occbin < 0) { - occbin = 0; - } else if (static_cast(occ_bin_edges.size()) - 2 < occbin) { - occbin = static_cast(occ_bin_edges.size()) - 2; - } - - // LOGF(info, "collision.globalIndex() = %d, collision.posZ() = %f, centrality = %f, ep2 = %f, collision.trackOccupancyInTimeRange() = %d, zbin = %d, centbin = %d, epbin = %d, occbin = %d", collision.globalIndex(), collision.posZ(), centrality, ep2, collision.trackOccupancyInTimeRange(), zbin, centbin, epbin, occbin); - - std::tuple key_bin = std::make_tuple(zbin, centbin, epbin, occbin); - std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); - - // make a vector of selected photons in this collision. - auto selected_posTracks_in_this_event = emh_pos->GetTracksPerCollision(key_df_collision); - auto selected_negTracks_in_this_event = emh_ele->GetTracksPerCollision(key_df_collision); - // LOGF(info, "N selected tracks in current event (%d, %d), zvtx = %f, centrality = %f , npos = %d , nele = %d, nuls = %d , nlspp = %d, nlsmm = %d", ndf, collision.globalIndex(), collision.posZ(), centralities[cfgCentEstimator], selected_posTracks_in_this_event.size(), selected_negTracks_in_this_event.size(), nuls, nlspp, nlsmm); - - auto collisionIds_in_mixing_pool = emh_pos->GetCollisionIdsFromEventPool(key_bin); // pos/ele does not matter. - // LOGF(info, "collisionIds_in_mixing_pool.size() = %d", collisionIds_in_mixing_pool.size()); - - for (auto& mix_dfId_collisionId : collisionIds_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int mix_collisionId = mix_dfId_collisionId.second; - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto posTracks_from_event_pool = emh_pos->GetTracksPerCollision(mix_dfId_collisionId); - auto negTracks_from_event_pool = emh_ele->GetTracksPerCollision(mix_dfId_collisionId); - // LOGF(info, "Do event mixing: current event (%d, %d) | event pool (%d, %d), npos = %d , nele = %d", ndf, collision.globalIndex(), mix_dfId, mix_collisionId, posTracks_from_event_pool.size(), negTracks_from_event_pool.size()); - - for (auto& pos : selected_posTracks_in_this_event) { // ULS mix - for (auto& ele : negTracks_from_event_pool) { - fillPairInfo<1>(collision, pos, ele); - } - } - - for (auto& ele : selected_negTracks_in_this_event) { // ULS mix - for (auto& pos : posTracks_from_event_pool) { - fillPairInfo<1>(collision, ele, pos); - } - } - - for (auto& pos1 : selected_posTracks_in_this_event) { // LS++ mix - for (auto& pos2 : posTracks_from_event_pool) { - fillPairInfo<1>(collision, pos1, pos2); - } - } - - for (auto& ele1 : selected_negTracks_in_this_event) { // LS-- mix - for (auto& ele2 : negTracks_from_event_pool) { - fillPairInfo<1>(collision, ele1, ele2); - } - } - } // end of loop over mixed event pool - - if (nuls > 0 || nlspp > 0 || nlsmm > 0) { - emh_pos->AddCollisionIdAtLast(key_bin, key_df_collision); - emh_ele->AddCollisionIdAtLast(key_bin, key_df_collision); - } - - } // end of collision loop - - ndf++; - } // end of process - PROCESS_SWITCH(dielectronQC, processQC, "run dielectron QC", true); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(dielectronQC, processDummy, "Dummy function", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"dielectron-qc"})}; -} diff --git a/PWGEM/PhotonMeson/Tasks/dielectronQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dielectronQCMC.cxx deleted file mode 100644 index 19ae5cd63a8..00000000000 --- a/PWGEM/PhotonMeson/Tasks/dielectronQCMC.cxx +++ /dev/null @@ -1,1035 +0,0 @@ -// Copyright 2019-2020 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 dalitz ee table for dalitz QC. -// Please write to: daiki.sekihata@cern.ch - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Tools/ML/model.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "DCAFitter/DCAFitterN.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::mcutil; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::mcutil; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyMCTracks = soa::Join; -using MyMCTrack = MyMCTracks::iterator; - -struct dielectronQCMC { - - // Configurables - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - - ConfigurableAxis ConfMeeBins{"ConfMeeBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00}, "mee bins for output histograms"}; - ConfigurableAxis ConfPteeBins{"ConfPteeBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.50, 6.00, 6.50, 7.00, 7.50, 8.00, 8.50, 9.00, 9.50, 10.00}, "pTee bins for output histograms"}; - ConfigurableAxis ConfDCAeeBins{"ConfDCAeeBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAee bins for output histograms"}; - ConfigurableAxis ConfPCAeeBins{"ConfPCAeeBins", {VARIABLE_WIDTH, 0.0, 0.5, 1.0, 1.5, 2, 3, 4, 5}, "PCAee bins for output histograms in mm"}; - - EMEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; - Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; - } eventcuts; - - DalitzEECut fDileptonCut; - struct : ConfigurableGroup { - std::string prefix = "dileptoncut_group"; - Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; - Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; - Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; - Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; - Configurable cfg_apply_pf{"cfg_apply_pf", false, "flag to apply phiv prefilter"}; - Configurable cfg_require_itsib_any{"cfg_require_itsib_any", true, "flag to require ITS ib any hits"}; - Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; - Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; - Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", 0.9, "max eta for single track"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 70, "min ncrossed rows"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; - Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; - Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - - // CCDB configuration for PID ML - Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "pid_ml_xgboost.onnx", "Path to the local .onnx file"}; - Configurable BDTPathCCDB{"BDTPathCCDB", "Users/d/dsekihat/pwgem/pidml/", "Path on CCDB"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; - } dileptoncuts; - - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; - o2::vertexing::DCAFitterN<2> fitter; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - int mRunNumber; - float d_bz; - - struct : ConfigurableGroup { - std::string prefix = "mctrackcut_group"; - Configurable min_mcPt{"min_mcPt", 0.05, "min. MC pT"}; - Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT"}; - Configurable max_mcEta{"max_mcEta", 0.9, "max. MC eta"}; - } mctrackcuts; - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; - static constexpr std::string_view ele_source_types[9] = {"lf/", "Photon/", "PromptJPsi/", "NonPromptJPsi/", "PromptPsi2S/", "NonPromptPsi2S/", "c2e/", "b2e/", "b2c2e/"}; - - ~dielectronQCMC() {} - - void addhistograms() - { - // event info - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); - - const AxisSpec axis_mass{ConfMeeBins, "m_{ee} (GeV/c^{2})"}; - const AxisSpec axis_pt{ConfPteeBins, "p_{T,ee} (GeV/c)"}; - const AxisSpec axis_dca{ConfDCAeeBins, "DCA_{ee}^{3D} (#sigma)"}; - const AxisSpec axis_pca{ConfPCAeeBins, "PCA (mm)"}; // particle closest approach - - // generated info - fRegistry.add("Generated/sm/Pi0/hMvsPt", "m_{ee} vs. p_{T,ee} ULS", kTH2F, {axis_mass, axis_pt}, true); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Eta/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/EtaPrime/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Rho/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Omega/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/Phi/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/PromptJPsi/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/NonPromptJPsi/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/PromptPsi2S/"); - fRegistry.addClone("Generated/sm/Pi0/", "Generated/sm/NonPromptPsi2S/"); - - fRegistry.add("Generated/ccbar/c2e_c2e/hadron_hadron/hMvsPt", "m_{ee} vs. p_{T,ee}", kTH2F, {axis_mass, axis_pt}, true); - fRegistry.addClone("Generated/ccbar/c2e_c2e/hadron_hadron/", "Generated/ccbar/c2e_c2e/meson_meson/"); - fRegistry.addClone("Generated/ccbar/c2e_c2e/hadron_hadron/", "Generated/ccbar/c2e_c2e/baryon_baryon/"); - fRegistry.addClone("Generated/ccbar/c2e_c2e/hadron_hadron/", "Generated/ccbar/c2e_c2e/meson_baryon/"); - fRegistry.addClone("Generated/ccbar/c2e_c2e/", "Generated/bbbar/b2e_b2e/"); - fRegistry.addClone("Generated/ccbar/c2e_c2e/", "Generated/bbbar/b2c2e_b2c2e/"); - fRegistry.addClone("Generated/ccbar/c2e_c2e/", "Generated/bbbar/b2c2e_b2e_sameb/"); - fRegistry.addClone("Generated/ccbar/c2e_c2e/", "Generated/bbbar/b2c2e_b2e_diffb/"); // LS - - // reconstructed pair info - fRegistry.add("Pair/sm/Photon/hs", "hs pair", kTHnSparseF, {axis_mass, axis_pt, axis_dca, axis_pca}, true); - fRegistry.add("Pair/sm/Photon/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 0.1f}}, false); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Pi0/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Eta/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/EtaPrime/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Rho/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Omega/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Phi/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/PromptJPsi/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/NonPromptJPsi/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/PromptPsi2S/"); - fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/NonPromptPsi2S/"); - - fRegistry.add("Pair/ccbar/c2e_c2e/hadron_hadron/hs", "hs pair", kTHnSparseF, {axis_mass, axis_pt, axis_dca, axis_pca}, true); - fRegistry.addClone("Pair/ccbar/c2e_c2e/hadron_hadron/", "Pair/ccbar/c2e_c2e/meson_meson/"); - fRegistry.addClone("Pair/ccbar/c2e_c2e/hadron_hadron/", "Pair/ccbar/c2e_c2e/baryon_baryon/"); - fRegistry.addClone("Pair/ccbar/c2e_c2e/hadron_hadron/", "Pair/ccbar/c2e_c2e/meson_baryon/"); - fRegistry.addClone("Pair/ccbar/c2e_c2e/", "Pair/bbbar/b2e_b2e/"); - fRegistry.addClone("Pair/ccbar/c2e_c2e/", "Pair/bbbar/b2c2e_b2c2e/"); - fRegistry.addClone("Pair/ccbar/c2e_c2e/", "Pair/bbbar/b2c2e_b2e_sameb/"); - fRegistry.addClone("Pair/ccbar/c2e_c2e/", "Pair/bbbar/b2c2e_b2e_diffb/"); // LS - - // track info - fRegistry.add("Track/lf/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/lf/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/lf/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); - fRegistry.add("Track/lf/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/lf/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxy_Pt", "DCA_{xy} vs. pT;p_{T} (GeV/c);DCA_{xy} (cm)", kTH2F, {{1000, 0, 10}, {200, -1, 1}}, false); - fRegistry.add("Track/hDCAz_Pt", "DCA_{z} vs. pT;p_{T} (GeV/c);DCA_{z} (cm)", kTH2F, {{1000, 0, 10}, {200, -1, 1}}, false); - fRegistry.add("Track/lf/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/lf/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/lf/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/lf/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/lf/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/lf/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("Track/lf/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTOFbeta", "TOF beta;p_{in} (GeV/c);TOF #beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); - fRegistry.add("Track/lf/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/lf/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/lf/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/lf/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/lf/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/lf/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/lf/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); - fRegistry.addClone("Track/lf/", "Track/Photon/"); - fRegistry.addClone("Track/lf/", "Track/PromptJPsi/"); - fRegistry.addClone("Track/lf/", "Track/NonPromptJPsi/"); - fRegistry.addClone("Track/lf/", "Track/PromptPsi2S/"); - fRegistry.addClone("Track/lf/", "Track/NonPromptPsi2S/"); - fRegistry.addClone("Track/lf/", "Track/c2e/"); - fRegistry.addClone("Track/lf/", "Track/b2e/"); - fRegistry.addClone("Track/lf/", "Track/b2c2e/"); - } - - bool cfgDoFlow = false; - void init(InitContext&) - { - DefineEMEventCut(); - DefineDileptonCut(); - addhistograms(); - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - fitter.setPropagateToPCA(true); - fitter.setMaxR(5.f); - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(true); - fitter.setWeightedFinalPCA(false); - fitter.setMatCorrType(matCorr); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - mRunNumber = collision.runNumber(); - fitter.setBz(d_bz); - return; - } - - auto run3grp_timestamp = collision.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = collision.runNumber(); - fitter.setBz(d_bz); - } - - void DefineEMEventCut() - { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); - } - - void DefineDileptonCut() - { - fDileptonCut = DalitzEECut("fDileptonCut", "fDileptonCut"); - - // for pair - fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); - fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.SetPairDCARange(dileptoncuts.cfg_min_pair_dca3d, dileptoncuts.cfg_max_pair_dca3d); // in sigma - fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.ApplyPrefilter(dileptoncuts.cfg_apply_pf); - fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); - fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); - - // for track - fDileptonCut.SetTrackPtRange(dileptoncuts.cfg_min_pt_track, 1e+10f); - fDileptonCut.SetTrackEtaRange(-dileptoncuts.cfg_max_eta_track, +dileptoncuts.cfg_max_eta_track); - fDileptonCut.SetMinNClustersTPC(dileptoncuts.cfg_min_ncluster_tpc); - fDileptonCut.SetMinNCrossedRowsTPC(dileptoncuts.cfg_min_ncrossedrows); - fDileptonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); - fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); - fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMeanClusterSizeITSob(0, 16); - fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); - fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); - - // for eID - fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); - fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaMuRange(dileptoncuts.cfg_min_TPCNsigmaMu, dileptoncuts.cfg_max_TPCNsigmaMu); - fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTPCNsigmaKaRange(dileptoncuts.cfg_min_TPCNsigmaKa, dileptoncuts.cfg_max_TPCNsigmaKa); - fDileptonCut.SetTPCNsigmaPrRange(dileptoncuts.cfg_min_TPCNsigmaPr, dileptoncuts.cfg_max_TPCNsigmaPr); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut - o2::ml::OnnxModel* eid_bdt = new o2::ml::OnnxModel(); - if (dileptoncuts.loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - std::map metadata; - bool retrieveSuccessGamma = ccdbApi.retrieveBlob(dileptoncuts.BDTPathCCDB.value, ".", metadata, dileptoncuts.timestampCCDB.value, false, dileptoncuts.BDTLocalPathGamma.value); - if (retrieveSuccessGamma) { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } else { - LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; - } - } else { - eid_bdt->initModel(dileptoncuts.BDTLocalPathGamma.value, dileptoncuts.enableOptimizations.value); - } - - fDileptonCut.SetPIDModel(eid_bdt); - } // end of PID ML - } - - template - int FindLF(TTrack const& posmc, TTrack const& elemc, TMCParticles const& mcparticles) - { - int arr[] = { - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 111, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 221, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 331, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 113, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 223, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 333, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 443, mcparticles), - FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 100443, mcparticles)}; - int size = sizeof(arr) / sizeof(*arr); - int max = *std::max_element(arr, arr + size); - return max; - } - - template - bool isInAcceptance(T const& t1) - { - if ((mctrackcuts.min_mcPt < t1.pt() && t1.pt() < mctrackcuts.max_mcPt) && abs(t1.eta()) < mctrackcuts.max_mcEta) { - return true; - } else { - return false; - } - } - - template - bool fillTruePairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TMCParticles const& mcparticles) - { - if (dileptoncuts.cfg_pid_scheme == static_cast(DalitzEECut::PIDSchemes::kPIDML)) { - if (!fDileptonCut.IsSelectedTrack(t1, collision) || !fDileptonCut.IsSelectedTrack(t2, collision)) { - return false; - } - } else { // cut-based - if (!fDileptonCut.IsSelectedTrack(t1) || !fDileptonCut.IsSelectedTrack(t2)) { - return false; - } - } - - if (!fDileptonCut.IsSelectedPair(t1, t2, d_bz)) { - return false; - } - - float pca = 999.f, lxy = 999.f; // in unit of cm - o2::aod::pwgem::dilepton::utils::pairutil::isSVFound(fitter, collision, t1, t2, pca, lxy); - - auto t1mc = t1.template emmcparticle_as(); - auto t2mc = t2.template emmcparticle_as(); - - int mother_id = FindLF(t1mc, t2mc, mcparticles); - int hfee_type = IsHF(t1mc, t2mc, mcparticles); - if (mother_id < 0 && hfee_type < 0) { - return false; - } - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - if (abs(v12.Rapidity()) > maxY) { - return false; - } - - float dca_t1_3d = dca3DinSigma(t1); - float dca_t2_3d = dca3DinSigma(t2); - float dca_ee_3d = std::sqrt((dca_t1_3d * dca_t1_3d + dca_t2_3d * dca_t2_3d) / 2.); - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); - - if (mother_id > -1 && t1mc.pdgCode() * t2mc.pdgCode() < 0) { - auto mcmother = mcparticles.iteratorAt(mother_id); - if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { - if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { - switch (abs(mcmother.pdgCode())) { - case 111: - fRegistry.fill(HIST("Pair/sm/Pi0/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/Pi0/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<0>(t1); - fillTrackInfo<0>(t2); - break; - case 221: - fRegistry.fill(HIST("Pair/sm/Eta/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/Eta/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<0>(t1); - fillTrackInfo<0>(t2); - break; - case 331: - fRegistry.fill(HIST("Pair/sm/EtaPrime/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/EtaPrime/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<0>(t1); - fillTrackInfo<0>(t2); - break; - case 113: - fRegistry.fill(HIST("Pair/sm/Rho/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/Rho/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<0>(t1); - fillTrackInfo<0>(t2); - break; - case 223: - fRegistry.fill(HIST("Pair/sm/Omega/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/Omega/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<0>(t1); - fillTrackInfo<0>(t2); - break; - case 333: - fRegistry.fill(HIST("Pair/sm/Phi/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/Phi/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<0>(t1); - fillTrackInfo<0>(t2); - break; - case 443: { - if (IsFromBeauty(mcmother, mcparticles) > 0) { - fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<3>(t1); - fillTrackInfo<3>(t2); - } else { - fRegistry.fill(HIST("Pair/sm/PromptJPsi/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/PromptJPsi/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<2>(t1); - fillTrackInfo<2>(t2); - } - break; - } - case 100443: { - if (IsFromBeauty(mcmother, mcparticles) > 0) { - fRegistry.fill(HIST("Pair/sm/NonPromptPsi2S/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/NonPromptPsi2S/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<5>(t1); - fillTrackInfo<5>(t2); - } else { - fRegistry.fill(HIST("Pair/sm/PromptPsi2S/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/PromptPsi2S/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<4>(t1); - fillTrackInfo<4>(t2); - } - break; - } - default: - break; - } - - } else if (!(t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && !(t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { - switch (abs(mcmother.pdgCode())) { - case 22: - fRegistry.fill(HIST("Pair/sm/Photon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fRegistry.fill(HIST("Pair/sm/Photon/hMvsPhiV"), phiv, v12.M()); - fillTrackInfo<1>(t1); - fillTrackInfo<1>(t2); - break; - default: - break; - } - } // end of primary/secondary selection - } // end of primary selection for same mother - } else if (hfee_type > -1) { - if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { - auto mp1 = mcparticles.iteratorAt(t1mc.mothersIds()[0]); - auto mp2 = mcparticles.iteratorAt(t2mc.mothersIds()[0]); - if (t1mc.pdgCode() * t2mc.pdgCode() < 0) { // ULS - switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): { - fRegistry.fill(HIST("Pair/ccbar/c2e_c2e/hadron_hadron/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - if (isCharmMeson(mp1) && isCharmMeson(mp2)) { - fRegistry.fill(HIST("Pair/ccbar/c2e_c2e/meson_meson/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<6>(t1); - fillTrackInfo<6>(t2); - } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { - fRegistry.fill(HIST("Pair/ccbar/c2e_c2e/baryon_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<6>(t1); - fillTrackInfo<6>(t2); - } else { - fRegistry.fill(HIST("Pair/ccbar/c2e_c2e/meson_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<6>(t1); - fillTrackInfo<6>(t2); - } - break; - } - case static_cast(EM_HFeeType::kBe_Be): { - fRegistry.fill(HIST("Pair/bbbar/b2e_b2e/hadron_hadron/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - if (isBeautyMeson(mp1) && isBeautyMeson(mp2)) { - fRegistry.fill(HIST("Pair/bbbar/b2e_b2e/meson_meson/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<7>(t1); - fillTrackInfo<7>(t2); - } else if (isBeautyBaryon(mp1) && isBeautyBaryon(mp2)) { - fRegistry.fill(HIST("Pair/bbbar/b2e_b2e/baryon_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<7>(t1); - fillTrackInfo<7>(t2); - } else { - fRegistry.fill(HIST("Pair/bbbar/b2e_b2e/meson_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<7>(t1); - fillTrackInfo<7>(t2); - } - break; - } - case static_cast(EM_HFeeType::kBCe_BCe): { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2c2e/hadron_hadron/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - if (isCharmMeson(mp1) && isCharmMeson(mp2)) { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2c2e/meson_meson/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<8>(t1); - fillTrackInfo<8>(t2); - } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2c2e/baryon_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<8>(t1); - fillTrackInfo<8>(t2); - } else { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2c2e/meson_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - fillTrackInfo<8>(t1); - fillTrackInfo<8>(t2); - } - break; - } - case static_cast(EM_HFeeType::kBCe_Be_SameB): { // ULS - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_sameb/hadron_hadron/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_sameb/meson_meson/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_sameb/baryon_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - } else { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_sameb/meson_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - } - if ((isCharmMeson(mp1) || isCharmBaryon(mp1)) && (isBeautyMeson(mp2) || isBeautyBaryon(mp2))) { - fillTrackInfo<7>(t1); - fillTrackInfo<8>(t2); - } else { - fillTrackInfo<8>(t1); - fillTrackInfo<7>(t2); - } - break; - } - case static_cast(EM_HFeeType::kBCe_Be_DiffB): // LS - LOGF(info, "You should not see kBCe_Be_DiffB in ULS. Good luck."); - break; - default: - break; - } - } else { // LS - switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): - LOGF(info, "You should not see kCe_Ce in LS. Good luck."); - break; - case static_cast(EM_HFeeType::kBe_Be): - LOGF(info, "You should not see kBe_Be in LS. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_BCe): - LOGF(info, "You should not see kBCe_BCe in LS. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_Be_SameB): // ULS - LOGF(info, "You should not see kBCe_Be_SameB in LS. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_Be_DiffB): { // LS - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_diffb/hadron_hadron/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_diffb/meson_meson/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_diffb/baryon_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - } else { - fRegistry.fill(HIST("Pair/bbbar/b2c2e_b2e_diffb/meson_baryon/hs"), v12.M(), v12.Pt(), dca_ee_3d, pca); - } - if ((isCharmMeson(mp1) || isCharmBaryon(mp1)) && (isBeautyMeson(mp2) || isBeautyBaryon(mp2))) { - fillTrackInfo<7>(t1); - fillTrackInfo<8>(t2); - } else { - fillTrackInfo<8>(t1); - fillTrackInfo<7>(t2); - } - break; - } - default: - break; - } - } - } - } // end of HF evaluation - return true; - } - - template - void fillTrackInfo(TTrack const& track) - { - // fill track info that belong to true pairs. - if (std::find(used_trackIds.begin(), used_trackIds.end(), track.globalIndex()) == used_trackIds.end()) { - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hPt"), track.pt()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hQoverPt"), track.sign() / track.pt()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hEtaPhi"), track.phi(), track.eta()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hDCAxy_Pt"), track.pt(), track.dcaXY()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hDCAz_Pt"), track.pt(), track.dcaZ()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hDCAzRes_Pt"), track.pt(), sqrt(track.cZZ()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hNcrTPC"), track.tpcNClsCrossedRows()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hChi2TPC"), track.tpcChi2NCl()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hChi2ITS"), track.itsChi2NCl()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hMeanClusterSizeITS"), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTOFbeta"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/") + HIST(ele_source_types[e_source_id]) + HIST("hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); - used_trackIds.emplace_back(track.globalIndex()); - } - } - - std::vector used_trackIds; - SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectron::emeventId; - Filter trackFilter = static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && o2::aod::track::tpcChi2NCl < static_cast(dileptoncuts.cfg_max_chi2tpc) && o2::aod::track::itsChi2NCl < static_cast(dileptoncuts.cfg_max_chi2its) && nabs(o2::aod::track::dcaXY) < static_cast(dileptoncuts.cfg_max_dcaxy) && nabs(o2::aod::track::dcaZ) < static_cast(dileptoncuts.cfg_max_dcaz); - Filter pidFilter = (static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl)) && (o2::aod::pidtpc::tpcNSigmaPi < static_cast(dileptoncuts.cfg_min_TPCNsigmaPi) || static_cast(dileptoncuts.cfg_max_TPCNsigmaPi) < o2::aod::pidtpc::tpcNSigmaPi) && ((0.96f < o2::aod::pidtofbeta::beta && o2::aod::pidtofbeta::beta < 1.04f) || o2::aod::pidtofbeta::beta < 0.f); - using FilteredMyMCTracks = soa::Filtered; - Partition posTracks = o2::aod::emprimaryelectron::sign > int8_t(0); - Partition negTracks = o2::aod::emprimaryelectron::sign < int8_t(0); - - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - using FilteredMyCollisions = soa::Filtered; - - void processQCMC(FilteredMyCollisions const& collisions, FilteredMyMCTracks const& tracks, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const&) - { - used_trackIds.reserve(tracks.size()); - - for (auto& collision : collisions) { - initCCDB(collision); - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); - - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - fillTruePairInfo(collision, pos, ele, mcparticles); - } // end of ULS pair loop - - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - fillTruePairInfo(collision, pos1, pos2, mcparticles); - } // end of ULS pair loop - - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS__ - fillTruePairInfo(collision, ele1, ele2, mcparticles); - } // end of ULS pair loop - - } // end of collision loop - - used_trackIds.clear(); - used_trackIds.shrink_to_fit(); - - } // end of process - PROCESS_SWITCH(dielectronQCMC, processQCMC, "run dielectron QC MC", true); - - Partition posTracksMC = o2::aod::mcparticle::pdgCode == -11; // e+ - Partition negTracksMC = o2::aod::mcparticle::pdgCode == +11; // e- - PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; - void processGen(MyCollisions const& collisions, aod::EMMCEvents const&, aod::EMMCParticles const& mcparticles) - { - // loop over mc stack and fill histograms for pure MC truth signals - // all MC tracks which belong to the MC event corresponding to the current reconstructed event - - for (auto& collision : collisions) { - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - auto mccollision = collision.emmcevent_as(); - - auto posTracks_per_coll = posTracksMC->sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); - auto negTracks_per_coll = negTracksMC->sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); - - for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); - - if (!isInAcceptance(t1) || !isInAcceptance(t2)) { - continue; - } - - if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { - continue; - } - if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { - continue; - } - - int mother_id = FindLF(t1, t2, mcparticles); - int hfee_type = IsHF(t1, t2, mcparticles); - if (mother_id < 0 && hfee_type < 0) { - continue; - } - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - if (abs(v12.Rapidity()) > maxY) { - continue; - } - - if (mother_id > -1) { - auto mcmother = mcparticles.iteratorAt(mother_id); - if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { - - switch (abs(mcmother.pdgCode())) { - case 111: - fRegistry.fill(HIST("Generated/sm/Pi0/hMvsPt"), v12.M(), v12.Pt()); - break; - case 221: - fRegistry.fill(HIST("Generated/sm/Eta/hMvsPt"), v12.M(), v12.Pt()); - break; - case 331: - fRegistry.fill(HIST("Generated/sm/EtaPrime/hMvsPt"), v12.M(), v12.Pt()); - break; - case 113: - fRegistry.fill(HIST("Generated/sm/Rho/hMvsPt"), v12.M(), v12.Pt()); - break; - case 223: - fRegistry.fill(HIST("Generated/sm/Omega/hMvsPt"), v12.M(), v12.Pt()); - break; - case 333: - fRegistry.fill(HIST("Generated/sm/Phi/hMvsPt"), v12.M(), v12.Pt()); - break; - case 443: { - if (IsFromBeauty(mcmother, mcparticles) > 0) { - fRegistry.fill(HIST("Generated/sm/NonPromptJPsi/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/sm/PromptJPsi/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - case 100443: { - if (IsFromBeauty(mcmother, mcparticles) > 0) { - fRegistry.fill(HIST("Generated/sm/NonPromptPsi2S/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/sm/PromptPsi2S/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - default: - break; - } - } - } else if (hfee_type > -1) { - auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); - auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); - switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): { - fRegistry.fill(HIST("Generated/ccbar/c2e_c2e/hadron_hadron/hMvsPt"), v12.M(), v12.Pt()); - if (isCharmMeson(mp1) && isCharmMeson(mp2)) { - fRegistry.fill(HIST("Generated/ccbar/c2e_c2e/meson_meson/hMvsPt"), v12.M(), v12.Pt()); - } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { - fRegistry.fill(HIST("Generated/ccbar/c2e_c2e/baryon_baryon/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/ccbar/c2e_c2e/meson_baryon/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - case static_cast(EM_HFeeType::kBe_Be): { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/hadron_hadron/hMvsPt"), v12.M(), v12.Pt()); - if (isBeautyMeson(mp1) && isBeautyMeson(mp2)) { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/meson_meson/hMvsPt"), v12.M(), v12.Pt()); - } else if (isBeautyBaryon(mp1) && isBeautyBaryon(mp2)) { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/baryon_baryon/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/meson_baryon/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - case static_cast(EM_HFeeType::kBCe_BCe): { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2c2e/hadron_hadron/hMvsPt"), v12.M(), v12.Pt()); - if (isCharmMeson(mp1) && isCharmMeson(mp2)) { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/meson_meson/hMvsPt"), v12.M(), v12.Pt()); - } else if (isCharmBaryon(mp1) && isCharmBaryon(mp2)) { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/baryon_baryon/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/bbbar/b2e_b2e/meson_baryon/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - case static_cast(EM_HFeeType::kBCe_Be_SameB): { // ULS - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_sameb/hadron_hadron/hMvsPt"), v12.M(), v12.Pt()); - if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_sameb/meson_meson/hMvsPt"), v12.M(), v12.Pt()); - } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_sameb/baryon_baryon/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_sameb/meson_baryon/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - case static_cast(EM_HFeeType::kBCe_Be_DiffB): // LS - LOGF(info, "You should not see kBCe_Be_DiffB in ULS. Good luck."); - break; - default: - break; - } - } // end of HF evaluation - } // end of true ULS pair loop - - for (auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { - // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); - - if (!isInAcceptance(t1) || !isInAcceptance(t2)) { - continue; - } - - if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { - continue; - } - if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { - continue; - } - - int hfee_type = IsHF(t1, t2, mcparticles); - if (hfee_type < 0) { - continue; - } - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (abs(v12.Rapidity()) > maxY) { - continue; - } - if (hfee_type > -1) { - auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); - auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); - switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): - LOGF(info, "You should not see kCe_Ce in LS++. Good luck."); - break; - case static_cast(EM_HFeeType::kBe_Be): - LOGF(info, "You should not see kBe_Be in LS++. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_BCe): - LOGF(info, "You should not see kBCe_BCe in LS++. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_Be_SameB): // ULS - LOGF(info, "You should not see kBCe_Be_SameB in LS++. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_Be_DiffB): { // LS - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/hadron_hadron/hMvsPt"), v12.M(), v12.Pt()); - if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/meson_meson/hMvsPt"), v12.M(), v12.Pt()); - } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/baryon_baryon/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/meson_baryon/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - default: - break; - } - } - } // end of true LS++ pair loop - - for (auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { - // LOGF(info, "pdg1 = %d, pdg2 = %d", t1.pdgCode(), t2.pdgCode()); - - if (!isInAcceptance(t1) || !isInAcceptance(t2)) { - continue; - } - - if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { - continue; - } - if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { - continue; - } - - int hfee_type = IsHF(t1, t2, mcparticles); - if (hfee_type < 0) { - continue; - } - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (abs(v12.Rapidity()) > maxY) { - continue; - } - if (hfee_type > -1) { - auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); - auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); - switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): - LOGF(info, "You should not see kCe_Ce in LS--. Good luck."); - break; - case static_cast(EM_HFeeType::kBe_Be): - LOGF(info, "You should not see kBe_Be in LS--. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_BCe): - LOGF(info, "You should not see kBCe_BCe in LS--. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_Be_SameB): // ULS - LOGF(info, "You should not see kBCe_Be_SameB in LS--. Good luck."); - break; - case static_cast(EM_HFeeType::kBCe_Be_DiffB): { // LS - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/hadron_hadron/hMvsPt"), v12.M(), v12.Pt()); - if ((isCharmMeson(mp1) && isBeautyMeson(mp2)) || (isCharmMeson(mp2) && isBeautyMeson(mp1))) { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/meson_meson/hMvsPt"), v12.M(), v12.Pt()); - } else if ((isCharmBaryon(mp1) && isBeautyBaryon(mp2)) || (isCharmBaryon(mp2) && isBeautyBaryon(mp1))) { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/baryon_baryon/hMvsPt"), v12.M(), v12.Pt()); - } else { - fRegistry.fill(HIST("Generated/bbbar/b2c2e_b2e_diffb/meson_baryon/hMvsPt"), v12.M(), v12.Pt()); - } - break; - } - default: - break; - } - } - } // end of true LS++ pair loop - - } // end of collision loop - } - PROCESS_SWITCH(dielectronQCMC, processGen, "run genrated info", true); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(dielectronQCMC, processDummy, "Dummy function", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"dielectron-qc-mc"})}; -} diff --git a/PWGEM/PhotonMeson/Tasks/dimuonQC.cxx b/PWGEM/PhotonMeson/Tasks/dimuonQC.cxx deleted file mode 100644 index 2dab2c2bcac..00000000000 --- a/PWGEM/PhotonMeson/Tasks/dimuonQC.cxx +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright 2019-2020 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. -// -// ======================== -// -// Analysis task for dimuon. -// Please write to: daiki.sekihata@cern.ch - -#include -#include -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" - -#include "DCAFitter/FwdDCAFitterN.h" -#include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" -#include "TGeoGlobalMagField.h" -#include "Field/MagneticField.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DimuonCut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EMFwdTrack.h" -#include "PWGEM/PhotonMeson/Utils/EventMixingHandler.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::photonmeson::utils::emfwdtrack; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; - -using MyEMH = o2::aod::pwgem::photonmeson::utils::EventMixingHandler, std::pair, EMFwdTrackWithCov>; - -struct dimuonQC { - - // Configurables - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable cfgDoFlow{"cfgDoFlow", false, "flag to analyze vn"}; - Configurable minY{"minY", -4.0, "minimum rapidity for reconstructed pairs"}; - Configurable maxY{"maxY", -2.5, "maximum rapidity for reconstructed pairs"}; - Configurable ndepth{"ndepth", 10, "depth for event mixing"}; - ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; - ConfigurableAxis ConfEPBins{"ConfEPBins", {VARIABLE_WIDTH, -M_PI / 2, -M_PI / 4, 0.0f, +M_PI / 4, +M_PI / 2}, "Mixing bins - event plane angle"}; - ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - - ConfigurableAxis ConfMmumuBins{"ConfMmumuBins", {VARIABLE_WIDTH, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.25, 3.30, 3.35, 3.40, 3.45, 3.50, 3.55, 3.60, 3.65, 3.70, 3.75, 3.80, 3.85, 3.90, 3.95, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.10, 5.20, 5.30, 5.40, 5.50, 5.60, 5.70, 5.80, 5.90, 6.00, 6.10, 6.20, 6.30, 6.40, 6.50, 6.60, 6.70, 6.80, 6.90, 7.00, 7.10, 7.20, 7.30, 7.40, 7.50, 7.60, 7.70, 7.80, 7.90, 8.00, 8.10, 8.20, 8.30, 8.40, 8.50, 8.60, 8.70, 8.80, 8.90, 9.00, 9.10, 9.20, 9.30, 9.40, 9.50, 9.60, 9.70, 9.80, 9.90, 10.00, 10.10, 10.20, 10.30, 10.40, 10.50, 10.60, 10.70, 10.80, 10.90, 11.00, 11.10, 11.20, 11.30, 11.40, 11.50, 11.60, 11.70, 11.80, 11.90, 12.00}, "mmumu bins for output histograms"}; - ConfigurableAxis ConfPtmumuBins{"ConfPtmumuBins", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.50, 6.00, 6.50, 7.00, 7.50, 8.00, 8.50, 9.00, 9.50, 10.00}, "pTmumu bins for output histograms"}; - ConfigurableAxis ConfDCAmumuBins{"ConfDCAmumuBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAmumu bins for output histograms"}; - ConfigurableAxis ConfPCAmumuBins{"ConfPCAmumuBins", {VARIABLE_WIDTH, 0.0, 0.5, 1, 1.5, 2, 3, 4, 5}, "PCAmumu bins for output histograms in mm"}; - - EMEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; - Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; - } eventcuts; - - DimuonCut fDimuonCut; - struct : ConfigurableGroup { - std::string prefix = "dimuoncut_group"; - Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; - Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; - Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; - Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; - Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; - Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; - - Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; - Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; - Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; - Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; - Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; - Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; - Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; - Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; - } dimuoncuts; - - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; - int mRunNumber; - float d_bz; - o2::vertexing::FwdDCAFitterN<2> fitter; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; - static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; - - std::vector cent_bin_edges; - std::vector zvtx_bin_edges; - std::vector ep_bin_edges; - std::vector occ_bin_edges; - - void init(InitContext& /*context*/) - { - zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); - zvtx_bin_edges.erase(zvtx_bin_edges.begin()); - - cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); - cent_bin_edges.erase(cent_bin_edges.begin()); - - ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); - ep_bin_edges.erase(ep_bin_edges.begin()); - - occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); - occ_bin_edges.erase(occ_bin_edges.begin()); - - emh_pos = new MyEMH(ndepth); - emh_neg = new MyEMH(ndepth); - - DefineEMEventCut(); - DefineDimuonCut(); - addhistograms(); - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - fitter.setPropagateToPCA(true); - fitter.setMaxR(90.f); - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(true); - fitter.setTGeoMat(false); - // fitter.setMatCorrType(matCorr); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - mRunNumber = collision.runNumber(); - fitter.setBz(d_bz); - return; - } - - auto run3grp_timestamp = collision.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = collision.runNumber(); - fitter.setBz(d_bz); - - o2::base::Propagator::initFieldFromGRP(grpmag); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); - } - o2::mch::TrackExtrap::setField(); - } - - ~dimuonQC() - { - delete emh_pos; - emh_pos = 0x0; - delete emh_neg; - emh_neg = 0x0; - - used_trackIds.clear(); - used_trackIds.shrink_to_fit(); - } - - void addhistograms() - { - // event info - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry, cfgDoFlow); - - // pair info - const AxisSpec axis_mass{ConfMmumuBins, "m_{#mu#mu} (GeV/c^{2})"}; - const AxisSpec axis_pt{ConfPtmumuBins, "p_{T,#mu#mu} (GeV/c)"}; - const AxisSpec axis_dca{ConfDCAmumuBins, "DCA_{#mu#mu}^{xy} (#sigma)"}; - const AxisSpec axis_pca{ConfPCAmumuBins, "PCA (mm)"}; // particle closest approach - - fRegistry.add("Pair/same/uls/hs", "dimuon", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_pca}, true); - fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); - fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); - fRegistry.addClone("Pair/same/", "Pair/mix/"); - - // for track info - fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {25, -4.5f, -2.0f}}, false); - fRegistry.add("Track/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); - fRegistry.add("Track/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxySigma", "DCA x vs. y;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxRes_Pt", "DCA_{x} resolution vs. pT;p_{T} (GeV/c);DCA_{x} resolution (#mum)", kTH2F, {{1000, 0, 10}, {200, 0., 200}}, false); - fRegistry.add("Track/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", kTH2F, {{1000, 0, 10}, {200, 0., 200}}, false); - fRegistry.add("Track/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); - fRegistry.add("Track/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); - fRegistry.add("Track/hPDCA", "pDCA;p_{T} at PV (GeV/c);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 10}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); - } - - void DefineEMEventCut() - { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); - } - - void DefineDimuonCut() - { - fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); - - // for pair - fDimuonCut.SetMassRange(dimuoncuts.cfg_min_mass, dimuoncuts.cfg_max_mass); - fDimuonCut.SetPairPtRange(dimuoncuts.cfg_min_pair_pt, dimuoncuts.cfg_max_pair_pt); - fDimuonCut.SetPairDCAxyRange(dimuoncuts.cfg_min_pair_dcaxy, dimuoncuts.cfg_max_pair_dcaxy); // DCAxy in cm - - // for track - fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); - fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, 1e10f); - fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_eta_track, dimuoncuts.cfg_max_eta_track); - fDimuonCut.SetNClustersMFT(dimuoncuts.cfg_min_ncluster_mft, 10); - fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 16); - fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); - fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); - fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); - fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); - fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); - } - - template - bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2) - { - if constexpr (ev_id == 1) { - if (t1.has_ambiguousMuons() && t2.has_ambiguousMuons()) { - for (auto& possible_id1 : t1.ambiguousMuonsIds()) { - for (auto& possible_id2 : t2.ambiguousMuonsIds()) { - if (possible_id1 == possible_id2) { - // LOGF(info, "event id = %d: same track is found. t1.fwdtrackId() = %d, t1.collisionId() = %d, t1.pt() = %f, t1.eta() = %f, t1.phi() = %f, t2.fwdtrackId() = %d, t2.collisionId() = %d, t2.pt() = %f, t2.eta() = %f, t2.phi() = %f", ev_id, t1.fwdtrackId(), t1.collisionId(), t1.pt(), t1.eta(), t1.phi(), t2.fwdtrackId(), t2.collisionId(), t2.pt(), t2.eta(), t2.phi()); - return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. - } - } - } - } - } - - if constexpr (ev_id == 0) { - if (!fDimuonCut.IsSelectedTrack(t1) || !fDimuonCut.IsSelectedTrack(t2)) { - return false; - } - } - - if (!fDimuonCut.IsSelectedPair(t1, t2)) { - return false; - } - - float pca = 999.f, lxy = 999.f; // in unit of cm - o2::aod::pwgem::dilepton::utils::pairutil::isSVFoundFwd(fitter, collision, t1, t2, pca, lxy); - - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (v12.Rapidity() < minY || maxY < v12.Rapidity()) { - return false; - } - - float dca_xy_t1 = fwdDcaXYinSigma(t1); - float dca_xy_t2 = fwdDcaXYinSigma(t2); - float dca_mumu_xy = std::sqrt((dca_xy_t1 * dca_xy_t1 + dca_xy_t2 * dca_xy_t2) / 2.); - - if (t1.sign() * t2.sign() < 0) { // ULS - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), dca_mumu_xy, pca * 10); - } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), dca_mumu_xy, pca * 10); - } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), dca_mumu_xy, pca * 10); - } - - // store tracks for event mixing without double counting - if constexpr (ev_id == 0) { - std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); - std::pair pair_tmp_id1 = std::make_pair(ndf, t1.globalIndex()); - std::pair pair_tmp_id2 = std::make_pair(ndf, t2.globalIndex()); - - std::vector possibleIds1; - std::vector possibleIds2; - std::copy(t1.ambiguousMuonsIds().begin(), t1.ambiguousMuonsIds().end(), std::back_inserter(possibleIds1)); - std::copy(t2.ambiguousMuonsIds().begin(), t2.ambiguousMuonsIds().end(), std::back_inserter(possibleIds2)); - - if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id1) == used_trackIds.end()) { - used_trackIds.emplace_back(pair_tmp_id1); - fillTrackInfo(t1); - if (cfgDoMix) { - if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, - t1.x(), t1.y(), t1.z(), t1.tgl(), t1.cXX(), t1.cXY(), t1.cYY(), - t1.cPhiX(), t1.cPhiY(), t1.cPhiPhi(), t1.cTglX(), t1.cTglY(), t1.cTglPhi(), t1.cTglTgl(), t1.c1PtX(), t1.c1PtY(), t1.c1PtPhi(), t1.c1PtTgl(), t1.c1Pt21Pt2(), t1.chi2())); - } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, - t1.x(), t1.y(), t1.z(), t1.tgl(), t1.cXX(), t1.cXY(), t1.cYY(), - t1.cPhiX(), t1.cPhiY(), t1.cPhiPhi(), t1.cTglX(), t1.cTglY(), t1.cTglPhi(), t1.cTglTgl(), t1.c1PtX(), t1.c1PtY(), t1.c1PtPhi(), t1.c1PtTgl(), t1.c1Pt21Pt2(), t1.chi2())); - } - } - } - if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id2) == used_trackIds.end()) { - used_trackIds.emplace_back(pair_tmp_id2); - fillTrackInfo(t2); - if (cfgDoMix) { - if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, - t2.x(), t2.y(), t2.z(), t2.tgl(), t2.cXX(), t2.cXY(), t2.cYY(), - t2.cPhiX(), t2.cPhiY(), t2.cPhiPhi(), t2.cTglX(), t2.cTglY(), t2.cTglPhi(), t2.cTglTgl(), t2.c1PtX(), t2.c1PtY(), t2.c1PtPhi(), t2.c1PtTgl(), t2.c1Pt21Pt2(), t2.chi2())); - } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrackWithCov(t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, - t2.x(), t2.y(), t2.z(), t2.tgl(), t2.cXX(), t2.cXY(), t2.cYY(), - t2.cPhiX(), t2.cPhiY(), t2.cPhiPhi(), t2.cTglX(), t2.cTglY(), t2.cTglPhi(), t2.cTglTgl(), t2.c1PtX(), t2.c1PtY(), t2.c1PtPhi(), t2.c1PtTgl(), t2.c1Pt21Pt2(), t2.chi2())); - } - } - } - } - return true; - } - - template - void fillTrackInfo(TTrack const& track) - { - fRegistry.fill(HIST("Track/hPt"), track.pt()); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); - fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); - fRegistry.fill(HIST("Track/hTrackType"), track.trackType()); - fRegistry.fill(HIST("Track/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/hDCAxySigma"), track.fwdDcaX() / sqrt(track.cXX()), track.fwdDcaY() / sqrt(track.cYY())); - fRegistry.fill(HIST("Track/hDCAxRes_Pt"), track.pt(), sqrt(track.cXX()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hNclsMFT"), track.nClustersMFT()); - fRegistry.fill(HIST("Track/hNclsMCH"), track.nClusters()); - fRegistry.fill(HIST("Track/hPDCA"), track.pt(), track.pDca()); - fRegistry.fill(HIST("Track/hChi2"), track.chi2()); - fRegistry.fill(HIST("Track/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); - fRegistry.fill(HIST("Track/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/hMFTClusterMap"), track.mftClusterMap()); - } - - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - using FilteredMyCollisions = soa::Filtered; - - SliceCache cache; - Preslice perCollision_track = aod::emprimarymuon::emeventId; - // Filter trackFilter = o2::aod::fwdtrack::pt > 1.f * dimuoncuts.cfg_min_pt_track.node(); - Filter trackFilter = static_cast(dimuoncuts.cfg_min_pt_track) < o2::aod::fwdtrack::pt && static_cast(dimuoncuts.cfg_min_eta_track) < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < static_cast(dimuoncuts.cfg_max_eta_track); - // Filter trackFilter = o2::aod::fwdtrack::trackType == static_cast(dimuoncuts.cfg_track_type) && static_cast(dimuoncuts.cfg_min_pt_track) < o2::aod::fwdtrack::pt && static_cast(dimuoncuts.cfg_min_eta_track) < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < static_cast(dimuoncuts.cfg_max_eta_track); - using FilteredMyTracks = soa::Filtered; - - MyEMH* emh_pos = nullptr; - MyEMH* emh_neg = nullptr; - - Partition posTracks = o2::aod::emprimarymuon::sign > int8_t(0); - Partition negTracks = o2::aod::emprimarymuon::sign < int8_t(0); - - std::vector> used_trackIds; - int ndf = 0; - void processQC(FilteredMyCollisions const& collisions, FilteredMyTracks const& /*tracks*/) - { - for (auto& collision : collisions) { - initCCDB(collision); - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, cfgDoFlow); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, cfgDoFlow); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimarymuon::emeventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimarymuon::emeventId, collision.globalIndex(), cache); - // LOGF(info, "collision.globalIndex() = %d , collision.posZ() = %f , collision.numContrib() = %d, centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", collision.globalIndex(), collision.posZ(), collision.numContrib(), centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); - - // for (auto& neg : negTracks_per_coll) { - // LOGF(info, "neg.trackType() = %d , neg.pt() = %f", neg.trackType(), neg.pt()); - // } - - int nuls = 0, nlspp = 0, nlsmm = 0; - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - bool is_pair_ok = fillPairInfo<0>(collision, pos, ele); - if (is_pair_ok) { - nuls++; - } - } - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - bool is_pair_ok = fillPairInfo<0>(collision, pos1, pos2); - if (is_pair_ok) { - nlspp++; - } - } - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- - bool is_pair_ok = fillPairInfo<0>(collision, ele1, ele2); - if (is_pair_ok) { - nlsmm++; - } - } - - if (!cfgDoMix || !(nuls > 0 || nlspp > 0 || nlsmm > 0)) { - continue; - } - - // event mixing - int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; - if (zbin < 0) { - zbin = 0; - } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { - zbin = static_cast(zvtx_bin_edges.size()) - 2; - } - - float centrality = centralities[cfgCentEstimator]; - int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; - if (centbin < 0) { - centbin = 0; - } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { - centbin = static_cast(cent_bin_edges.size()) - 2; - } - - float ep2 = collision.ep2ft0c(); - int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; - if (epbin < 0) { - epbin = 0; - } else if (static_cast(ep_bin_edges.size()) - 2 < epbin) { - epbin = static_cast(ep_bin_edges.size()) - 2; - } - - int occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - if (occbin < 0) { - occbin = 0; - } else if (static_cast(occ_bin_edges.size()) - 2 < occbin) { - occbin = static_cast(occ_bin_edges.size()) - 2; - } - - // LOGF(info, "collision.globalIndex() = %d, collision.posZ() = %f, centrality = %f, ep2 = %f, collision.trackOccupancyInTimeRange() = %d, zbin = %d, centbin = %d, epbin = %d, occbin = %d", collision.globalIndex(), collision.posZ(), centrality, ep2, collision.trackOccupancyInTimeRange(), zbin, centbin, epbin, occbin); - - std::tuple key_bin = std::make_tuple(zbin, centbin, epbin, occbin); - std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); - - // make a vector of selected photons in this collision. - auto selected_posTracks_in_this_event = emh_pos->GetTracksPerCollision(key_df_collision); - auto selected_negTracks_in_this_event = emh_neg->GetTracksPerCollision(key_df_collision); - // LOGF(info, "N selected tracks in current event (%d, %d), zvtx = %f, centrality = %f , npos = %d , nele = %d, nuls = %d , nlspp = %d, nlsmm = %d", ndf, collision.globalIndex(), collision.posZ(), centralities[cfgCentEstimator], selected_posTracks_in_this_event.size(), selected_negTracks_in_this_event.size(), nuls, nlspp, nlsmm); - - auto collisionIds_in_mixing_pool = emh_pos->GetCollisionIdsFromEventPool(key_bin); // pos/ele does not matter. - // LOGF(info, "collisionIds_in_mixing_pool.size() = %d", collisionIds_in_mixing_pool.size()); - - for (auto& mix_dfId_collisionId : collisionIds_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int mix_collisionId = mix_dfId_collisionId.second; - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto posTracks_from_event_pool = emh_pos->GetTracksPerCollision(mix_dfId_collisionId); - auto negTracks_from_event_pool = emh_neg->GetTracksPerCollision(mix_dfId_collisionId); - // LOGF(info, "Do event mixing: current event (%d, %d) | event pool (%d, %d), npos = %d , nele = %d", ndf, collision.globalIndex(), mix_dfId, mix_collisionId, posTracks_from_event_pool.size(), negTracks_from_event_pool.size()); - - for (auto& pos : selected_posTracks_in_this_event) { // ULS mix - for (auto& ele : negTracks_from_event_pool) { - fillPairInfo<1>(collision, pos, ele); - } - } - - for (auto& ele : selected_negTracks_in_this_event) { // ULS mix - for (auto& pos : posTracks_from_event_pool) { - fillPairInfo<1>(collision, ele, pos); - } - } - - for (auto& pos1 : selected_posTracks_in_this_event) { // LS++ mix - for (auto& pos2 : posTracks_from_event_pool) { - fillPairInfo<1>(collision, pos1, pos2); - } - } - - for (auto& ele1 : selected_negTracks_in_this_event) { // LS-- mix - for (auto& ele2 : negTracks_from_event_pool) { - fillPairInfo<1>(collision, ele1, ele2); - } - } - } // end of loop over mixed event pool - - if (nuls > 0 || nlspp > 0 || nlsmm > 0) { - emh_pos->AddCollisionIdAtLast(key_bin, key_df_collision); - emh_neg->AddCollisionIdAtLast(key_bin, key_df_collision); - } - - } // end of collision loop - - ndf++; - } // end of process - PROCESS_SWITCH(dimuonQC, processQC, "run dimuon QC", true); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(dimuonQC, processDummy, "Dummy function", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"dimuon-qc"})}; -} diff --git a/PWGEM/PhotonMeson/Tasks/emcalPi0QC.cxx b/PWGEM/PhotonMeson/Tasks/emcalPi0QC.cxx index d1bbb378827..509e74402b5 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalPi0QC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalPi0QC.cxx @@ -137,6 +137,8 @@ struct Pi0QCTask { // configurable parameters // TODO adapt mDoEventSel switch to also allow selection of other triggers (e.g. EMC7) Configurable mDoEventSel{"doEventSel", 0, "demand kINT7"}; + Configurable mRequireCaloReadout{"RequireCaloReadout", 0, "require kTVXinEMC"}; + Configurable mRequireEMCalCells{"RequireEMCalCells", 0, "require at least one EMC cell in each collision"}; Configurable mVetoBCID{"vetoBCID", "", "BC ID(s) to be excluded, this should be used as an alternative to the event selection"}; Configurable mSelectBCID{"selectBCID", "all", "BC ID(s) to be included, this should be used as an alternative to the event selection"}; Configurable mVertexCut{"vertexCut", -1, "apply z-vertex cut with value in cm"}; @@ -266,7 +268,7 @@ struct Pi0QCTask { for (auto& collision : collisions) { mHistManager.fill(HIST("events"), 1); // Fill "All events" bin of event histogram - if (mDoEventSel && (!collision.sel8() || !collision.alias_bit(kTVXinEMC))) { // Check sel8 and whether EMC was read out + if (mDoEventSel && (!collision.sel8() || (mRequireCaloReadout && !collision.alias_bit(kTVXinEMC)))) { // Check sel8 and whether EMC was read out continue; } mHistManager.fill(HIST("events"), 2); // Fill sel8 + readout @@ -290,7 +292,7 @@ struct Pi0QCTask { if (mDoEventSel) { auto found = cellGlobalBCs.find(collision.foundBC_as().globalBC()); - if (found == cellGlobalBCs.end() || found->second == 0) { // Skip collisions without any readout EMCal cells + if (mRequireEMCalCells && (found == cellGlobalBCs.end() || found->second == 0)) { // Skip collisions without any readout EMCal cells continue; } } diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx index ed909f4dfbd..4e80081162d 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -32,7 +32,8 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" -#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/Utils/ClusterHistograms.h" using namespace o2; using namespace o2::aod; @@ -40,191 +41,160 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using std::array; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; +using MyEMCClusters = soa::Join; +using MyEMCCluster = MyEMCClusters::iterator; + struct emcalQC { - Configurable requireCaloReadout{"requireCaloReadout", true, "Require calorimeters readout when analyzing EMCal/PHOS"}; - 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() + Configurable cfgDo2DQA{"cfgDo2DQA", true, "perform 2 dimensional cluster QA"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgRequireEMCReadoutInMB{"cfgRequireEMCReadoutInMB", false, "require the EMC to be read out in an MB collision (kTVXinEMC)"}; + Configurable cfgRequireEMCHardwareTriggered{"cfgRequireEMCHardwareTriggered", false, "require the EMC to be hardware triggered (kEMC7 or kDMC7)"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; + } eventcuts; + + EMCPhotonCut fEMCCut; + struct : ConfigurableGroup { + std::string prefix = "emccut_group"; + Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; + 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"}; + } emccuts; + + void DefineEMEventCut() { - fMainList->SetOwner(true); - fMainList->SetName("fMainList"); - - // create sub lists first. - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Event"); - THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); - o2::aod::pwgem::photon::histogram::DefineHistograms(list_ev, "Event"); - - list_ev->Add(new TH1F("hNEvents", "hNEvents", 6, 0.5f, 6.5f)); - reinterpret_cast(list_ev->FindObject("hNEvents"))->GetXaxis()->SetBinLabel(1, "all cols"); - reinterpret_cast(list_ev->FindObject("hNEvents"))->GetXaxis()->SetBinLabel(2, "sel8"); - reinterpret_cast(list_ev->FindObject("hNEvents"))->GetXaxis()->SetBinLabel(3, "emc readout"); - reinterpret_cast(list_ev->FindObject("hNEvents"))->GetXaxis()->SetBinLabel(4, "1+ Contributor"); - reinterpret_cast(list_ev->FindObject("hNEvents"))->GetXaxis()->SetBinLabel(5, "z<10cm"); - reinterpret_cast(list_ev->FindObject("hNEvents"))->GetXaxis()->SetBinLabel(6, "unique col"); - - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Cluster"); - THashList* list_cluster = reinterpret_cast(fMainList->FindObject("Cluster")); - - for (const auto& cut : fEMCCuts) { - const char* cutname = cut.GetName(); - o2::aod::pwgem::photon::histogram::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::pwgem::photon::histogram::DefineHistograms(list, "Cluster", fDo2DQC ? "2D_EMC" : "EMC"); - } + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireEMCReadoutInMB(eventcuts.cfgRequireEMCReadoutInMB); + fEMEventCut.SetRequireEMCHardwareTriggered(eventcuts.cfgRequireEMCHardwareTriggered); + fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); } - void DefineCuts() + void DefineEMCCut() { - 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 a = emccuts.EMC_TM_Eta->at(0); + const float b = emccuts.EMC_TM_Eta->at(1); + const float c = emccuts.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); + const float d = emccuts.EMC_TM_Phi->at(0); + const float e = emccuts.EMC_TM_Phi->at(1); + const float f = emccuts.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(*emccuts::GetCut(cutname)); - } - } - } - LOGF(info, "Number of EMC cuts = %d", fEMCCuts.size()); + fEMCCut.SetMinE(emccuts.EMC_minE); + fEMCCut.SetMinNCell(emccuts.EMC_minNCell); + fEMCCut.SetM02Range(emccuts.EMC_minM02, emccuts.EMC_maxM02); + fEMCCut.SetTimeRange(emccuts.EMC_minTime, emccuts.EMC_maxTime); + + fEMCCut.SetTrackMatchingEta([&a, &b, &c](float pT) { return a + pow(pT + b, c); }); + fEMCCut.SetTrackMatchingPhi([&d, &e, &f](float pT) { return d + pow(pT + e, f); }); + + fEMCCut.SetMinEoverP(emccuts.EMC_Eoverp); + fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); } + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + std::vector zvtx_bin_edges; + void init(InitContext&) { - DefineCuts(); - addhistograms(); // please call this after DefinCuts(); + zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); + zvtx_bin_edges.erase(zvtx_bin_edges.begin()); + + DefineEMCCut(); + DefineEMEventCut(); - fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); - fOutputCluster.setObject(reinterpret_cast(fMainList->FindObject("Cluster"))); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); + o2::aod::pwgem::photonmeson::utils::clusterhistogram::addClusterHistograms(&fRegistry, cfgDo2DQA); } 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("hNEvents"))->Fill(1.0); - if (!collision.sel8()) { - continue; - } - reinterpret_cast(fMainList->FindObject("Event")->FindObject("hNEvents"))->Fill(2.0); - if (collision.alias_bit(triggerAliases::kTVXinEMC) == 0 && requireCaloReadout) { - continue; - } - reinterpret_cast(fMainList->FindObject("Event")->FindObject("hNEvents"))->Fill(3.0); - - if (collision.numContrib() < 0.5) { - continue; - } - reinterpret_cast(fMainList->FindObject("Event")->FindObject("hNEvents"))->Fill(4.0); - if (abs(collision.posZ()) > 10.0) { + if (eventcuts.onlyKeepWeightedEvents && fabs(collision.weight() - 1.) < 1E-10) { continue; } - reinterpret_cast(fMainList->FindObject("Event")->FindObject("hNEvents"))->Fill(5.0); - reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx"))->Fill(collision.posZ()); - if (collision.ncollsPerBC() != 1) { // Check that the collision is unique (the only one in the bc) + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { continue; } - reinterpret_cast(fMainList->FindObject("Event")->FindObject("hNEvents"))->Fill(6.0); - o2::aod::pwgem::photon::histogram::FillHistClass(list_ev, "", collision); // Fill event histograms + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted 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; - } + fRegistry.fill(HIST("Cluster/before/hNgamma"), clusters_per_coll.size(), collision.weight()); + int ng = 0; + for (auto& cluster : clusters_per_coll) { + // Fill the cluster properties before applying any cuts + o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<0>(&fRegistry, cluster, cfgDo2DQA, collision.weight()); + + // Apply cuts one by one and fill in hClusterQualityCuts histogram + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), 0., cluster.e(), collision.weight()); + + // 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 = fEMCCut.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 (!fEMCCut.IsSelectedEMCal(specificcut, cluster)) { // Check whether cluster passes this cluster requirement, if not, fill why in the next row + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), icut + 1, cluster.e(), collision.weight()); + survivesIsSelectedEMCalCuts = false; } + } - if (survivesIsSelectedCuts != survivesIsSelectedEMCalCuts) { - LOGF(info, "Cummulative application of IsSelectedEMCal cuts does not equal the IsSelected result"); - } + if (survivesIsSelectedCuts != survivesIsSelectedEMCalCuts) { + LOGF(info, "Cummulative application of IsSelectedEMCal cuts does not equal the IsSelected result"); + } - if (survivesIsSelectedCuts) { - o2::aod::pwgem::photon::histogram::FillHistClass(list_cluster_cut, fDo2DQC ? "2D" : "1D", cluster); - reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cut.GetName())->FindObject("hClusterQualityCuts"))->Fill(7., cluster.e()); - ng++; - } + if (survivesIsSelectedCuts) { + o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<1>(&fRegistry, cluster, cfgDo2DQA, collision.weight()); + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), 7., cluster.e(), collision.weight()); + ng++; } - reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cut.GetName())->FindObject("hNgamma"))->Fill(ng); - } // end of cut loop - } // end of collision loop - } // end of process + } + fRegistry.fill(HIST("Cluster/after/hNgamma"), ng, collision.weight()); + } // end of collision loop + } // end of process void processDummy(MyCollisions const&) {} diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index f8f19c80f53..64d106ff78e 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -22,7 +22,7 @@ #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" using namespace o2; using namespace o2::aod; @@ -34,7 +34,7 @@ using namespace o2::aod::pwgem::photon; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; struct PCMQC { @@ -42,19 +42,20 @@ struct PCMQC { Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; } eventcuts; V0PhotonCut fV0PhotonCut; @@ -65,7 +66,8 @@ struct PCMQC { Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; Configurable cfg_require_v0_on_wwire_ib{"cfg_require_v0_on_wwire_ib", false, "flag to select V0s on W wires ITSib"}; Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.9, "max eta for v0 photons at PV"}; + Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; + Configurable cfg_max_eta_v0{"cfg_max_eta_v0", +0.8, "max eta for v0 photons at PV"}; Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; @@ -80,6 +82,7 @@ struct PCMQC { Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; } pcmcuts; static constexpr std::string_view event_types[2] = {"before/", "after/"}; @@ -120,7 +123,7 @@ struct PCMQC { // v0 info fRegistry.add("V0/hPt", "pT;p_{T,#gamma} (GeV/c)", kTH1F, {{2000, 0.0f, 20}}, false); - fRegistry.add("V0/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); + fRegistry.add("V0/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {40, -1.0f, 1.0f}}, false); fRegistry.add("V0/hRadius", "V0Radius; radius in Z (cm);radius in XY (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}, false); fRegistry.add("V0/hCosPA", "V0CosPA;cosine pointing angle", kTH1F, {{100, 0.9f, 1.0f}}, false); fRegistry.add("V0/hCosPA_Rxy", "cos PA vs. R_{xy};R_{xy} (cm);cosine pointing angle", kTH2F, {{200, 0.f, 100.f}, {100, 0.9f, 1.0f}}, false); @@ -136,12 +139,17 @@ struct PCMQC { fRegistry.add("V0/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/hPResolution", "p resolution;p_{#gamma} (GeV/c);#Deltap/p", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); + fRegistry.add("V0/hPtResolution", "p_{T} resolution;p_{#gamma} (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); + fRegistry.add("V0/hEtaResolution", "#eta resolution;p_{#gamma} (GeV/c);#Delta#eta", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); + fRegistry.add("V0/hThetaResolution", "#theta resolution;p_{#gamma} (GeV/c);#Delta#theta (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); + fRegistry.add("V0/hPhiResolution", "#varphi resolution;p_{#gamma} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); // v0leg info fRegistry.add("V0Leg/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); fRegistry.add("V0Leg/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); - fRegistry.add("V0Leg/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); + fRegistry.add("V0Leg/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {40, -1.0f, 1.0f}}, false); fRegistry.add("V0Leg/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -50.0f, 50.0f}, {200, -50.0f, 50.0f}}, false); fRegistry.add("V0Leg/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); fRegistry.add("V0Leg/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); @@ -151,18 +159,19 @@ struct PCMQC { fRegistry.add("V0Leg/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("V0Leg/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("V0Leg/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("V0Leg/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("V0Leg/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("V0Leg/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("V0Leg/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); - fRegistry.add("V0Leg/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {100, -50, 50}}, false); + fRegistry.add("V0Leg/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + fRegistry.add("V0Leg/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {80, -20, 20}}, false); fRegistry.add("V0Leg/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); - fRegistry.add("V0Leg/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {100, -50, 50}}, false); + fRegistry.add("V0Leg/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {80, -20, 20}}, false); } void DefineEMEventCut() { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); @@ -172,6 +181,7 @@ struct PCMQC { fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); } void DefinePCMCut() @@ -180,7 +190,7 @@ struct PCMQC { // for v0 fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, 1e10f); - fV0PhotonCut.SetV0EtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetV0EtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius); @@ -189,13 +199,15 @@ struct PCMQC { // for track fV0PhotonCut.SetTrackPtRange(pcmcuts.cfg_min_pt_v0 * 0.4, 1e+10f); - fV0PhotonCut.SetTrackEtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetTrackEtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); + if (pcmcuts.cfg_reject_v0_on_itsib) { fV0PhotonCut.SetNClustersITS(2, 4); } else { @@ -287,6 +299,11 @@ struct PCMQC { fRegistry.fill(HIST("V0/hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/hPResolution"), v0.p(), getPResolution(v0) / v0.p()); + fRegistry.fill(HIST("V0/hPtResolution"), v0.p(), getPtResolution(v0) / v0.pt()); + fRegistry.fill(HIST("V0/hEtaResolution"), v0.p(), getEtaResolution(v0)); + fRegistry.fill(HIST("V0/hThetaResolution"), v0.p(), getThetaResolution(v0)); + fRegistry.fill(HIST("V0/hPhiResolution"), v0.p(), getPhiResolution(v0)); } template @@ -301,10 +318,13 @@ struct PCMQC { fRegistry.fill(HIST("V0Leg/hNcrTPC"), leg.tpcNClsCrossedRows()); fRegistry.fill(HIST("V0Leg/hTPCNcr2Nf"), leg.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("V0Leg/hTPCNcls2Nf"), leg.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("V0Leg/hTPCNclsShared"), leg.pt(), leg.tpcFractionSharedCls()); fRegistry.fill(HIST("V0Leg/hChi2TPC"), leg.tpcChi2NCl()); fRegistry.fill(HIST("V0Leg/hChi2ITS"), leg.itsChi2NCl()); fRegistry.fill(HIST("V0Leg/hITSClusterMap"), leg.itsClusterMap()); - fRegistry.fill(HIST("V0Leg/hMeanClusterSizeITS"), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl()))); + if (leg.hasITS()) { + fRegistry.fill(HIST("V0Leg/hMeanClusterSizeITS"), leg.p(), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl()))); + } fRegistry.fill(HIST("V0Leg/hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); fRegistry.fill(HIST("V0Leg/hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); fRegistry.fill(HIST("V0Leg/hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); @@ -315,6 +335,7 @@ struct PCMQC { Preslice perCollision = aod::v0photonkf::emeventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; using FilteredMyCollisions = soa::Filtered; void processQC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const&) @@ -339,17 +360,18 @@ struct PCMQC { auto pos = v0.posTrack_as(); auto ele = v0.negTrack_as(); - if (fV0PhotonCut.IsSelected(v0)) { - nv0++; - fillV0Info(v0); - for (auto& leg : {pos, ele}) { - fillV0LegInfo(leg); - } + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + fillV0Info(v0); + for (auto& leg : {pos, ele}) { + fillV0LegInfo(leg); } + nv0++; } // end of v0 loop fRegistry.fill(HIST("V0/hNgamma"), nv0); } // end of collision loop - } // end of process + } // end of process void processDummy(MyCollisions const&) {} diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index d5137eac18c..656c0a7442c 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -22,15 +22,17 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMEventCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::pwgem::mcutil; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; using MyCollisions = soa::Join; @@ -39,7 +41,7 @@ using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; using MyMCV0Legs = soa::Join; @@ -47,26 +49,27 @@ using MyMCV0Leg = MyMCV0Legs::iterator; struct PCMQCMC { - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; - EMEventCut fEMEventCut; + EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgOccupancyMin{"cfgOccupancyMin", -1, "min. occupancy"}; Configurable cfgOccupancyMax{"cfgOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; } eventcuts; V0PhotonCut fV0PhotonCut; @@ -77,7 +80,8 @@ struct PCMQCMC { Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; Configurable cfg_require_v0_on_wwire_ib{"cfg_require_v0_on_wwire_ib", false, "flag to select V0s on W wires ITSib"}; Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.9, "max eta for v0 photons at PV"}; + Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; + Configurable cfg_max_eta_v0{"cfg_max_eta_v0", +0.8, "max eta for v0 photons at PV"}; Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; @@ -92,10 +96,12 @@ struct PCMQCMC { Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; } pcmcuts; - static constexpr std::string_view event_types[2] = {"before/", "after/"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_types[2] = {"before/", "after/"}; + static constexpr std::string_view mcphoton_types[3] = {"primary/", "fromWD/", "fromHS/"}; void init(InitContext&) { @@ -108,27 +114,30 @@ struct PCMQCMC { { std::vector ptbins; for (int i = 0; i < 2; i++) { - ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.1 GeV/c, every 0.05 GeV/c + ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c } - for (int i = 2; i < 52; i++) { - ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 5 GeV/c, every 0.1 GeV/c + for (int i = 2; i < 51; i++) { + ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c } - for (int i = 52; i < 62; i++) { - ptbins.emplace_back(0.5 * (i - 52) + 5.0); // from 5 to 10 GeV/c, evety 0.5 GeV/c + for (int i = 51; i < 61; i++) { + ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c } - for (int i = 62; i < 73; i++) { - ptbins.emplace_back(1.0 * (i - 62) + 10.0); // from 10 to 20 GeV/c, evety 1 GeV/c + for (int i = 61; i < 72; i++) { + ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c } const AxisSpec axis_pt{ptbins, "p_{T,#gamma} (GeV/c)"}; const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y_{#gamma}|"}; - fRegistry.add("Generated/hPt", "pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); - fRegistry.add("Generated/hPtY", "Generated info", kTH2F, {axis_pt, axis_rapidity}, true); - fRegistry.add("Generated/hPt_ConvertedPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); - fRegistry.add("Generated/hY_ConvertedPhoton", "converted photon y;rapidity y", kTH1F, {{40, -2.0f, 2.0f}}, true); - fRegistry.add("Generated/hPhi_ConvertedPhoton", "converted photon #varphi;#varphi (rad.)", kTH1F, {{180, 0, 2 * M_PI}}, true); - fRegistry.add("Generated/hPhotonRxy", "conversion point in XY MC;V_{x} (cm);V_{y} (cm)", kTH2F, {{800, -100.0f, 100.0f}, {800, -100.0f, 100.0f}}, true); - fRegistry.add("Generated/hPhotonRZ", "conversion point in RZ MC;V_{z} (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, 0.f, 100.0f}}, true); - fRegistry.add("Generated/hPhotonPhivsRxy", "conversion point of #varphi vs. R_{xy} MC;#varphi (rad.);R_{xy} (cm);N_{e}", kTH2F, {{360, 0.0f, 2 * M_PI}, {400, 0, 100}}, true); + + if (doprocessGen) { + fRegistry.add("Generated/hPt", "pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); + fRegistry.add("Generated/hPtY", "Generated info", kTH2F, {axis_pt, axis_rapidity}, true); + fRegistry.add("Generated/hPt_ConvertedPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); + fRegistry.add("Generated/hY_ConvertedPhoton", "converted photon y;rapidity y", kTH1F, {{40, -2.0f, 2.0f}}, true); + fRegistry.add("Generated/hPhi_ConvertedPhoton", "converted photon #varphi;#varphi (rad.)", kTH1F, {{180, 0, 2 * M_PI}}, true); + fRegistry.add("Generated/hPhotonRxy", "conversion point in XY MC;V_{x} (cm);V_{y} (cm)", kTH2F, {{800, -100.0f, 100.0f}, {800, -100.0f, 100.0f}}, true); + fRegistry.add("Generated/hPhotonRZ", "conversion point in RZ MC;V_{z} (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, 0.f, 100.0f}}, true); + fRegistry.add("Generated/hPhotonPhivsRxy", "conversion point of #varphi vs. R_{xy} MC;#varphi (rad.);R_{xy} (cm);N_{e}", kTH2F, {{360, 0.0f, 2 * M_PI}, {400, 0, 100}}, true); + } // event info auto hCollisionCounter = fRegistry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); @@ -155,89 +164,71 @@ struct PCMQCMC { fRegistry.addClone("Event/before/", "Event/after/"); // v0 info - fRegistry.add("V0/hPt", "pT;p_{T,#gamma} (GeV/c)", kTH1F, {{2000, 0.0f, 20}}, false); - fRegistry.add("V0/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); - fRegistry.add("V0/hRadius", "V0Radius; radius in Z (cm);radius in XY (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}, false); - fRegistry.add("V0/hCosPA", "V0CosPA;cosine pointing angle", kTH1F, {{100, 0.9f, 1.0f}}, false); - fRegistry.add("V0/hCosPA_Rxy", "cos PA vs. R_{xy};R_{xy} (cm);cosine pointing angle", kTH2F, {{200, 0.f, 100.f}, {100, 0.9f, 1.0f}}, false); - fRegistry.add("V0/hPCA", "distance between 2 legs;PCA (cm)", kTH1F, {{500, 0.0f, 5.0f}}, false); - fRegistry.add("V0/hPCA_Rxy", "distance between 2 legs vs. R_{xy};R_{xy} (cm);PCA (cm)", kTH2F, {{200, 0.f, 100.f}, {500, 0.0f, 5.0f}}, false); - fRegistry.add("V0/hPCA_CosPA", "distance between 2 legs vs. cosPA;cosine of pointing angle;PCA (cm)", kTH2F, {{100, 0.9f, 1.f}, {500, 0.0f, 5.0f}}, false); - fRegistry.add("V0/hDCAxyz", "DCA to PV;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -5.f, +5.f}, {200, -5.f, +5.f}}, false); - fRegistry.add("V0/hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}, false); - fRegistry.add("V0/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); - fRegistry.add("V0/hGammaRxy", "conversion point in XY;V_{x} (cm);V_{y} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, -100.0f, 100.0f}}, false); - fRegistry.add("V0/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); - - fRegistry.add("V0/hPt_Photon_Candidate", "pT of photon candidate;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); // for denominator of purity - fRegistry.add("V0/hEtaPhi_Photon_Candidate", "#eta vs. #varphi of photon candidate ;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, true); // for denominator of purity - - fRegistry.add("V0/hPt_Photon_Primary", "pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); // for MC efficiency - fRegistry.add("V0/hEtaPhi_Photon_Primary", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, true); // for MC efficiency - fRegistry.add("V0/hCosPA_Rxy_Photon_Primary", "cos PA vs. R_{xy};R_{xy} (cm);cosine pointing angle", kTH2F, {{200, 0.f, 100.f}, {100, 0.9f, 1.0f}}, true); - fRegistry.add("V0/hXY_Photon_Primary", "X vs. Y of photon rec.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); - fRegistry.add("V0/hXY_Photon_Primary_MC", "X vs. Y of photon gen.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); - fRegistry.add("V0/hRZ_Photon_Primary", "R vs. Z of photon rec.;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); - fRegistry.add("V0/hRZ_Photon_Primary_MC", "R vs. Z of photon gen;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); - - fRegistry.add("V0/hPt_Photon_FromWD", "pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); // for MC feed down correction - fRegistry.add("V0/hEtaPhi_Photon_FromWD", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, true); // for MC feed down correction - fRegistry.add("V0/hCosPA_Rxy_Photon_FromWD", "cos PA vs. R_{xy};R_{xy} (cm);cosine pointing angle", kTH2F, {{200, 0.f, 100.f}, {100, 0.9f, 1.0f}}, true); - - fRegistry.add("V0/hPt_Photon_hs", "pT of photon from hadronic shower in materials;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); - fRegistry.add("V0/hEtaPhi_Photon_hs", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, true); - fRegistry.add("V0/hCosPA_Rxy_Photon_hs", "cos PA vs. R_{xy};R_{xy} (cm);cosine pointing angle", kTH2F, {{200, 0.f, 100.f}, {100, 0.9f, 1.0f}}, true); - fRegistry.add("V0/hXY_Photon_hs_MC", "X vs. Y of photon from hadronic shower in materials gen.;Z (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, 100}}, true); // production vertex of photons - fRegistry.add("V0/hRZ_Photon_hs_MC", "R vs. Z of photon from hadronic shower in materials gen.;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); // production vertex of photons - - fRegistry.add("V0/hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); - fRegistry.add("V0/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); - fRegistry.add("V0/hConvPoint_diffZ", "conversion point diff Z MC;Z_{MC} (cm);Z_{rec} - Z_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); - - fRegistry.add("V0/hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0/hEtaRec_DeltaPtOverPtGen", "photon p_{T} resolution;#eta^{rec} of conversion point;(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{400, -2, +2}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0/hEtaRec_DeltaEta", "photon #eta resolution;#eta^{rec} of conversion point;#eta^{rec} - #eta^{gen}", kTH2F, {{400, -2, +2}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0/hEtaRec_DeltaPhi", "photon #varphi resolution;#eta^{rec} of conversion point;#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{400, -2, +2}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hPt", "pT;p_{T,#gamma} (GeV/c)", kTH1F, {{2000, 0.0f, 20}}, false); + fRegistry.add("V0/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {40, -1.0f, 1.0f}}, false); + fRegistry.add("V0/primary/hRadius", "V0Radius; radius in Z (cm);radius in XY (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}, false); + fRegistry.add("V0/primary/hCosPA", "V0CosPA;cosine pointing angle", kTH1F, {{100, 0.9f, 1.0f}}, false); + fRegistry.add("V0/primary/hCosPA_Rxy", "cos PA vs. R_{xy};R_{xy} (cm);cosine pointing angle", kTH2F, {{200, 0.f, 100.f}, {100, 0.9f, 1.0f}}, false); + fRegistry.add("V0/primary/hPCA", "distance between 2 legs;PCA (cm)", kTH1F, {{500, 0.0f, 5.0f}}, false); + fRegistry.add("V0/primary/hPCA_Rxy", "distance between 2 legs vs. R_{xy};R_{xy} (cm);PCA (cm)", kTH2F, {{200, 0.f, 100.f}, {500, 0.0f, 5.0f}}, false); + fRegistry.add("V0/primary/hPCA_CosPA", "distance between 2 legs vs. cosPA;cosine of pointing angle;PCA (cm)", kTH2F, {{100, 0.9f, 1.f}, {500, 0.0f, 5.0f}}, false); + fRegistry.add("V0/primary/hDCAxyz", "DCA to PV;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -5.f, +5.f}, {200, -5.f, +5.f}}, false); + fRegistry.add("V0/primary/hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}, false); + fRegistry.add("V0/primary/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); + fRegistry.add("V0/primary/hGammaRxy", "conversion point in XY;V_{x} (cm);V_{y} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, -100.0f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hPResolution", "p resolution;p_{#gamma} (GeV/c);#Deltap/p", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); + fRegistry.add("V0/primary/hPtResolution", "p_{T} resolution;p_{#gamma} (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); + fRegistry.add("V0/primary/hEtaResolution", "#eta resolution;p_{#gamma} (GeV/c);#Delta#eta", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); + fRegistry.add("V0/primary/hThetaResolution", "#theta resolution;p_{#gamma} (GeV/c);#Delta#theta (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); + fRegistry.add("V0/primary/hPhiResolution", "#varphi resolution;p_{#gamma} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); + fRegistry.add("V0/primary/hNgamma", "Number of true #gamma per collision", kTH1F, {{101, -0.5f, 100.5f}}); + fRegistry.add("V0/primary/hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hConvPoint_diffZ", "conversion point diff Z MC;Z_{MC} (cm);Z_{rec} - Z_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hXY_Photon_MC", "X vs. Y of true photon conversion point.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); + fRegistry.add("V0/primary/hRZ_Photon_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); + fRegistry.addClone("V0/primary/", "V0/fromWD/"); // from weak decay + fRegistry.addClone("V0/primary/", "V0/fromHS/"); // from hadronic shower in detector materials // v0leg info - fRegistry.add("V0Leg/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("V0Leg/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); - fRegistry.add("V0Leg/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {40, -2.0f, 2.0f}}, false); - fRegistry.add("V0Leg/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -50.0f, 50.0f}, {200, -50.0f, 50.0f}}, false); - fRegistry.add("V0Leg/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("V0Leg/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("V0Leg/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("V0Leg/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("V0Leg/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("V0Leg/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("V0Leg/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("V0Leg/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("V0Leg/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("V0Leg/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("V0Leg/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("V0Leg/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, false); - fRegistry.add("V0Leg/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {100, -50, 50}}, false); - fRegistry.add("V0Leg/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); - fRegistry.add("V0Leg/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {100, -50, 50}}, false); - - fRegistry.add("V0Leg/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/hEtaRec_DeltaPtOverPtGen", "electron p_{T} resolution;#eta^{rec} of conversion point;(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{400, -2, +2}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/hEtaRec_DeltaEta", "electron #eta resolution;#eta^{rec} of conversion point;#eta^{rec} - #eta^{gen}", kTH2F, {{400, -2, +2}, {400, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/hEtaRec_DeltaPhi", "electron #varphi resolution;#eta^{rec} of conversion point;#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{400, -2, +2}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("V0Leg/primary/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); + fRegistry.add("V0Leg/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {40, -3.0f, 1.0f}}, false); + fRegistry.add("V0Leg/primary/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -50.0f, 50.0f}, {200, -50.0f, 50.0f}}, false); + fRegistry.add("V0Leg/primary/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("V0Leg/primary/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("V0Leg/primary/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("V0Leg/primary/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/primary/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/primary/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("V0Leg/primary/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("V0Leg/primary/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("V0Leg/primary/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("V0Leg/primary/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + fRegistry.add("V0Leg/primary/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {40, -20, 20}}, false); + fRegistry.add("V0Leg/primary/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); + fRegistry.add("V0Leg/primary/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {40, -20, 20}}, false); + fRegistry.add("V0Leg/primary/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {400, -1.0f, 1.0f}}, true); + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromWD/"); // from weak decay + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromHS/"); // from hadronic shower in detector materials } void DefineEMEventCut() { - fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); @@ -247,6 +238,7 @@ struct PCMQCMC { fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); fEMEventCut.SetOccupancyRange(eventcuts.cfgOccupancyMin, eventcuts.cfgOccupancyMax); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); } void DefinePCMCut() @@ -255,7 +247,7 @@ struct PCMQCMC { // for v0 fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, 1e10f); - fV0PhotonCut.SetV0EtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetV0EtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius); @@ -264,13 +256,15 @@ struct PCMQCMC { // for track fV0PhotonCut.SetTrackPtRange(pcmcuts.cfg_min_pt_v0 * 0.4, 1e+10f); - fV0PhotonCut.SetTrackEtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetTrackEtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); + if (pcmcuts.cfg_reject_v0_on_itsib) { fV0PhotonCut.SetNClustersITS(2, 4); } else { @@ -342,60 +336,81 @@ struct PCMQCMC { fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0MvsMultNTracksPV"), collision.multFT0A() + collision.multFT0C(), collision.multNTracksPV()); } - template - void fillV0Info(TV0 const& v0, const float weight = 1.f) + template + void fillV0Info(TV0 const& v0, TMCV0 const& mcphoton, TMCLeg const& mcleg) { - fRegistry.fill(HIST("V0/hPt"), v0.pt(), weight); - fRegistry.fill(HIST("V0/hEtaPhi"), v0.phi(), v0.eta(), weight); - fRegistry.fill(HIST("V0/hRadius"), v0.vz(), v0.v0radius(), weight); - fRegistry.fill(HIST("V0/hCosPA"), v0.cospa(), weight); - fRegistry.fill(HIST("V0/hCosPA_Rxy"), v0.v0radius(), v0.cospa(), weight); - fRegistry.fill(HIST("V0/hPCA"), v0.pca(), weight); - fRegistry.fill(HIST("V0/hPCA_CosPA"), v0.cospa(), v0.pca(), weight); - fRegistry.fill(HIST("V0/hPCA_Rxy"), v0.v0radius(), v0.pca(), weight); - fRegistry.fill(HIST("V0/hDCAxyz"), v0.dcaXYtopv(), v0.dcaZtopv(), weight); - fRegistry.fill(HIST("V0/hAPplot"), v0.alpha(), v0.qtarm(), weight); - fRegistry.fill(HIST("V0/hMassGamma"), v0.v0radius(), v0.mGamma(), weight); - fRegistry.fill(HIST("V0/hGammaRxy"), v0.vx(), v0.vy(), weight); - fRegistry.fill(HIST("V0/hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF(), weight); - fRegistry.fill(HIST("V0/hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF(), weight); - fRegistry.fill(HIST("V0/hKFChi2vsX"), v0.vx(), v0.chiSquareNDF(), weight); - fRegistry.fill(HIST("V0/hKFChi2vsY"), v0.vy(), v0.chiSquareNDF(), weight); - fRegistry.fill(HIST("V0/hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF(), weight); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), v0.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), v0.phi(), v0.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRadius"), v0.vz(), v0.v0radius()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPA"), v0.cospa()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPA_Rxy"), v0.v0radius(), v0.cospa()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPCA"), v0.pca()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPCA_CosPA"), v0.cospa(), v0.pca()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPCA_Rxy"), v0.v0radius(), v0.pca()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), v0.dcaXYtopv(), v0.dcaZtopv()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hAPplot"), v0.alpha(), v0.qtarm()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMassGamma"), v0.v0radius(), v0.mGamma()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hGammaRxy"), v0.vx(), v0.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPResolution"), v0.p(), getPResolution(v0) / v0.p()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtResolution"), v0.p(), getPtResolution(v0) / v0.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaResolution"), v0.p(), getEtaResolution(v0)); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hThetaResolution"), v0.p(), getThetaResolution(v0)); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiResolution"), v0.p(), getPhiResolution(v0)); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcphoton.pt(), v0.eta() - mcphoton.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcphoton.pt(), v0.phi() - mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffX"), mcleg.vx(), v0.vx() - mcleg.vx()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffY"), mcleg.vy(), v0.vy() - mcleg.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffZ"), mcleg.vz(), v0.vz() - mcleg.vz()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY_Photon_MC"), mcleg.vx(), mcleg.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ_Photon_MC"), mcleg.vz(), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); } - template - void fillV0LegInfo(TLeg const& leg, const float weight = 1.f) + template + void fillV0LegInfo(TLeg const& leg) { - fRegistry.fill(HIST("V0Leg/hPt"), leg.pt(), weight); - fRegistry.fill(HIST("V0Leg/hQoverPt"), leg.sign() / leg.pt(), weight); - fRegistry.fill(HIST("V0Leg/hEtaPhi"), leg.phi(), leg.eta(), weight); - fRegistry.fill(HIST("V0Leg/hDCAxyz"), leg.dcaXY(), leg.dcaZ(), weight); - fRegistry.fill(HIST("V0Leg/hNclsITS"), leg.itsNCls(), weight); - fRegistry.fill(HIST("V0Leg/hNclsTPC"), leg.tpcNClsFound(), weight); - fRegistry.fill(HIST("V0Leg/hNcrTPC"), leg.tpcNClsCrossedRows(), weight); - fRegistry.fill(HIST("V0Leg/hTPCNcr2Nf"), leg.tpcCrossedRowsOverFindableCls(), weight); - fRegistry.fill(HIST("V0Leg/hTPCNcls2Nf"), leg.tpcFoundOverFindableCls(), weight); - fRegistry.fill(HIST("V0Leg/hChi2TPC"), leg.tpcChi2NCl(), weight); - fRegistry.fill(HIST("V0Leg/hChi2ITS"), leg.itsChi2NCl(), weight); - fRegistry.fill(HIST("V0Leg/hITSClusterMap"), leg.itsClusterMap(), weight); - fRegistry.fill(HIST("V0Leg/hMeanClusterSizeITS"), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl())), weight); - fRegistry.fill(HIST("V0Leg/hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal(), weight); - fRegistry.fill(HIST("V0Leg/hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl(), weight); - fRegistry.fill(HIST("V0Leg/hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi(), weight); - fRegistry.fill(HIST("V0Leg/hXY"), leg.x(), leg.y(), weight); - fRegistry.fill(HIST("V0Leg/hZX"), leg.z(), leg.x(), weight); - fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y(), weight); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), leg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hQoverPt"), leg.sign() / leg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), leg.phi(), leg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), leg.dcaXY(), leg.dcaZ()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsITS"), leg.itsNCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsTPC"), leg.tpcNClsFound()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNcrTPC"), leg.tpcNClsCrossedRows()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcr2Nf"), leg.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcls2Nf"), leg.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNclsShared"), leg.pt(), leg.tpcFractionSharedCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2TPC"), leg.tpcChi2NCl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2ITS"), leg.itsChi2NCl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hITSClusterMap"), leg.itsClusterMap()); + if (leg.hasITS()) { + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hMeanClusterSizeITS"), leg.p(), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl()))); + } + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), leg.x(), leg.y()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZX"), leg.z(), leg.x()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZY"), leg.z(), leg.y()); + auto mcleg = leg.template emmcparticle_as(); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcleg.pt(), leg.eta() - mcleg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcleg.pt(), leg.phi() - mcleg.phi()); } Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_occupancy = eventcuts.cfgOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgOccupancyMax; using FilteredMyCollisions = soa::Filtered; Preslice perCollision = aod::v0photonkf::emeventId; - void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const&, aod::EMMCParticles const& mcparticles, MyMCCollisions const&) + void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const&, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const&) { for (auto& collision : collisions) { - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -409,7 +424,7 @@ struct PCMQCMC { fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted auto V0Photons_coll = v0photons.sliceBy(perCollision, collision.globalIndex()); - int nv0 = 0; + int ng_primary = 0, ng_wd = 0, ng_hs = 0; for (auto& v0 : V0Photons_coll) { auto pos = v0.posTrack_as(); auto ele = v0.negTrack_as(); @@ -418,69 +433,41 @@ struct PCMQCMC { // LOGF(info, "posmc.isPhysicalPrimary() = %d, posmc.producedByGenerator() = %d, elemc.isPhysicalPrimary() = %d, elemc.producedByGenerator() = %d", posmc.isPhysicalPrimary(), posmc.producedByGenerator(), elemc.isPhysicalPrimary(), elemc.producedByGenerator()); - if (fV0PhotonCut.IsSelected(v0)) { - fRegistry.fill(HIST("V0/hPt_Photon_Candidate"), v0.pt()); - fRegistry.fill(HIST("V0/hEtaPhi_Photon_Candidate"), v0.phi(), v0.eta()); + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + if (photonid < 0) { + continue; + } + auto mcphoton = mcparticles.iteratorAt(photonid); - int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); - if (photonid < 0) { - continue; + if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { + fillV0Info<0>(v0, mcphoton, elemc); + for (auto& leg : {pos, ele}) { + fillV0LegInfo<0>(leg); + } + ng_primary++; + } else if (IsFromWD(mcphoton.template emmcevent_as(), mcphoton, mcparticles) > 0) { + fillV0Info<1>(v0, mcphoton, elemc); + for (auto& leg : {pos, ele}) { + fillV0LegInfo<1>(leg); } - auto mcphoton = mcparticles.iteratorAt(photonid); - nv0++; // number of true photons regardless of primary or feeddown or hadronic shower - - if (IsConversionPointInAcceptance(mcphoton, maxRgen, pcmcuts.cfg_max_eta_v0, margin_z_mc, mcparticles)) { - if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { - float rxy_rec = sqrt(v0.vx() * v0.vx() + v0.vy() * v0.vy()); - float rxy_mc = sqrt(posmc.vx() * posmc.vx() + posmc.vy() * posmc.vy()); - float eta_cp = std::atanh(v0.vz() / sqrt(pow(v0.vx(), 2) + pow(v0.vy(), 2) + pow(v0.vz(), 2))); - fillV0Info(v0, 1.f); - fRegistry.fill(HIST("V0/hPt_Photon_Primary"), v0.pt()); - fRegistry.fill(HIST("V0/hEtaPhi_Photon_Primary"), v0.phi(), v0.eta()); - fRegistry.fill(HIST("V0/hXY_Photon_Primary"), v0.vx(), v0.vy()); - fRegistry.fill(HIST("V0/hXY_Photon_Primary_MC"), posmc.vx(), posmc.vy()); - fRegistry.fill(HIST("V0/hRZ_Photon_Primary"), v0.vz(), rxy_rec); - fRegistry.fill(HIST("V0/hRZ_Photon_Primary_MC"), posmc.vz(), rxy_mc); - fRegistry.fill(HIST("V0/hCosPA_Rxy_Photon_Primary"), v0.v0radius(), v0.cospa()); - fRegistry.fill(HIST("V0/hPtGen_DeltaPtOverPtGen"), mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); - fRegistry.fill(HIST("V0/hPtGen_DeltaEta"), mcphoton.pt(), v0.eta() - mcphoton.eta()); - fRegistry.fill(HIST("V0/hPtGen_DeltaPhi"), mcphoton.pt(), v0.phi() - mcphoton.phi()); - fRegistry.fill(HIST("V0/hEtaRec_DeltaPtOverPtGen"), eta_cp, (v0.pt() - mcphoton.pt()) / mcphoton.pt()); - fRegistry.fill(HIST("V0/hEtaRec_DeltaEta"), eta_cp, v0.eta() - mcphoton.eta()); - fRegistry.fill(HIST("V0/hEtaRec_DeltaPhi"), eta_cp, v0.phi() - mcphoton.phi()); - fRegistry.fill(HIST("V0/hConvPoint_diffX"), elemc.vx(), v0.vx() - elemc.vx()); - fRegistry.fill(HIST("V0/hConvPoint_diffY"), elemc.vy(), v0.vy() - elemc.vy()); - fRegistry.fill(HIST("V0/hConvPoint_diffZ"), elemc.vz(), v0.vz() - elemc.vz()); - - for (auto& leg : {pos, ele}) { - fillV0LegInfo(leg, 1.f); - auto mcleg = leg.template emmcparticle_as(); - fRegistry.fill(HIST("V0Leg/hPtGen_DeltaPtOverPtGen"), mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); - fRegistry.fill(HIST("V0Leg/hPtGen_DeltaEta"), mcleg.pt(), leg.eta() - mcleg.eta()); - fRegistry.fill(HIST("V0Leg/hPtGen_DeltaPhi"), mcleg.pt(), leg.phi() - mcleg.phi()); - fRegistry.fill(HIST("V0Leg/hEtaRec_DeltaPtOverPtGen"), eta_cp, (leg.pt() - mcleg.pt()) / mcleg.pt()); - fRegistry.fill(HIST("V0Leg/hEtaRec_DeltaEta"), eta_cp, leg.eta() - mcleg.eta()); - fRegistry.fill(HIST("V0Leg/hEtaRec_DeltaPhi"), eta_cp, leg.phi() - mcleg.phi()); - } - } else if (IsFromWD(mcphoton.template emmcevent_as(), mcphoton, mcparticles) > 0) { - fRegistry.fill(HIST("V0/hPt_Photon_FromWD"), v0.pt()); - fRegistry.fill(HIST("V0/hEtaPhi_Photon_FromWD"), v0.phi(), v0.eta()); - fRegistry.fill(HIST("V0/hCosPA_Rxy_Photon_FromWD"), v0.v0radius(), v0.cospa()); - } else { - // LOGF(info, "mcphoton.vx() = %f, mcphoton.vy() = %f, mcphoton.vz() = %f, mother_pdg = %d", mcphoton.vx(), mcphoton.vy(), mcphoton.vz(), mother_pdg); - float rxy_photon_hs = sqrt(mcphoton.vx() * mcphoton.vx() + mcphoton.vy() * mcphoton.vy()); - fRegistry.fill(HIST("V0/hPt_Photon_hs"), v0.pt()); - fRegistry.fill(HIST("V0/hEtaPhi_Photon_hs"), v0.phi(), v0.eta()); - fRegistry.fill(HIST("V0/hXY_Photon_hs_MC"), mcphoton.vx(), mcphoton.vy()); - fRegistry.fill(HIST("V0/hRZ_Photon_hs_MC"), mcphoton.vz(), rxy_photon_hs); - fRegistry.fill(HIST("V0/hCosPA_Rxy_Photon_hs"), v0.v0radius(), v0.cospa()); - } + ng_wd++; + } else { + fillV0Info<2>(v0, mcphoton, elemc); + for (auto& leg : {pos, ele}) { + fillV0LegInfo<2>(leg); } + ng_hs++; + // LOGF(info, "mcphoton.vx() = %f, mcphoton.vy() = %f, mcphoton.vz() = %f, mother_pdg = %d", mcphoton.vx(), mcphoton.vy(), mcphoton.vz(), mother_pdg); } } // end of v0 loop - fRegistry.fill(HIST("V0/hNgamma"), nv0); + fRegistry.fill(HIST("V0/primary/hNgamma"), ng_primary); + fRegistry.fill(HIST("V0/fromWD/hNgamma"), ng_wd); + fRegistry.fill(HIST("V0/fromHS/hNgamma"), ng_hs); } // end of collision loop - } // end of process + } // end of process template void fillBinnedData(TBinnedData const& binned_data, const float weight = 1.f) @@ -513,7 +500,7 @@ struct PCMQCMC { // all MC tracks which belong to the MC event corresponding to the current reconstructed event for (auto& collision : collisions) { - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -533,7 +520,7 @@ struct PCMQCMC { continue; } - if (abs(mctrack.pdgCode()) == 22 && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator()) && IsConversionPointInAcceptance(mctrack, maxRgen, pcmcuts.cfg_max_eta_v0, margin_z_mc, mcparticles)) { + if (abs(mctrack.pdgCode()) == 22 && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { fRegistry.fill(HIST("Generated/hPt_ConvertedPhoton"), mctrack.pt()); fRegistry.fill(HIST("Generated/hY_ConvertedPhoton"), mctrack.y()); fRegistry.fill(HIST("Generated/hPhi_ConvertedPhoton"), mctrack.phi()); @@ -544,7 +531,7 @@ struct PCMQCMC { fRegistry.fill(HIST("Generated/hPhotonPhivsRxy"), daughter.phi(), rxy_gen_e); } } // end of mctrack loop per collision - } // end of collision loop + } // end of collision loop } void processDummy(MyCollisions const&) {} diff --git a/PWGEM/PhotonMeson/Utils/ClusterHistograms.h b/PWGEM/PhotonMeson/Utils/ClusterHistograms.h new file mode 100644 index 00000000000..74f3db1b2cf --- /dev/null +++ b/PWGEM/PhotonMeson/Utils/ClusterHistograms.h @@ -0,0 +1,78 @@ +// 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. + +/// Header file for histograms used in EMC cluster QA +/// \author nicolas.strangmann@cern.ch + +#ifndef PWGEM_PHOTONMESON_UTILS_CLUSTERHISTOGRAMS_H_ +#define PWGEM_PHOTONMESON_UTILS_CLUSTERHISTOGRAMS_H_ + +using namespace o2::framework; + +namespace o2::aod::pwgem::photonmeson::utils::clusterhistogram +{ +void addClusterHistograms(HistogramRegistry* fRegistry, bool do2DQA) +{ + fRegistry->add("Cluster/before/hE", "E_{cluster};#it{E}_{cluster} (GeV);#it{N}_{cluster}", kTH1F, {{500, 0, 50}}, true); + fRegistry->add("Cluster/before/hPt", "Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{cluster}", kTH1F, {{1000, 0.0f, 20}}, true); + fRegistry->add("Cluster/before/hNgamma", "Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}", kTH1F, {{101, -0.5f, 100.5f}}, true); + fRegistry->add("Cluster/before/hEtaPhi", "#eta vs #varphi;#eta;#varphi (rad.)", kTH2F, {{200, -1.0f, 1.0f}, {180, 0, 2 * M_PI}}, true); + fRegistry->add("Cluster/before/hTrackEtaPhi", "d#eta vs. d#varphi of matched tracks;d#eta;d#varphi (rad.)", kTH2F, {{100, -0.5, 0.5}, {100, -0.5, 0.5}}, true); + + if (do2DQA) { // Check if 2D QA histograms were selected in em-qc task + fRegistry->add("Cluster/before/hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{E}_{cluster} (GeV)", kTH2F, {{51, -0.5, 50.5}, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{E}_{cluster} (GeV)", kTH2F, {{500, 0, 5}, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{E}_{cluster} (GeV)", kTH2F, {{100, -250, 250}, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hCellTime", "Cell time;#it{t}_{cell} (ns);#it{E}_{cluster} (GeV)", kTH2F, {{100, -250, 250}, {200, 0, 20}}, true); + } else { + fRegistry->add("Cluster/before/hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{N}_{cluster}", kTH1F, {{51, -0.5, 50.5}}, true); + fRegistry->add("Cluster/before/hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{N}_{cluster}", kTH1F, {{500, 0, 5}}, true); + fRegistry->add("Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{N}_{cluster}", kTH1F, {{500, -250, 250}}, true); + fRegistry->add("Cluster/before/hCellTime", "Cluster time;#it{t}_{cell} (ns);#it{N}_{cluster}", kTH1F, {{500, -250, 250}}, true); + } + + auto hClusterQualityCuts = fRegistry->add("Cluster/hClusterQualityCuts", "Energy at which clusters are removed by a given cut;;#it{E} (GeV)", kTH2F, {{8, -0.5, 7.5}, {500, 0, 50}}, true); + hClusterQualityCuts->GetXaxis()->SetBinLabel(1, "In"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(2, "Energy"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(3, "NCell"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(4, "M02"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(5, "Timing"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(6, "Track matching"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(7, "Exotic"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(8, "Out"); + + fRegistry->addClone("Cluster/before/", "Cluster/after/"); +} + +template +void fillClusterHistograms(HistogramRegistry* fRegistry, SkimEMCCluster cluster, bool do2DQA, float weight = 1.f) +{ + static constexpr std::string_view cluster_types[2] = {"before/", "after/"}; + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hE"), cluster.e(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hPt"), cluster.pt(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hEtaPhi"), cluster.eta(), cluster.phi(), weight); + for (size_t itrack = 0; itrack < cluster.tracketa().size(); itrack++) { // Fill TrackEtaPhi histogram with delta phi and delta eta of all tracks saved in the vectors in skimmerGammaCalo.cxx + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackEtaPhi"), cluster.tracketa()[itrack] - cluster.eta(), cluster.trackphi()[itrack] - cluster.phi(), weight); + } + if (do2DQA) { + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hNCell"), cluster.nCells(), cluster.e(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hM02"), cluster.m02(), cluster.e(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTime"), cluster.time(), cluster.e(), weight); + } else { + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hNCell"), cluster.nCells(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hM02"), cluster.m02(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTime"), cluster.time(), weight); + } +} + +} // namespace o2::aod::pwgem::photonmeson::utils::clusterhistogram + +#endif // PWGEM_PHOTONMESON_UTILS_CLUSTERHISTOGRAMS_H_ diff --git a/PWGEM/PhotonMeson/Utils/EventHistograms.h b/PWGEM/PhotonMeson/Utils/EventHistograms.h index 4d4fb0f5a1e..fd6f6f31f7f 100644 --- a/PWGEM/PhotonMeson/Utils/EventHistograms.h +++ b/PWGEM/PhotonMeson/Utils/EventHistograms.h @@ -18,10 +18,10 @@ using namespace o2::framework; namespace o2::aod::pwgem::photonmeson::utils::eventhistogram { -void addEventHistograms(HistogramRegistry* fRegistry, bool doFlow) +void addEventHistograms(HistogramRegistry* fRegistry) { // event info - auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); + auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{12, 0.5, 12.5}}, false); hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); @@ -31,7 +31,9 @@ void addEventHistograms(HistogramRegistry* fRegistry, bool doFlow) hCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); hCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); hCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); - hCollisionCounter->GetXaxis()->SetBinLabel(10, "accepted"); + hCollisionCounter->GetXaxis()->SetBinLabel(10, "EMC MB Readout"); + hCollisionCounter->GetXaxis()->SetBinLabel(11, "EMC L0 Triggered"); + hCollisionCounter->GetXaxis()->SetBinLabel(12, "accepted"); fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); @@ -43,46 +45,11 @@ void addEventHistograms(HistogramRegistry* fRegistry, bool doFlow) fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {500, 0, 5000}}, false); fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {500, 0, 5000}}, false); fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{60, 0, 60000}, {2000, 0, 20000}}, false); - - if (doFlow) { - fRegistry->add("Event/before/hQ2xFT0M_CentFT0C", "hQ2xFT0M_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0M}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFT0M_CentFT0C", "hQ2yFT0M_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0M}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xFT0A_CentFT0C", "hQ2xFT0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0A}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFT0A_CentFT0C", "hQ2yFT0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0A}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xFT0C_CentFT0C", "hQ2xFT0C_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0C}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFT0C_CentFT0C", "hQ2yFT0C_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0C}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xFV0A_CentFT0C", "hQ2xFV0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FV0A}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFV0A_CentFT0C", "hQ2yFV0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FV0A}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xBPos_CentFT0C", "hQ2xBPos_CentFT0C;centrality FT0C (%);Q_{2,x}^{BPos}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yBPos_CentFT0C", "hQ2yBPos_CentFT0C;centrality FT0C (%);Q_{2,y}^{BPos}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xBNeg_CentFT0C", "hQ2xBNeg_CentFT0C;centrality FT0C (%);Q_{2,x}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yBNeg_CentFT0C", "hQ2yBNeg_CentFT0C;centrality FT0C (%);Q_{2,y}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - - fRegistry->add("Event/before/hEP2FT0M_CentFT0C", "2nd harmonics event plane FT0M;centrality FT0C (%);#Psi_{2}^{FT0M} (rad.)", kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP2FT0A_CentFT0C", "2nd harmonics event plane FT0A;centrality FT0C (%);#Psi_{2}^{FT0A} (rad.)", kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP2FT0C_CentFT0C", "2nd harmonics event plane FT0C;centrality FT0C (%);#Psi_{2}^{FT0C} (rad.)", kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP2FV0A_CentFT0C", "2nd harmonics event plane FV0A;centrality FT0C (%);#Psi_{2}^{FV0A} (rad.)", kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP2BPos_CentFT0C", "2nd harmonics event plane BPos;centrality FT0C (%);#Psi_{2}^{BPos} (rad.)", kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP2BNeg_CentFT0C", "2nd harmonics event plane BNeg;centrality FT0C (%);#Psi_{2}^{BNeg} (rad.)", kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); - - fRegistry->add("Event/before/hQ2FT0MQ2BPos_CentFT0C", "Q_{2}^{FT0M} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0M} #upoint Q_{2}^{BPos}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2FT0MQ2BNeg_CentFT0C", "Q_{2}^{FT0M} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FT0M} #upoint Q_{2}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2BPosQ2BNeg_CentFT0C", "Q_{2}^{BPos} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{BPos} #upoint Q_{2}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); // this is common for FT0M, FT0A, FT0C, FV0A resolution. - - fRegistry->add("Event/before/hQ2FT0CQ2BPos_CentFT0C", "Q_{2}^{FT0C} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0C} #upoint Q_{2}^{BPos}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2FT0CQ2BNeg_CentFT0C", "Q_{2}^{FT0C} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FT0C} #upoint Q_{2}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - - fRegistry->add("Event/before/hQ2FT0AQ2BPos_CentFT0C", "Q_{2}^{FT0A} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0A} #upoint Q_{2}^{BPos}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2FT0AQ2BNeg_CentFT0C", "Q_{2}^{FT0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FT0A} #upoint Q_{2}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - - fRegistry->add("Event/before/hQ2FV0AQ2BPos_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BPos}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2FV0AQ2BNeg_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BNeg}", kTH2F, {{110, 0, 110}, {200, -10, +10}}, false); - } fRegistry->addClone("Event/before/", "Event/after/"); } template -void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, const bool doFlow, const float /*weight*/ = 1.f) +void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision) { static constexpr std::string_view event_types[2] = {"before/", "after/"}; fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); @@ -111,6 +78,12 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); } fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); + if (collision.alias_bit(kTVXinEMC)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 10.0); + } + if (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7)) { + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 11.0); + } fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); @@ -121,45 +94,6 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); - - if (doFlow) { - std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; - std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; - std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; - // std::array q2fv0a = {collision.q2xfv0a(), collision.q2yfv0a()}; - std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; - std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; - - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFT0M_CentFT0C"), collision.centFT0C(), collision.q2xft0m()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFT0M_CentFT0C"), collision.centFT0C(), collision.q2yft0m()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFT0A_CentFT0C"), collision.centFT0C(), collision.q2xft0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFT0A_CentFT0C"), collision.centFT0C(), collision.q2yft0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFT0C_CentFT0C"), collision.centFT0C(), collision.q2xft0c()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFT0C_CentFT0C"), collision.centFT0C(), collision.q2yft0c()); - // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xFV0A_CentFT0C"), collision.centFT0C(), collision.q2xfv0a()); - // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yFV0A_CentFT0C"), collision.centFT0C(), collision.q2yfv0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xBPos_CentFT0C"), collision.centFT0C(), collision.q2xbpos()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yBPos_CentFT0C"), collision.centFT0C(), collision.q2ybpos()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2xBNeg_CentFT0C"), collision.centFT0C(), collision.q2xbneg()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2yBNeg_CentFT0C"), collision.centFT0C(), collision.q2ybneg()); - - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FT0M_CentFT0C"), collision.centFT0C(), collision.ep2ft0m()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FT0A_CentFT0C"), collision.centFT0C(), collision.ep2ft0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FT0C_CentFT0C"), collision.centFT0C(), collision.ep2ft0c()); - // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2FV0A_CentFT0C"), collision.centFT0C(), collision.ep2fv0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2BPos_CentFT0C"), collision.centFT0C(), collision.ep2bpos()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP2BNeg_CentFT0C"), collision.centFT0C(), collision.ep2bneg()); - - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FT0MQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0m, q2bpos)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FT0MQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0m, q2bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FT0AQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0a, q2bpos)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FT0AQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0a, q2bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FT0CQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0c, q2bpos)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FT0CQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2ft0c, q2bneg)); - // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FV0AQ2BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2fv0a, q2bpos)); - // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2FV0AQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2fv0a, q2bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ2BPosQ2BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q2bpos, q2bneg)); - } } } // namespace o2::aod::pwgem::photonmeson::utils::eventhistogram diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 748f5f46c7d..0d9fe36920c 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -20,7 +20,7 @@ #include "Framework/AnalysisTask.h" //_______________________________________________________________________ -namespace o2::aod::pwgem::mcutil +namespace o2::aod::pwgem::photonmeson::utils::mcutil { template bool IsPhysicalPrimary(TTrack const& mctrack) @@ -122,101 +122,6 @@ int IsEleFromPC(T const& mctrack, TMCs const& mcTracks) return -1; } //_______________________________________________________________________ -template -int FindCommonMotherFrom2Prongs(TMCParticle1 const& p1, TMCParticle2 const& p2, const int expected_pdg1, const int expected_pdg2, const int expected_mother_pdg, TMCParticles const& mcparticles) -{ - if (p1.globalIndex() == p2.globalIndex()) - return -1; // mc particle p1 and p2 is identical. reject. - - if (p1.pdgCode() != expected_pdg1) - return -1; - if (p2.pdgCode() != expected_pdg2) - return -1; - - if (!p1.has_mothers()) - return -1; - if (!p2.has_mothers()) - return -1; - - // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); - - int motherid1 = p1.mothersIds()[0]; - auto mother1 = mcparticles.iteratorAt(motherid1); - int mother1_pdg = mother1.pdgCode(); - - int motherid2 = p2.mothersIds()[0]; - auto mother2 = mcparticles.iteratorAt(motherid2); - int mother2_pdg = mother2.pdgCode(); - - // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); - - if (motherid1 != motherid2) - return -1; - if (mother1_pdg != mother2_pdg) - return -1; - if (mother1_pdg != expected_mother_pdg) - return -1; - return motherid1; -} -template -int FindCommonMotherFrom3Prongs(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticle3 const& p3, const int expected_pdg1, const int expected_pdg2, const int expected_pdg3, const int expected_mother_pdg, TMCParticles const& mcparticles) -{ - if (p1.globalIndex() == p2.globalIndex()) - return -1; // mc particle p1 and p2 are identical. reject. - if (p2.globalIndex() == p3.globalIndex()) - return -1; // mc particle p2 and p3 are identical. reject. - if (p3.globalIndex() == p1.globalIndex()) - return -1; // mc particle p3 and p1 are identical. reject. - - if (p1.pdgCode() != expected_pdg1) - return -1; - if (p2.pdgCode() != expected_pdg2) - return -1; - if (p3.pdgCode() != expected_pdg3) - return -1; - - if (!p1.has_mothers()) - return -1; - if (!p2.has_mothers()) - return -1; - if (!p3.has_mothers()) - return -1; - - // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); - - int motherid1 = p1.mothersIds()[0]; - auto mother1 = mcparticles.iteratorAt(motherid1); - int mother1_pdg = mother1.pdgCode(); - - int motherid2 = p2.mothersIds()[0]; - auto mother2 = mcparticles.iteratorAt(motherid2); - int mother2_pdg = mother2.pdgCode(); - - int motherid3 = p3.mothersIds()[0]; - auto mother3 = mcparticles.iteratorAt(motherid3); - int mother3_pdg = mother3.pdgCode(); - - // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); - - if (motherid1 != motherid2) - return -1; - if (motherid2 != motherid3) - return -1; - if (motherid3 != motherid1) - return -1; - - if (mother1_pdg != mother2_pdg) - return -1; - if (mother2_pdg != mother3_pdg) - return -1; - if (mother3_pdg != mother1_pdg) - return -1; - - if (mother1_pdg != expected_mother_pdg) - return -1; - return motherid1; -} -//_______________________________________________________________________ template bool IsInAcceptanceNonDerived(TMCParticle const& mcparticle, TMCParticles const& mcparticles, TTargetPDGs target_pdgs, const float ymin, const float ymax, const float phimin, const float phimax) { @@ -351,7 +256,7 @@ bool IsConversionPointInAcceptance(TMCPhoton const& mcphoton, const float max_r_ return true; } //_______________________________________________________________________ -} // namespace o2::aod::pwgem::mcutil +} // namespace o2::aod::pwgem::photonmeson::utils::mcutil //_______________________________________________________________________ //_______________________________________________________________________ #endif // PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Utils/NMHistograms.h b/PWGEM/PhotonMeson/Utils/NMHistograms.h index 42bbe8cf2d1..95abaf92292 100644 --- a/PWGEM/PhotonMeson/Utils/NMHistograms.h +++ b/PWGEM/PhotonMeson/Utils/NMHistograms.h @@ -12,50 +12,43 @@ /// \header file for histograms /// \author daiki.sekihata@cern.ch +#ifndef PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ +#define PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ + #include #include "TF1.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#ifndef PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ -#define PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ - using namespace o2::framework; -using namespace o2::aod::photonpair; -using namespace o2::aod::pwgem::mcutil; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; namespace o2::aod::pwgem::photonmeson::utils::nmhistogram { -void addNMHistograms(HistogramRegistry* fRegistry, bool doFlow, bool isMC, const char* pairname = "#gamma#gamma", const char* epdetname = "") +void addNMHistograms(HistogramRegistry* fRegistry, bool isMC, const char* pairname = "#gamma#gamma") { // !!Don't change pt,eta,y binning. These binnings have to be consistent with binned data at skimming.!! std::vector ptbins; for (int i = 0; i < 2; i++) { - ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.1 GeV/c, every 0.05 GeV/c + ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c } - for (int i = 2; i < 52; i++) { - ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 5 GeV/c, every 0.1 GeV/c + for (int i = 2; i < 51; i++) { + ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c } - for (int i = 52; i < 62; i++) { - ptbins.emplace_back(0.5 * (i - 52) + 5.0); // from 5 to 10 GeV/c, evety 0.5 GeV/c + for (int i = 51; i < 61; i++) { + ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c } - for (int i = 62; i < 73; i++) { - ptbins.emplace_back(1.0 * (i - 62) + 10.0); // from 10 to 20 GeV/c, evety 1 GeV/c + for (int i = 61; i < 72; i++) { + ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c } const AxisSpec axis_pt{ptbins, Form("p_{T,%s} (GeV/c)", pairname)}; - const AxisSpec axis_mass{400, 0, 0.8, Form("m_{%s} (GeV/c^{2})", pairname)}; - int nbin_sp = 1; - if (doFlow && !isMC) { - nbin_sp = 100; - } - const AxisSpec axis_sp2{nbin_sp, -5.f, 5.f, Form("u_{2}^{%s} #upoint Q_{2}^{%s}", pairname, epdetname)}; - if (isMC) { - fRegistry->add("Pair/Pi0/hs_Primary", "rec. true pi0", kTHnSparseD, {axis_mass, axis_pt, axis_sp2}, true); - fRegistry->add("Pair/Pi0/hs_FromWD", "rec. true pi0 from weak decay", kTHnSparseD, {axis_mass, axis_pt, axis_sp2}, true); - fRegistry->add("Pair/Eta/hs_Primary", "rec. true eta", kTHnSparseD, {axis_mass, axis_pt, axis_sp2}, true); + fRegistry->add("Pair/Pi0/hs_Primary", "rec. true pi0", kTHnSparseD, {axis_mass, axis_pt}, true); + fRegistry->add("Pair/Pi0/hs_FromWD", "rec. true pi0 from weak decay", kTHnSparseD, {axis_mass, axis_pt}, true); + fRegistry->add("Pair/Pi0/hs_FromHS", "rec. true pi0 from hadronic shower in material", kTHnSparseD, {axis_mass, axis_pt}, true); + fRegistry->add("Pair/Eta/hs_Primary", "rec. true eta", kTHnSparseD, {axis_mass, axis_pt}, true); const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y|"}; fRegistry->add("Generated/Pi0/hPt", "pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); @@ -69,50 +62,35 @@ void addNMHistograms(HistogramRegistry* fRegistry, bool doFlow, bool isMC, const fRegistry->get(HIST("Generated/Eta/hPtY"))->SetXTitle("p_{T} (GeV/c)"); fRegistry->get(HIST("Generated/Eta/hPtY"))->SetYTitle("rapidity |y|"); } else { - fRegistry->add("Pair/same/hs", "2photon", kTHnSparseD, {axis_mass, axis_pt, axis_sp2}, true); + fRegistry->add("Pair/same/hs", "diphoton", kTHnSparseD, {axis_mass, axis_pt}, true); fRegistry->addClone("Pair/same/", "Pair/mix/"); } } -template -void fillPairInfo(HistogramRegistry* fRegistry, TCollision const& collision, TDiphoton const& diphoton, const bool doFlow, const float /*weight*/ = 1.f) -{ - static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; - if (doFlow) { - std::array q2ft0m = {collision.q2xft0m(), collision.q2yft0m()}; - std::array q2ft0a = {collision.q2xft0a(), collision.q2yft0a()}; - std::array q2ft0c = {collision.q2xft0c(), collision.q2yft0c()}; - std::array u2_gg = {static_cast(std::cos(2 * diphoton.Phi())), static_cast(std::sin(2 * diphoton.Phi()))}; - double sp2[3] = {RecoDecay::dotProd(u2_gg, q2ft0m), RecoDecay::dotProd(u2_gg, q2ft0a), RecoDecay::dotProd(u2_gg, q2ft0c)}; - - fRegistry->fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs"), diphoton.M(), diphoton.Pt(), sp2[ep_det_id]); - } else { - fRegistry->fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs"), diphoton.M(), diphoton.Pt(), 0.0); - } -} - template -void fillTruePairInfo(HistogramRegistry* fRegistry, TDiphoton const& v12, TMCParitlce const& mcparticle, TMCParticles const& mcparticles, TMCCollisions const&, const TF1* f1fd_k0s_to_pi0 = nullptr) +void fillTruePairInfo(HistogramRegistry* fRegistry, TDiphoton const& v12, TMCParitlce const& mcparticle, TMCParticles const& mcparticles, TMCCollisions const&, const TF1* f1fd_k0s_to_pi0 = nullptr, float eventWeight = 1.f) { int pdg = abs(mcparticle.pdgCode()); + float weight = eventWeight; switch (pdg) { case 111: { int motherid_strhad = IsFromWD(mcparticle.template emmcevent_as(), mcparticle, mcparticles); if (mcparticle.isPhysicalPrimary() || mcparticle.producedByGenerator()) { - fRegistry->fill(HIST("Pair/Pi0/hs_Primary"), v12.M(), v12.Pt(), 0.0); + fRegistry->fill(HIST("Pair/Pi0/hs_Primary"), v12.M(), v12.Pt(), weight); } else if (motherid_strhad > 0) { - float weight = 1.f; auto str_had = mcparticles.iteratorAt(motherid_strhad); if (abs(str_had.pdgCode()) == 310 && f1fd_k0s_to_pi0 != nullptr) { - weight = f1fd_k0s_to_pi0->Eval(str_had.pt()); + weight *= f1fd_k0s_to_pi0->Eval(str_had.pt()); } - fRegistry->fill(HIST("Pair/Pi0/hs_FromWD"), v12.M(), v12.Pt(), 0.0, weight); + fRegistry->fill(HIST("Pair/Pi0/hs_FromWD"), v12.M(), v12.Pt(), weight); + } else { + fRegistry->fill(HIST("Pair/Pi0/hs_FromHS"), v12.M(), v12.Pt(), weight); } break; } case 221: { if (mcparticle.isPhysicalPrimary() || mcparticle.producedByGenerator()) { - fRegistry->fill(HIST("Pair/Eta/hs_Primary"), v12.M(), v12.Pt(), 0.0); + fRegistry->fill(HIST("Pair/Eta/hs_Primary"), v12.M(), v12.Pt(), weight); } break; } diff --git a/PWGEM/PhotonMeson/Utils/PCMUtilities.h b/PWGEM/PhotonMeson/Utils/PCMUtilities.h index a75d80e4c65..63101c41418 100644 --- a/PWGEM/PhotonMeson/Utils/PCMUtilities.h +++ b/PWGEM/PhotonMeson/Utils/PCMUtilities.h @@ -47,20 +47,11 @@ inline float v0_qt(float pxpos, float pypos, float pzpos, float pxneg, float pyn return std::sqrt(RecoDecay::p2(pxneg, pyneg, pzneg) - dp * dp / momTot); // qt of v0 } //_______________________________________________________________________ -template -inline void Vtx_recalculation(o2::base::Propagator* prop, T1 lTrackPos, T2 lTrackNeg, float xyz[3], o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE) +template +inline void Vtx_recalculationParCov(o2::base::Propagator* prop, const o2::track::TrackParametrizationWithError& trackPosInformation, const o2::track::TrackParametrizationWithError& trackNegInformation, float xyz[3], o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE) { float bz = prop->getNominalBz(); - //******************************************************* - - // o2::track::TrackParametrizationWithError = TrackParCov, I use the full version to have control over the data type - o2::track::TrackParametrizationWithError trackPosInformation = getTrackParCov(lTrackPos); // first get an object that stores Track information (positive) - o2::track::TrackParametrizationWithError trackNegInformation = getTrackParCov(lTrackNeg); // first get an object that stores Track information (negative) - - // trackPosInformation.setPID(o2::track::PID::Electron); - // trackNegInformation.setPID(o2::track::PID::Electron); - o2::track::TrackAuxPar helixPos(trackPosInformation, bz); // This object is a descendant of a CircleXY and stores cirlce information with respect to the magnetic field. This object uses functions and information of the o2::track::TrackParametrizationWithError object (positive) o2::track::TrackAuxPar helixNeg(trackNegInformation, bz); // This object is a descendant of a CircleXY and stores cirlce information with respect to the magnetic field. This object uses functions and information of the o2::track::TrackParametrizationWithError object (negative) @@ -68,10 +59,8 @@ inline void Vtx_recalculation(o2::base::Propagator* prop, T1 lTrackPos, T2 lTrac xyz[1] = (helixPos.yC * helixNeg.rC + helixNeg.yC * helixPos.rC) / (helixPos.rC + helixNeg.rC); // If this calculation doesn't work check if the rotateZ function, because the "documentation" says I get global coordinates but maybe i don't. // I am unsure about the Z calculation but this is how it is done in AliPhysics as far as I understand - o2::track::TrackParametrizationWithError trackPosInformationCopy = o2::track::TrackParametrizationWithError(trackPosInformation); - o2::track::TrackParametrizationWithError trackNegInformationCopy = o2::track::TrackParametrizationWithError(trackNegInformation); - // trackPosInformationCopy.setPID(o2::track::PID::Electron); - // trackNegInformationCopy.setPID(o2::track::PID::Electron); + auto trackPosInformationCopy = trackPosInformation; + auto trackNegInformationCopy = trackNegInformation; // I think this calculation gets the closest point on the track to the conversion point // This alpha is a different alpha than the usual alpha and I think it is the angle between X axis and conversion point @@ -106,112 +95,89 @@ inline void Vtx_recalculation(o2::base::Propagator* prop, T1 lTrackPos, T2 lTrac xyz[2] = (trackPosInformationCopy.getZ() * helixNeg.rC + trackNegInformationCopy.getZ() * helixPos.rC) / (helixPos.rC + helixNeg.rC); } //_______________________________________________________________________ -inline float getPhivPair(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, int cpos, int cneg, float bz) +template +inline void Vtx_recalculation(o2::base::Propagator* prop, T1 lTrackPos, T2 lTrackNeg, float xyz[3], o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE) { - // cos(phiv) = w*a /|w||a| - // with w = u x v - // and a = u x z / |u x z| , unit vector perpendicular to v12 and z-direction (magnetic field) - // u = v12 / |v12| , the unit vector of v12 - // v = v1 x v2 / |v1 x v2| , unit vector perpendicular to v1 and v2 - - // momentum of e+ and e- in (ax,ay,az) axis. Note that az=0 by definition. - // vector product of pep X pem - // std::array arr_pos{t1.GetPx(), t1.GetPy(), t1.GetPz()}; - // std::array arr_ele{t2.GetPx(), t2.GetPy(), t2.GetPz()}; - std::array arr_pos{pxpos, pypos, pzpos}; - std::array arr_ele{pxneg, pyneg, pzneg}; - std::array pos_x_ele{0, 0, 0}; - // LOGF(info, "Q1 = %d , Q2 = %d", cpos, cneg); - - if (cpos * cneg > 0) { // Like Sign - if (bz < 0) { - if (cpos > 0) { - pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); - } else { - pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); - } - } else { - if (cpos > 0) { - pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); - } else { - pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); - } - } - } else { // Unlike Sign - if (bz > 0) { - if (cpos > 0) { - pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); - } else { - pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); - } - } else { - if (cpos > 0) { - pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); - } else { - pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); - } - } - } - - // unit vector of pep X pem - float vx = pos_x_ele[0] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); - float vy = pos_x_ele[1] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); - float vz = pos_x_ele[2] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); - - // unit vector of (pep+pem) - float ux = (pxpos + pxneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); - float uy = (pypos + pyneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); - float uz = (pzpos + pzneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); - - float ax = uy / std::sqrt(ux * ux + uy * uy); - float ay = -ux / std::sqrt(ux * ux + uy * uy); - - // The third axis defined by vector product (ux,uy,uz)X(vx,vy,vz) - float wx = uy * vz - uz * vy; - float wy = uz * vx - ux * vz; - // by construction, (wx,wy,wz) must be a unit vector. Measure angle between (wx,wy,wz) and (ax,ay,0). - // The angle between them should be small if the pair is conversion. This function then returns values close to pi! - auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; - - // if (!std::isfinite(std::acos(wx * ax + wy * ay))) { - // LOGF(info, "pxpos = %f, pypos = %f, pzpos = %f", pxpos, pypos, pzpos); - // LOGF(info, "pxneg = %f, pyneg = %f, pzneg = %f", pxneg, pyneg, pzneg); - // LOGF(info, "pos_x_ele[0] = %f, pos_x_ele[1] = %f, pos_x_ele[2] = %f", pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); - // LOGF(info, "ux = %f, uy = %f, uz = %f", ux, uy, uz); - // LOGF(info, "ax = %f, ay = %f", ax, ay); - // LOGF(info, "wx = %f, wy = %f", wx, wy); - // LOGF(info, "wx * ax + wy * ay = %f", wx * ax + wy * ay); - // LOGF(info, "std::acos(wx * ax + wy * ay) = %f", std::acos(wx * ax + wy * ay)); - // LOGF(info, "std::acos(clipToPM1(wx * ax + wy * ay)) = %f", std::acos(clipToPM1(wx * ax + wy * ay))); - // } + // o2::track::TrackParametrizationWithError = TrackParCov, I use the full version to have control over the data type + o2::track::TrackParametrizationWithError trackPosInformation = getTrackParCov(lTrackPos); // first get an object that stores Track information (positive) + o2::track::TrackParametrizationWithError trackNegInformation = getTrackParCov(lTrackNeg); // first get an object that stores Track information (negative) - return std::acos(clipToPM1(wx * ax + wy * ay)); // phiv in [0,pi] //cosPhiV = wx * ax + wy * ay; + Vtx_recalculationParCov(prop, trackPosInformation, trackNegInformation, xyz, matCorr); } //_______________________________________________________________________ -inline float getPsiPair(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) +template +float getPtResolution(TV0 const& v0) { - // float pxpos = t1.GetPx(); - // float pypos = t1.GetPy(); - // float pzpos = t1.GetPz(); - // float pxneg = t2.GetPx(); - // float pyneg = t2.GetPy(); - // float pzneg = t2.GetPz(); - - auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; - float ptot2 = RecoDecay::p2(pxpos, pypos, pzpos) * RecoDecay::p2(pxneg, pyneg, pzneg); - float argcos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); - float thetaPos = std::atan2(RecoDecay::sqrtSumOfSquares(pxpos, pypos), pzpos); - float thetaNeg = std::atan2(RecoDecay::sqrtSumOfSquares(pxneg, pyneg), pzneg); - float argsin = (thetaNeg - thetaPos) / std::acos(clipToPM1(argcos)); - return std::asin(clipToPM1(argsin)); + float px = v0.px(); + float py = v0.py(); + float pt = v0.pt(); + float px_err = std::sqrt(fabs(v0.sigmaPx2())); + float py_err = std::sqrt(fabs(v0.sigmaPy2())); + float pxy_err = v0.sigmaPxPy(); + return std::sqrt(std::pow(px / pt * px_err, 2) + std::pow(py / pt * py_err, 2) + 2.f * px / pt * py / pt * pxy_err); +} +//_______________________________________________________________________ +template +float getPhiResolution(TV0 const& v0) +{ + float px = v0.px(); + float py = v0.py(); + float pt = v0.pt(); + float px_err = std::sqrt(fabs(v0.sigmaPx2())); + float py_err = std::sqrt(fabs(v0.sigmaPy2())); + float pxy_err = v0.sigmaPxPy(); + return std::sqrt(std::pow(px / pt / pt * py_err, 2) + std::pow(py / pt / pt * px_err, 2) - 2.f * px / pt / pt * py / pt / pt * pxy_err); +} +//_______________________________________________________________________ +template +float getThetaResolution(TV0 const& v0) +{ + float px = v0.px(); + float py = v0.py(); + float pz = v0.pz(); + float pt = v0.pt(); + float p = v0.p(); + float px_err = std::sqrt(fabs(v0.sigmaPx2())); + float py_err = std::sqrt(fabs(v0.sigmaPy2())); + float pz_err = std::sqrt(fabs(v0.sigmaPz2())); + float pxy_err = v0.sigmaPxPy(); + float pyz_err = v0.sigmaPyPz(); + float pzx_err = v0.sigmaPzPx(); + return std::sqrt(std::pow(pz * pz / p / p, 2) * (std::pow(px / pz / pt * px_err, 2) + std::pow(py / pz / pt * py_err, 2) + std::pow(pt / pz / pz * pz_err, 2) + 2.f * (px * py / pz / pz / pt / pt * pxy_err - py / pz / pz / pz * pyz_err - px / pz / pz / pz * pzx_err))); } //_______________________________________________________________________ -inline float getOpeningAngle(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) +template +float getEtaResolution(TV0 const& v0) { - auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; - float ptot2 = RecoDecay::p2(pxpos, pypos, pzpos) * RecoDecay::p2(pxneg, pyneg, pzneg); - float argcos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); - return std::acos(clipToPM1(argcos)); + float px = v0.px(); + float py = v0.py(); + float pz = v0.pz(); + float pt = v0.pt(); + float p = v0.p(); + float px_err = std::sqrt(fabs(v0.sigmaPx2())); + float py_err = std::sqrt(fabs(v0.sigmaPy2())); + float pz_err = std::sqrt(fabs(v0.sigmaPz2())); + float pxy_err = v0.sigmaPxPy(); + float pyz_err = v0.sigmaPyPz(); + float pzx_err = v0.sigmaPzPx(); + return std::sqrt(std::pow(1.f / p / pt / pt, 2) * (std::pow(pz * px * px_err, 2) + std::pow(pz * py * py_err, 2) + std::pow(pt * pt * pz_err, 2) + 2.f * (pz * pz * px * py * pxy_err - pt * pt * py * pz * pyz_err - pt * pt * pz * px * pzx_err))); } //_______________________________________________________________________ +template +float getPResolution(TV0 const& v0) +{ + float px = v0.px(); + float py = v0.py(); + float pz = v0.pz(); + float p = v0.p(); + float px_err = std::sqrt(fabs(v0.sigmaPx2())); + float py_err = std::sqrt(fabs(v0.sigmaPy2())); + float pz_err = std::sqrt(fabs(v0.sigmaPz2())); + float pxy_err = v0.sigmaPxPy(); + float pyz_err = v0.sigmaPyPz(); + float pzx_err = v0.sigmaPzPx(); + return std::sqrt(std::pow(1.f / p, 2) * (std::pow(px * px_err, 2) + std::pow(py * py_err, 2) + std::pow(pz * pz_err, 2) + 2.f * (px * py * pxy_err + py * pz * pyz_err + pz * px * pzx_err))); +} +//_______________________________________________________________________ +//_______________________________________________________________________ #endif // PWGEM_PHOTONMESON_UTILS_PCMUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Utils/PairUtilities.h b/PWGEM/PhotonMeson/Utils/PairUtilities.h index 39b41bfd655..2277caea505 100644 --- a/PWGEM/PhotonMeson/Utils/PairUtilities.h +++ b/PWGEM/PhotonMeson/Utils/PairUtilities.h @@ -18,7 +18,7 @@ #include #include -namespace o2::aod::photonpair +namespace o2::aod::pwgem::photonmeson::photonpair { enum PairType { kPCMPCM = 0, @@ -29,7 +29,7 @@ enum PairType { kPCMDalitzEE = 5, kPCMDalitzMuMu = 6, kPHOSEMC = 7, - kDalitzEEDalitzEE = 8, + kEEEE = 8, // dielectron-dielectron kNpair, }; @@ -52,6 +52,6 @@ bool DoesV0LegMatchWithCluster(TV0Leg const& v0leg, TCluster const& cluster, con float Ep = cluster.e() / v0leg.p(); return (pow(deta / max_deta, 2) + pow(dphi / max_dphi, 2) < 1) && (abs(Ep - 1) < max_Ep_width); } -} // namespace o2::aod::photonpair +} // namespace o2::aod::pwgem::photonmeson::photonpair #endif // PWGEM_PHOTONMESON_UTILS_PAIRUTILITIES_H_ diff --git a/PWGEM/Tasks/phosElId.cxx b/PWGEM/Tasks/phosElId.cxx index 3899075fe04..327061dbfbc 100644 --- a/PWGEM/Tasks/phosElId.cxx +++ b/PWGEM/Tasks/phosElId.cxx @@ -40,6 +40,7 @@ #include "DetectorsBase/Propagator.h" #include "TF1.h" +#include "TLorentzVector.h" /// \struct PHOS electron id analysis /// \brief Task for calculating electron identification parameters @@ -50,14 +51,37 @@ /// using namespace o2; +using namespace o2::soa; using namespace o2::aod::evsel; using namespace o2::framework; using namespace o2::framework::expressions; +namespace o2::aod +{ +namespace PHOSMatch +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_INDEX_COLUMN(Track, track); +DECLARE_SOA_INDEX_COLUMN(CaloCluster, caloCluster); +DECLARE_SOA_COLUMN(SignalCharge, signalCharge, float); +DECLARE_SOA_COLUMN(SignalZ, signalZ, float); +DECLARE_SOA_COLUMN(SignalPx, signalPx, double); +DECLARE_SOA_COLUMN(SignalPy, signalPy, double); +DECLARE_SOA_COLUMN(SignalPz, signalPz, double); +DECLARE_SOA_COLUMN(SignalE, signalE, double); +} // namespace PHOSMatch + +DECLARE_SOA_TABLE(PHOSMatchindexTable, "AOD", "PHSMTCH", //! + o2::soa::Index<>, PHOSMatch::CollisionId, PHOSMatch::CaloClusterId, PHOSMatch::TrackId); //! + +} // namespace o2::aod + struct phosElId { + Produces phosMatch; + using SelCollisions = soa::Join; - using tracks = soa::Join; + using myTracks = soa::Join; Configurable mMinCluE{"mMinCluE", 0.3, "Minimum cluster energy for analysis"}; Configurable mMinCluTime{"minCluTime", -25.e-9, "Min. cluster time"}; @@ -77,21 +101,53 @@ struct phosElId { Configurable mEpmin{"mEpmin", -1., "Min for E/p histograms"}; Configurable mEpmax{"mEpmax", 3., "Max for E/p histograms"}; - Configurable> pSigma_dz{"pSigma_dz", {20., 0.76, 6.6, 3.6, 0.1}, "parameters for sigma dz function"}; - Configurable> pSigma_dx{"pSigma_dx", {3, 2.3, 3.1}, "parameters for sigma dx function"}; + Configurable> pSigma_dz{"pSigma_dz", {0.642, 0., 1.77, 2.725, 0.}, "parameters for sigma dz function"}; + Configurable> pSigma_dx{"pSigma_dx", {2.17769, 1.60275, 2.24136}, "parameters for sigma dx function"}; + + Configurable> pPhosShiftZ{"pPhosShiftZ", {4.78838, 2.75138, 1.40825, 2.28735}, "Phos coordinate centering Z per module"}; + Configurable> pPhosShiftX{"pPhosShiftX", {2.158702, -1.526772, -0.814658, -1.852678}, "Phos coordinate centering X per module"}; - Configurable> pPhosShiftZ{"pPhosShiftZ", {4.5, 3., 2., 2.}, "Phos coordinate centering Z per module"}; - Configurable> pPhosShiftX{"pPhosShiftX", {1.99, -0.63, -1.55, -1.63}, "Phos coordinate centering X per module"}; + Configurable> pMean_dx_pos_mod1{"pMean_dx_pos_mod1", {-10.57, -0.42, 1.06}, "parameters for mean dx function on module 1 for positive tracks"}; + Configurable> pMean_dx_pos_mod2{"pMean_dx_pos_mod2", {-8.1, -0.42, 1.14}, "parameters for mean dx function on module 2 for positive tracks"}; + Configurable> pMean_dx_pos_mod3{"pMean_dx_pos_mod3", {-8.34, -0.42, 1.04}, "parameters for mean dx function on module 3 for positive tracks"}; + Configurable> pMean_dx_pos_mod4{"pMean_dx_pos_mod4", {-7.38, -0.42, 1.17}, "parameters for mean dx function on module 4 for positive tracks"}; - Configurable> pMean_dx_pos_mod1{"pMean_dx_pos_mod1", {-9.57, -0.47, 1.04}, "parameters for mean dx function on module 1 for positive tracks"}; - Configurable> pMean_dx_pos_mod2{"pMean_dx_pos_mod2", {-12.24, -0.18, 1.59}, "parameters for mean dx function on module 2 for positive tracks"}; - Configurable> pMean_dx_pos_mod3{"pMean_dx_pos_mod3", {-5.73, -0.58, 1.13}, "parameters for mean dx function on module 3 for positive tracks"}; - Configurable> pMean_dx_pos_mod4{"pMean_dx_pos_mod4", {-5.14, -0.67, 1.05}, "parameters for mean dx function on module 4 for positive tracks"}; + Configurable> pMean_dx_neg_mod1{"pMean_dx_neg_mod1", {9.92, -0.42, 1.29}, "parameters for mean dx function on module 1 for negative tracks"}; + Configurable> pMean_dx_neg_mod2{"pMean_dx_neg_mod2", {7.82, -0.4, 1.34}, "parameters for mean dx function on module 2 for negative tracks"}; + Configurable> pMean_dx_neg_mod3{"pMean_dx_neg_mod3", {8.45, -0.33, 1.5}, "parameters for mean dx function on module 3 for negative tracks"}; + Configurable> pMean_dx_neg_mod4{"pMean_dx_neg_mod4", {7.5, -0.42, 1.25}, "parameters for mean dx function on module 4 for negative tracks"}; - Configurable> pMean_dx_neg_mod1{"pMean_dx_neg_mod1", {10.29, -0.42, 1.12}, "parameters for mean dx function on module 1 for negative tracks"}; - Configurable> pMean_dx_neg_mod2{"pMean_dx_neg_mod2", {8.24, -0.42, 1.31}, "parameters for mean dx function on module 2 for negative tracks"}; - Configurable> pMean_dx_neg_mod3{"pMean_dx_neg_mod3", {11.83, -0.17, 1.71}, "parameters for mean dx function on module 3 for negative tracks"}; - Configurable> pMean_dx_neg_mod4{"pMean_dx_neg_mod4", {84.96, 0.79, 2.83}, "parameters for mean dx function on module 4 for negative tracks"}; + Configurable cfgEtaMax{"cfgEtaMax", {0.8f}, "eta ranges"}; + Configurable cfgPtMin{"cfgPtMin", {0.2f}, "pt min"}; + Configurable cfgPtMax{"cfgPtMax", {20.f}, "pt max"}; + Configurable cfgDCAxyMax{"cfgDCAxyMax", {3.f}, "dcaxy max"}; + Configurable cfgDCAzMax{"cfgDCAzMax", {3.f}, "dcaz max"}; + Configurable cfgITSchi2Max{"cfgITSchi2Max", {5.f}, "its chi2 max"}; + Configurable cfgITSnclsMin{"cfgITSnclsMin", {4.5f}, "min number of ITS clusters"}; + Configurable cfgITSnclsMax{"cfgITSnclsMax", {7.5f}, "max number of ITS clusters"}; + Configurable cfgTPCchi2Max{"cfgTPCchi2Max", {4.f}, "tpc chi2 max"}; + Configurable cfgTPCnclsMin{"cfgTPCnclsMin", {90.f}, "min number of TPC clusters"}; + Configurable cfgTPCnclsMax{"cfgTPCnclsMax", {170.f}, "max number of TPC clusters"}; + Configurable cfgTPCnclsCRMin{"cfgTPCnclsCRMin", {80.f}, "min number of TPC crossed rows"}; + Configurable cfgTPCnclsCRMax{"cfgTPCnclsCRMax", {161.f}, "max number of TPC crossed rows"}; + Configurable cfgTPCNSigmaElMin{"cfgTPCNSigmaElMin", {-3.f}, "min TPC nsigma e for inclusion"}; + Configurable cfgTPCNSigmaElMax{"cfgTPCNSigmaElMax", {2.f}, "max TPC nsigma e for inclusion"}; + Configurable cfgTPCNSigmaPiMin{"cfgTPCNSigmaPiMin", {-3.f}, "min TPC nsigma pion for exclusion"}; + Configurable cfgTPCNSigmaPiMax{"cfgTPCNSigmaPiMax", {3.5f}, "max TPC nsigma pion for exclusion"}; + Configurable cfgTPCNSigmaPrMin{"cfgTPCNSigmaPrMin", {-3.f}, "min TPC nsigma proton for exclusion"}; + Configurable cfgTPCNSigmaPrMax{"cfgTPCNSigmaPrMax", {4.f}, "max TPC nsigma proton for exclusion"}; + Configurable cfgTPCNSigmaKaMin{"cfgTPCNSigmaKaMin", {-3.f}, "min TPC nsigma kaon for exclusion"}; + Configurable cfgTPCNSigmaKaMax{"cfgTPCNSigmaKaMax", {4.f}, "max TPC nsigma kaon for exclusion"}; + Configurable cfgTOFNSigmaElMin{"cfgTOFNSigmaElMin", {-3.f}, "min TOF nsigma e for inclusion"}; + Configurable cfgTOFNSigmaElMax{"cfgTOFNSigmaElMax", {3.f}, "max TOF nsigma e for inclusion"}; + + Filter ptFilter = (aod::track::pt > cfgPtMin) && (aod::track::pt < cfgPtMax); + Filter etafilter = nabs(aod::track::eta) < cfgEtaMax; + Filter dcaxyfilter = nabs(aod::track::dcaXY) < cfgDCAxyMax; + Filter dcazfilter = nabs(aod::track::dcaZ) < cfgDCAzMax; + Filter itschi2filter = aod::track::itsChi2NCl < cfgITSchi2Max; + Filter tpcchi2filter = aod::track::tpcChi2NCl < cfgTPCchi2Max; + Filter mapfilter = (aod::track::itsClusterMap & uint8_t(1)) > 0; Service ccdb; std::unique_ptr geomPHOS; @@ -115,9 +171,9 @@ struct phosElId { { LOG(info) << "Initializing PHOS electron identification analysis task ..."; - std::vector momentum_binning = {0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.8, 0.85, 0.9, 0.95, 1.0, + std::vector momentum_binning = {0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, - 4.5, 5.0, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 10.}; + 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 10.}; std::vector parameters_sigma_dz = pSigma_dz; std::vector parameters_sigma_dx = pSigma_dx; std::vector vPhosShiftX = pPhosShiftX; @@ -150,6 +206,7 @@ struct phosElId { axisEta{200, -0.2, 0.2, "#eta"}, axisPhi{80, 240, 320, "#varphi"}, axisE{200, 0, 10, "E (GeV)", "E (GeV)"}, + axisMassSpectrum{4000, 0, 4, "M (GeV/c^{2})", "Mass e^{+}e^{-} (GeV/c^{2})"}, axisEp{nBinsEp, mEpmin, mEpmax, "E/p", "E_{cluster}/p_{track}"}, axisdX{nBinsDeltaX, mDeltaXmin, mDeltaXmax, "x_{tr}-x_{clu} (cm)", "x_{tr}-x_{clu} (cm)"}, axisdZ{nBinsDeltaZ, mDeltaZmin, mDeltaZmax, "z_{tr}-z_{clu} (cm)", "z_{tr}-z_{clu} (cm)"}, @@ -160,10 +217,10 @@ struct phosElId { axisZ{150, -75., 75., "z (cm)", "z (cm)"}, axisDCATrackXY{400, -.1, .1, "DCA XY (cm)", "DCA XY (cm)"}, axisDCATrackZ{400, -.1, .1, "DCA Z (cm)", "DCA Z (cm)"}, - axisVColX{400, -.1, .1, "colision vertex x (cm)", "colision vertex x (cm)"}, // make 3 different histo + axisVColX{400, -.1, .1, "colision vertex x (cm)", "colision vertex x (cm)"}, axisVColY{400, -.1, .1, "colision vertex y (cm)", "colision vertex y (cm)"}, axisVColZ{400, -20., 20., "colision vertex z (cm)", "colision vertex z (cm)"}, // should look like gauss - axisVTrackX{400, -10., 10., "track vertex x (cm)", "track vertex x (cm)"}, // make 3 different histo + axisVTrackX{400, -10., 10., "track vertex x (cm)", "track vertex x (cm)"}, axisVTrackY{400, -10., 10., "track vertex y (cm)", "track vertex y (cm)"}, axisVTrackZ{400, -10., 10., "track vertex z (cm)", "track vertex z (cm)"}; @@ -191,31 +248,54 @@ struct phosElId { mHistManager.add("hCluE_ncells_mod", "Cluster energy spectrum per module", HistType::kTH3F, {axisE, axisCells, axisModes}); mHistManager.add("hCluXZ_mod", "Local cluster X Z per module", HistType::kTH3F, {axisX, axisZ, axisModes}); - mHistManager.add("hCluE_v_p", "Cluster energy vs p", HistType::kTH3F, {axisE, axisP, axisModes}); - mHistManager.add("hCluE_v_p_disp", "Cluster energy vs p | OK dispersion", HistType::kTH3F, {axisE, axisP, axisModes}); - mHistManager.add("hCluE_v_p_1sigma", "Cluster energy vs p within trackmatch 1sigma", HistType::kTH3F, {axisE, axisP, axisModes}); - mHistManager.add("hCluE_v_p_1sigma_disp", "Cluster energy vs p within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisE, axisP, axisModes}); - mHistManager.add("hCluE_v_p_2sigma", "Cluster energy vs p within trackmatch 2sigma", HistType::kTH3F, {axisE, axisP, axisModes}); - mHistManager.add("hCluE_v_p_2sigma_disp", "Cluster energy vs p within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisE, axisP, axisModes}); - - mHistManager.add("hEp_v_p_disp", "E/p ratio vs p | OK dispersion", HistType::kTH3F, {axisEp, axisP, axisModes}); - mHistManager.add("hEp_v_p_1sigma", "E/p ratio vs p within trackmatch 1sigma", HistType::kTH3F, {axisEp, axisP, axisModes}); - mHistManager.add("hEp_v_p_1sigma_disp", "E/p ratio vs p within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisEp, axisP, axisModes}); - mHistManager.add("hEp_v_p_2sigma", "E/p ratio vs p within trackmatch 2sigma", HistType::kTH3F, {axisEp, axisP, axisModes}); - mHistManager.add("hEp_v_p_2sigma_disp", "E/p ratio vs p within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisEp, axisP, axisModes}); - - mHistManager.add("hdZpmod", "dz,p_{tr},module", HistType::kTH3F, {axisdZ, axisP, axisModes}); - mHistManager.add("hdZpmod_pos", "dz,p_{tr},module positive tracks", HistType::kTH3F, {axisdZ, axisP, axisModes}); - mHistManager.add("hdZpmod_neg", "dz,p_{tr},module negative tracks", HistType::kTH3F, {axisdZ, axisP, axisModes}); - mHistManager.add("hdXpmod", "dx,p_{tr},module", HistType::kTH3F, {axisdX, axisP, axisModes}); - mHistManager.add("hdXpmod_pos", "dx,p_{tr},module positive tracks", HistType::kTH3F, {axisdX, axisP, axisModes}); - mHistManager.add("hdXpmod_neg", "dx,p_{tr},module negative tracks", HistType::kTH3F, {axisdX, axisP, axisModes}); + mHistManager.add("hdZpmod", "dz,p_{tr},module", HistType::kTH3F, {axisdZ, axisPt, axisModes}); + mHistManager.add("hdZpmod_pos", "dz,p_{tr},module positive tracks", HistType::kTH3F, {axisdZ, axisPt, axisModes}); + mHistManager.add("hdZpmod_neg", "dz,p_{tr},module negative tracks", HistType::kTH3F, {axisdZ, axisPt, axisModes}); + mHistManager.add("hdXpmod", "dx,p_{tr},module", HistType::kTH3F, {axisdX, axisPt, axisModes}); + mHistManager.add("hdXpmod_pos", "dx,p_{tr},module positive tracks", HistType::kTH3F, {axisdX, axisPt, axisModes}); + mHistManager.add("hdXpmod_neg", "dx,p_{tr},module negative tracks", HistType::kTH3F, {axisdX, axisPt, axisModes}); + + mHistManager.add("hCluE_v_pt_disp", "Cluster energy vs p | OK dispersion", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_1sigma", "Cluster energy vs p within trackmatch 1sigma", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_1sigma_disp", "Cluster energy vs p within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_2sigma", "Cluster energy vs p within trackmatch 2sigma", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_2sigma_disp", "Cluster energy vs p within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisE, axisPt, axisModes}); + + mHistManager.add("hCluE_v_pt_disp_TPC", "Cluster energy vs p | OK dispersion", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_1sigma_TPC", "Cluster energy vs p within trackmatch 1sigma", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_1sigma_disp_TPC", "Cluster energy vs p within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_2sigma_TPC", "Cluster energy vs p within trackmatch 2sigma", HistType::kTH3F, {axisE, axisPt, axisModes}); + mHistManager.add("hCluE_v_pt_2sigma_disp_TPC", "Cluster energy vs p within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisE, axisPt, axisModes}); + + mHistManager.add("hEp_v_pt_disp", "E/p ratio vs p | OK dispersion", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_1sigma", "E/p ratio vs p within trackmatch 1sigma", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_1sigma_disp", "E/p ratio vs p within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_2sigma", "E/p ratio vs p within trackmatch 2sigma", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_2sigma_disp", "E/p ratio vs p within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisEp, axisPt, axisModes}); + + mHistManager.add("hEp_v_E_disp", "E/p ratio vs cluster E | OK dispersion", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_1sigma", "E/p ratio vs cluster E within trackmatch 1sigma", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_1sigma_disp", "E/p ratio vs cluster E within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_2sigma", "E/p ratio vs cluster E within trackmatch 2sigma", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_2sigma_disp", "E/p ratio vs cluster E within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisEp, axisE, axisModes}); + + mHistManager.add("hEp_v_pt_disp_TPC", "E/p ratio vs p | OK dispersion", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_1sigma_TPC", "E/p ratio vs p within trackmatch 1sigma", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_1sigma_disp_TPC", "E/p ratio vs p within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_2sigma_TPC", "E/p ratio vs p within trackmatch 2sigma", HistType::kTH3F, {axisEp, axisPt, axisModes}); + mHistManager.add("hEp_v_pt_2sigma_disp_TPC", "E/p ratio vs p within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisEp, axisPt, axisModes}); + + mHistManager.add("hEp_v_E_disp_TPC", "E/p ratio vs cluster E | OK dispersion", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_1sigma_TPC", "E/p ratio vs cluster E within trackmatch 1sigma", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_1sigma_disp_TPC", "E/p ratio vs cluster E within trackmatch 1sigma | OK dispersion", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_2sigma_TPC", "E/p ratio vs cluster E within trackmatch 2sigma", HistType::kTH3F, {axisEp, axisE, axisModes}); + mHistManager.add("hEp_v_E_2sigma_disp_TPC", "E/p ratio vs cluster E within trackmatch 2sigma | OK dispersion", HistType::kTH3F, {axisEp, axisE, axisModes}); geomPHOS = std::make_unique("PHOS"); - fSigma_dz = new TF1("func", "[0]/(x+[1])^[2]+pol1(3)", 0.3, 10); + fSigma_dz = new TF1("fSigma_dz", "[0]/(x+[1])^[2]+pol1(3)", 0.3, 10); fSigma_dz->SetParameters(parameters_sigma_dz.at(0), parameters_sigma_dz.at(1), parameters_sigma_dz.at(2), parameters_sigma_dz.at(3), parameters_sigma_dz.at(4)); - fSigma_dx = new TF1("fSigma_dz_dx", "[0]/x^[1]+[2]", 0.1, 10); + fSigma_dx = new TF1("fSigma_dx", "[0]/x^[1]+[2]", 0.1, 10); fSigma_dx->SetParameters(parameters_sigma_dx.at(0), parameters_sigma_dx.at(1), parameters_sigma_dx.at(2)); fMean_dx_pos_mod1 = new TF1("funcMeandx_pos_mod1", "[0]/(x+[1])^[2]", 0.1, 10); @@ -239,7 +319,7 @@ struct phosElId { } void process(soa::Join::iterator const& collision, aod::CaloClusters& clusters, - tracks& tracks, + soa::Filtered const& tracks, aod::BCsWithTimestamps const&) { auto bc = collision.bc_as(); @@ -254,6 +334,8 @@ struct phosElId { LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; runNumber = bc.runNumber(); } + if (fabs(collision.posZ()) > 10.f) + return; mHistManager.fill(HIST("eventCounter"), 0.5); if (!collision.alias_bit(mEvSelTrig)) return; @@ -261,23 +343,31 @@ struct phosElId { if (clusters.size() == 0) return; // Nothing to process + mHistManager.fill(HIST("hColVX"), collision.posX()); + mHistManager.fill(HIST("hColVY"), collision.posY()); + mHistManager.fill(HIST("hColVZ"), collision.posZ()); for (auto const& track : tracks) { - if (!track.has_collision()) + if (!track.has_collision() || fabs(track.dcaXY()) > cfgDCAxyMax || fabs(track.dcaZ()) > cfgDCAzMax || !track.hasTPC() || fabs(track.eta()) > 0.15) + continue; + if (track.pt() < cfgPtMin || track.pt() > cfgPtMax) + continue; + if (track.itsChi2NCl() > cfgITSchi2Max) + continue; + if (track.itsNCls() < cfgITSnclsMin || track.itsNCls() > cfgITSnclsMax || !((track.itsClusterMap() & uint8_t(1)) > 0)) + continue; + if (track.tpcChi2NCl() > cfgTPCchi2Max) continue; + if (track.tpcNClsFound() < cfgTPCnclsMin || track.tpcNClsFound() > cfgTPCnclsMax) + continue; + if (track.tpcNClsCrossedRows() < cfgTPCnclsCRMin || track.tpcNClsCrossedRows() > cfgTPCnclsCRMax) + continue; + mHistManager.fill(HIST("hTrackVX"), track.x()); mHistManager.fill(HIST("hTrackVY"), track.y()); mHistManager.fill(HIST("hTrackVZ"), track.z()); - mHistManager.fill(HIST("hColVX"), collision.posX()); - mHistManager.fill(HIST("hColVY"), collision.posY()); - mHistManager.fill(HIST("hColVZ"), collision.posZ()); - if (std::abs(track.collision_as().posZ()) > 10.f) - continue; - // calculate coordinate in PHOS plane - if (std::abs(track.eta()) > 0.3) - continue; int16_t module; float trackX = 999., trackZ = 999.; @@ -286,8 +376,28 @@ struct phosElId { continue; float trackMom = track.p(); + float trackPT = track.pt(); + + bool isElectron = false; + if (track.hasTPC()) { + float nsigmaTPCEl = track.tpcNSigmaEl(); + float nsigmaTOFEl = track.tofNSigmaEl(); + bool isTPC_electron = nsigmaTPCEl > cfgTPCNSigmaElMin && nsigmaTPCEl < cfgTPCNSigmaElMax; + bool isTOF_electron = nsigmaTOFEl > cfgTOFNSigmaElMin && nsigmaTOFEl < cfgTOFNSigmaElMax; + isElectron = isTPC_electron || isTOF_electron; + + float nsigmaTPCPi = track.tpcNSigmaPi(); + float nsigmaTPCKa = track.tpcNSigmaKa(); + float nsigmaTPCPr = track.tpcNSigmaPr(); + bool isPion = nsigmaTPCPi > cfgTPCNSigmaPiMin && nsigmaTPCPi < cfgTPCNSigmaPiMax; + bool isKaon = nsigmaTPCKa > cfgTPCNSigmaKaMin && nsigmaTPCKa < cfgTPCNSigmaKaMax; + bool isProton = nsigmaTPCPr > cfgTPCNSigmaPrMin && nsigmaTPCPr < cfgTPCNSigmaPrMax; + if (isElectron && !(isPion || isKaon || isProton)) + isElectron = true; + } + bool posTrack = (track.sign() > 0 && bz > 0) || (track.sign() < 0 && bz < 0); - for (const auto& clu : clusters) { + for (auto const& clu : clusters) { if (module != clu.mod()) continue; double cluE = clu.e(); @@ -299,39 +409,70 @@ struct phosElId { continue; bool isDispOK = testLambda(cluE, clu.m02(), clu.m20()); + float posX = clu.x(), posZ = clu.z(), dX = trackX - posX, dZ = trackZ - posZ, Ep = cluE / trackMom; mHistManager.fill(HIST("hCluXZ_mod"), posX, posZ, module); - mHistManager.fill(HIST("hdZpmod"), dZ, trackMom, module); - mHistManager.fill(HIST("hdXpmod"), dX, trackMom, module); + mHistManager.fill(HIST("hdZpmod"), dZ, trackPT, module); + mHistManager.fill(HIST("hdXpmod"), dX, trackPT, module); if (posTrack) { - mHistManager.fill(HIST("hdZpmod_pos"), dZ, trackMom, module); - mHistManager.fill(HIST("hdXpmod_pos"), dX, trackMom, module); + mHistManager.fill(HIST("hdZpmod_pos"), dZ, trackPT, module); + mHistManager.fill(HIST("hdXpmod_pos"), dX, trackPT, module); } else { - mHistManager.fill(HIST("hdZpmod_neg"), dZ, trackMom, module); - mHistManager.fill(HIST("hdXpmod_neg"), dX, trackMom, module); + mHistManager.fill(HIST("hdZpmod_neg"), dZ, trackPT, module); + mHistManager.fill(HIST("hdXpmod_neg"), dX, trackPT, module); } - mHistManager.fill(HIST("hCluE_v_p"), cluE, trackMom, module); if (isDispOK) { - mHistManager.fill(HIST("hCluE_v_p_disp"), cluE, trackMom, module); - mHistManager.fill(HIST("hEp_v_p_disp"), Ep, trackMom, module); + mHistManager.fill(HIST("hCluE_v_pt_disp"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_disp"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_disp"), Ep, cluE, module); + if (isElectron) { + mHistManager.fill(HIST("hCluE_v_pt_disp_TPC"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_disp_TPC"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_disp_TPC"), Ep, cluE, module); + } } - if (!isWithin2Sigma(module, trackMom, dZ, dX)) + if (!isWithin2Sigma(module, trackPT, dZ, dX)) continue; - mHistManager.fill(HIST("hCluE_v_p_2sigma"), cluE, trackMom, module); - mHistManager.fill(HIST("hEp_v_p_2sigma"), Ep, trackMom, module); + mHistManager.fill(HIST("hCluE_v_pt_2sigma"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_2sigma"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_2sigma"), Ep, cluE, module); + if (isElectron) { + mHistManager.fill(HIST("hCluE_v_pt_2sigma_TPC"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_2sigma_TPC"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_2sigma_TPC"), Ep, cluE, module); + } if (isDispOK) { - mHistManager.fill(HIST("hCluE_v_p_2sigma_disp"), cluE, trackMom, module); - mHistManager.fill(HIST("hEp_v_p_2sigma_disp"), Ep, trackMom, module); + mHistManager.fill(HIST("hCluE_v_pt_2sigma_disp"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_2sigma_disp"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_2sigma_disp"), Ep, cluE, module); + if (isElectron) { + mHistManager.fill(HIST("hCluE_v_pt_2sigma_disp_TPC"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_2sigma_disp_TPC"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_2sigma_disp_TPC"), Ep, cluE, module); + } + phosMatch(collision.index(), clu.index(), track.index()); } - if (isWithin1Sigma(module, trackMom, dZ, dX)) { - mHistManager.fill(HIST("hCluE_v_p_1sigma"), cluE, trackMom, module); - mHistManager.fill(HIST("hEp_v_p_1sigma"), Ep, trackMom, module); + if (isWithin1Sigma(module, trackPT, dZ, dX)) { + mHistManager.fill(HIST("hCluE_v_pt_1sigma"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_1sigma"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_1sigma"), Ep, cluE, module); + if (isElectron) { + mHistManager.fill(HIST("hCluE_v_pt_1sigma_TPC"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_1sigma_TPC"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_1sigma_TPC"), Ep, cluE, module); + } if (isDispOK) { - mHistManager.fill(HIST("hCluE_v_p_1sigma_disp"), cluE, trackMom, module); - mHistManager.fill(HIST("hEp_v_p_1sigma_disp"), Ep, trackMom, module); + mHistManager.fill(HIST("hCluE_v_pt_1sigma_disp"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_1sigma_disp"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_1sigma_disp"), Ep, cluE, module); + if (isElectron) { + mHistManager.fill(HIST("hCluE_v_pt_1sigma_disp_TPC"), cluE, trackPT, module); + mHistManager.fill(HIST("hEp_v_pt_1sigma_disp_TPC"), Ep, trackPT, module); + mHistManager.fill(HIST("hEp_v_E_1sigma_disp_TPC"), Ep, cluE, module); + } } } } @@ -342,7 +483,7 @@ struct phosElId { mHistManager.fill(HIST("hTrackPhosProjMod"), trackX, trackZ, module); } // end of double loop - for (const auto& clu : clusters) { + for (auto const& clu : clusters) { double cluE = clu.e(), cluTime = clu.time(); int mod = clu.mod(); if (cluE > mMinCluE) { @@ -497,9 +638,404 @@ struct phosElId { } }; +struct massSpectra { + + using SelCollisions = soa::Join; + using myTracks = soa::Join; + + Configurable mEvSelTrig{"mEvSelTrig", kTVXinPHOS, "Select events with this trigger"}; + + Configurable cfgEtaMax{"cfgEtaMax", {0.8f}, "eta ranges"}; + Configurable cfgPtMin{"cfgPtMin", {0.2f}, "pt min"}; + Configurable cfgPtMax{"cfgPtMax", {20.f}, "pt max"}; + Configurable cfgDCAxyMax{"cfgDCAxyMax", {3.f}, "dcaxy max"}; + Configurable cfgDCAzMax{"cfgDCAzMax", {3.f}, "dcaz max"}; + Configurable cfgITSchi2Max{"cfgITSchi2Max", {5.f}, "its chi2 max"}; + Configurable cfgITSnclsMin{"cfgITSnclsMin", {4.5f}, "min number of ITS clusters"}; + Configurable cfgITSnclsMax{"cfgITSnclsMax", {7.5f}, "max number of ITS clusters"}; + Configurable cfgTPCchi2Max{"cfgTPCchi2Max", {4.f}, "tpc chi2 max"}; + Configurable cfgTPCnclsMin{"cfgTPCnclsMin", {90.f}, "min number of TPC clusters"}; + Configurable cfgTPCnclsMax{"cfgTPCnclsMax", {170.f}, "max number of TPC clusters"}; + Configurable cfgTPCnclsCRMin{"cfgTPCnclsCRMin", {80.f}, "min number of TPC crossed rows"}; + Configurable cfgTPCnclsCRMax{"cfgTPCnclsCRMax", {161.f}, "max number of TPC crossed rows"}; + + Configurable cfgTPCNSigmaElMin{"cfgTPCNSigmaElMin", {-3.f}, "min TPC nsigma e for inclusion"}; + Configurable cfgTPCNSigmaElMax{"cfgTPCNSigmaElMax", {2.f}, "max TPC nsigma e for inclusion"}; + Configurable cfgTPCNSigmaPiMin{"cfgTPCNSigmaPiMin", {-3.f}, "min TPC nsigma pion for exclusion"}; + Configurable cfgTPCNSigmaPiMax{"cfgTPCNSigmaPiMax", {3.5f}, "max TPC nsigma pion for exclusion"}; + Configurable cfgTPCNSigmaPrMin{"cfgTPCNSigmaPrMin", {-3.f}, "min TPC nsigma proton for exclusion"}; + Configurable cfgTPCNSigmaPrMax{"cfgTPCNSigmaPrMax", {4.f}, "max TPC nsigma proton for exclusion"}; + Configurable cfgTPCNSigmaKaMin{"cfgTPCNSigmaKaMin", {-3.f}, "min TPC nsigma kaon for exclusion"}; + Configurable cfgTPCNSigmaKaMax{"cfgTPCNSigmaKaMax", {4.f}, "max TPC nsigma kaon for exclusion"}; + Configurable cfgTOFNSigmaElMin{"cfgTOFNSigmaElMin", {-3.f}, "min TOF nsigma e for inclusion"}; + Configurable cfgTOFNSigmaElMax{"cfgTOFNSigmaElMax", {3.f}, "max TOF nsigma e for inclusion"}; + + Configurable> cfgEpSigmaPars{"cfgEpSigmaPars", {1.3e-02, 1.9e-02, 1.1e-02, 3.e-02}, "E/p sigma function parameters (from alice 3 mc tests + const)"}; + + Service ccdb; + std::unique_ptr geomPHOS; + double bz{0.}; // magnetic field + int runNumber{0}; + + HistogramRegistry mHistManager{"MassSpectraHistograms"}; + TF1* fEp_sigma_phos; + + void init(InitContext const&) + { + LOG(info) << "Initializing PHOS electron identification analysis task ..."; + + std::vector momentum_binning = {0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, + 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, + 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 10.}; + + const AxisSpec + axisCounter{1, 0, +1, ""}, + axisPt{momentum_binning, "p_{T} (GeV/c)"}, + axisE{200, 0, 10, "E (GeV)", "E (GeV)"}, + axisMassSpectrum{4000, 0, 4, "M (GeV/c^{2})", "Mass e^{+}e^{-} (GeV/c^{2})"}; + + mHistManager.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); + mHistManager.add("TVXinPHOSCounter", "TVXinPHOSCounter", kTH1F, {axisCounter}); + + mHistManager.add("h_eh_pp_mass_spectra_v_Pt", "Mass e^{+}h^{+} vs momentum e^{+}h^{+}", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_ee_pp_mass_spectra_v_Pt", "Mass e^{+}e^{+} vs momentum e^{+}e^{+}", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_eh_mm_mass_spectra_v_Pt", "Mass e^{-}h^{-} vs momentum e^{-}h^{-}", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_ee_mm_mass_spectra_v_Pt", "Mass e^{-}e^{-} vs momentum e^{-}e^{-}", HistType::kTH2F, {axisMassSpectrum, axisPt}); + + mHistManager.add("h_eh_pp_mass_spectra_v_E", "Mass e^{+}h^{+} vs cluster E e^{+}h^{+}", HistType::kTH2F, {axisMassSpectrum, axisE}); + mHistManager.add("h_ee_pp_mass_spectra_v_E", "Mass e^{+}e^{+} vs cluster E e^{+}e^{+}", HistType::kTH2F, {axisMassSpectrum, axisE}); + mHistManager.add("h_eh_mm_mass_spectra_v_E", "Mass e^{-}h^{-} vs cluster E e^{-}h^{-}", HistType::kTH2F, {axisMassSpectrum, axisE}); + mHistManager.add("h_ee_mm_mass_spectra_v_E", "Mass e^{-}e^{-} vs cluster E e^{-}e^{-}", HistType::kTH2F, {axisMassSpectrum, axisE}); + + mHistManager.add("h_eh_mp_mass_spectra_v_Pt", "Mass e^{#pm}h^{#mp} vs momentum e^{#pm}h^{#mp}", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_ee_mp_mass_spectra_v_Pt", "Mass e^{#pm}e^{#mp} vs momentum e^{#pm}e^{#mp}", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_eh_mp_mass_spectra_v_E", "Mass e^{#pm}h^{#mp} vs cluster E e^{#pm}h^{#mp}", HistType::kTH2F, {axisMassSpectrum, axisE}); + mHistManager.add("h_ee_mp_mass_spectra_v_E", "Mass e^{#pm}e^{#mp} vs cluster E e^{#pm}e^{#mp}", HistType::kTH2F, {axisMassSpectrum, axisE}); + + geomPHOS = std::make_unique("PHOS"); + + std::vector EpSigmaPars = cfgEpSigmaPars; + fEp_sigma_phos = new TF1("fEp_sigma_phos", "sqrt([0]*[0]/x/x+[1]*[1]/x+[2]*[2])+[3]", 0.01, 10); + fEp_sigma_phos->SetParameters(EpSigmaPars.at(0), EpSigmaPars.at(1), EpSigmaPars.at(2), EpSigmaPars.at(3)); + } + + void process(soa::Join::iterator const& collision, + aod::CaloClusters const& clusters, + myTracks const& tracks, + o2::aod::PHOSMatchindexTable const& matches, + aod::BCsWithTimestamps const&) + { + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", bc.timestamp()); + if (grpo == nullptr) { + LOGF(fatal, "Run 3 GRP object (type o2::parameters::GRPMagField) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); + } + o2::base::Propagator::initFieldFromGRP(grpo); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + runNumber = bc.runNumber(); + } + if (fabs(collision.posZ()) > 10.f) + return; + mHistManager.fill(HIST("eventCounter"), 0.5); + if (!collision.alias_bit(mEvSelTrig)) + return; + mHistManager.fill(HIST("TVXinPHOSCounter"), 0.5); + + if (clusters.size() == 0) + return; // Nothing to process + + for (auto const& TPCel : tracks) { + + if (!TPCel.has_collision() || fabs(TPCel.dcaXY()) > cfgDCAxyMax || fabs(TPCel.dcaZ()) > cfgDCAzMax || !TPCel.hasTPC() || fabs(TPCel.eta()) > 0.15) + continue; + if (TPCel.pt() < cfgPtMin || TPCel.pt() > cfgPtMax) + continue; + if (TPCel.itsChi2NCl() > cfgITSchi2Max) + continue; + if (TPCel.itsNCls() < cfgITSnclsMin || TPCel.itsNCls() > cfgITSnclsMax || !((TPCel.itsClusterMap() & uint8_t(1)) > 0)) + continue; + if (TPCel.tpcChi2NCl() > cfgTPCchi2Max) + continue; + if (TPCel.tpcNClsFound() < cfgTPCnclsMin || TPCel.tpcNClsFound() > cfgTPCnclsMax) + continue; + if (TPCel.tpcNClsCrossedRows() < cfgTPCnclsCRMin || TPCel.tpcNClsCrossedRows() > cfgTPCnclsCRMax) + continue; + + bool isElectron = false; + float nsigmaTPCEl = TPCel.tpcNSigmaEl(); + float nsigmaTOFEl = TPCel.tofNSigmaEl(); + bool isTPC_electron = nsigmaTPCEl > cfgTPCNSigmaElMin && nsigmaTPCEl < cfgTPCNSigmaElMax; + bool isTOF_electron = nsigmaTOFEl > cfgTOFNSigmaElMin && nsigmaTOFEl < cfgTOFNSigmaElMax; + isElectron = isTPC_electron || isTOF_electron; + + float nsigmaTPCPi = TPCel.tpcNSigmaPi(); + float nsigmaTPCKa = TPCel.tpcNSigmaKa(); + float nsigmaTPCPr = TPCel.tpcNSigmaPr(); + bool isPion = nsigmaTPCPi > cfgTPCNSigmaPiMin && nsigmaTPCPi < cfgTPCNSigmaPiMax; + bool isKaon = nsigmaTPCKa > cfgTPCNSigmaKaMin && nsigmaTPCKa < cfgTPCNSigmaKaMax; + bool isProton = nsigmaTPCPr > cfgTPCNSigmaPrMin && nsigmaTPCPr < cfgTPCNSigmaPrMax; + if (isElectron && !(isPion || isKaon || isProton)) + isElectron = true; + if (!isElectron) + continue; + + for (auto const& match : matches) { + auto clust2 = clusters.iteratorAt(match.caloClusterId()); + auto track2 = tracks.iteratorAt(match.trackId()); + + if (TPCel.collisionId() != track2.collisionId()) + continue; + if (TPCel.index() >= track2.index()) + break; + + float mass_2tracks = 0, mom_2tracks = 0, cluE = clust2.e(); + TLorentzVector P1, P2; + P1.SetPxPyPzE(TPCel.px(), TPCel.py(), TPCel.pz(), TPCel.energy(0)); + P2.SetPxPyPzE(track2.px(), track2.py(), track2.pz(), track2.energy(0)); + mom_2tracks = (P1 + P2).Pt(); + mass_2tracks = (P1 + P2).M(); + bool posTrack = (TPCel.sign() > 0 && bz > 0) || (TPCel.sign() < 0 && bz < 0); + bool elCandidate = (fabs(clust2.e() / track2.p() - 1) < 2 * fEp_sigma_phos->Eval(mom_2tracks)); + + if (TPCel.sign() == track2.sign()) { + if (posTrack) { + mHistManager.fill(HIST("h_eh_pp_mass_spectra_v_Pt"), mass_2tracks, mom_2tracks); + mHistManager.fill(HIST("h_eh_pp_mass_spectra_v_E"), mass_2tracks, cluE); + if (elCandidate) { + mHistManager.fill(HIST("h_ee_pp_mass_spectra_v_Pt"), mass_2tracks, mom_2tracks); + mHistManager.fill(HIST("h_ee_pp_mass_spectra_v_E"), mass_2tracks, cluE); + } + } else { + mHistManager.fill(HIST("h_eh_mm_mass_spectra_v_Pt"), mass_2tracks, mom_2tracks); + mHistManager.fill(HIST("h_eh_mm_mass_spectra_v_E"), mass_2tracks, cluE); + if (elCandidate) { + mHistManager.fill(HIST("h_ee_mm_mass_spectra_v_Pt"), mass_2tracks, mom_2tracks); + mHistManager.fill(HIST("h_ee_mm_mass_spectra_v_E"), mass_2tracks, cluE); + } + } + } else { + mHistManager.fill(HIST("h_eh_mp_mass_spectra_v_Pt"), mass_2tracks, mom_2tracks); + mHistManager.fill(HIST("h_eh_mp_mass_spectra_v_E"), mass_2tracks, cluE); + if (elCandidate) { + mHistManager.fill(HIST("h_ee_mp_mass_spectra_v_Pt"), mass_2tracks, mom_2tracks); + mHistManager.fill(HIST("h_ee_mp_mass_spectra_v_E"), mass_2tracks, cluE); + } + } + } + } // end of double loop + } +}; + +struct tpcElIdMassSpectrum { + + using SelCollisions = soa::Join; + using myTracks = soa::Join; + + Configurable cfgEtaMax{"cfgEtaMax", {0.8f}, "eta ranges"}; + Configurable cfgPtMin{"cfgPtMin", {0.2f}, "pt min"}; + Configurable cfgPtMax{"cfgPtMax", {20.f}, "pt max"}; + Configurable cfgDCAxyMax{"cfgDCAxyMax", {3.f}, "dcaxy max"}; + Configurable cfgDCAzMax{"cfgDCAzMax", {3.f}, "dcaz max"}; + Configurable cfgITSchi2Max{"cfgITSchi2Max", {5.f}, "its chi2 max"}; + Configurable cfgITSnclsMin{"cfgITSnclsMin", {4.5f}, "min number of ITS clusters"}; + Configurable cfgITSnclsMax{"cfgITSnclsMax", {7.5f}, "max number of ITS clusters"}; + Configurable cfgTPCchi2Max{"cfgTPCchi2Max", {4.f}, "tpc chi2 max"}; + Configurable cfgTPCnclsMin{"cfgTPCnclsMin", {90.f}, "min number of TPC clusters"}; + Configurable cfgTPCnclsMax{"cfgTPCnclsMax", {170.f}, "max number of TPC clusters"}; + Configurable cfgTPCnclsCRMin{"cfgTPCnclsCRMin", {80.f}, "min number of TPC crossed rows"}; + Configurable cfgTPCnclsCRMax{"cfgTPCnclsCRMax", {161.f}, "max number of TPC crossed rows"}; + Configurable cfgTPCNSigmaElMin{"cfgTPCNSigmaElMin", {-3.f}, "min TPC nsigma e for inclusion"}; + Configurable cfgTPCNSigmaElMax{"cfgTPCNSigmaElMax", {2.f}, "max TPC nsigma e for inclusion"}; + Configurable cfgTPCNSigmaPiMin{"cfgTPCNSigmaPiMin", {-3.f}, "min TPC nsigma pion for exclusion"}; + Configurable cfgTPCNSigmaPiMax{"cfgTPCNSigmaPiMax", {3.5f}, "max TPC nsigma pion for exclusion"}; + Configurable cfgTPCNSigmaPrMin{"cfgTPCNSigmaPrMin", {-3.f}, "min TPC nsigma proton for exclusion"}; + Configurable cfgTPCNSigmaPrMax{"cfgTPCNSigmaPrMax", {4.f}, "max TPC nsigma proton for exclusion"}; + Configurable cfgTPCNSigmaKaMin{"cfgTPCNSigmaKaMin", {-3.f}, "min TPC nsigma kaon for exclusion"}; + Configurable cfgTPCNSigmaKaMax{"cfgTPCNSigmaKaMax", {4.f}, "max TPC nsigma kaon for exclusion"}; + Configurable cfgTOFNSigmaElMin{"cfgTOFNSigmaElMin", {-3.f}, "min TOF nsigma e for inclusion"}; + Configurable cfgTOFNSigmaElMax{"cfgTOFNSigmaElMax", {3.f}, "max TOF nsigma e for inclusion"}; + + Filter ptFilter = (aod::track::pt > cfgPtMin) && (aod::track::pt < cfgPtMax); + Filter etafilter = nabs(aod::track::eta) < cfgEtaMax; + Filter dcaxyfilter = nabs(aod::track::dcaXY) < cfgDCAxyMax; + Filter dcazfilter = nabs(aod::track::dcaZ) < cfgDCAzMax; + + Filter tpcEl = ((aod::pidtpc::tpcNSigmaEl > cfgTPCNSigmaElMin) && (aod::pidtpc::tpcNSigmaEl < cfgTPCNSigmaElMax)) || ((aod::pidtof::tofNSigmaEl > cfgTOFNSigmaElMin) && (aod::pidtof::tofNSigmaEl < cfgTOFNSigmaElMax)); + Filter tpcPi_rej = (aod::pidtpc::tpcNSigmaPi < cfgTPCNSigmaPiMin) || (aod::pidtpc::tpcNSigmaPi > cfgTPCNSigmaPiMax); + Filter tpcKa_rej = (aod::pidtpc::tpcNSigmaKa < cfgTPCNSigmaKaMin) || (aod::pidtpc::tpcNSigmaKa > cfgTPCNSigmaPrMax); + Filter tpcPr_rej = (aod::pidtpc::tpcNSigmaPr < cfgTPCNSigmaPrMin) || (aod::pidtpc::tpcNSigmaPr > cfgTPCNSigmaPrMax); + + Service ccdb; + double bz{0.}; // magnetic field + int runNumber{0}; + + HistogramRegistry mHistManager{"tpcElIdHistograms"}; + + void init(InitContext const&) + { + LOG(info) << "Initializing ee mass spectrum via TPC electron identification analysis task ..."; + + std::vector momentum_binning = {0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, + 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, + 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 10.}; + const AxisSpec + axisCounter{1, 0, +1, ""}, + axisVTrackX{400, -5., 5., "track vertex x (cm)", "track vertex x (cm)"}, + axisVTrackY{400, -5., 5., "track vertex y (cm)", "track vertex y (cm)"}, + axisVTrackZ{400, -20., 20., "track vertex z (cm)", "track vertex z (cm)"}, + axisMassSpectrum{4000, 0, 4, "M (GeV/c^{2})", "Mass e^{+}e^{-} (GeV/c^{2})"}, + axisTPC{1000, 0, 200, "TPC signal (dE/dx)"}, + axisPt{momentum_binning, "p_{T} (GeV/c)"}, + axisPtBig{2000, 0, 20, "p_{T} (GeV/c)"}, + axisEta{600, -3., 3., "#eta"}; + + mHistManager.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); + mHistManager.add("hTPCspectra_isElectronRej", "isElectron with rejection | TPC dE/dx spectra", HistType::kTH2F, {axisPt, axisTPC}); + + mHistManager.add("h_TPCee_MS_mp", "Mass e^{#pm}e^{#mp} vs momentum e^{#pm}e^{#mp} (from TPC candidates) vs pair pt", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_TPCee_MS_mm", "Mass e^{-}e^{-} vs momentum e^{-}e^{-} (from TPC candidates) vs pair pt", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_TPCee_MS_pp", "Mass e^{+}e^{+} vs momentum e^{+}e^{+} (from TPC candidates) vs pair pt", HistType::kTH2F, {axisMassSpectrum, axisPt}); + + mHistManager.add("h_TPCee_MS_mp_phosRange", "Mass e^{#pm}e^{#mp} vs momentum e^{#pm}e^{#mp} (from TPC candidates) vs pair pt with one e in phos acceptance range", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_TPCee_MS_mm_phosRange", "Mass e^{-}e^{-} vs momentum e^{-}e^{-} (from TPC candidates) vs pair pt with one e in phos acceptance range", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_TPCee_MS_pp_phosRange", "Mass e^{+}e^{+} vs momentum e^{+}e^{+} (from TPC candidates) vs pair pt with one e in phos acceptance range", HistType::kTH2F, {axisMassSpectrum, axisPt}); + + mHistManager.add("h_TPCee_MS_mp_phosRange_kTVXinPHOS", "Mass e^{#pm}e^{#mp} vs momentum e^{#pm}e^{#mp} (from TPC candidates) vs pair pt with one e in phos acceptance range", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_TPCee_MS_mm_phosRange_kTVXinPHOS", "Mass e^{-}e^{-} vs momentum e^{-}e^{-} (from TPC candidates) vs pair pt with one e in phos acceptance range", HistType::kTH2F, {axisMassSpectrum, axisPt}); + mHistManager.add("h_TPCee_MS_pp_phosRange_kTVXinPHOS", "Mass e^{+}e^{+} vs momentum e^{+}e^{+} (from TPC candidates) vs pair pt with one e in phos acceptance range", HistType::kTH2F, {axisMassSpectrum, axisPt}); + + mHistManager.add("hTrackVX", "Track vertex coordinate X", HistType::kTH1F, {axisVTrackX}); + mHistManager.add("hTrackVY", "Track vertex coordinate Y", HistType::kTH1F, {axisVTrackY}); + mHistManager.add("hTrackVZ", "Track vertex coordinate Z", HistType::kTH1F, {axisVTrackZ}); + mHistManager.add("hTrackVX_Cut", "Track vertex coordinate X after cut", HistType::kTH1F, {axisVTrackX}); + mHistManager.add("hTrackVY_Cut", "Track vertex coordinate Y after cut", HistType::kTH1F, {axisVTrackY}); + mHistManager.add("hTrackVZ_Cut", "Track vertex coordinate Z after cut", HistType::kTH1F, {axisVTrackZ}); + + mHistManager.add("hTrackPt", "Track pt", HistType::kTH1F, {axisPtBig}); + mHistManager.add("hTrackPt_Cut", "Track pt after cut", HistType::kTH1F, {axisPtBig}); + mHistManager.add("hTrackEta", "Track eta", HistType::kTH1F, {axisEta}); + mHistManager.add("hTrackEta_Cut", "Track eta after cut", HistType::kTH1F, {axisEta}); + } + void process(soa::Join::iterator const& collision, + soa::Filtered const& tracks, + aod::BCsWithTimestamps const&) + { + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", bc.timestamp()); + if (grpo == nullptr) { + LOGF(fatal, "Run 3 GRP object (type o2::parameters::GRPMagField) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); + } + o2::base::Propagator::initFieldFromGRP(grpo); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + runNumber = bc.runNumber(); + } + mHistManager.fill(HIST("eventCounter"), 0.5); + if (fabs(collision.posZ()) > 10.f) + return; + + for (auto& [track1, track2] : combinations(CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { + if (!track1.has_collision() || !track1.hasTPC()) + continue; + if (!track2.has_collision() || !track2.hasTPC()) + continue; + if (track1.collisionId() != track2.collisionId()) + continue; + if (!((track1.itsClusterMap() & uint8_t(1)) > 0) || !((track2.itsClusterMap() & uint8_t(1)) > 0)) + continue; + if (track1.itsChi2NCl() > cfgITSchi2Max || track2.itsChi2NCl() > cfgITSchi2Max) + continue; + if (track1.tpcChi2NCl() > cfgTPCchi2Max || track2.tpcChi2NCl() > cfgTPCchi2Max) + continue; + if (track1.itsNCls() < cfgITSnclsMin || track2.itsNCls() < cfgITSnclsMin) + continue; + if (track1.itsNCls() > cfgITSnclsMax || track2.itsNCls() > cfgITSnclsMax) + continue; + if (track1.tpcNClsFound() < cfgTPCnclsMin || track2.tpcNClsFound() < cfgTPCnclsMin) + continue; + if (track1.tpcNClsFound() > cfgTPCnclsMax || track2.tpcNClsFound() > cfgTPCnclsMax) + continue; + if (track1.tpcNClsCrossedRows() < cfgTPCnclsCRMin || track2.tpcNClsCrossedRows() < cfgTPCnclsCRMin) + continue; + if (track1.tpcNClsCrossedRows() > cfgTPCnclsCRMax || track2.tpcNClsCrossedRows() > cfgTPCnclsCRMax) + continue; + + TLorentzVector P1, P2; + P1.SetPxPyPzE(track1.px(), track1.py(), track1.pz(), track1.energy(0)); + P2.SetPxPyPzE(track2.px(), track2.py(), track2.pz(), track2.energy(0)); + + bool inPhosEtaRange1 = fabs(track1.eta()) < 0.12; + bool inPhosEtaRange2 = fabs(track2.eta()) < 0.12; + bool inPhosPhiRange1 = (track1.phi() * TMath::RadToDeg() > 250 && track1.phi() * TMath::RadToDeg() < 320); + bool inPhosPhiRange2 = (track2.phi() * TMath::RadToDeg() > 250 && track2.phi() * TMath::RadToDeg() < 320); + bool inPhosRange = (inPhosEtaRange1 && inPhosPhiRange1) || (inPhosEtaRange2 && inPhosPhiRange2); + bool posTrack = (track1.sign() > 0 && bz > 0) || (track1.sign() < 0 && bz < 0); + + if (track1.sign() == track2.sign()) { + if (posTrack) { + mHistManager.fill(HIST("h_TPCee_MS_pp"), (P1 + P2).M(), (P1 + P2).Pt()); + if (inPhosRange) { + mHistManager.fill(HIST("h_TPCee_MS_pp_phosRange"), (P1 + P2).M(), (P1 + P2).Pt()); + if (collision.alias_bit(kTVXinPHOS)) + mHistManager.fill(HIST("h_TPCee_MS_pp_phosRange_kTVXinPHOS"), (P1 + P2).M(), (P1 + P2).Pt()); + } + } else { + mHistManager.fill(HIST("h_TPCee_MS_mm"), (P1 + P2).M(), (P1 + P2).Pt()); + if (inPhosRange) { + mHistManager.fill(HIST("h_TPCee_MS_mm_phosRange"), (P1 + P2).M(), (P1 + P2).Pt()); + if (collision.alias_bit(kTVXinPHOS)) + mHistManager.fill(HIST("h_TPCee_MS_mm_phosRange_kTVXinPHOS"), (P1 + P2).M(), (P1 + P2).Pt()); + } + } + } else { + mHistManager.fill(HIST("h_TPCee_MS_mp"), (P1 + P2).M(), (P1 + P2).Pt()); + if (inPhosRange) { + mHistManager.fill(HIST("h_TPCee_MS_mp_phosRange"), (P1 + P2).M(), (P1 + P2).Pt()); + if (collision.alias_bit(kTVXinPHOS)) + mHistManager.fill(HIST("h_TPCee_MS_mp_phosRange_kTVXinPHOS"), (P1 + P2).M(), (P1 + P2).Pt()); + } + } + } + + for (auto const& track1 : tracks) { + mHistManager.fill(HIST("hTrackPt"), track1.pt()); + mHistManager.fill(HIST("hTrackEta"), track1.eta()); + mHistManager.fill(HIST("hTrackVX"), track1.x()); + mHistManager.fill(HIST("hTrackVY"), track1.y()); + mHistManager.fill(HIST("hTrackVZ"), track1.z()); + + if (!track1.has_collision() || !track1.hasTPC()) + continue; + if (track1.itsChi2NCl() > cfgITSchi2Max || track1.tpcChi2NCl() > cfgTPCchi2Max) + continue; + if (track1.itsNCls() < cfgITSnclsMin || track1.itsNCls() > cfgITSnclsMax || !((track1.itsClusterMap() & uint8_t(1)) > 0)) + continue; + if (track1.tpcNClsFound() < cfgTPCnclsMin || track1.tpcNClsFound() > cfgTPCnclsMax) + continue; + if (track1.tpcNClsCrossedRows() < cfgTPCnclsCRMin || track1.tpcNClsCrossedRows() > cfgTPCnclsCRMax) + continue; + + mHistManager.fill(HIST("hTPCspectra_isElectronRej"), track1.pt(), track1.tpcSignal()); + + mHistManager.fill(HIST("hTrackPt_Cut"), track1.pt()); + mHistManager.fill(HIST("hTrackEta_Cut"), track1.eta()); + mHistManager.fill(HIST("hTrackVX_Cut"), track1.x()); + mHistManager.fill(HIST("hTrackVY_Cut"), track1.y()); + mHistManager.fill(HIST("hTrackVZ_Cut"), track1.z()); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { auto workflow = WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGEM/Tasks/phosNbar.cxx b/PWGEM/Tasks/phosNbar.cxx index 4c5fb57904b..7cd2e4387a7 100644 --- a/PWGEM/Tasks/phosNbar.cxx +++ b/PWGEM/Tasks/phosNbar.cxx @@ -984,7 +984,7 @@ struct phosNbar { PROCESS_SWITCH(phosNbar, processData, "process data", false); void processMC(SelCollisionMC const& coll, - aod::BCsWithTimestamps const&, mcClusters const& clusters, mcTracks const& tracks, aod::McParticles const& mcPart, aod::McCollisions const& mcCol) + aod::BCsWithTimestamps const&, mcClusters const& clusters, mcTracks const& tracks, aod::McParticles const& mcPart, aod::McCollisions const& /*mcCol*/) { // Initialize B-field if (mBz == 123456.) { diff --git a/PWGEM/Tasks/phosPi0.cxx b/PWGEM/Tasks/phosPi0.cxx index 89406a21706..fe248dbeaa6 100644 --- a/PWGEM/Tasks/phosPi0.cxx +++ b/PWGEM/Tasks/phosPi0.cxx @@ -236,7 +236,7 @@ struct phosPi0 { void processMC(SelCollisionsMC::iterator const& col, mcClusters const& clusters, aod::McParticles const& mcPart, - aod::McCollisions const& mcCol) + aod::McCollisions const& /*mcCol*/) { scanAll(col, clusters, &mcPart); } diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index 23fd5d6ebb7..ea9d1f257b6 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -28,6 +28,91 @@ enum CentralityEstimator { NTracksPV, NCentralityEstimators }; + +template +concept hasFT0ACent = requires(T collision) +{ + collision.centFT0A(); +}; + +template +concept hasFT0CCent = requires(T collision) +{ + collision.centFT0C(); +}; + +template +concept hasFT0MCent = requires(T collision) +{ + collision.centFT0M(); +}; + +template +concept hasFV0ACent = requires(T collision) +{ + collision.centFV0A(); +}; + +template +concept hasNTracksPVCent = requires(T collision) +{ + collision.centNTPV(); +}; + +/// Evaluate centrality/multiplicity percentile using FT0A estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const Coll& collision) +{ + return collision.centFT0A(); +} + +/// Evaluate centrality/multiplicity percentile using FT0C estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const Coll& collision) +{ + return collision.centFT0C(); +} + +/// Evaluate centrality/multiplicity percentile using FT0M estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const Coll& collision) +{ + return collision.centFT0M(); +} + +/// Evaluate centrality/multiplicity percentile using FV0A estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const Coll& collision) +{ + return collision.centFV0A(); +} + +/// Evaluate centrality/multiplicity percentile using NTracksPV estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const Coll& collision) +{ + return collision.centNTPV(); +} + +/// Default case if no centrality/multiplicity estimator is provided +/// \param candidate is candidate +/// \return dummy value for centrality/multiplicity percentile of the collision +template +float getCentralityColl(const Coll&) +{ + return 105.0f; +} + } // namespace o2::hf_centrality #endif // PWGHF_CORE_CENTRALITYESTIMATION_H_ diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 888ca12b6b9..b610c194fe9 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -370,6 +370,30 @@ class HfHelper return RecoDecay::m(std::array{candidate.pVectorProng1(), candidate.pVectorProng0()}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); } + template + auto invMassPKPairLcToPKPi(const T& candidate) + { + return RecoDecay::m(std::array{candidate.pVectorProng0(), candidate.pVectorProng1()}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus}); + } + + template + auto invMassPKPairLcToPiKP(const T& candidate) + { + return RecoDecay::m(std::array{candidate.pVectorProng2(), candidate.pVectorProng1()}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus}); + } + + template + auto invMassPPiPairLcToPKPi(const T& candidate) + { + return RecoDecay::m(std::array{candidate.pVectorProng0(), candidate.pVectorProng2()}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPiPlus}); + } + + template + auto invMassPPiPairLcToPiKP(const T& candidate) + { + return RecoDecay::m(std::array{candidate.pVectorProng2(), candidate.pVectorProng0()}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPiPlus}); + } + // Ξc± → p± K∓ π± template @@ -665,6 +689,14 @@ class HfHelper return candidate.y(o2::constants::physics::MassSigmaCPlusPlus); } + /// ÎŁc0,++ → Λc+(→K0sP) π-,+ + /// @brief Sc inv. mass using reco mass for Lc in K0sP and PDG mass for pion + template + auto invMassScRecoLcToK0sP(const T& candidateSc, const U& candidateLc) + { + return candidateSc.m(std::array{static_cast(invMassLcToK0sP(candidateLc)), o2::constants::physics::MassPiMinus}); + } + /// Apply topological cuts as defined in SelectorCuts.h /// \param candB0 B0 candidate /// \param cuts B0 candidate selection per pT bin" diff --git a/PWGHF/Core/HfMlResponseD0ToKPi.h b/PWGHF/Core/HfMlResponseD0ToKPi.h index 91790751503..b520a946e38 100644 --- a/PWGHF/Core/HfMlResponseD0ToKPi.h +++ b/PWGHF/Core/HfMlResponseD0ToKPi.h @@ -73,6 +73,19 @@ break; \ } +// Variation of CHECK_AND_FILL_VEC_D0_HFHELPER(OBJECT, FEATURE, GETTER) +// where GETTER1 and GETTER2 are methods of hfHelper, and the variable +// is filled depending on whether it is a D0 or a D0bar +#define CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(OBJECT1, OBJECT2, FEATURE, GETTER) \ + case static_cast(InputFeaturesD0ToKPi::FEATURE): { \ + if (pdgCode == o2::constants::physics::kD0) { \ + inputFeatures.emplace_back(OBJECT1.GETTER()); \ + } else { \ + inputFeatures.emplace_back(OBJECT2.GETTER()); \ + } \ + break; \ + } + namespace o2::analysis { enum class InputFeaturesD0ToKPi : uint8_t { @@ -100,6 +113,18 @@ enum class InputFeaturesD0ToKPi : uint8_t { nSigTofKa1, nSigTpcTofPi1, nSigTpcTofKa1, + nSigTpcPiExpPi, + nSigTpcKaExpPi, + nSigTpcPiExpKa, + nSigTpcKaExpKa, + nSigTofPiExpPi, + nSigTofKaExpPi, + nSigTofPiExpKa, + nSigTofKaExpKa, + nSigTpcTofPiExpPi, + nSigTpcTofKaExpPi, + nSigTpcTofPiExpKa, + nSigTpcTofKaExpKa, maxNormalisedDeltaIP, impactParameterProduct, cosThetaStar, @@ -148,16 +173,28 @@ class HfMlResponseD0ToKPi : public HfMlResponse CHECK_AND_FILL_VEC_D0_FULL(prong0, nSigTpcKa0, tpcNSigmaKa); CHECK_AND_FILL_VEC_D0_FULL(prong1, nSigTpcPi1, tpcNSigmaPi); CHECK_AND_FILL_VEC_D0_FULL(prong1, nSigTpcKa1, tpcNSigmaKa); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong0, prong1, nSigTpcPiExpPi, tpcNSigmaPi); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong0, prong1, nSigTpcKaExpPi, tpcNSigmaKa); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong1, prong0, nSigTpcPiExpKa, tpcNSigmaPi); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong1, prong0, nSigTpcKaExpKa, tpcNSigmaKa); // TOF PID variables CHECK_AND_FILL_VEC_D0_FULL(prong0, nSigTofPi0, tofNSigmaPi); CHECK_AND_FILL_VEC_D0_FULL(prong0, nSigTofKa0, tofNSigmaKa); CHECK_AND_FILL_VEC_D0_FULL(prong1, nSigTofPi1, tofNSigmaPi); CHECK_AND_FILL_VEC_D0_FULL(prong1, nSigTofKa1, tofNSigmaKa); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong0, prong1, nSigTofPiExpPi, tofNSigmaPi); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong0, prong1, nSigTofKaExpPi, tofNSigmaKa); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong1, prong0, nSigTofPiExpKa, tofNSigmaPi); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong1, prong0, nSigTofKaExpKa, tofNSigmaKa); // Combined PID variables CHECK_AND_FILL_VEC_D0_FULL(prong0, nSigTpcTofPi0, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_D0_FULL(prong0, nSigTpcTofKa0, tpcTofNSigmaKa); CHECK_AND_FILL_VEC_D0_FULL(prong1, nSigTpcTofPi1, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_D0_FULL(prong1, nSigTpcTofKa1, tpcTofNSigmaKa); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong0, prong1, nSigTpcTofPiExpPi, tpcTofNSigmaPi); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong0, prong1, nSigTpcTofKaExpPi, tpcTofNSigmaKa); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong1, prong0, nSigTpcTofPiExpKa, tpcTofNSigmaPi); + CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED(prong1, prong0, nSigTpcTofKaExpKa, tpcTofNSigmaKa); CHECK_AND_FILL_VEC_D0(maxNormalisedDeltaIP); CHECK_AND_FILL_VEC_D0_FULL(candidate, impactParameterProduct, impactParameterProduct); @@ -192,16 +229,28 @@ class HfMlResponseD0ToKPi : public HfMlResponse FILL_MAP_D0(nSigTpcKa0), FILL_MAP_D0(nSigTpcPi1), FILL_MAP_D0(nSigTpcKa1), + FILL_MAP_D0(nSigTpcPiExpPi), + FILL_MAP_D0(nSigTpcKaExpPi), + FILL_MAP_D0(nSigTpcPiExpKa), + FILL_MAP_D0(nSigTpcKaExpKa), // TOF PID variables FILL_MAP_D0(nSigTofPi0), FILL_MAP_D0(nSigTofKa0), FILL_MAP_D0(nSigTofPi1), FILL_MAP_D0(nSigTofKa1), + FILL_MAP_D0(nSigTofPiExpPi), + FILL_MAP_D0(nSigTofKaExpPi), + FILL_MAP_D0(nSigTofPiExpKa), + FILL_MAP_D0(nSigTofKaExpKa), // Combined PID variables FILL_MAP_D0(nSigTpcTofPi0), FILL_MAP_D0(nSigTpcTofKa0), FILL_MAP_D0(nSigTpcTofPi1), FILL_MAP_D0(nSigTpcTofKa1), + FILL_MAP_D0(nSigTpcTofPiExpPi), + FILL_MAP_D0(nSigTpcTofKaExpPi), + FILL_MAP_D0(nSigTpcTofPiExpKa), + FILL_MAP_D0(nSigTpcTofKaExpKa), FILL_MAP_D0(maxNormalisedDeltaIP), FILL_MAP_D0(impactParameterProduct), @@ -219,5 +268,6 @@ class HfMlResponseD0ToKPi : public HfMlResponse #undef CHECK_AND_FILL_VEC_D0 #undef CHECK_AND_FILL_VEC_D0_HFHELPER #undef CHECK_AND_FILL_VEC_D0_HFHELPER_SIGNED +#undef CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED #endif // PWGHF_CORE_HFMLRESPONSED0TOKPI_H_ diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index b655a243890..92f62d72cca 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -700,6 +700,55 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "pT p", "pT K", "pT Pi", "chi2PCA", "decay length", "cos pointing angle", "decLengthXY", "normDecLXY", "ct", "impParXY"}; } // namespace hf_cuts_xic_to_p_k_pi +namespace hf_cuts_xic_to_xi_pi_pi +{ +static const int nBinsPt = 10; +static const int nCutVars = 12; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double binsPt[nBinsPt + 1] = { + 0., + 1., + 2., + 3., + 4., + 5., + 6., + 8., + 12., + 24., + 36.}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; + +// default values for the cuts m ptXi ptPi0 ptPi1 chi2PCA dL dLXY cosp cospXY impParXY Xi Pi0 Pi1 +constexpr double cuts[nBinsPt][nCutVars] = {{0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 0 < pT < 1 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 1 < pT < 2 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 2 < pT < 3 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 3 < pT < 4 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 4 < pT < 5 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 5 < pT < 6 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 6 < pT < 8 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 8 < pT < 10 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 12 < pT < 24 */ + {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}}; /* 24 < pT < 36 */ + +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9"}; + +// column labels +static const std::vector labelsCutVar = {"m", "pT Xi", "pT Pi0", "pT Pi1", "chi2PCA", "max decay length", "max decay length XY", "cos pointing angle", "cos pointing angle XY", "max impParXY Xi", "max impParXY Pi0", "max impParXY Pi1"}; +} // namespace hf_cuts_xic_to_xi_pi_pi + namespace hf_cuts_xicc_to_p_k_pi_pi { static const int nBinsPt = 10; diff --git a/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h b/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h new file mode 100644 index 00000000000..a698b8152a6 --- /dev/null +++ b/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h @@ -0,0 +1,81 @@ +// Copyright 2019-2020 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. +// +/// \file SelectorCutsRedDataFormat.h +/// \brief Default pT bins and cut arrays for heavy-flavour selectors and analysis tasks +/// +/// \author Luca Aglietta , UniversitĂ  degli Studi di Torino + +// namespace with D selections for reduced charmed-resonances analysis + +#ifndef PWGHF_D2H_CORE_SELECTORCUTSREDDATAFORMAT_H_ +#define PWGHF_D2H_CORE_SELECTORCUTSREDDATAFORMAT_H_ + +#include // std::string +#include // std::vector + +namespace hf_cuts_d_daughter +{ +const int nBinsPt = 7; +static constexpr int nCutVars = 6; +constexpr double binsPt[nBinsPt + 1] = { + 1., + 2., + 4., + 6., + 8., + 12., + 24., + 1000.}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; +// default values for the cuts +constexpr double cuts[nBinsPt][nCutVars] = {{1.84, 1.89, 1.77, 1.81, 1.92, 1.96}, /* 1 < pt < 2 */ + {1.84, 1.89, 1.77, 1.81, 1.92, 1.96}, /* 2 < pt < 4 */ + {1.84, 1.89, 1.77, 1.81, 1.92, 1.96}, /* 4 < pt < 6 */ + {1.84, 1.89, 1.77, 1.81, 1.92, 1.96}, /* 6 < pt < 8 */ + {1.84, 1.89, 1.77, 1.81, 1.92, 1.96}, /* 8 < pt < 12 */ + {1.84, 1.89, 1.77, 1.81, 1.92, 1.96}, /* 12 < pt < 24 */ + {1.84, 1.89, 1.77, 1.81, 1.92, 1.96}}; /* 24 < pt < 1000 */ +// row labels +static const std::vector labelsPt{}; +// column labels +static const std::vector labelsCutVar = {"invMassSignalLow", "invMassSignalHigh", "invMassLeftSBLow", "invMassLeftSBHigh", "invMassRightSBLow", "invMassRightSBHigh"}; +} // namespace hf_cuts_d_daughter + +// namespace with v0 selections for reduced charmed-resonances analysis +namespace hf_cuts_v0_daughter +{ +const int nBinsPt = 7; +static constexpr int nCutVars = 5; +constexpr double binsPt[nBinsPt + 1] = { + 0., + 1., + 2., + 4., + 8., + 12., + 24., + 1000.}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; +// default values for the cuts +constexpr double cuts[nBinsPt][nCutVars] = {{0.48, 0.52, 0.99, 1., 0.9}, /* 1 < pt < 2 */ + {0.48, 0.52, 0.99, 1., 0.9}, /* 2 < pt < 4 */ + {0.48, 0.52, 0.99, 1., 0.9}, /* 4 < pt < 6 */ + {0.48, 0.52, 0.99, 1., 0.9}, /* 6 < pt < 8 */ + {0.48, 0.52, 0.99, 1., 0.9}, /* 8 < pt < 12 */ + {0.48, 0.52, 0.99, 1., 0.9}, /* 12 < pt < 24 */ + {0.48, 0.52, 0.99, 1., 0.9}}; /* 24 < pt < 1000 */ +// row labels +static const std::vector labelsPt{}; +// column labels +static const std::vector labelsCutVar = {"invMassLow", "invMassHigh", "cpaMin", "dcaMax", "radiusMin"}; +} // namespace hf_cuts_v0_daughter +#endif // PWGHF_D2H_CORE_SELECTORCUTSREDDATAFORMAT_H_ diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 11a7dd1b599..07fe57f18bc 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -37,6 +37,7 @@ namespace aod namespace hf_reduced_collision { DECLARE_SOA_COLUMN(Bz, bz, float); //! Magnetic field in z-direction +DECLARE_SOA_COLUMN(HfCollisionRejectionMap, hfCollisionRejectionMap, uint16_t); //! Bitmask with failed selection criteria // keep track of the number of studied events (for normalization purposes) DECLARE_SOA_COLUMN(OriginalCollisionCount, originalCollisionCount, int); //! Size of COLLISION table processed DECLARE_SOA_COLUMN(ZvtxSelectedCollisionCount, zvtxSelectedCollisionCount, int); //! Number of COLLISIONS with |zvtx| < zvtxMax @@ -51,6 +52,9 @@ DECLARE_SOA_TABLE(HfRedCollisions, "AOD", "HFREDCOLLISION", //! Table with colli collision::PosX, collision::PosY, collision::PosZ, + collision::NumContrib, + hf_reduced_collision::HfCollisionRejectionMap, + hf_reduced_collision::Bz, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfRedCollExtras, "AOD", "HFREDCOLLEXTRA", //! Table with collision extras for reduced workflow @@ -59,8 +63,7 @@ DECLARE_SOA_TABLE(HfRedCollExtras, "AOD", "HFREDCOLLEXTRA", //! Table with colli collision::CovYY, collision::CovXZ, collision::CovYZ, - collision::CovZZ, - hf_reduced_collision::Bz); + collision::CovZZ); using HfRedCollision = HfRedCollisions::iterator; @@ -424,15 +427,25 @@ DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with confi // Charm resonances analysis namespace hf_reso_cand_reduced { -DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass in GeV/c2 -DECLARE_SOA_COLUMN(Pt, pt, float); //! Pt of Resonance candidate in GeV/c -DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Pt of D daughter in GeV/c -DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Pt of V0 daughter in GeV/c +DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass in GeV/c2 DECLARE_SOA_COLUMN(InvMassProng0, invMassProng0, float); //! Invariant Mass of D daughter in GeV/c DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0 daughter in GeV/c DECLARE_SOA_COLUMN(MlScoreBkgProng0, mlScoreBkgProng0, float); //! Bkg ML score of the D daughter DECLARE_SOA_COLUMN(MlScorePromptProng0, mlScorePromptProng0, float); //! Prompt ML score of the D daughter DECLARE_SOA_COLUMN(MlScoreNonpromptProng0, mlScoreNonpromptProng0, float); //! Nonprompt ML score of the D daughter + +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! + [](float pxProng0, float pxProng1, float pyProng0, float pyProng1) -> float { return RecoDecay::pt((1.f * pxProng0 + 1.f * pxProng1), (1.f * pyProng0 + 1.f * pyProng1)); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! + [](float pxProng0, float pyProng0) -> float { return RecoDecay::pt(pxProng0, pyProng0); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! + [](float pxProng1, float pyProng1) -> float { return RecoDecay::pt(pxProng1, pyProng1); }); +DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarDs1, cosThetaStarDs1, //! costhetastar under Ds1 hypothesis + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0}, invMass, 1); }); +DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarDs2Star, cosThetaStarDs2Star, //! costhetastar under Ds2Star hypothesis + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0}, invMass, 1); }); +DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarXiC3055, cosThetaStarXiC3055, //! costhetastar under XiC3055 hypothesis + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}, invMass, 1); }); } // namespace hf_reso_cand_reduced namespace hf_reso_3_prong @@ -457,7 +470,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(InvMassAntiDstar, invMassAntiDstar, -> float { return RecoDecay::m(std::array{std::array{pxSoftPi, pySoftPi, pzSoftPi}, std::array{pxProng0, pyProng0, pzProng0}, std::array{pxProng1, pyProng1, pzProng1}}, std::array{constants::physics::MassPiPlus, constants::physics::MassKPlus, constants::physics::MassPiPlus}) - RecoDecay::m(std::array{std::array{pxProng0, pyProng0, pzProng0}, std::array{pxProng1, pyProng1, pzProng1}}, std::array{constants::physics::MassKPlus, constants::physics::MassPiPlus}); }); } // namespace hf_reso_3_prong -namespace hf_reso_2_prong +namespace hf_reso_v0 { DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine of Pointing Angle of V0 candidate DECLARE_SOA_COLUMN(Dca, dca, float); //! DCA of V0 candidate @@ -471,7 +484,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, //! [](float pzProng0, float pzProng1) -> float { return 1.f * pzProng0 + 1.f * pzProng1; }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! [](float pxProng0, float pxProng1, float pyProng0, float pyProng1) -> float { return RecoDecay::pt((1.f * pxProng0 + 1.f * pxProng1), (1.f * pyProng0 + 1.f * pyProng1)); }); -DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, //! V0 decay radius (2D, centered at zero) +DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0Radius, //! V0 decay radius (2D, centered at zero) [](float x, float y) -> float { return RecoDecay::sqrtSumOfSquares(x, y); }); DECLARE_SOA_DYNAMIC_COLUMN(InvMassLambda, invMassLambda, //! mass under lambda hypothesis [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); @@ -479,7 +492,29 @@ DECLARE_SOA_DYNAMIC_COLUMN(InvMassAntiLambda, invMassAntiLambda, //! mass under [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); DECLARE_SOA_DYNAMIC_COLUMN(InvMassK0s, invMassK0s, //! mass under K0short hypothesis [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); }); -} // namespace hf_reso_2_prong +} // namespace hf_reso_v0 + +namespace hf_reso_track +{ +DECLARE_SOA_COLUMN(Px, px, float); //! x-component of momentum +DECLARE_SOA_COLUMN(Py, py, float); //! y-component of momentum +DECLARE_SOA_COLUMN(Pz, pz, float); //! z-component of momentum +DECLARE_SOA_COLUMN(Sign, sign, uint8_t); //! charge sign +DECLARE_SOA_COLUMN(NSigmaTpcPi, nSigmaTpcPi, float); //! TPC Nsigma for pion hypothesis +DECLARE_SOA_COLUMN(NSigmaTpcKa, nSigmaTpcKa, float); //! TPC Nsigma for kaon hypothesis +DECLARE_SOA_COLUMN(NSigmaTpcPr, nSigmaTpcPr, float); //! TPC Nsigma for proton hypothesis +DECLARE_SOA_COLUMN(NSigmaTofPi, nSigmaTofPi, float); //! TOF Nsigma for pion hypothesis +DECLARE_SOA_COLUMN(NSigmaTofKa, nSigmaTofKa, float); //! TOF Nsigma for kaon hypothesis +DECLARE_SOA_COLUMN(NSigmaTofPr, nSigmaTofPr, float); //! TOF Nsigma for proton hypothesis +DECLARE_SOA_COLUMN(HasTof, hasTof, bool); //! flag for presence of TOF +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! + [](float px, float py) -> float { return RecoDecay::phi(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! + [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); + +} // namespace hf_reso_track DECLARE_SOA_TABLE(HfRedVzeros, "AOD", "HFREDVZERO", //! Table with V0 candidate information for resonances reduced workflow o2::soa::Index<>, @@ -490,18 +525,39 @@ DECLARE_SOA_TABLE(HfRedVzeros, "AOD", "HFREDVZERO", //! Table with V0 candidate hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, - hf_reso_2_prong::Cpa, - hf_reso_2_prong::Dca, - hf_reso_2_prong::V0Type, + hf_reso_v0::Cpa, + hf_reso_v0::Dca, + hf_reso_v0::V0Type, // Dynamic - hf_reso_2_prong::Px, - hf_reso_2_prong::Py, - hf_reso_2_prong::Pz, - hf_reso_2_prong::InvMassK0s, - hf_reso_2_prong::InvMassLambda, - hf_reso_2_prong::InvMassAntiLambda, - hf_reso_2_prong::V0Radius, - hf_reso_2_prong::Pt); + hf_reso_v0::Px, + hf_reso_v0::Py, + hf_reso_v0::Pz, + hf_reso_v0::InvMassK0s, + hf_reso_v0::InvMassLambda, + hf_reso_v0::InvMassAntiLambda, + hf_reso_v0::V0Radius, + hf_reso_v0::Pt); + +DECLARE_SOA_TABLE(HfRedTrkNoParams, "AOD", "HFREDTRKNOPARAM", //! Table with tracks without track parameters for resonances reduced workflow + o2::soa::Index<>, + // Indices + hf_track_index_reduced::HfRedCollisionId, + // Static + hf_reso_track::Px, + hf_reso_track::Py, + hf_reso_track::Pz, + hf_reso_track::Sign, + hf_reso_track::NSigmaTpcPi, + hf_reso_track::NSigmaTpcKa, + hf_reso_track::NSigmaTpcPr, + hf_reso_track::NSigmaTofPi, + hf_reso_track::NSigmaTofKa, + hf_reso_track::NSigmaTofPr, + hf_reso_track::HasTof, + // Dynamic + hf_reso_track::Pt, + hf_reso_track::Eta, + hf_reso_track::Phi); DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong candidate information for resonances reduced workflow o2::soa::Index<>, @@ -525,16 +581,26 @@ DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Resonance candidate information for resonances reduced workflow o2::soa::Index<>, + // Indices hf_track_index_reduced::HfRedCollisionId, + // Static + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_reso_cand_reduced::InvMass, - hf_reso_cand_reduced::Pt, hf_reso_cand_reduced::InvMassProng0, - hf_reso_cand_reduced::PtProng0, hf_reso_cand_reduced::InvMassProng1, - hf_reso_cand_reduced::PtProng1, - hf_reso_2_prong::Cpa, - hf_reso_2_prong::Dca, - hf_reso_2_prong::Radius); + hf_reso_v0::Cpa, + hf_reso_v0::Dca, + hf_reso_v0::Radius, + // Dynamic + hf_reso_cand_reduced::Pt, + hf_reso_cand_reduced::PtProng0, + hf_reso_cand_reduced::PtProng1, + hf_cand::PVectorProng0, + hf_cand::PVectorProng1, + hf_reso_cand_reduced::CosThetaStarDs1, + hf_reso_cand_reduced::CosThetaStarDs2Star, + hf_reso_cand_reduced::CosThetaStarXiC3055); DECLARE_SOA_TABLE(HfCharmResoMLs, "AOD", "HFCHARMRESOML", //! Table with ML scores for the D daughter hf_reso_cand_reduced::MlScoreBkgProng0, diff --git a/PWGHF/D2H/Macros/ML/config_training_DplusToPiKPi.yml b/PWGHF/D2H/Macros/ML/config_training_DplusToPiKPi.yml index 6f9fe561d7d..0cc7d55f23d 100644 --- a/PWGHF/D2H/Macros/ML/config_training_DplusToPiKPi.yml +++ b/PWGHF/D2H/Macros/ML/config_training_DplusToPiKPi.yml @@ -18,6 +18,8 @@ data_prep: dirPath/ ] + tree_name: treeMLDplus # null if .parquet input files, not null if .root input files + pt_bins_limits: [1, 24] name_pt_var: fPt # name of pT branch in original TTree downsample_bkg_factor: 1 # value of downSampleBkgFactor set at TTree creation level diff --git a/PWGHF/D2H/Macros/ML/train_models.py b/PWGHF/D2H/Macros/ML/train_models.py index 8e0963b1ee6..dfdb3840eb4 100644 --- a/PWGHF/D2H/Macros/ML/train_models.py +++ b/PWGHF/D2H/Macros/ML/train_models.py @@ -26,21 +26,25 @@ import pickle import sys +# pylint: disable=import-error +try: + from hipe4ml import plot_utils + from hipe4ml.model_handler import ModelHandler + from hipe4ml.tree_handler import TreeHandler +except ModuleNotFoundError: + print("Module 'hipe4ml' is not installed. Please install it to run this macro") + import matplotlib.pyplot as plt # pylint: disable=import-error import numpy as np # pylint: disable=import-error import pandas as pd # pylint: disable=import-error import xgboost as xgb # pylint: disable=import-error import yaml # pylint: disable=import-error +from sklearn.model_selection import train_test_split # pylint: disable=import-error -# pylint: disable=import-error try: - from hipe4ml import plot_utils - from hipe4ml.model_handler import ModelHandler - from hipe4ml.tree_handler import TreeHandler from hipe4ml_converter.h4ml_converter import H4MLConverter - from sklearn.model_selection import train_test_split except ModuleNotFoundError: - print("Module 'hipe4ml' is not installed. Please install it to run this macro") + print("Module 'hipe4ml_converter' is not installed. Please install it to run this macro") LABEL_BKG = 0 LABEL_PROMPT = 1 diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index d81347d4eea..383ca9c42b1 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -148,7 +148,7 @@ struct HfCandidateCreatorB0Reduced { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx index 7f7fc71bd6e..d47ac5f3d4d 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx @@ -142,7 +142,7 @@ struct HfCandidateCreatorBplusReduced { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index ad9ff090907..c3f3af5086b 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -22,11 +22,15 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "EventFiltering/PWGHF/HFFilterHelpers.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Core/SelectorCutsRedDataFormat.h" +#include "PWGHF/Utils/utilsAnalysis.h" using namespace o2; using namespace o2::aod; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; @@ -47,8 +51,9 @@ enum V0Type : uint8_t { Lambda, AntiLambda }; -const int nBins = 7; -constexpr double binsPt[nBins + 1] = { + +const int nBinsPt = 7; +constexpr double binsPt[nBinsPt + 1] = { 1., 2., 4., @@ -56,32 +61,36 @@ constexpr double binsPt[nBins + 1] = { 8., 12., 24., - 50.}; -auto vecBins = std::vector{binsPt, binsPt + nBins + 1}; + 1000.}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; struct HfCandidateCreatorCharmResoReduced { // Produces: Tables with resonance info Produces rowCandidateReso; - // Optional D daughter ML scores table + // Optional daughter ML scores table Produces mlScores; // Configurables - Configurable invMassWindowD{"invMassWindowD", 0.5, "invariant-mass window for D candidates (GeV/c2)"}; - Configurable invMassWindowV0{"invMassWindowV0", 0.5, "invariant-mass window for V0 candidates (GeV/c2)"}; + Configurable rejectDV0PairsWithCommonDaughter{"rejectDV0PairsWithCommonDaughter", true, "flag to reject the pairs that share a daughter track if not done in the derived data creation"}; + Configurable keepSideBands{"keepSideBands", false, "flag to keep events from D meson sidebands for backgorund estimation"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - // Hist Axis - Configurable> binsPt{"binsPt", std::vector{vecBins}, "pT bin limits"}; + Configurable> binsPt{"binsPt", std::vector{vecBinsPt}, "Histogram pT bin limits"}; + // Daughters selection cuts + Configurable> cutsD{"cutsDdaughter", {hf_cuts_d_daughter::cuts[0], hf_cuts_d_daughter::nBinsPt, hf_cuts_d_daughter::nCutVars, hf_cuts_d_daughter::labelsPt, hf_cuts_d_daughter::labelsCutVar}, "D daughter selections"}; + Configurable> binsPtD{"binsPtD", std::vector{hf_cuts_d_daughter::vecBinsPt}, "pT bin limits for D daughter cuts"}; + Configurable> cutsV0{"cutsV0daughter", {hf_cuts_v0_daughter::cuts[0], hf_cuts_v0_daughter::nBinsPt, hf_cuts_v0_daughter::nCutVars, hf_cuts_v0_daughter::labelsPt, hf_cuts_v0_daughter::labelsCutVar}, "V0 daughter selections"}; + Configurable> binsPtV0{"binsPtV0", std::vector{hf_cuts_v0_daughter::vecBinsPt}, "pT bin limits for V0 daughter cuts"}; using reducedDWithMl = soa::Join; // Partition of V0 candidates based on v0Type - Partition candidatesK0s = aod::hf_reso_2_prong::v0Type == (uint8_t)1 || aod::hf_reso_2_prong::v0Type == (uint8_t)3 || aod::hf_reso_2_prong::v0Type == (uint8_t)5; - Partition candidatesLambda = aod::hf_reso_2_prong::v0Type == (uint8_t)2 || aod::hf_reso_2_prong::v0Type == (uint8_t)4; + Partition candidatesK0s = aod::hf_reso_v0::v0Type == (uint8_t)1 || aod::hf_reso_v0::v0Type == (uint8_t)3 || aod::hf_reso_v0::v0Type == (uint8_t)5; + Partition candidatesLambda = aod::hf_reso_v0::v0Type == (uint8_t)2 || aod::hf_reso_v0::v0Type == (uint8_t)4; Preslice candsV0PerCollision = aod::hf_track_index_reduced::hfRedCollisionId; Preslice candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; - // aod::HfRedVzeros + // Useful constants double massK0{0.}; double massLambda{0.}; @@ -89,7 +98,6 @@ struct HfCandidateCreatorCharmResoReduced { double massDstar{0.}; double massD0{0.}; - // Histogram registry: if task make it with a THNsparse with all variables you want to save HistogramRegistry registry{"registry"}; void init(InitContext const&) @@ -100,7 +108,7 @@ struct HfCandidateCreatorCharmResoReduced { LOGP(fatal, "Only one process function should be enabled! Please check your configuration!"); } // histograms - const AxisSpec axisPt{(std::vector)vecBins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisPt{(std::vector)vecBinsPt, "#it{p}_{T} (GeV/#it{c})"}; registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassDs2Star", "Ds^{*}2 candidates; m_Ds^{*}2 (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassXcRes", "XcRes candidates; m_XcRes (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.9, 3.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -130,21 +138,33 @@ struct HfCandidateCreatorCharmResoReduced { template bool isDSelected(DRedTable const& candD) { - float massD{0.}; float invMassD{0.}; + float ptD = candD.pt(); + int ptBin = findBin(binsPtD, ptD); + if (ptBin == -1) { + return false; + } // slection on D candidate mass if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { - massD = massDplus; invMassD = candD.invMassDplus(); } else if (channel == DecayChannel::Ds1ToDstarK0s) { - massD = massDstar - massD0; if (candD.dType() > 0) invMassD = candD.invMassDstar(); else invMassD = candD.invMassAntiDstar(); } - if (std::fabs(invMassD - massD) > invMassWindowD) { - return false; + // invariant mass selection + if (!keepSideBands) { + if (invMassD < cutsD->get(ptBin, "invMassSignalLow") || invMassD > cutsD->get(ptBin, "invMassSignalHigh")) { + return false; + } + } else { + if ((invMassD < cutsD->get(ptBin, "invMassLeftSBLow")) || + (invMassD > cutsD->get(ptBin, "invMassLeftSBHigh") && invMassD < cutsD->get(ptBin, "invMassSignalLow")) || + (invMassD > cutsD->get(ptBin, "invMassSignalHigh") && invMassD < cutsD->get(ptBin, "invMassRightSBLow")) || + (invMassD > cutsD->get(ptBin, "invMassRightSBHigh"))) { + return false; + } } return true; } @@ -158,6 +178,11 @@ struct HfCandidateCreatorCharmResoReduced { { float massV0{0.}; float invMassV0{0.}; + float ptV0 = candV0.pt(); + int ptBin = findBin(binsPtV0, ptV0); + if (ptBin == -1) { + return false; + } if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::Ds1ToDstarK0s) { massV0 = massK0; invMassV0 = candV0.invMassK0s(); @@ -174,12 +199,17 @@ struct HfCandidateCreatorCharmResoReduced { invMassV0 = candV0.invMassAntiLambda(); targetV0Type = V0Type::AntiLambda; } + // check skimming cuts if (!TESTBIT(candV0.v0Type(), targetV0Type)) { return false; } } - // slection on V0 candidate mass - if (std::fabs(invMassV0 - massV0) > invMassWindowV0) { + // selection on V0 candidate mass + if ((invMassV0 - massV0) > cutsV0->get(ptBin, "invMassLow") && (massV0 - invMassV0) < cutsV0->get(ptBin, "invMassLow")) { + return false; + } + // selection on kinematics and topology + if (candV0.dca() > cutsV0->get(ptBin, "dcaMax") || candV0.cpa() < cutsV0->get(ptBin, "cpaMin") || candV0.v0Radius() < cutsV0->get(ptBin, "radiusMin")) { return false; } return true; @@ -210,11 +240,18 @@ struct HfCandidateCreatorCharmResoReduced { if (candD.dType() == -2) invMassD = candD.invMassAntiDstar(); std::array pVecD = {candD.px(), candD.py(), candD.pz()}; - float ptD = RecoDecay::pt(pVecD); + std::array dDaughtersIds = {candD.prong0Id(), candD.prong1Id(), candD.prong2Id()}; ; // loop on V0 candidates bool alreadyCounted{false}; for (const auto& candV0 : candsV0) { + if (rejectDV0PairsWithCommonDaughter) { + const std::array dDaughtersIDs = {candD.prong0Id(), candD.prong1Id(), candD.prong2Id()}; + if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0.prong1Id()) != dDaughtersIDs.end()) { + continue; + } + } + if (!isV0Selected(candV0, candD)) { continue; } @@ -225,7 +262,6 @@ struct HfCandidateCreatorCharmResoReduced { float invMassReso{0.}; float invMassV0{0.}; std::array pVecV0 = {candV0.px(), candV0.py(), candV0.pz()}; - float ptV0 = RecoDecay::pt(pVecV0); float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0, pVecD)); switch (channel) { case DecayChannel::Ds1ToDstarK0s: @@ -261,15 +297,14 @@ struct HfCandidateCreatorCharmResoReduced { } // Filling Output table rowCandidateReso(collision.globalIndex(), + pVecD[0], pVecD[1], pVecD[2], + pVecV0[0], pVecV0[1], pVecV0[2], invMassReso, - ptReso, invMassD, - ptD, invMassV0, - ptV0, candV0.cpa(), candV0.dca(), - candV0.v0radius()); + candV0.v0Radius()); if constexpr (fillMl) { mlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); } diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 2426cf49251..bb8f606c402 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -570,7 +570,7 @@ struct HfDataCreatorCharmHadPiReduced { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidatesDPlus->Fill(SVFitting::Fail); continue; } @@ -594,7 +594,7 @@ struct HfDataCreatorCharmHadPiReduced { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidatesD0->Fill(SVFitting::Fail); continue; } @@ -728,11 +728,12 @@ struct HfDataCreatorCharmHadPiReduced { return; } registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); + float centrality = -1.f; + uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a DPi pair a minima - hfReducedCollision(collision.posX(), collision.posY(), collision.posZ()); + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), - collision.covXZ(), collision.covYZ(), collision.covZZ(), - bz); + collision.covXZ(), collision.covYZ(), collision.covZZ()); } template @@ -833,7 +834,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); @@ -863,7 +864,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); @@ -893,7 +894,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsD0PerCollision, thisCollId); @@ -923,7 +924,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsD0PerCollisionWithMl, thisCollId); @@ -957,7 +958,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); @@ -989,7 +990,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); @@ -1021,7 +1022,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsD0PerCollision, thisCollId); @@ -1053,7 +1054,7 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsCThisColl = candsC.sliceBy(candsD0PerCollisionWithMl, thisCollId); diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index 30d5550743c..39f647b6b94 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -13,6 +13,7 @@ /// \brief Creation of D-V0 pairs /// /// \author Luca Aglietta , UniTO Turin +/// \author Fabrizio Grosa , CERN #include #include @@ -27,6 +28,7 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -55,13 +57,15 @@ enum Event : uint8_t { enum DecayChannel : uint8_t { DstarV0 = 0, - DplusV0 + DplusV0, + DstarTrack }; -enum V0Type : uint8_t { +enum BachelorType : uint8_t { K0s = 0, Lambda, - AntiLambda + AntiLambda, + Track }; enum DType : uint8_t { @@ -75,8 +79,9 @@ struct HfDataCreatorCharmResoReduced { // Produces AOD tables to store track information Produces hfReducedCollision; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCollisionCounter; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h - // V0 and D candidates reduced tables + // tracks, V0 and D candidates reduced tables Produces hfCandV0; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h + Produces hfTrackNoParam; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // ML optional Tables Produces hfCandDMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h @@ -90,41 +95,89 @@ struct HfDataCreatorCharmResoReduced { int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. // selection D - Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D"}; - Configurable selectionFlagDstarToD0Pi{"selectionFlagDstarToD0Pi", true, "Selection Flag for D* decay to D0 & Pi"}; + struct : ConfigurableGroup { + std::string prefix = "dmesons"; + Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D"}; + Configurable selectionFlagDstarToD0Pi{"selectionFlagDstarToD0Pi", true, "Selection Flag for D* decay to D0 & Pi"}; + } cfgDmesCuts; + // selection V0 - Configurable minK0sLambdaCosinePa{"minK0sLambdaCosinePa", 0.97, "minimum cosp for K0S and Lambda"}; - Configurable minK0sLambdaRadius{"minK0sLambdaRadius", 0.5, "minimum radius for K0S and Lambda"}; - Configurable deltaMassK0s{"deltaMassK0s", 0.03, "delta mass cut for K0S"}; - Configurable deltaMassLambda{"deltaMassLambda", 0.015, "delta mass cut for Lambda"}; - Configurable minV0dauEta{"minV0dauEta", 1., "minimum eta for V0 daughters"}; - Configurable maxV0DCA{"maxV0DCA", 0.1, "maximum DCA for K0S and Lambda"}; - Configurable minV0dauDCA{"minV0dauDCA", 0.05, "minimum DCA for V0 daughters"}; - Configurable maxV0dauDCA{"maxV0dauDCA", 1., "maximum DCA for V0 daughters"}; - Configurable maxNsigmaPrForLambda{"maxNsigmaPrForLambda", 4., "maximum proton NSigma in TPC and TOF for Lambdas"}; + struct : ConfigurableGroup { + std::string prefix = "v0s"; + Configurable deltaMassK0s{"deltaMassK0s", 0.02, "delta mass cut for K0S"}; + Configurable deltaMassLambda{"deltaMassLambda", 0.01, "delta mass cut for Lambda"}; + Configurable etaMax{"etaMax", 0.8f, "maximum eta"}; + Configurable etaMaxDau{"etaMaxDau", 5.f, "maximum eta V0 daughters"}; + Configurable trackNclusItsCut{"trackNclusItsCut", 0, "Minimum number of ITS clusters for V0 daughter"}; + Configurable trackNCrossedRowsTpc{"trackNCrossedRowsTpc", 50, "Minimum TPC crossed rows"}; + Configurable trackNsharedClusTpc{"trackNsharedClusTpc", 1000, "Maximum number of shared TPC clusters for V0 daughter"}; + Configurable dcaDau{"dcaDau", 1.f, "DCA V0 daughters"}; + Configurable dcaMaxDauToPv{"dcaMaxDauToPv", 0.1f, "Maximum daughter's DCA to PV"}; + Configurable dcaPv{"dcaPv", 1.f, "DCA V0 to PV"}; + Configurable cosPa{"cosPa", 0.99f, "V0 CosPA"}; + Configurable radiusMin{"radiusMin", 0.9f, "Minimum v0 radius accepted"}; + Configurable nSigmaTpc{"nSigmaTpc", 4.f, "Nsigmatpc"}; + Configurable nSigmaTofPr{"nSigmaTofPr", 4.f, "N sigma TOF for protons only"}; + } cfgV0Cuts; + + // selection single tracks + struct : ConfigurableGroup { + std::string prefix = "single_tracks"; + Configurable setTrackSelections{"setTrackSelections", 2, "flag to apply track selections: 0=none; 1=global track w/o DCA selection; 2=global track; 3=only ITS quality"}; + Configurable maxEta{"maxEta", 0.8, "maximum pseudorapidity for single tracks to be paired with D mesons"}; + Configurable minPt{"minPt", 0.1, "minimum pT for single tracks to be paired with D mesons"}; + Configurable maxNsigmaTpcPi{"maxNsigmaTpcPi", -1., "maximum pion NSigma in TPC for single tracks to be paired with D mesons; set negative to reject"}; + Configurable maxNsigmaTpcKa{"maxNsigmaTpcKa", -1., "maximum kaon NSigma in TPC for single tracks to be paired with D mesons; set negative to reject"}; + Configurable maxNsigmaTpcPr{"maxNsigmaTpcPr", 3., "maximum proton NSigma in TPC for single tracks to be paired with D mesons; set negative to reject"}; + } cfgSingleTrackCuts; + + // other configurables + Configurable rejectPairsWithCommonDaughter{"rejectPairsWithCommonDaughter", true, "flag to reject already at this stage the pairs that share a daughter track"}; // material correction for track propagation o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; HfHelper hfHelper; o2::hf_evsel::HfEventSelection hfEvSel; + o2::vertexing::DCAFitterN<2> fitter; + double bz{0.}; bool isHfCandResoConfigFilled = false; + // Helper struct to pass V0 informations + struct { + std::array pos; + std::array mom; + std::array momPos; + std::array momNeg; + float pT; + float cosPA; + float dcaV0ToPv; + float dcaDau; + float alpha; + float eta; + float radius; + float mK0Short; + float mLambda; + uint8_t v0Type; + } candidateV0; + using CandsDplusFiltered = soa::Filtered>; using CandsDplusFilteredWithMl = soa::Filtered>; using CandDstarFiltered = soa::Filtered>; using CandDstarFilteredWithMl = soa::Filtered>; - using TracksWithPID = soa::Join; + using TracksWithPID = soa::Join; + using TracksIUWithPID = soa::Join; - Filter filterSelectDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus); - Filter filterSelectedCandDstar = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi); + Filter filterSelectDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= cfgDmesCuts.selectionFlagDplus); + Filter filterSelectedCandDstar = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == cfgDmesCuts.selectionFlagDstarToD0Pi); - Preslice candsDplusPerCollision = aod::track_association::collisionId; - Preslice candsDplusPerCollisionWithMl = aod::track_association::collisionId; - Preslice candsDstarPerCollision = aod::track_association::collisionId; - Preslice candsDstarPerCollisionWithMl = aod::track_association::collisionId; - Preslice candsV0PerCollision = aod::track_association::collisionId; + Preslice candsDplusPerCollision = aod::hf_cand::collisionId; + Preslice candsDplusPerCollisionWithMl = aod::hf_cand::collisionId; + Preslice candsDstarPerCollision = aod::hf_cand::collisionId; + Preslice candsDstarPerCollisionWithMl = aod::hf_cand::collisionId; + Preslice candsV0PerCollision = aod::v0::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; HistogramRegistry registry{"registry"}; @@ -141,85 +194,277 @@ struct HfDataCreatorCharmResoReduced { for (int iBin = 0; iBin < kNBinsEvents; iBin++) { registry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } - registry.add("hMassDplus", "Dplus candidates;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 1.7, 2}}}); - registry.add("hMassDstar", "Dstar candidates;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 0.14, 0.17}}}); - registry.add("hMassK0s", "K0^{s} candidates;inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 0.35, 0.65}}}); - registry.add("hMassLambda", "Lambda candidates;inv. mass (p #pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 1.05, 1.35}}}); - registry.add("hPtDplus", "D^{#minus} candidates;D^{#minus} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); - registry.add("hPtDstar", "D^{*} candidates;D^{*} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); - registry.add("hPtV0", "V0 candidates;V0 candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); - registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} - m_{D^{*}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 2.4, 2.7}}}); - registry.add("hMassDsStar2", "Ds^{*}2 candidates; Ds^{*}2 - m_{D^{#plus}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 2.4, 2.7}}}); - registry.add("hMassXcRes", "XcRes candidates; XcRes - m_{D^{#plus}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 2.9, 3.3}}}); - registry.add("hV0Type", "V0 selection flag", {HistType::kTH1F, {{8, -0.5, 7.5}}}); + + const AxisSpec axisPt{50, 0.f, 50.f, ""}; + const AxisSpec axisP{100, 0.f, 10.f, ""}; + const AxisSpec axisDeDx{500, 0.f, 1000.f, ""}; + const AxisSpec axisMassDplus{200, 1.7f, 2.1f, ""}; + const AxisSpec axisMassDstar{200, 0.139f, 0.179f, ""}; + const AxisSpec axisMassLambda{100, 1.05f, 1.35f, ""}; + const AxisSpec axisMassKzero{100, 0.35f, 0.65f, ""}; + + registry.add("hMassVsPtDplusAll", "Dplus candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPt, axisMassDplus}}); + registry.add("hMassVsPtDstarAll", "Dstar candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPt, axisMassDstar}}); + registry.add("hMassVsPtDplusPaired", "Dplus candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPt, axisMassDplus}}); + registry.add("hMassVsPtDstarPaired", "Dstar candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPt, axisMassDstar}}); + + registry.add("hMassVsPtK0s", "K0^{s} candidates;#it{p}_{T} (GeV/#it{c});inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPt, axisMassKzero}}); + registry.add("hMassVsPtLambda", "Lambda candidates;#it{p}_{T} (GeV/#it{c});inv. mass (p #pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPt, axisMassLambda}}); + registry.add("hdEdxVsP", "Tracks;#it{p} (GeV/#it{c});d#it{E}/d#it{x};entries", {HistType::kTH2F, {axisP, axisDeDx}}); + + registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} - m_{D^{*}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{400, 0.49, 0.89}}}); + registry.add("hMassDsStar2", "Ds^{*}2 candidates; Ds^{*}2 - m_{D^{#plus}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{400, 0.49, 0.89}}}); + registry.add("hMassXcRes", "XcRes candidates; XcRes - m_{D^{#plus}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{300, 1.1, 1.4}}}); + registry.add("hMassDstarProton", "D^{*}-proton candidates;m_{D^{*}p} - m_{D^{*}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0.9, 1.4}}}); registry.add("hDType", "D selection flag", {HistType::kTH1F, {{5, -2.5, 2.5}}}); + // Configure CCDB access ccdb->setURL(url.value); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); ccdbApi.init(url); + runNumber = 0; lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + // Configure DCA fitter + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxDXYIni(4); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + fitter.setWeightedFinalPCA(false); + } + + /// Basic track quality selections for V0 daughters + /// \param Tr is a track + /// \param dDaughtersIds are the IDs of the D meson daughter tracks + template + bool selectV0Daughter(Tr const& track, const std::array& dDaughtersIds) + { + // acceptance selection + if (std::abs(track.eta()) > cfgV0Cuts.etaMaxDau) { + return false; + } + // Tpc Refit + if (!(track.hasTPC())) { + return false; + } + // track quality selection + if (track.itsNCls() < cfgV0Cuts.trackNclusItsCut || + track.tpcNClsFound() < cfgV0Cuts.trackNCrossedRowsTpc || + track.tpcNClsCrossedRows() < cfgV0Cuts.trackNCrossedRowsTpc || + track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || + track.tpcNClsShared() > cfgV0Cuts.trackNsharedClusTpc) { + return false; + } + // rejection of tracks that share a daughter with the D meson + if (rejectPairsWithCommonDaughter && std::find(dDaughtersIds.begin(), dDaughtersIds.end(), track.globalIndex()) != dDaughtersIds.end()) { + return false; + } + return true; } + // Utility to find which v0 daughter carries the largest fraction of the mother longitudinal momentum + float alphaAP(std::array const& momA, std::array const& momB, std::array const& momC) + { + float momTot = std::sqrt(std::pow(momA[0], 2.) + std::pow(momA[1], 2.) + std::pow(momA[2], 2.)); + float lQlPos = (momB[0] * momA[0] + momB[1] * momA[1] + momB[2] * momA[2]) / momTot; + float lQlNeg = (momC[0] * momA[0] + momC[1] * momA[1] + momC[2] * momA[2]) / momTot; + return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); + } + // Utility to find DCA of V0 to Primary vertex + float calculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) + { + return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); + } /// Basic selection of V0 candidates - /// \param v0 is the v0 candidate /// \param collision is the current collision /// \param dauTracks are the v0 daughter tracks - /// \param dDaughtersIDs are the IDs of the D meson daughter tracks + /// \param dDaughtersIds are the IDs of the D meson daughter tracks /// \return a bitmap with mass hypotesis if passes all cuts - template - inline uint8_t getSelectionMapV0(const V0& v0, const Coll& /*collision*/, const std::array& dauTracks, const std::array& dDaughtersIDs) + template + bool buildAndSelectV0(const Coll& collision, const std::array& dDaughtersIds, const std::array& dauTracks) { - uint8_t selMap{BIT(K0s) | BIT(Lambda) | BIT(AntiLambda)}; - // reject VOs that share daughters with D - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), v0.posTrackId()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), v0.negTrackId()) != dDaughtersIDs.end()) { - return 0; + auto trackPos = dauTracks[0]; + auto trackNeg = dauTracks[1]; + + // single-tracks selection + if (!selectV0Daughter(trackPos, dDaughtersIds) || !selectV0Daughter(trackNeg, dDaughtersIds)) + return false; + // daughters DCA to V0's collision primary vertex + gpu::gpustd::array dcaInfo; + auto trackPosPar = getTrackPar(trackPos); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackPosPar, 2.f, fitter.getMatCorrType(), &dcaInfo); + auto trackPosDcaXY = dcaInfo[0]; + auto trackNegPar = getTrackPar(trackNeg); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackNegPar, 2.f, fitter.getMatCorrType(), &dcaInfo); + auto trackNegDcaXY = dcaInfo[0]; + if (fabs(trackPosDcaXY) < cfgV0Cuts.dcaMaxDauToPv || fabs(trackNegDcaXY) < cfgV0Cuts.dcaMaxDauToPv) { + return false; + } + // vertex reconstruction + auto trackPosCov = getTrackParCov(trackPos); + auto trackNegCov = getTrackParCov(trackNeg); + int nCand = 0; + try { + nCand = fitter.process(trackPosCov, trackNegCov); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return false; + } + if (nCand == 0) { + return false; + } + // compute candidate momentum from tracks propagated to decay vertex + auto& trackPosProp = fitter.getTrack(0); + auto& trackNegProp = fitter.getTrack(1); + trackPosProp.getPxPyPzGlo(candidateV0.momPos); + trackNegProp.getPxPyPzGlo(candidateV0.momNeg); + for (int i = 0; i < 3; ++i) { + candidateV0.mom[i] = candidateV0.momPos[i] + candidateV0.momNeg[i]; } - // eta of daughters - if (std::fabs(v0.negativeeta()) > minV0dauEta || std::fabs(v0.positiveeta()) > minV0dauEta) { // cut all V0 daughters with |eta| > 1. - return 0; + candidateV0.pT = std::hypot(candidateV0.mom[0], candidateV0.mom[1]); + // topological selections: + // v0 eta + candidateV0.eta = RecoDecay::eta(candidateV0.mom); + if (std::abs(candidateV0.eta) > cfgV0Cuts.etaMax) { + return false; } - // minimum v0radius - if (v0.v0radius() < minK0sLambdaRadius) { - return 0; + // daughters DCA + candidateV0.dcaDau = std::sqrt(fitter.getChi2AtPCACandidate()); + if (candidateV0.dcaDau > cfgV0Cuts.dcaDau) { + return false; } - // cosine of pointing angle - auto v0CosinePa = v0.v0cosPA(); - if (v0CosinePa < minK0sLambdaCosinePa) { - return 0; + // v0 radius + const auto& vtx = fitter.getPCACandidate(); + candidateV0.radius = std::hypot(vtx[0], vtx[1]); + if (candidateV0.radius < cfgV0Cuts.radiusMin) { + return false; } - // DCA V0 and V0 daughters to select for primary V0s - if (v0.dcav0topv() > maxV0DCA || v0.dcaV0daughters() > maxV0dauDCA || std::fabs(v0.dcapostopv()) < minV0dauDCA || std::fabs(v0.dcanegtopv()) < minV0dauDCA) { - return 0; + for (int i = 0; i < 3; i++) { + candidateV0.pos[i] = vtx[i]; } + // v0 DCA to primary vertex + candidateV0.dcaV0ToPv = calculateDCAStraightToPV( + vtx[0], vtx[1], vtx[2], + candidateV0.momPos[0] + candidateV0.momNeg[0], + candidateV0.momPos[1] + candidateV0.momNeg[1], + candidateV0.momPos[2] + candidateV0.momNeg[2], + collision.posX(), collision.posY(), collision.posZ()); + if (std::abs(candidateV0.dcaV0ToPv) > cfgV0Cuts.dcaPv) { + return false; + } + // v0 cosine of pointing angle + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; + candidateV0.cosPA = RecoDecay::cpa(primVtx, vtx, candidateV0.mom); + if (candidateV0.cosPA < cfgV0Cuts.cosPa) { + return false; + } + + // distinguish between K0s, and Lambda hypotesys + candidateV0.v0Type = {BIT(K0s) | BIT(Lambda) | BIT(AntiLambda)}; + // for lambda hypotesys define if its lambda or anti-lambda + candidateV0.alpha = alphaAP(candidateV0.mom, candidateV0.momPos, candidateV0.momNeg); + bool matter = candidateV0.alpha > 0; + CLRBIT(candidateV0.v0Type, matter ? AntiLambda : Lambda); + auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; + auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; // mass hypotesis - if (std::fabs(v0.mK0Short() - MassK0) > deltaMassK0s) { - CLRBIT(selMap, K0s); + candidateV0.mLambda = RecoDecay::m(std::array{candidateV0.momPos, candidateV0.momNeg}, std::array{massPos, massNeg}); + candidateV0.mK0Short = RecoDecay::m(std::array{candidateV0.momPos, candidateV0.momNeg}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); + if (std::fabs(candidateV0.mK0Short - MassK0) > cfgV0Cuts.deltaMassK0s) { + CLRBIT(candidateV0.v0Type, K0s); + } + if (std::fabs(candidateV0.mLambda - MassLambda0) > cfgV0Cuts.deltaMassLambda) { + CLRBIT(candidateV0.v0Type, Lambda); + CLRBIT(candidateV0.v0Type, AntiLambda); + } + // PID + if (TESTBIT(candidateV0.v0Type, K0s)) { + if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc) || + (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc)) + CLRBIT(candidateV0.v0Type, K0s); } - if (std::fabs(v0.mLambda() - MassLambda0) > deltaMassLambda) { - CLRBIT(selMap, Lambda); + if (TESTBIT(candidateV0.v0Type, Lambda)) { + if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPr()) > cfgV0Cuts.nSigmaTpc) || + (trackPos.hasTOF() && std::fabs(trackPos.tofNSigmaPr()) > cfgV0Cuts.nSigmaTofPr) || + (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc)) + CLRBIT(candidateV0.v0Type, Lambda); } - if (std::fabs(v0.mAntiLambda() - MassLambda0) > deltaMassLambda) { - CLRBIT(selMap, AntiLambda); + if (TESTBIT(candidateV0.v0Type, AntiLambda)) { + if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc) || + (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPr()) > cfgV0Cuts.nSigmaTpc) || + (trackNeg.hasTOF() && std::fabs(trackNeg.tofNSigmaPr()) > cfgV0Cuts.nSigmaTofPr)) + CLRBIT(candidateV0.v0Type, AntiLambda); } - // PID (Lambda/AntiLambda only) - float nSigmaPrTpc[2] = {dauTracks[0].tpcNSigmaPr(), dauTracks[1].tpcNSigmaPr()}; - float nSigmaPrTof[2] = {dauTracks[0].tofNSigmaPr(), dauTracks[1].tofNSigmaPr()}; - if (TESTBIT(selMap, Lambda) && ((dauTracks[0].hasTPC() && std::fabs(nSigmaPrTpc[0]) > maxNsigmaPrForLambda) || (dauTracks[0].hasTOF() && std::fabs(nSigmaPrTof[0]) > maxNsigmaPrForLambda))) { - CLRBIT(selMap, Lambda); + if (candidateV0.v0Type == 0) { + return false; } - if (TESTBIT(selMap, AntiLambda) && ((dauTracks[1].hasTPC() && std::fabs(nSigmaPrTpc[1]) > maxNsigmaPrForLambda) || (dauTracks[1].hasTOF() && std::fabs(nSigmaPrTof[1]) > maxNsigmaPrForLambda))) { - CLRBIT(selMap, AntiLambda); + return true; + } + + /// Basic selection of tracks + /// \param track is the track + /// \param dDaughtersIds are the IDs of the D meson daughter tracks + /// \return true if passes all cuts + template + bool isTrackSelected(const Tr& track, const std::array& dDaughtersIds) + { + + if (rejectPairsWithCommonDaughter && std::find(dDaughtersIds.begin(), dDaughtersIds.end(), track.globalIndex()) != dDaughtersIds.end()) { + return false; + } + + switch (cfgSingleTrackCuts.setTrackSelections) { + case 1: + if (!track.isGlobalTrackWoDCA()) { + return false; + } + break; + case 2: + if (!track.isGlobalTrack()) { + return false; + } + break; + case 3: + if (!track.isQualityTrackITS()) { + return false; + } + break; } - return selMap; + + if (track.pt() < cfgSingleTrackCuts.minPt) { + return false; + } + + if (std::abs(track.eta()) > cfgSingleTrackCuts.maxEta) { + return false; + } + + if (!track.hasTPC()) { + return false; + } + + bool isPion = std::abs(track.tpcNSigmaPi()) < cfgSingleTrackCuts.maxNsigmaTpcPi; + bool isKaon = std::abs(track.tpcNSigmaKa()) < cfgSingleTrackCuts.maxNsigmaTpcKa; + bool isProton = std::abs(track.tpcNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTpcPr; + + if (!isPion && !isKaon && !isProton) { // we keep the track if is it compatible with at least one of the PID hypotheses selected + return false; + } + + return true; } - template + template void runDataCreation(Coll const& collision, CCands const& candsD, - aod::V0Datas const& V0s, - TracksWithPID const&, + BBach const& bachelors, + Tr const&, aod::BCsWithTimestamps const&) { // helpers for ReducedTables filling @@ -227,29 +472,35 @@ struct HfDataCreatorCharmResoReduced { // std::map where the key is the V0.globalIndex() and // the value is the V0 index in the table of the selected v0s std::map selectedV0s; + std::map selectedTracks; bool fillHfReducedCollision = false; auto bc = collision.template bc_as(); - initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + } + fitter.setBz(bz); // loop on D candidates for (const auto& candD : candsD) { // initialize variables depending on decay channel bool fillHfCandD = false; - float invMassD; - float massD; - float massV0{0.}; + float invMassD{0.f}, invMassDdau{0.f}; std::array pVecD; std::array pVecProng2; std::array secondaryVertexD; std::array prongIdsD; - uint8_t v0type; int8_t dtype; std::array bdtScores; - if constexpr (DecayChannel == DecayChannel::DstarV0) { - if (candD.signSoftPi() > 0) - invMassD = candD.invMassDstar() - candD.invMassD0(); - else - invMassD = candD.invMassAntiDstar() - candD.invMassD0Bar(); - massD = MassDStar; + if constexpr (DecayChannel == DecayChannel::DstarV0 || DecayChannel == DecayChannel::DstarTrack) { + if (candD.signSoftPi() > 0) { + invMassD = candD.invMassDstar(); + invMassDdau = candD.invMassD0(); + } else { + invMassD = candD.invMassAntiDstar(); + invMassDdau = candD.invMassD0Bar(); + } pVecD = candD.pVector(); secondaryVertexD[0] = candD.xSecondaryVertexD0(); secondaryVertexD[1] = candD.ySecondaryVertexD0(); @@ -257,18 +508,16 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[0] = candD.prong0Id(); prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prongPiId(); - pVecProng2[0] = candD.pxSoftPi(); - pVecProng2[1] = candD.pySoftPi(); - pVecProng2[2] = candD.pzSoftPi(); + pVecProng2 = candD.pVecSoftPi(); dtype = candD.signSoftPi() * DType::Dstar; if constexpr (withMl) { std::copy(candD.mlProbDstarToD0Pi().begin(), candD.mlProbDstarToD0Pi().end(), bdtScores.begin()); } + registry.fill(HIST("hMassVsPtDstarAll"), candD.pt(), invMassD - invMassDdau); } else if constexpr (DecayChannel == DecayChannel::DplusV0) { - auto prong0 = candD.template prong0_as(); + auto prong0 = candD.template prong0_as(); invMassD = hfHelper.invMassDplusToPiKPi(candD); - massD = MassDPlus; pVecD = candD.pVector(); secondaryVertexD[0] = candD.xSecondaryVertex(); secondaryVertexD[1] = candD.ySecondaryVertex(); @@ -276,85 +525,121 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[0] = candD.prong0Id(); prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prong2Id(); - pVecProng2[0] = candD.pxProng2(); - pVecProng2[1] = candD.pyProng2(); - pVecProng2[2] = candD.pzProng2(); + pVecProng2 = candD.pVectorProng2(); dtype = static_cast(prong0.sign() * DType::Dplus); if constexpr (withMl) { std::copy(candD.mlProbDplusToPiKPi().begin(), candD.mlProbDplusToPiKPi().end(), bdtScores.begin()); } + registry.fill(HIST("hMassVsPtDplusAll"), candD.pt(), invMassD); } // else if - // Loop on V0 candidates - for (const auto& v0 : V0s) { - auto posTrack = v0.posTrack_as(); - auto negTrack = v0.negTrack_as(); - // Apply selsection - v0type = getSelectionMapV0(v0, collision, std::array{posTrack, negTrack}, prongIdsD); - if (v0type == 0) { - continue; - } - // propagate V0 to primary vertex (if enabled) - std::array pVecV0 = {v0.px(), v0.py(), v0.pz()}; - if (propagateV0toPV) { - std::array pVecV0Orig = {v0.px(), v0.py(), v0.pz()}; - std::array posVecV0 = {v0.x(), v0.y(), v0.z()}; - gpu::gpustd::array dcaInfo; - auto trackParK0 = o2::track::TrackPar(posVecV0, pVecV0Orig, 0, true); - trackParK0.setPID(o2::track::PID::K0); - trackParK0.setAbsCharge(0); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParK0, 2.f, matCorr, &dcaInfo); - getPxPyPz(trackParK0, pVecV0); - } - float ptV0 = RecoDecay::pt(pVecV0); // fill histos - registry.fill(HIST("hPtV0"), ptV0); - registry.fill(HIST("hV0Type"), v0type); - if (TESTBIT(v0type, K0s)) { - massV0 = MassK0; - auto invMassDV0 = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massD, massV0}); - registry.fill(HIST("hMassK0s"), v0.mK0Short()); - switch (DecayChannel) { - case DecayChannel::DstarV0: - registry.fill(HIST("hMassDs1"), invMassDV0); - break; - case DecayChannel::DplusV0: - registry.fill(HIST("hMassDsStar2"), invMassDV0); - break; - default: - break; + if constexpr (DecayChannel == DecayChannel::DplusV0 || DecayChannel == DecayChannel::DstarV0) { + // Loop on V0 candidates + for (const auto& v0 : bachelors) { + auto trackPos = v0.template posTrack_as(); + auto trackNeg = v0.template negTrack_as(); + // Apply selsection + if (!buildAndSelectV0(collision, prongIdsD, std::array{trackPos, trackNeg})) { + continue; } - } - if (TESTBIT(v0type, Lambda)) { - massV0 = MassLambda0; - auto invMassDV0 = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massD, massV0}); - registry.fill(HIST("hMassLambda"), v0.mLambda()); - if (DecayChannel == DecayChannel::DplusV0) { - registry.fill(HIST("hMassXcRes"), invMassDV0); + // propagate V0 to primary vertex (if enabled) + if (propagateV0toPV) { + std::array pVecV0Orig = {candidateV0.mom[0], candidateV0.mom[1], candidateV0.mom[2]}; + gpu::gpustd::array dcaInfo; + auto trackParK0 = o2::track::TrackPar(candidateV0.pos, pVecV0Orig, 0, true); + trackParK0.setPID(o2::track::PID::K0); + trackParK0.setAbsCharge(0); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParK0, 2.f, matCorr, &dcaInfo); + getPxPyPz(trackParK0, candidateV0.mom); } - } - if (TESTBIT(v0type, AntiLambda)) { - massV0 = MassLambda0; - auto invMassDV0 = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massD, massV0}); - registry.fill(HIST("hMassLambda"), v0.mAntiLambda()); - if (DecayChannel == DecayChannel::DplusV0) { - registry.fill(HIST("hMassXcRes"), invMassDV0); + float invMassKPiPiV0{0.f}; + if (TESTBIT(candidateV0.v0Type, K0s)) { + if constexpr (DecayChannel == DecayChannel::DplusV0) { + invMassKPiPiV0 = RecoDecay::m(std::array{candD.pVectorProng0(), candD.pVectorProng1(), candD.pVectorProng2(), candidateV0.mom}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); + } else if (DecayChannel == DecayChannel::DstarV0) { + if (candD.signSoftPi() > 0) { + invMassKPiPiV0 = RecoDecay::m(std::array{candD.pVectorProng0(), candD.pVectorProng1(), candD.pVecSoftPi(), candidateV0.mom}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); + } else { + invMassKPiPiV0 = RecoDecay::m(std::array{candD.pVectorProng1(), candD.pVectorProng0(), candD.pVecSoftPi(), candidateV0.mom}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); + } + } + + registry.fill(HIST("hMassVsPtK0s"), candidateV0.pT, candidateV0.mK0Short); + if constexpr (DecayChannel == DecayChannel::DstarV0) { + registry.fill(HIST("hMassDs1"), invMassKPiPiV0 - invMassD); + } else if constexpr (DecayChannel == DecayChannel::DplusV0) { + registry.fill(HIST("hMassDsStar2"), invMassKPiPiV0 - invMassD); + } + } + bool isLambda = TESTBIT(candidateV0.v0Type, Lambda); + bool isAntiLambda = TESTBIT(candidateV0.v0Type, AntiLambda); + if (isLambda || isAntiLambda) { + if constexpr (DecayChannel == DecayChannel::DplusV0) { + invMassKPiPiV0 = RecoDecay::m(std::array{candD.pVectorProng0(), candD.pVectorProng1(), candD.pVectorProng2(), candidateV0.mom}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda0}); + } else if (DecayChannel == DecayChannel::DstarV0) { + if (candD.signSoftPi() > 0) { + invMassKPiPiV0 = RecoDecay::m(std::array{candD.pVectorProng0(), candD.pVectorProng1(), candD.pVecSoftPi(), candidateV0.mom}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda0}); + } else { + invMassKPiPiV0 = RecoDecay::m(std::array{candD.pVectorProng1(), candD.pVectorProng0(), candD.pVecSoftPi(), candidateV0.mom}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda0}); + } + } + if (isLambda || isAntiLambda) { + registry.fill(HIST("hMassVsPtLambda"), candidateV0.pT, candidateV0.mLambda); + } + if constexpr (DecayChannel == DecayChannel::DplusV0) { + registry.fill(HIST("hMassXcRes"), invMassKPiPiV0 - invMassD); + } + } + // fill V0 table + // if information on V0 already stored, go to next V0 + if (!selectedV0s.count(v0.globalIndex())) { + hfCandV0(trackPos.globalIndex(), trackNeg.globalIndex(), + indexHfReducedCollision, + candidateV0.pos[0], candidateV0.pos[1], candidateV0.pos[2], + candidateV0.momPos[0], candidateV0.momPos[1], candidateV0.momPos[2], + candidateV0.momNeg[0], candidateV0.momNeg[1], candidateV0.momNeg[2], + candidateV0.cosPA, + candidateV0.dcaV0ToPv, + candidateV0.v0Type); + selectedV0s[v0.globalIndex()] = hfCandV0.lastIndex(); + } + fillHfCandD = true; + } // V0 loop + } else if constexpr (DecayChannel == DecayChannel::DstarTrack) { + for (const auto& trackIndex : bachelors) { + auto track = trackIndex.template track_as(); + if (!isTrackSelected(track, prongIdsD)) { + continue; + } + + // if the track has been reassociated, re-propagate it to PV (minor difference) + auto trackParCovTrack = getTrackParCov(track); + o2::gpu::gpustd::array dcaTrack{track.dcaXY(), track.dcaZ()}; + std::array pVecTrack = track.pVector(); + if (track.collisionId() != collision.globalIndex()) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovTrack, 2.f, matCorr, &dcaTrack); + getPxPyPz(trackParCovTrack, pVecTrack); } - } - // fill V0 table - // if information on V0 already stored, go to next V0 - if (!selectedV0s.count(v0.globalIndex())) { - hfCandV0(v0.posTrackId(), v0.negTrackId(), - indexHfReducedCollision, - v0.x(), v0.y(), v0.z(), - v0.pxpos(), v0.pypos(), v0.pzpos(), - v0.pxneg(), v0.pyneg(), v0.pzneg(), - v0.v0cosPA(), - v0.dcav0topv(), - v0type); - selectedV0s[v0.globalIndex()] = hfCandV0.lastIndex(); - } - fillHfCandD = true; - } // V0 loop + + registry.fill(HIST("hdEdxVsP"), track.p(), track.tpcSignal()); + float invMassKPiPiP{0.f}; + if (candD.signSoftPi() > 0) { + invMassKPiPiP = RecoDecay::m(std::array{candD.pVectorProng0(), candD.pVectorProng1(), candD.pVecSoftPi(), pVecTrack}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}); + } else { + invMassKPiPiP = RecoDecay::m(std::array{candD.pVectorProng1(), candD.pVectorProng0(), candD.pVecSoftPi(), pVecTrack}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}); + } + registry.fill(HIST("hMassDstarProton"), invMassKPiPiP - invMassD); + if (!selectedTracks.count(track.globalIndex())) { + hfTrackNoParam(indexHfReducedCollision, + track.px(), track.py(), track.pz(), track.sign(), + track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.hasTOF()); + selectedTracks[track.globalIndex()] = hfTrackNoParam.lastIndex(); + } + fillHfCandD = true; + } // track loop + } if (fillHfCandD) { // fill candDplus table only once per D candidate, only if at least one V0 is found hfCandD(prongIdsD[0], prongIdsD[1], prongIdsD[2], @@ -368,17 +653,10 @@ struct HfDataCreatorCharmResoReduced { hfCandDMl(bdtScores[0], bdtScores[1], bdtScores[2]); } fillHfReducedCollision = true; - switch (DecayChannel) { - case DecayChannel::DstarV0: - registry.fill(HIST("hMassDstar"), invMassD); - registry.fill(HIST("hPtDstar"), candD.pt()); - break; - case DecayChannel::DplusV0: - registry.fill(HIST("hMassDplus"), invMassD); - registry.fill(HIST("hPtDplus"), candD.pt()); - break; - default: - break; + if constexpr (DecayChannel == DecayChannel::DstarV0 || DecayChannel == DecayChannel::DstarTrack) { + registry.fill(HIST("hMassVsPtDstarPaired"), candD.pt(), invMassD - invMassDdau); + } else if constexpr (DecayChannel == DecayChannel::DplusV0) { + registry.fill(HIST("hMassVsPtDplusPaired"), candD.pt(), invMassD); } registry.fill(HIST("hDType"), dtype); } @@ -389,15 +667,16 @@ struct HfDataCreatorCharmResoReduced { return; } registry.fill(HIST("hEvents"), 1 + Event::DV0Selected); + float centrality = -1.f; + uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a DPi pair a minima - hfReducedCollision(collision.posX(), collision.posY(), collision.posZ()); + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); } // run data creation void processDplusV0(soa::Join const& collisions, CandsDplusFiltered const& candsDplus, - aod::TrackAssoc const&, - aod::V0Datas const& V0s, - TracksWithPID const& tracks, + aod::V0s const& V0s, + TracksIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) { int zvtxColl{0}; @@ -406,7 +685,7 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); @@ -414,14 +693,13 @@ struct HfDataCreatorCharmResoReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0, "Process Dplus candidates without MC info and without ML info", true); + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0, "Process Dplus candidates paired with V0s without MC info and without ML info", true); void processDplusV0WithMl(soa::Join const& collisions, CandsDplusFilteredWithMl const& candsDplus, - aod::V0Datas const& V0s, - TracksWithPID const& tracks, + aod::V0s const& V0s, + TracksIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) { int zvtxColl{0}; @@ -430,7 +708,7 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); @@ -438,15 +716,13 @@ struct HfDataCreatorCharmResoReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0WithMl, "Process Dplus candidates with ML info", false); + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0WithMl, "Process Dplus candidates paired with V0s with ML info", false); void processDstarV0(soa::Join const& collisions, CandDstarFiltered const& candsDstar, - aod::TrackAssoc const&, - aod::V0Datas const& V0s, - TracksWithPID const& tracks, + aod::V0s const& V0s, + TracksIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) { int zvtxColl{0}; @@ -455,7 +731,7 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); @@ -463,14 +739,13 @@ struct HfDataCreatorCharmResoReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0, "Process DStar candidates without MC info and without ML info", false); + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0, "Process DStar candidates paired with V0s without MC info and without ML info", false); void processDstarV0WithMl(soa::Join const& collisions, CandDstarFilteredWithMl const& candsDstar, - aod::V0Datas const& V0s, - TracksWithPID const& tracks, + aod::V0s const& V0s, + TracksIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) { int zvtxColl{0}; @@ -479,7 +754,7 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); @@ -488,9 +763,56 @@ struct HfDataCreatorCharmResoReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0WithMl, "Process DStar candidates paired with V0s with ML info", false); + + void processDstarTrack(soa::Join const& collisions, + CandDstarFiltered const& candsDstar, + aod::TrackAssoc const& trackIndices, + TracksWithPID const& tracks, + aod::BCsWithTimestamps const& bcs) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, tracks, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarTrack, "Process DStar candidates paired with tracks without MC info and without ML info", false); + + void processDstarTrackWithMl(soa::Join const& collisions, + CandDstarFilteredWithMl const& candsDstar, + aod::TrackAssoc const& trackIndices, + TracksWithPID const& tracks, + aod::BCsWithTimestamps const& bcs) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, tracks, bcs); + } + // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0WithMl, "Process DStar candidates with ML info", false); + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarTrackWithMl, "Process DStar candidates paired with tracks with ML info", false); + }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 4a533812364..70837975a00 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -39,6 +39,11 @@ o2physics_add_dpl_workflow(task-charm-polarisation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-charm-reso-reduced + SOURCES taskCharmResoReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-d0 SOURCES taskD0.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -61,7 +66,7 @@ o2physics_add_dpl_workflow(task-dstar-to-d0-pi o2physics_add_dpl_workflow(task-flow-charm-hadrons SOURCES taskFlowCharmHadrons.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-lb @@ -84,11 +89,21 @@ o2physics_add_dpl_workflow(task-sigmac PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-sigmac-to-cascade + SOURCES taskSigmacToCascade.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-xic SOURCES taskXic.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-xic-to-xi-pi-pi + SOURCES taskXicToXiPiPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-xicc SOURCES taskXicc.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index bc95e9c176a..cbcfb44a85b 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -59,10 +59,50 @@ enum MassHyposLcToPKPi : uint8_t { PiKP, NMassHypoLcToPKPi }; + +/// columns for table to study the Lc->PKPi background +DECLARE_SOA_COLUMN(MassLc, massLc, float); +DECLARE_SOA_COLUMN(PtLc, ptLc, float); +DECLARE_SOA_COLUMN(RapidityLc, rapidityLc, float); +DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); +DECLARE_SOA_COLUMN(PdgMotherProng0, pdgMotherProng0, int); +DECLARE_SOA_COLUMN(PdgMotherProng1, pdgMotherProng1, int); +DECLARE_SOA_COLUMN(PdgMotherProng2, pdgMotherProng2, int); +DECLARE_SOA_COLUMN(MassKPi, massKPi, float); +DECLARE_SOA_COLUMN(MassKProton, massKProton, float); +DECLARE_SOA_COLUMN(MassPiProton, massPiProton, float); +DECLARE_SOA_COLUMN(BdtBkgScore, bdtBkgScore, float); +DECLARE_SOA_COLUMN(BdtNonPromptScore, bdtNonPromptScore, float); +DECLARE_SOA_COLUMN(IsRealPKPi, isRealPKPi, int8_t); +DECLARE_SOA_COLUMN(IsRealLcPKPi, isRealLcPKPi, int8_t); +DECLARE_SOA_COLUMN(IsReflected, isReflected, int8_t); +DECLARE_SOA_COLUMN(Charge, charge, int8_t); + } // namespace charm_polarisation + +/// table to study the Lc->PKPi background +DECLARE_SOA_TABLE(HfLcPolBkg, "AOD", "HFLCPOLBKG", + charm_polarisation::MassLc, + charm_polarisation::PtLc, + charm_polarisation::RapidityLc, + charm_polarisation::CosThetaStar, + charm_polarisation::PdgMotherProng0, + charm_polarisation::PdgMotherProng1, + charm_polarisation::PdgMotherProng2, + charm_polarisation::MassKPi, + charm_polarisation::MassKProton, + charm_polarisation::MassPiProton, + charm_polarisation::BdtBkgScore, + charm_polarisation::BdtNonPromptScore, + charm_polarisation::IsRealPKPi, + charm_polarisation::IsRealLcPKPi, + charm_polarisation::IsReflected, + charm_polarisation::Charge); + } // namespace o2::aod struct TaskPolarisationCharmHadrons { + Produces rowCandLcBkg; float massPi{0.f}; float massProton{0.f}; @@ -91,12 +131,19 @@ struct TaskPolarisationCharmHadrons { // ConfigurableAxis configThnAxisCent{"configThnAxisCent", {102, -1.f, 101.f}, "centrality (%)"}; ConfigurableAxis configThnAxisNumPvContributors{"configThnAxisNumPvContributors", {300, -0.5f, 299.5f}, "num PV contributors"}; ConfigurableAxis configThnAxisPtB{"configThnAxisPtB", {3000, 0.f, 300.f}, "#it{p}_{T}(B mother) (GeV/#it{c})"}; + ConfigurableAxis configThnAxisAbsEtaTrackMin{"configThnAxisEtaTrackMin", {3, 0.f, 0.3f}, "min |#it{#eta_{track}}|"}; + ConfigurableAxis configThnAxisNumItsClsMin{"configThnAxisNumItsClsMin", {4, 3.5f, 7.5f}, "min #it{N}_{cls ITS}"}; + ConfigurableAxis configThnAxisNumTpcClsMin{"configThnAxisNumTpcClsMin", {3, 79.5f, 140.5f}, "min #it{N}_{cls TPC}"}; + ConfigurableAxis configThnAxisCharge{"configThnAxisCharge", {2, -2.f, 2.f}, "electric charge"}; /// activate rotational background Configurable nBkgRotations{"nBkgRotations", 0, "Number of rotated copies (background) per each original candidate"}; Configurable minRotAngleMultByPi{"minRotAngleMultByPi", 5. / 6, "Minimum angle rotation for track rotation, to be multiplied by pi"}; Configurable maxRotAngleMultByPi{"maxRotAngleMultByPi", 7. / 6, "Maximum angle rotation for track rotation, to be multiplied by pi"}; + // activate study of systematic uncertainties of tracking + Configurable activateTrackingSys{"activateTrackingSys", false, "Activate the study of systematic uncertainties of tracking"}; + /// output THnSparses Configurable activateTHnSparseCosThStarHelicity{"activateTHnSparseCosThStarHelicity", true, "Activate the THnSparse with cosThStar w.r.t. helicity axis"}; Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", true, "Activate the THnSparse with cosThStar w.r.t. production axis"}; @@ -105,10 +152,49 @@ struct TaskPolarisationCharmHadrons { float minInvMass{0.f}; float maxInvMass{1000.f}; + /// table for Lc->pKpi background studies in MC + Configurable cosThStarAxisLcPKPiBkgMc{"cosThStarAxisLcPKPiBkgMc", 1, "cos(Theta*) axis for background studies (1 = helicity; 2 = production; 3 = beam; 4 = random)"}; + + /// veto conditions for Lc->pKpi analysis + struct : ConfigurableGroup { + Configurable applyLcBkgVeto{"applyLcBkgVeto", false, "Flag to enable the veto on D+ and Ds+ background for Lc->pKpi analysis"}; + /// background from D+->K-pi+pi+ + Configurable enableLcBkgVetoDplusKPiPi{"enableLcBkgVetoDplusKPiPi", false, "Flag to enable the veto on D+->K-pi+pi+ for Lc->pKpi analysis"}; + Configurable massDplusKPiPiMinVeto{"massDplusKPiPiMinVeto", 1.85, "Min. value for D+->K-pi+pi+ veto"}; + Configurable massDplusKPiPiMaxVeto{"massDplusKPiPiMaxVeto", 1.90, "Max. value for D+->K-pi+pi+ veto"}; + /// background from D+->K+K-pi+ + Configurable enableLcBkgVetoDplusKKPi{"enableLcBkgVetoDplusKKPi", false, "Flag to enable the veto on D+->K+K-pi+ for Lc->pKpi analysis"}; + Configurable massDplusKKPiMinVeto{"massDplusKKPiMinVeto", 1.85, "Min. value for D+->K+K-pi+ veto"}; // one can use also massDplusKPiPiMinVeto, but this allows more flexibility in analysis + Configurable massDplusKKPiMaxVeto{"massDplusKKPiMaxVeto", 1.90, "Max. value for D+->K+K-pi+ veto"}; // one can use also massDplusKPiPiMaxVeto, but this allows more flexibility in analysis + /// background from Ds+->K+K-pi+ + Configurable enableLcBkgVetoDsKKPi{"enableLcBkgVetoDsKKPi", false, "Flag to enable the veto on Ds+->K+K-pi+ for Lc->pKpi analysis"}; + Configurable massDsKKPiMinVeto{"massDsKKPiMinVeto", 1.94, "Min. value for Ds+->K+K-pi+ veto"}; + Configurable massDsKKPiMaxVeto{"massDsKKPiMaxVeto", 2.00, "Max. value for Ds+->K+K-pi+ veto"}; + } lcBkgVeto; + struct : ConfigurableGroup { + /// monitoring histograms (Dalitz plot) + Configurable activateTHnLcChannelMonitor{"activateTHnLcChannelMonitor", false, "Flag to switch on the monitoring THnSparse of M2(Kpi), M2(pK), M2(ppi), pt correlation for Lc -> pKpi"}; + ConfigurableAxis configThnAxisInvMass2KPiLcMonitoring{"configThnAxisInvMassKPiLcMonitoring", {200, 0.3f, 2.3f}, "#it{M}^{2}(K#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisInvMass2PKLcMonitoring{"configThnAxisInvMass2PKLcMonitoring", {320, 2.f, 5.2f}, "#it{M}^{2}(pK) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisInvMass2PPiLcMonitoring{"configThnAxisInvMass2PPiLcMonitoring", {400, 1.f, 5.f}, "#it{M}^{2}(p#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; + + /// veto conditions on Lc->pKpi signals + Configurable applyLcSignalVeto{"applyLcSignalVeto", false, "Flag to enable the veto on Lc->pKpi resonant channels"}; + Configurable mass2PPiLcMinVeto{"mass2PPiLcMinVeto", 1.f, "Min. value for Delta++(<-Lc) mass veto"}; + Configurable mass2PPiLcMaxVeto{"mass2PPiLcMaxVeto", 1.6f, "Max. value for Delta++(<-Lc) mass veto"}; + + } lcPKPiChannels; + + /// Monitoring of phi Euler angle + Configurable activateTHnEulerPhiMonitor{"activateTHnEulerPhiMonitor", false, "Flag to switch on the monitoring THnSparse vs. Euler angle phi (Lc -> pKpi)"}; + ConfigurableAxis configTHnAxisEulerPhi{"configTHnAxisEulerPhi", {24, -o2::constants::math::PI, o2::constants::math::PI}, "Euler polar angle #phi"}; + Filter filterSelectDstarCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; Filter filterSelectLcToPKPiCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLcToPKPi) || (aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLcToPKPi); using CollisionsWithMcLabels = soa::SmallGroups>; + using TracksWithMcLabels = soa::Join; + using TracksWithExtra = soa::Join; using McParticlesDstarMatched = soa::Join; using McParticles3ProngMatched = soa::Join; @@ -143,7 +229,7 @@ struct TaskPolarisationCharmHadrons { void init(InitContext&) { /// check process functions - std::array processes = {doprocessDstar, doprocessDstarWithMl, doprocessLcToPKPi, doprocessLcToPKPiWithMl, doprocessDstarMc, doprocessDstarMcWithMl, doprocessLcToPKPiMc, doprocessLcToPKPiMcWithMl}; + std::array processes = {doprocessDstar, doprocessDstarWithMl, doprocessLcToPKPi, doprocessLcToPKPiWithMl, doprocessDstarMc, doprocessDstarMcWithMl, doprocessLcToPKPiMc, doprocessLcToPKPiMcWithMl, doprocessLcToPKPiBackgroundMcWithMl}; const int nProcesses = std::accumulate(processes.begin(), processes.end(), 0); if (nProcesses > 1) { LOGP(fatal, "Only one process function should be enabled at a time, please check your configuration"); @@ -171,7 +257,7 @@ struct TaskPolarisationCharmHadrons { } // check bkg rotation for MC (not supported currently) - if (nBkgRotations > 0 && (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl)) { + if (nBkgRotations > 0 && (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl)) { LOGP(fatal, "No background rotation supported for MC."); } @@ -198,6 +284,14 @@ struct TaskPolarisationCharmHadrons { const AxisSpec thnAxisPtB{configThnAxisPtB, "#it{p}_{T}(B mother) (GeV/#it{c})"}; const AxisSpec thnAxisDausAcc{2, -0.5f, 1.5f, "daughters in acceptance"}; const AxisSpec thnAxisResoChannelLc{4, -0.5, 3.5, "0: direct 1,2,3: resonant"}; // 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± + const AxisSpec thnAxisAbsEtaTrackMin{configThnAxisAbsEtaTrackMin, "min |#it{#eta_{track}}|"}; + const AxisSpec thnAxisNumItsClsMin{configThnAxisNumItsClsMin, "min #it{N}_{cls ITS}"}; + const AxisSpec thnAxisNumTpcClsMin{configThnAxisNumTpcClsMin, "min #it{N}_{cls TPC}"}; + const AxisSpec thnAxisCharge{configThnAxisCharge, "charge"}; + const AxisSpec thnAxisInvMass2KPiLcMonitoring{lcPKPiChannels.configThnAxisInvMass2KPiLcMonitoring, "#it{M}^{2}(K#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2}"}; + const AxisSpec thnAxisInvMass2PKLcMonitoring{lcPKPiChannels.configThnAxisInvMass2PKLcMonitoring, "#it{M}^{2}(pK) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisInvMass2PPiLcMonitoring{lcPKPiChannels.configThnAxisInvMass2PPiLcMonitoring, "#it{M}^{2}(p#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisTHnAxisEulerPhi{configTHnAxisEulerPhi, "Euler polar angle #phi"}; auto invMassBins = thnAxisInvMass.binEdges; minInvMass = invMassBins.front(); @@ -211,156 +305,203 @@ struct TaskPolarisationCharmHadrons { /// analysis for D*+ meson with ML, w/o rot. background axis if (doprocessDstarWithMl) { if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } } else { if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisPtB}); + registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisPtB}); + registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisPtB}); + registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisPtB}); + registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } } - } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl) { + } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { /// analysis for Lc+ baryon with ML, w/ rot. background axis (for data only) if (doprocessLcToPKPiWithMl) { if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisCharge}); + } } if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisCharge}); + } } if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisCharge}); + } } if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisIsRotatedCandidate}); + registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); } } else { if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); + registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hRecPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecNonPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + } } if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); + registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hRecPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecNonPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + } } if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); + registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hRecPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecNonPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + } } if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc}); + registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); + registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); } } } else if (doprocessDstar || doprocessDstarMc) { /// analysis for D*+ meson, w/o rot. background axis if (doprocessDstar) { if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisIsRotatedCandidate}); + registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisIsRotatedCandidate}); + registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisIsRotatedCandidate}); + registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisIsRotatedCandidate}); + registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); } } else { if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisPtB}); + registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisPtB}); + registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisPtB}); + registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisPtB}); + registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisPtB}); } } } else if (doprocessLcToPKPi || doprocessLcToPKPiMc) { /// analysis for Lc+ baryon, rot. background axis (for data only) if (doprocessLcToPKPi) { if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisIsRotatedCandidate}); + registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisCharge}); + } } if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisIsRotatedCandidate}); + registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisCharge}); + } } if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisIsRotatedCandidate}); + registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisCharge}); + } } if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisIsRotatedCandidate}); + registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); } } else { if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisResoChannelLc}); + registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hRecPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecNonPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + } } if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisResoChannelLc}); + registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hRecPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecNonPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + } } if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisResoChannelLc}); + registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + if (activateTHnEulerPhiMonitor) { + registry.add("hRecPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecNonPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + } } if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisResoChannelLc}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisResoChannelLc}); + registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); } } } // MC Gen histos - if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl) { + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { if (activateTHnSparseCosThStarHelicity) { - registry.add("hGenPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisDausAcc, thnAxisResoChannelLc}); - registry.add("hGenNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc}); + registry.add("hGenPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hGenNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); } if (activateTHnSparseCosThStarProduction) { - registry.add("hGenPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisDausAcc, thnAxisResoChannelLc}); - registry.add("hGenNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc}); + registry.add("hGenPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hGenNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); } if (activateTHnSparseCosThStarBeam) { - registry.add("hGenPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisDausAcc, thnAxisResoChannelLc}); - registry.add("hGenNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc}); + registry.add("hGenPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hGenNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); } if (activateTHnSparseCosThStarRandom) { - registry.add("hGenPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc}); - registry.add("hGenNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc}); + registry.add("hGenPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hGenNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); } } + /// control plots for Lc->pKPi + if ((doprocessLcToPKPi || doprocessLcToPKPiWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl) && lcPKPiChannels.activateTHnLcChannelMonitor) { + registry.add("hMass2PairsLcPKPi", "THnSparse to monitor M2(Kpi), M2(pK), M2(ppi), pt correlation for Lc -> pKpi", HistType::kTHnSparseF, {thnAxisInvMass2KPiLcMonitoring, thnAxisInvMass2PKLcMonitoring, thnAxisInvMass2PPiLcMonitoring, thnAxisPt}); + } + // inv. mass hypothesis to loop over // e.g.: Lc->pKpi has the ambiguity pKpi vs. piKp if (doprocessLcToPKPi || doprocessLcToPKPiWithMl) { @@ -378,57 +519,80 @@ struct TaskPolarisationCharmHadrons { /// \param rapCharmHad is the rapidity of the candidate /// \param invMassD0 is the invariant-mass of the D0 daugher (only for D*+) /// \param invMassKPiLc is the invariant-mass of the K-pi pair (only for Lc+) + /// \param invMassPKLc is the invariant-mass of the p-K pair (only for Lc+) + /// \param invMassPPiLc is the invariant-mass of the p-pi pair (only for Lc+) /// \param cosThetaStar is the cosThetaStar of the candidate /// \param outputMl is the array with ML output scores /// \param isRotatedCandidate is a flag that keeps the info of the rotation of the candidate for bkg studies /// \param origin is the MC origin /// \param ptBhadMother is the pt of the b-hadron mother (only in case of non-prompt) /// \param resoChannelLc indicates the Lc decay channel (direct, resonant) + /// \param absEtaMin is the minimum absolute eta of the daughter tracks + /// \param numItsClsMin is the minimum number of ITS clusters of the daughter tracks + /// \param numTpcClsMin is the minimum number of TPC clusters of the daughter tracks template - void fillRecoHistos(float invMassCharmHad, float ptCharmHad, int numPvContributors, float rapCharmHad, float invMassD0, float invMassKPiLc, float cosThetaStar, std::array outputMl, int isRotatedCandidate, int8_t origin, float ptBhadMother, int8_t resoChannelLc) + void fillRecoHistos(float invMassCharmHad, float ptCharmHad, int numPvContributors, float rapCharmHad, float invMassD0, float invMassKPiLc, float cosThetaStar, float phiEuler, std::array outputMl, int isRotatedCandidate, int8_t origin, float ptBhadMother, int8_t resoChannelLc, float absEtaMin, int numItsClsMin, int numTpcClsMin, int8_t charge) { if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], charge); + } } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, charge); + } } } } else { // MC --> no distinction among channels, since rotational bkg not supported if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); + } } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecNonPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); + } } } } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); + } } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecNonPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); + } } } } @@ -437,44 +601,62 @@ struct TaskPolarisationCharmHadrons { if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], charge); + } } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, charge); + } } } } else { // MC --> no distinction among channels, since rotational bkg not supported if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); + } } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecNonPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); + } } } } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); + } } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecNonPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); + } } } } @@ -483,44 +665,62 @@ struct TaskPolarisationCharmHadrons { if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], charge); + } } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, charge); + } } } } else { // MC --> no distinction among channels, since rotational bkg not supported if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); + } } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecNonPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); + } } } } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); + } } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + if (activateTHnEulerPhiMonitor) { + registry.fill(HIST("hRecNonPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); + } } } } @@ -529,44 +729,44 @@ struct TaskPolarisationCharmHadrons { if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); } } } else { // MC --> no distinction among channels, since rotational bkg not supported if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], ptBhadMother); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, ptBhadMother); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, ptBhadMother); } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } } @@ -583,31 +783,31 @@ struct TaskPolarisationCharmHadrons { /// \param areDausInAcc is a flag indicating whether the daughters are in acceptance or not /// \param resoChannelLc indicates the Lc decay channel (direct, resonant) template - void fillGenHistos(float ptCharmHad, int numPvContributors, float rapCharmHad, float cosThetaStar, int8_t origin, float ptBhadMother, bool areDausInAcc, uint8_t resoChannelLc) + void fillGenHistos(float ptCharmHad, int numPvContributors, float rapCharmHad, float cosThetaStar, int8_t origin, float ptBhadMother, bool areDausInAcc, uint8_t resoChannelLc, int8_t charge) { if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if (origin == RecoDecay::OriginType::Prompt) { // prompt - registry.fill(HIST("hGenPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { // non-prompt - registry.fill(HIST("hGenNonPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenNonPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } else if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::Production) { // Production if (origin == RecoDecay::OriginType::Prompt) { // prompt - registry.fill(HIST("hGenPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { // non-prompt - registry.fill(HIST("hGenNonPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenNonPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } else if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::Beam) { // Beam if (origin == RecoDecay::OriginType::Prompt) { // prompt - registry.fill(HIST("hGenPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { // non-prompt - registry.fill(HIST("hGenNonPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenNonPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } else if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::Random) { // Random if (origin == RecoDecay::OriginType::Prompt) { // prompt - registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { // non-prompt - registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc); + registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } @@ -661,18 +861,67 @@ struct TaskPolarisationCharmHadrons { return true; } + /// \param prongTrack is the track we want to find the mother of + /// \param idMothers is the vector containing the mother IDs + /// \param particles are the MC particles + template + void searchFirstLevelMother(Trk const& prongTrack, std::vector& idMothers, Part const& /*particles*/) + { + /// particle associated to the prong track + if (!prongTrack.has_mcParticle()) { + return; + } + auto prongParticle = prongTrack.template mcParticle_as(); + /// leave the vector of mother indices empty if the currect paticle has no mothers + if (!prongParticle.has_mothers()) { + return; + } + // loop over the mother particles of the analysed particle + for (auto iMother = prongParticle.mothersIds().front(); iMother <= prongParticle.mothersIds().back(); ++iMother) { + idMothers.push_back(iMother); + break; // we keep only the first one + } + }; + + /// prongTracks is the vector of daughter tracks + /// etaMin is the minimum eta + /// nItsClsMin is the minumum number of clusters in ITS + /// nTpcClsMin is the minumum number of clusters in TPC + template + void getTrackingInfos(std::vector const& prongTracks, float& etaMin, int& nItsClsMin, int& nTpcClsMin) + { + etaMin = 10.f; + nItsClsMin = 10; + nTpcClsMin = 1000; + + for (const auto& track : prongTracks) { + if (std::abs(track.eta()) < etaMin) { + etaMin = std::abs(track.eta()); + } + if (track.itsNCls() < nItsClsMin) { + nItsClsMin = track.itsNCls(); + } + if (track.tpcNClsCrossedRows() < nTpcClsMin) { + nTpcClsMin = track.tpcNClsCrossedRows(); + } + } + } + /// \param candidates are the selected candidates /// \param bkgRotationId is the id for the background rotation /// \param numPvContributors is the number of PV contributors + /// \param particles are the generated particles + /// \param tracks are the reconstructed tracks /// \return true if candidate in signal region - template - bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors) + template + bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/) { bool isCandidateInSignalRegion{false}; int8_t origin{RecoDecay::OriginType::None}; int8_t massHypoMcTruth{-1}; float ptBhadMother{-1.f}; int8_t resoChannelLc = -1; + int8_t charge = -99; if constexpr (doMc) { if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { if (!TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { // this candidate is not signal, skip @@ -686,16 +935,31 @@ struct TaskPolarisationCharmHadrons { return isCandidateInSignalRegion; } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { - if (!TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { // this candidate is not signal, skip - return isCandidateInSignalRegion; - } - origin = candidate.originMcRec(); - if (candidate.isCandidateSwapped()) { - massHypoMcTruth = charm_polarisation::MassHyposLcToPKPi::PiKP; - } else { - massHypoMcTruth = charm_polarisation::MassHyposLcToPKPi::PKPi; + if constexpr (!studyLcPKPiBkgMc) { // skip this if studyLcPKPiBkgMc is true, since we are interested in background + if (!TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { // this candidate is not signal, skip + return isCandidateInSignalRegion; + } + origin = candidate.originMcRec(); + if (candidate.isCandidateSwapped()) { + massHypoMcTruth = charm_polarisation::MassHyposLcToPKPi::PiKP; + } else { + massHypoMcTruth = charm_polarisation::MassHyposLcToPKPi::PKPi; + } + resoChannelLc = candidate.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± } - resoChannelLc = candidate.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± + + /// Lc electric charge from MC truth + /// This is checked when the reconstructed 3-prong candidate is matched to MC with RecoDecay::getMatchedMCRec + int8_t flagMc = candidate.flagMcMatchRec(); + charge = std::abs(flagMc) > 0 ? flagMc / std::abs(flagMc) : 0; /// 0 should never happen, debug protection + } + } else { + /// data + if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { + /// Calculate the electric charge from reconstructed daughter tracks + /// Lc charge == first daughter charge + auto trackProng0 = candidate.template prong0_as(); + charge = static_cast(trackProng0.sign()); } } @@ -705,7 +969,7 @@ struct TaskPolarisationCharmHadrons { // variable definition float pxDau{-1000.f}, pyDau{-1000.f}, pzDau{-1000.f}; float pxCharmHad{-1000.f}, pyCharmHad{-1000.f}, pzCharmHad{-1000.f}; - float massDau{0.f}, invMassCharmHad{0.f}, invMassCharmHadForSparse{0.f}, invMassD0{0.f}, invMassKPiLc{0.f}; + float massDau{0.f}, invMassCharmHad{0.f}, invMassCharmHadForSparse{0.f}, invMassD0{0.f}, invMassKPiLc{0.f}, invMassPKLc{0.f}, invMassPPiLc{0.f}; float rapidity{-999.f}; std::array outputMl{-1.f, -1.f, -1.f}; int isRotatedCandidate = 0; // currently meaningful only for Lc->pKpi @@ -795,6 +1059,9 @@ struct TaskPolarisationCharmHadrons { rapidity = RecoDecay::y(candidate.pVector(), massLc); /// mass-hypothesis-dependent variables + float invMassPiKPi = 0.f; // bkg. from D+ -> K+pi-pi- + float invMassKKPi = 0.f; // bkg. from D+, Ds+ -> K+K-pi+ (1st mass hypothesis) + float invMassPiKK = 0.f; // bkg. from D+, Ds+ -> pi+K-K+ (2nd mass hypothesis) if (iMass == charm_polarisation::MassHyposLcToPKPi::PKPi && candidate.isSelLcToPKPi() >= selectionFlagLcToPKPi) { // reconstructed as pKpi pxDau = candidate.pxProng0(); @@ -821,6 +1088,14 @@ struct TaskPolarisationCharmHadrons { } // invariant mass of the KPi pair invMassKPiLc = hfHelper.invMassKPiPairLcToPKPi(candidate); + invMassPKLc = hfHelper.invMassPKPairLcToPKPi(candidate); + invMassPPiLc = hfHelper.invMassPPiPairLcToPKPi(candidate); + + // D+ and Ds+ invariant mass values, to put a veto on background sources + invMassPiKPi = hfHelper.invMassDplusToPiKPi(candidate); // bkg. from D+ -> K+pi-pi- + invMassKKPi = hfHelper.invMassDsToKKPi(candidate); // bkg. from D+, Ds+ -> K+K-pi+ (1st mass hypothesis) + invMassPiKK = hfHelper.invMassDsToPiKK(candidate); // bkg. from D+, Ds+ -> pi+K-K+ (2nd mass hypothesis) + } else if (iMass == charm_polarisation::MassHyposLcToPKPi::PiKP && candidate.isSelLcToPiKP() >= selectionFlagLcToPKPi) { // reconstructed as piKp pxDau = candidate.pxProng2(); @@ -847,6 +1122,14 @@ struct TaskPolarisationCharmHadrons { } // invariant mass of the KPi pair invMassKPiLc = hfHelper.invMassKPiPairLcToPiKP(candidate); + invMassPKLc = hfHelper.invMassPKPairLcToPiKP(candidate); + invMassPPiLc = hfHelper.invMassPPiPairLcToPiKP(candidate); + + // D+ and Ds+ invariant mass values, to put a veto on background sources + invMassPiKPi = hfHelper.invMassDplusToPiKPi(candidate); // bkg. from D+ -> K+pi-pi- + invMassKKPi = hfHelper.invMassDsToKKPi(candidate); // bkg. from D+, Ds+ -> K+K-pi+ (1st mass hypothesis) + invMassPiKK = hfHelper.invMassDsToPiKK(candidate); // bkg. from D+, Ds+ -> pi+K-K+ (2nd mass hypothesis) + } else { // NB: no need to check cases in which candidate.isSelLcToPKPi() and candidate.isSelLcToPiKP() are both false, because they are rejected already by the Filter // ... but we need to put this protections here! @@ -854,6 +1137,31 @@ struct TaskPolarisationCharmHadrons { continue; } + /// put veto on D+, Ds+ inv. masses, to reduce the background + if (lcBkgVeto.applyLcBkgVeto && ((lcBkgVeto.enableLcBkgVetoDplusKPiPi && lcBkgVeto.massDplusKPiPiMinVeto < invMassPiKPi && invMassPiKPi < lcBkgVeto.massDplusKPiPiMaxVeto) /*bkg. from D+ -> K+pi-pi-*/ || + (lcBkgVeto.enableLcBkgVetoDplusKKPi && lcBkgVeto.massDplusKKPiMinVeto < invMassKKPi && invMassKKPi < lcBkgVeto.massDplusKKPiMaxVeto) /*bkg. from D+ -> K+K-pi+ (1st mass hypothesis)*/ || + (lcBkgVeto.enableLcBkgVetoDplusKKPi && lcBkgVeto.massDplusKKPiMinVeto < invMassPiKK && invMassPiKK < lcBkgVeto.massDplusKKPiMaxVeto) /*bkg. from D+ -> K+K-pi+ (2nd mass hypothesis)*/ || + (lcBkgVeto.enableLcBkgVetoDsKKPi && lcBkgVeto.massDsKKPiMinVeto < invMassKKPi && invMassKKPi < lcBkgVeto.massDsKKPiMaxVeto) /*bkg. from Ds+ -> K+K-pi+ (1st mass hypothesis)*/ || + (lcBkgVeto.enableLcBkgVetoDsKKPi && lcBkgVeto.massDsKKPiMinVeto < invMassPiKK && invMassPiKK < lcBkgVeto.massDsKKPiMaxVeto)) /*bkg. from Ds+ -> K+K-pi+ (2nd mass hypothesis)*/) { + /// this candidate has D+ and/or Ds+ in the veto range, let's reject it + continue; + } + + /// control plots on pair masses + double invMass2KPiLc = invMassKPiLc * invMassKPiLc; + double invMass2PKLc = invMassPKLc * invMassPKLc; + double invMass2PPiLc = invMassPPiLc * invMassPPiLc; + if (lcPKPiChannels.activateTHnLcChannelMonitor && bkgRotationId == 0) { + /// fill Dalitz plot only for genuine candidates (i.e. non-rotated) + registry.fill(HIST("hMass2PairsLcPKPi"), invMass2KPiLc, invMass2PKLc, invMass2PPiLc, candidate.pt()); + } + + /// veto cut on pair masses + if (lcPKPiChannels.applyLcSignalVeto && lcPKPiChannels.mass2PPiLcMinVeto < invMass2PPiLc && invMass2PPiLc < lcPKPiChannels.mass2PPiLcMaxVeto) { + /// this candidate has a significant contribution from Lc+ -> Delta++ K-, let's reject it + continue; + } + } // Lc->pKpi if (invMassCharmHadForSparse < minInvMass || invMassCharmHadForSparse > maxInvMass) { @@ -874,26 +1182,208 @@ struct TaskPolarisationCharmHadrons { isCandidateInSignalRegion = isInSignalRegion(invMassCharmHadForSparse); } + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + + if (activateTrackingSys) { + auto trackProng0 = candidate.template prong0_as(); + auto trackProng1 = candidate.template prong1_as(); + if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { + auto trackProng2 = candidate.template prongPi_as(); + getTrackingInfos(std::vector{trackProng0, trackProng1, trackProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else if (channel == charm_polarisation::DecayChannel::LcToPKPi) { + auto trackProng2 = candidate.template prong2_as(); + getTrackingInfos(std::vector{trackProng0, trackProng1, trackProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } + } + + // helicity + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); + float cosThetaStarHelicity = -10.f; + float phiHelicity = -10.f; + // production + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(pyCharmHad, -pxCharmHad, 0.f); + float cosThetaStarProduction = -10.f; + float phiProduction = -10.f; + // beam + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + float cosThetaStarBeam = -10.f; + float phiBeam = -10.f; + // random + float cosThetaStarRandom = -10.f; + if (activateTHnSparseCosThStarHelicity) { - ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); - float cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(helicityVec.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarHelicity, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc); + // helicity + cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(helicityVec.Mag2()); + phiHelicity = std::atan2(beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()), normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2()))); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarHelicity, phiHelicity, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge); } if (activateTHnSparseCosThStarProduction) { - ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(pyCharmHad, -pxCharmHad, 0.f); - float cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(normalVec.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarProduction, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc); + // production + cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(normalVec.Mag2()); + phiProduction = std::atan2(normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())), helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2()))); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarProduction, phiProduction, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge); } if (activateTHnSparseCosThStarBeam) { - ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - float cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarBeam, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc); + // beam + cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + phiBeam = std::atan2(helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())), beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2())); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarBeam, phiBeam, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge); } if (activateTHnSparseCosThStarRandom) { + // random ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - float cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc); + cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, -99.f, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge); } + + /// Table for Lc->pKpi background studies + /// Defined only in MC simulations, to study resonances and reflected signal + if constexpr (doMc && channel == charm_polarisation::DecayChannel::LcToPKPi) { + if constexpr (studyLcPKPiBkgMc) { + /****************************************************************************************** + The code below can work only without grouping on "mcCollision". + In fact, grouping by "mcCollision" introduces the following inconsistencies: + + 1) the particle getters "track.template mcParticle_as()" retrieve the daughter particles quering the full particle table in the dataframe. + In other words, even if the 3-prong candidate is reconstructed in a completely wrong reco. collision due to the track-to-collision associator, + therefore this collision points to a "mcCollision" different from the current one and the daughter particles are associated to this different "mcCollision", + the getter "mcParticle_as" works anyway, because it works with unbound tables ignoring the fact that "particles" is grouped; + + 2) when we look for the mother index from the daughter particles of the previous point, but the daughter particles belong to a "mcCollision" different from the current one, + then also the mother particle belongs to this different "mcCollision". This means that the mother index ( - "particles.offset()") is outside the "particles.size()", + because the table "particles" is grouped w.r.t. the current "mcCollision". + *******************************************************************************************/ + + /// check if the tracks are associated to a pion + a kaon + a proton + int8_t isRealPKPi = 0; /// true only if the triplet is formed by a MC pion + a MC kaon + a MC proton + bool isGenPKPi = false; + bool isGenPiKP = false; + auto trackProng0 = candidate.template prong0_as(); + auto trackProng1 = candidate.template prong1_as(); + auto trackProng2 = candidate.template prong2_as(); + int pdgProng0 = 0; + int pdgProng1 = 0; + int pdgProng2 = 0; + if (trackProng0.has_mcParticle()) { + /// BEWARE: even when grouping by mcCollision, mcParticle_as<> gets the mcParticle even if it belongs to a different mcCollision + /// because _as<> works with unbound tables. (*) + auto particleProng0 = trackProng0.template mcParticle_as(); + pdgProng0 = particleProng0.pdgCode(); + } + if (trackProng1.has_mcParticle()) { + /// BEWARE: even when grouping by mcCollision, mcParticle_as<> gets the mcParticle even if it belongs to a different mcCollision + /// because _as<> works with unbound tables. (*) + auto particleProng1 = trackProng1.template mcParticle_as(); + pdgProng1 = particleProng1.pdgCode(); + } + if (trackProng2.has_mcParticle()) { + /// BEWARE: even when grouping by mcCollision, mcParticle_as<> gets the mcParticle even if it belongs to a different mcCollision + /// because _as<> works with unbound tables. (*) + auto particleProng2 = trackProng2.template mcParticle_as(); + pdgProng2 = particleProng2.pdgCode(); + } + isGenPKPi = std::abs(pdgProng0) == kProton && std::abs(pdgProng1) == kKPlus && std::abs(pdgProng2) == kPiPlus; + isGenPiKP = std::abs(pdgProng0) == kPiPlus && std::abs(pdgProng1) == kKPlus && std::abs(pdgProng2) == kProton; + if (isGenPKPi || isGenPiKP) { + isRealPKPi = 1; + } + + /// check if the triplet is reflected or not + /// i.e. generated as pKpi but reconstructed as piKp, or viceversa + int8_t isReflected = 0; + if (isRealPKPi && ((iMass == charm_polarisation::MassHyposLcToPKPi::PKPi && candidate.isSelLcToPKPi() >= selectionFlagLcToPKPi && isGenPiKP) || (iMass == charm_polarisation::MassHyposLcToPKPi::PiKP && candidate.isSelLcToPiKP() >= selectionFlagLcToPKPi && isGenPKPi))) { + isReflected = 1; + } + + /// check if the pKpi triplet is a Lc->pKpi + int8_t isRealLcPKPi = 0; + if (isRealPKPi && TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + isRealLcPKPi = 1; + } + + /// look for daughters' mothers (1st level only) + std::vector idMothersProng0 = {}; + std::vector idMothersProng1 = {}; + std::vector idMothersProng2 = {}; + searchFirstLevelMother(trackProng0, idMothersProng0, particles); + searchFirstLevelMother(trackProng1, idMothersProng1, particles); + searchFirstLevelMother(trackProng2, idMothersProng2, particles); + + /// check if daughter pairs have the same mother + /// it should be enough to check the 1st one only (only particles from partonic events, or interactions with material, can have more than 1 mother) + int pdgMotherProng0 = -1; + int pdgMotherProng1 = -1; + int pdgMotherProng2 = -1; + bool atLeast2ProngsFromSameMother = (idMothersProng0.size() > 0 && idMothersProng1.size() > 0 && idMothersProng0.at(0) == idMothersProng1.at(0)) || + (idMothersProng1.size() > 0 && idMothersProng2.size() > 0 && idMothersProng1.at(0) == idMothersProng2.at(0)) || + (idMothersProng0.size() > 0 && idMothersProng2.size() > 0 && idMothersProng0.at(0) == idMothersProng2.at(0)); + if (atLeast2ProngsFromSameMother) { + if (idMothersProng0.size() > 0) { + /// BEWARE: in case of mcCollision grouping, the idMother can anyway point to a particle in another collision (*) + /// therefore the rawIteratorAt call might crash the code because one goes above the (grouped) particles table size + auto mother = particles.rawIteratorAt(idMothersProng0.at(0) - particles.offset()); + pdgMotherProng0 = std::abs(mother.pdgCode()); // PDG code of the mother + } + if (idMothersProng1.size() > 0) { + /// BEWARE: in case of mcCollision grouping, the idMother can anyway point to a particle in another collision (*) + /// therefore the rawIteratorAt call might crash the code because one goes above the (grouped) particles table size + auto mother = particles.rawIteratorAt(idMothersProng1.at(0) - particles.offset()); + pdgMotherProng1 = std::abs(mother.pdgCode()); // PDG code of the mother + } + if (idMothersProng2.size() > 0) { + /// BEWARE: in case of mcCollision grouping, the idMother can anyway point to a particle in another collision (*) + /// therefore the rawIteratorAt call might crash the code because one goes above the (grouped) particles table size + auto mother = particles.rawIteratorAt(idMothersProng2.at(0) - particles.offset()); + pdgMotherProng2 = std::abs(mother.pdgCode()); // PDG code of the mother + } + } + + /// calculate inv. masses for pairs, depending on mass hypothesis + std::array pVecPion = {}; + std::array pVecKaon = candidate.pVectorProng1(); + std::array pVecProton = {}; + if (iMass == charm_polarisation::MassHyposLcToPKPi::PKPi && candidate.isSelLcToPKPi() >= selectionFlagLcToPKPi) { + pVecProton = candidate.pVectorProng0(); + pVecPion = candidate.pVectorProng2(); + } else if (iMass == charm_polarisation::MassHyposLcToPKPi::PiKP && candidate.isSelLcToPiKP() >= selectionFlagLcToPKPi) { + pVecProton = candidate.pVectorProng2(); + pVecPion = candidate.pVectorProng0(); + } + const float massKPi = RecoDecay::m(std::array{pVecKaon, pVecPion}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + const float massKProton = RecoDecay::m(std::array{pVecKaon, pVecProton}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); + const float massPiProton = RecoDecay::m(std::array{pVecPion, pVecProton}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassProton}); + + /// Fill the table for selected candidates + /// No need to check explicitly if candidates are selected, since the Filter is applied + float cosThetaStarForTable = -10.f; + switch (cosThStarAxisLcPKPiBkgMc) { + case 1: + cosThetaStarForTable = cosThetaStarHelicity; + break; + case 2: + cosThetaStarForTable = cosThetaStarProduction; + break; + case 3: + cosThetaStarForTable = cosThetaStarBeam; + break; + case 4: + cosThetaStarForTable = cosThetaStarRandom; + break; + default: + LOG(fatal) << "cosThStarAxisLcPKPiBkgMc must be between 1 and 4 (1: helicity; 2: production; 3: beam; 4: random), but cosThStarAxisLcPKPiBkgMc = " << cosThStarAxisLcPKPiBkgMc << ". Fix it!"; + break; + } + rowCandLcBkg(invMassCharmHadForSparse, ptCharmHad, rapidity, + cosThetaStarForTable, + pdgMotherProng0, pdgMotherProng1, pdgMotherProng2, + massKPi, massKProton, massPiProton, + outputMl.at(0), outputMl.at(2), + isRealPKPi, isRealLcPKPi, isReflected, + charge); + } // end studyLcPKPiBkgMc + } // end table for Lc->pKpi background studies + } /// end loop over mass hypotheses return isCandidateInSignalRegion; @@ -911,6 +1401,7 @@ struct TaskPolarisationCharmHadrons { float ptBhadMother{-1.f}; bool areDauInAcc{true}; int8_t resoChannelLc = -1; + int8_t charge = -99; if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { if (!TESTBIT(std::abs(mcParticle.flagMcMatchGen()), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { // this particle is not signal, skip return; @@ -940,6 +1431,10 @@ struct TaskPolarisationCharmHadrons { RecoDecay::getDaughters(mcParticle, &listDaughters, dauPdgs, 2); massDau = massProton; massCharmHad = massLc; + + /// electric charge from PDG code + int pdgCode = mcParticle.pdgCode(); + charge = static_cast(pdgCode / std::abs(pdgCode)); } float rapidity = mcParticle.y(); @@ -997,22 +1492,22 @@ struct TaskPolarisationCharmHadrons { if (activateTHnSparseCosThStarHelicity) { ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); float cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(helicityVec.Mag2()); - fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarHelicity, origin, ptBhadMother, areDauInAcc, resoChannelLc); + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarHelicity, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge); } if (activateTHnSparseCosThStarProduction) { ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(pyCharmHad, -pxCharmHad, 0.f); float cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(normalVec.Mag2()); - fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarProduction, origin, ptBhadMother, areDauInAcc, resoChannelLc); + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarProduction, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge); } if (activateTHnSparseCosThStarBeam) { ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); float cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarBeam, origin, ptBhadMother, areDauInAcc, resoChannelLc); + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarBeam, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge); } if (activateTHnSparseCosThStarRandom) { ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); float cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc); + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge); } } @@ -1022,7 +1517,8 @@ struct TaskPolarisationCharmHadrons { // Dstar with rectangular cuts void processDstar(aod::Collisions const& collisions, - FilteredCandDstarWSelFlag const& dstarCandidates) + FilteredCandDstarWSelFlag const& dstarCandidates, + TracksWithExtra const& tracks) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); @@ -1032,12 +1528,12 @@ struct TaskPolarisationCharmHadrons { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } for (int iRotation{1}; iRotation <= nBkgRotations; ++iRotation) { - runPolarisationAnalysis(dstarCandidate, iRotation, numPvContributors); + runPolarisationAnalysis(dstarCandidate, iRotation, numPvContributors, -1 /*MC particles*/, tracks); } } fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); @@ -1047,7 +1543,8 @@ struct TaskPolarisationCharmHadrons { // Dstar with ML cuts void processDstarWithMl(aod::Collisions const& collisions, - FilteredCandDstarWSelFlagAndMl const& dstarCandidates) + FilteredCandDstarWSelFlagAndMl const& dstarCandidates, + TracksWithExtra const& tracks) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); @@ -1057,12 +1554,12 @@ struct TaskPolarisationCharmHadrons { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } for (int iRotation{1}; iRotation <= nBkgRotations; ++iRotation) { - runPolarisationAnalysis(dstarCandidate, iRotation, numPvContributors); + runPolarisationAnalysis(dstarCandidate, iRotation, numPvContributors, -1 /*MC particles*/, tracks); } } fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); @@ -1074,7 +1571,8 @@ struct TaskPolarisationCharmHadrons { void processDstarMc(aod::McCollisions::iterator const&, McParticlesDstarMatched const& mcParticles, CollisionsWithMcLabels const& collisions, // this is grouped with SmallGroupsCollisionsWithMcLabels const& collisions, - FilteredCandDstarWSelFlagAndMc const& dstarCandidates) + FilteredCandDstarWSelFlagAndMc const& dstarCandidates, + TracksWithExtra const& tracks) { int numPvContributorsGen{0}; for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision @@ -1089,7 +1587,7 @@ struct TaskPolarisationCharmHadrons { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } } @@ -1106,7 +1604,8 @@ struct TaskPolarisationCharmHadrons { void processDstarMcWithMl(aod::McCollisions::iterator const&, McParticlesDstarMatched const& mcParticles, CollisionsWithMcLabels const& collisions, // this is grouped with SmallGroupsCollisionsWithMcLabels const& collisions, - FilteredCandDstarWSelFlagAndMcAndMl const& dstarCandidates) + FilteredCandDstarWSelFlagAndMcAndMl const& dstarCandidates, + TracksWithExtra const& tracks) { int numPvContributorsGen{0}; for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision @@ -1121,7 +1620,7 @@ struct TaskPolarisationCharmHadrons { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } } @@ -1140,7 +1639,8 @@ struct TaskPolarisationCharmHadrons { // Lc->pKpi with rectangular cuts void processLcToPKPi(aod::Collisions const& collisions, - FilteredCandLcToPKPiWSelFlag const& lcCandidates) + FilteredCandLcToPKPiWSelFlag const& lcCandidates, + TracksWithExtra const& tracks) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); @@ -1150,13 +1650,13 @@ struct TaskPolarisationCharmHadrons { for (const auto& lcCandidate : groupedLcCandidates) { nCands++; - if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } /// rotational background for (int iRotation{1}; iRotation <= nBkgRotations; ++iRotation) { - runPolarisationAnalysis(lcCandidate, iRotation, numPvContributors); + runPolarisationAnalysis(lcCandidate, iRotation, numPvContributors, -1 /*MC particles*/, tracks); } } fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); @@ -1166,7 +1666,8 @@ struct TaskPolarisationCharmHadrons { // Lc->pKpi with ML cuts void processLcToPKPiWithMl(aod::Collisions const& collisions, - FilteredCandLcToPKPiWSelFlagAndMl const& lcCandidates) + FilteredCandLcToPKPiWSelFlagAndMl const& lcCandidates, + TracksWithExtra const& tracks) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); @@ -1176,13 +1677,13 @@ struct TaskPolarisationCharmHadrons { for (const auto& lcCandidate : groupedLcCandidates) { nCands++; - if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } /// rotational background for (int iRotation{1}; iRotation <= nBkgRotations; ++iRotation) { - runPolarisationAnalysis(lcCandidate, iRotation, numPvContributors); + runPolarisationAnalysis(lcCandidate, iRotation, numPvContributors, -1 /*MC particles*/, tracks); } } fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); @@ -1194,7 +1695,8 @@ struct TaskPolarisationCharmHadrons { void processLcToPKPiMc(aod::McCollisions::iterator const&, McParticles3ProngMatched const& mcParticles, CollisionsWithMcLabels const& collisions, // this is grouped with SmallGroupsCollisionsWithMcLabels const& collisions, - FilteredCandLcToPKPiWSelFlagAndMc const& lcCandidates) + FilteredCandLcToPKPiWSelFlagAndMc const& lcCandidates, + TracksWithExtra const& tracks) { int numPvContributorsGen{0}; for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision @@ -1209,7 +1711,7 @@ struct TaskPolarisationCharmHadrons { for (const auto& lcCandidate : groupedLcCandidates) { nCands++; - if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } } @@ -1226,7 +1728,8 @@ struct TaskPolarisationCharmHadrons { void processLcToPKPiMcWithMl(aod::McCollisions::iterator const&, McParticles3ProngMatched const& mcParticles, CollisionsWithMcLabels const& collisions, // this is grouped with SmallGroups - FilteredCandLcToPKPiWSelFlagAndMcAndMl const& lcCandidates) + FilteredCandLcToPKPiWSelFlagAndMcAndMl const& lcCandidates, + TracksWithExtra const& tracks) { int numPvContributorsGen{0}; for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision @@ -1241,7 +1744,7 @@ struct TaskPolarisationCharmHadrons { for (const auto& lcCandidate : groupedLcCandidates) { nCands++; - if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors)) { + if (runPolarisationAnalysis(lcCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { nCandsInSignalRegion++; } } @@ -1253,6 +1756,21 @@ struct TaskPolarisationCharmHadrons { } } PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPiMcWithMl, "Process Lc candidates in MC with ML", false); + + // Lc->pKpi in MC with ML cuts w/o mcCollision grouping (to study Lc background) + void processLcToPKPiBackgroundMcWithMl(McParticles3ProngMatched const& mcParticles, + FilteredCandLcToPKPiWSelFlagAndMcAndMl const& lcCandidates, + TracksWithMcLabels const& tracks) + { + for (const auto& lcCandidate : lcCandidates) { + runPolarisationAnalysis(lcCandidate, 0, /*numPvContributors*/ -1, mcParticles, tracks); + } + + for (const auto& mcParticle : mcParticles) { + runMcGenPolarisationAnalysis(mcParticle, mcParticles, /*numPvContributorsGen*/ -1); + } + } + PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPiBackgroundMcWithMl, "Process Lc candidates in MC with ML w/o mcCollision grouping", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx new file mode 100644 index 00000000000..d50644fe55e --- /dev/null +++ b/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx @@ -0,0 +1,238 @@ +// Copyright 2019-2020 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. + +/// \file taskCharmResoReduced.cxx +/// \brief Charmed Resonances analysis task +/// +/// \author Luca Aglietta , University and INFN Torino + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/RecoDecay.h" + +// #include "PWGHF/Core/HfHelper.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +enum DecayChannel : uint8_t { + Ds1ToDstarK0s = 0, + Ds2StarToDplusK0s, + XcToDplusLambda, + LambdaDminus +}; + +struct HfTaskCharmResoReduced { + Configurable ptMinReso{"ptMinReso", 5, "Discard events with smaller pT"}; + Configurable cutBeforeMixing{"cutBeforeMixing", false, "Apply pT cut to candidates before event mixing"}; + Configurable cutAfterMixing{"cutAfterMixing", false, "Apply pT cut to candidates after event mixing"}; + // Configurables axis for histos + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng0{"axisPtProng0", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong0 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng1{"axisPtProng1", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong1 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisInvMassReso{"axisInvMassReso", {200, 2.34, 2.74}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {175, 1.70, 2.05}, "inv. mass (D) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {80, 0.46, 0.54}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisCosThetaStar{"axisCosThetaStar", {40, -1, 1}, "cos(#vartheta*)"}; + ConfigurableAxis axisBkgBdtScore{"axisBkgBdtScore", {100, 0, 1}, "bkg BDT Score"}; + ConfigurableAxis axisNonPromptBdtScore{"axisNonPromptBdtScore", {100, 0, 1}, "non-prompt BDT Score"}; + // Configurables for ME + Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; + Configurable numberEventsToSkip{"numberEventsToSkip", -1, "Number of events to Skip in ME process"}; + ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0., 45., 60., 75., 95, 250}, "event multiplicity pools (PV contributors for now)"}; + ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0, -4, -1, 1, 4, 10.0}, "z vertex position pools"}; + // ConfigurableAxis bzPoolBins{"bzPoolBins", {2, -10, 10}, "Bz of collision"}; + + using ReducedResoWithMl = soa::Join; + SliceCache cache; + Preslice resoPerCollision = aod::hf_track_index_reduced::hfRedCollisionId; + + // Histogram Registry + HistogramRegistry registry; + + // init + void init(InitContext&) + { + registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1F, {axisInvMassReso}}); + registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1F, {axisInvMassProng0}}); + registry.add("hMassProng1", "V0 daughter inv. mass", {HistType::kTH1F, {axisInvMassProng1}}); + registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1F, {axisPt}}); + registry.add("hPtProng0", "D daughters pT", {HistType::kTH1F, {axisPtProng0}}); + registry.add("hPtProng1", "V0 daughter pT", {HistType::kTH1F, {axisPtProng1}}); + registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1F, {{100, 0, 250}}}); + registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1F, {{120, -12., 12.}}}); + registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1F, {{20, -10., 10.}}}); + registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisInvMassProng1, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); + + if (doprocessDs1DataMixedEvent || doprocessDs2StarDataMixedEvent) { + registry.add("hNPvContCorr", "Collision number of PV contributors ; N contrib ; N contrib", {HistType::kTH2F, {{100, 0, 250}, {100, 0, 250}}}); + registry.add("hZvertCorr", "Collision Z Vtx ; z PV [cm] ; z PV [cm]", {HistType::kTH2F, {{120, -12., 12.}, {120, -12., 12.}}}); + registry.add("hMassProng0Corr", "D daughters inv. mass", {HistType::kTH2F, {axisInvMassProng0, axisInvMassProng0}}); + registry.add("hMassProng1Corr", "V0 daughter inv. mass", {HistType::kTH2F, {axisInvMassProng1, axisInvMassProng1}}); + } + } + + // Fill histograms + /// \tparam channel is the decay channel of the Resonance + /// \param candidate is a candidate + /// \param coll is a reduced collision + template + void fillHisto(const Cand& candidate, const Coll& collision) + { + // Collision properties + registry.fill(HIST("hNPvCont"), collision.numContrib()); + registry.fill(HIST("hZvert"), collision.posZ()); + registry.fill(HIST("hBz"), collision.bz()); + // Candidate properties + registry.fill(HIST("hMass"), candidate.invMass()); + registry.fill(HIST("hMassProng0"), candidate.invMassProng0()); + registry.fill(HIST("hMassProng1"), candidate.invMassProng1()); + registry.fill(HIST("hPt"), candidate.pt()); + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + float cosThetaStar{0.}; + switch (channel) { + case DecayChannel::Ds1ToDstarK0s: + cosThetaStar = candidate.cosThetaStarDs1(); + break; + case DecayChannel::Ds2StarToDplusK0s: + cosThetaStar = candidate.cosThetaStarDs2Star(); + break; + default: + cosThetaStar = candidate.cosThetaStarXiC3055(); + break; + } + registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.invMass(), candidate.invMassProng0(), candidate.invMassProng1(), cosThetaStar, candidate.mlScoreBkgProng0(), candidate.mlScoreNonpromptProng0()); + } // fillHisto + + // Process data + /// \tparam channel is the decay channel of the Resonance + /// \param Coll is the reduced collisions table + /// \param Cand is the candidates table + template + void processData(Coll const&, Candidates const& candidates) + { + for (const auto& cand : candidates) { + if (cand.pt() < ptMinReso) { + continue; + } + auto coll = cand.template hfRedCollision_as(); + fillHisto(cand, coll); + } + } + + // Process data with Mixed Event + /// \tparam channel is the decay channel of the Resonance + /// \param Coll is the reduced collisions table + /// \param Cand is the candidates table + template + void processDataMixedEvent(Coll const& collisions, Candidates const& candidates) + { + using BinningType = ColumnBinningPolicy; + BinningType corrBinning{{zPoolBins, multPoolBins}, true}; + auto candsTuple = std::make_tuple(candidates); + SameKindPair pairs{corrBinning, numberEventsMixed, numberEventsToSkip, collisions, candsTuple, &cache}; + for (const auto& [collision1, cands1, collision2, cands2] : pairs) { + // For each couple of candidate resonances I can make 2 mixed candidates by swithching daughters + for (const auto& [cand1, cand2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(cands1, cands2))) { + if (cutBeforeMixing && (cand1.pt() < ptMinReso || cand2.pt() < ptMinReso)) { + continue; + } + float ptME1 = RecoDecay::pt(cand1.pVectorProng0(), cand2.pVectorProng1()); + float invMassME1; + float cosThetaStarME1; + if (!cutAfterMixing || ptME1 > ptMinReso) { + switch (channel) { + case DecayChannel::Ds1ToDstarK0s: + invMassME1 = RecoDecay::m(std::array{cand1.pVectorProng0(), cand2.pVectorProng1()}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0Short}); + cosThetaStarME1 = RecoDecay::cosThetaStar(std::array{cand1.pVectorProng0(), cand2.pVectorProng1()}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0Short}, invMassME1, 1); + break; + case DecayChannel::Ds2StarToDplusK0s: + invMassME1 = RecoDecay::m(std::array{cand1.pVectorProng0(), cand2.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0Short}); + cosThetaStarME1 = RecoDecay::cosThetaStar(std::array{cand1.pVectorProng0(), cand2.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0Short}, invMassME1, 1); + break; + default: + invMassME1 = RecoDecay::m(std::array{cand1.pVectorProng0(), cand2.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}); + cosThetaStarME1 = RecoDecay::cosThetaStar(std::array{cand1.pVectorProng0(), cand2.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}, invMassME1, 1); + break; + } + registry.fill(HIST("hMass"), invMassME1); + registry.fill(HIST("hPt"), ptME1); + registry.fill(HIST("hNPvContCorr"), collision1.numContrib(), collision2.numContrib()); + registry.fill(HIST("hZvertCorr"), collision1.posZ(), collision2.posZ()); + registry.fill(HIST("hMassProng0Corr"), cand1.invMassProng0(), cand2.invMassProng0()); + registry.fill(HIST("hMassProng1Corr"), cand1.invMassProng1(), cand2.invMassProng1()); + registry.fill(HIST("hSparse"), ptME1, cand1.ptProng0(), cand2.ptProng1(), invMassME1, cand1.invMassProng0(), cand2.invMassProng1(), cosThetaStarME1, cand1.mlScoreBkgProng0(), cand1.mlScoreNonpromptProng0()); + } + float ptME2 = RecoDecay::pt(cand2.pVectorProng0(), cand1.pVectorProng1()); + float invMassME2; + float cosThetaStarME2; + if (!cutAfterMixing || ptME2 > ptMinReso) { + switch (channel) { + case DecayChannel::Ds1ToDstarK0s: + invMassME2 = RecoDecay::m(std::array{cand2.pVectorProng0(), cand1.pVectorProng1()}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0Short}); + cosThetaStarME2 = RecoDecay::cosThetaStar(std::array{cand2.pVectorProng0(), cand1.pVectorProng1()}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0Short}, invMassME2, 1); + break; + case DecayChannel::Ds2StarToDplusK0s: + invMassME2 = RecoDecay::m(std::array{cand2.pVectorProng0(), cand1.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0Short}); + cosThetaStarME2 = RecoDecay::cosThetaStar(std::array{cand2.pVectorProng0(), cand1.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0Short}, invMassME2, 1); + break; + default: + invMassME2 = RecoDecay::m(std::array{cand2.pVectorProng0(), cand1.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}); + cosThetaStarME2 = RecoDecay::cosThetaStar(std::array{cand2.pVectorProng0(), cand1.pVectorProng1()}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}, invMassME2, 1); + break; + } + registry.fill(HIST("hMass"), invMassME2); + registry.fill(HIST("hPt"), ptME2); + registry.fill(HIST("hSparse"), ptME2, cand2.ptProng0(), cand1.ptProng1(), invMassME2, cand2.invMassProng0(), cand1.invMassProng1(), cosThetaStarME2, cand2.mlScoreBkgProng0(), cand2.mlScoreNonpromptProng0()); + } + } + } + } + + // process functions + + void processDs1Data(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates) + { + processData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1Data, "Process data", true); + + void processDs1DataMixedEvent(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates) + { + processDataMixedEvent(collisions, candidates); + } + PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1DataMixedEvent, "Process data with Event Mixing", false); + + void processDs2StarData(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates) + { + processData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarData, "Process data", false); + + void processDs2StarDataMixedEvent(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates) + { + processDataMixedEvent(collisions, candidates); + } + PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarDataMixedEvent, "Process data with Event Mixing", false); + +}; // struct HfTaskCharmResoReduced +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index e778ae64a9e..94c1e28f498 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -211,23 +211,27 @@ struct HfTaskD0 { registry.add("hDecLengthVsPtSig", "2-prong candidates;decay length (cm) vs #it{p}_{T} for signal;entries", {HistType::kTH2F, {{800, 0., 4.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hDecLengthxyVsPtSig", "2-prong candidates;decay length xy (cm) vs #it{p}_{T} for signal;entries", {HistType::kTH2F, {{800, 0., 4.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (#pi K) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisPtB{thnConfigAxisPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; + const AxisSpec thnAxisY{thnConfigAxisY, "y"}; + const AxisSpec thnAxisOrigin{thnConfigAxisOrigin, "Origin"}; + const AxisSpec thnAxisCandType{thnConfigAxisCandType, "D0 type"}; + const AxisSpec thnAxisGenPtD{thnConfigAxisGenPtD, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisGenPtB{thnConfigAxisGenPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; + + registry.add("hSparseAcc", "Thn for generated D0 from charm and beauty", HistType::kTHnSparseD, {thnAxisGenPtD, thnAxisGenPtB, thnAxisY, thnAxisOrigin}); + registry.get(HIST("hSparseAcc"))->Sumw2(); + if (applyMl) { const AxisSpec thnAxisBkgScore{thnConfigAxisBkgScore, "BDT score bkg."}; const AxisSpec thnAxisNonPromptScore{thnConfigAxisNonPromptScore, "BDT score non-prompt."}; - const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (#pi K) (GeV/#it{c}^{2})"}; - const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec thnAxisPtB{thnConfigAxisPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; - const AxisSpec thnAxisY{thnConfigAxisY, "y"}; - const AxisSpec thnAxisOrigin{thnConfigAxisOrigin, "Origin"}; - const AxisSpec thnAxisCandType{thnConfigAxisCandType, "D0 type"}; - const AxisSpec thnAxisGenPtD{thnConfigAxisGenPtD, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec thnAxisGenPtB{thnConfigAxisGenPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; - - registry.add("hSparseAcc", "Thn for generated D0 from charm and beauty", HistType::kTHnSparseD, {thnAxisGenPtD, thnAxisGenPtB, thnAxisY, thnAxisOrigin}); - registry.get(HIST("hSparseAcc"))->Sumw2(); registry.add("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type", "Thn for D0 candidates with BDT scores", HistType::kTHnSparseD, {thnAxisBkgScore, thnAxisNonPromptScore, thnAxisMass, thnAxisPt, thnAxisPtB, thnAxisY, thnAxisOrigin, thnAxisCandType}); registry.get(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Sumw2(); + } else { + registry.add("hMassVsPtVsPtBVsYVsOriginVsD0Type", "Thn for D0 candidates without BDT scores", HistType::kTHnSparseD, {thnAxisMass, thnAxisPt, thnAxisPtB, thnAxisY, thnAxisOrigin, thnAxisCandType}); + registry.get(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"))->Sumw2(); } } @@ -298,6 +302,13 @@ struct HfTaskD0 { if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], massD0bar, ptCandidate, -1, hfHelper.yD0(candidate), 0, SigD0bar); } + } else { + if (candidate.isSelD0() >= selectionFlagD0) { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, -1, hfHelper.yD0(candidate), 0, SigD0); + } + if (candidate.isSelD0bar() >= selectionFlagD0bar) { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, -1, hfHelper.yD0(candidate), 0, SigD0bar); + } } } } @@ -464,6 +475,8 @@ struct HfTaskD0 { registry.fill(HIST("hMassSigD0"), massD0, ptCandidate, rapidityCandidate); if constexpr (applyMl) { registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], massD0, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), SigD0); + } else { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), SigD0); } } else { registry.fill(HIST("hPtProng0Bkg"), ptProng0, rapidityCandidate); @@ -484,6 +497,8 @@ struct HfTaskD0 { registry.fill(HIST("hMassReflBkgD0"), massD0, ptCandidate, rapidityCandidate); if constexpr (applyMl) { registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], massD0, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), ReflectedD0); + } else { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), ReflectedD0); } } } @@ -494,6 +509,8 @@ struct HfTaskD0 { registry.fill(HIST("hMassSigD0bar"), massD0bar, ptCandidate, rapidityCandidate); if constexpr (applyMl) { registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], massD0bar, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), SigD0bar); + } else { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), SigD0bar); } } else { registry.fill(HIST("hMassBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); @@ -501,6 +518,8 @@ struct HfTaskD0 { registry.fill(HIST("hMassReflBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); if constexpr (applyMl) { registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], massD0bar, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), ReflectedD0bar); + } else { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, candidate.ptBhadMotherPart(), rapidityCandidate, candidate.originMcRec(), ReflectedD0bar); } } } @@ -522,17 +541,13 @@ struct HfTaskD0 { registry.fill(HIST("hPtGenPrompt"), ptGen); registry.fill(HIST("hYGenPrompt"), yGen); registry.fill(HIST("hPtVsYGenPrompt"), ptGen, yGen); - if constexpr (applyMl) { - registry.fill(HIST("hSparseAcc"), ptGen, ptGenB, yGen, 1); - } + registry.fill(HIST("hSparseAcc"), ptGen, ptGenB, yGen, 1); } else { ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); registry.fill(HIST("hPtGenNonPrompt"), ptGen); registry.fill(HIST("hYGenNonPrompt"), yGen); registry.fill(HIST("hPtVsYGenNonPrompt"), ptGen, yGen); - if constexpr (applyMl) { - registry.fill(HIST("hSparseAcc"), ptGen, ptGenB, yGen, 2); - } + registry.fill(HIST("hSparseAcc"), ptGen, ptGenB, yGen, 2); } registry.fill(HIST("hEtaGen"), particle.eta()); } diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index 2c45ba0d846..e113c5fef63 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -49,6 +49,13 @@ enum SpeciesAndDecay { DsToKKPi = 0, DplusToPiKPi, kSpeciesAndDecay }; +template +concept hasDsMlInfo = requires(T candidate) +{ + candidate.mlProbDsToKKPi(); + candidate.mlProbDsToPiKK(); +}; + /// Ds± analysis task struct HfTaskDs { @@ -56,9 +63,15 @@ struct HfTaskDs { Configurable fillDplusMc{"fillDplusMc", true, "Switch to fill Dplus MC information"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable> classMl{"classMl", {0, 2, 3}, "Indexes of ML scores to be stored. Three indexes max."}; - Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; - Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable massDsSignalMin{"massDsSignalMin", 1.934, "min mass for Ds signal"}; + Configurable massDsSignalMax{"massDsSignalMax", 1.994, "max mass for Ds signal"}; + Configurable massDplusSignalMin{"massDplusSignalMin", 1.866, "min mass for Dplus signal"}; + Configurable massDplusSignalMax{"massDplusSignalMax", 1.906, "max mass for Dplus signal"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f}, "axis for pT"}; + ConfigurableAxis axisNPvContributors{"axisNPvContributors", {200, -0.5f, 199.5f}, "axis for NPvContributors"}; ConfigurableAxis axisMlScore0{"axisMlScore0", {100, 0., 1.}, "axis for ML output score 0"}; ConfigurableAxis axisMlScore1{"axisMlScore1", {100, 0., 1.}, "axis for ML output score 1"}; ConfigurableAxis axisMlScore2{"axisMlScore2", {100, 0., 1.}, "axis for ML output score 2"}; @@ -70,44 +83,39 @@ struct HfTaskDs { using TH2_ptr = std::shared_ptr; using THnSparse_ptr = std::shared_ptr; using histTypes = std::variant; + template + using MemberFunctionPointer = bool (HfTaskDs::*)(const CandDs&); using CollisionsWithFT0C = soa::Join; using CollisionsWithFT0M = soa::Join; using CollisionsWithNTracksPV = soa::Join; + + using CollisionsMc = soa::Join; + using CollisionsMcWithFT0C = soa::Join; + using CollisionsMcWithFT0M = soa::Join; + using CollisionsMcWithNTracksPV = soa::Join; + using CandDsData = soa::Filtered>; using CandDsDataWithMl = soa::Filtered>; using CandDsMcReco = soa::Filtered>; using CandDsMcRecoWithMl = soa::Filtered>; using CandDsMcGen = soa::Join; + Preslice candDsDataPerCollision = aod::hf_cand::collisionId; + Preslice candDsDataWithMlPerCollision = aod::hf_cand::collisionId; + Preslice candDsMcRecoPerCollision = aod::hf_cand::collisionId; + Preslice candDsMcRecoWithMlPerCollision = aod::hf_cand::collisionId; + + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionWithFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionWithFT0M = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionWithNTracksPV = aod::mccollisionlabel::mcCollisionId; + SliceCache cache; + int offsetDplusDecayChannel = aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi - aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; // Offset between Dplus and Ds to use the same decay channel. See aod::hf_cand_3prong::DecayChannelDToKKPi Filter filterDsFlag = (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi))) != static_cast(0); - // Data - Partition selectedDsToKKPiCandData = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; - Partition selectedDsToKKPiCandWithMlData = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; - Partition selectedDsToPiKKCandData = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Partition selectedDsToPiKKCandWithMlData = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - - // MC - Partition selectedDsToKKPiCandMc = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; - Partition selectedDsToKKPiCandWithMlMc = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; - Partition selectedDsToPiKKCandMc = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Partition selectedDsToPiKKCandWithMlMc = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - - // Matched MC, no ML - Partition reconstructedCandDsSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == decayChannel; - Partition reconstructedCandDplusSig = fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == (decayChannel + offsetDplusDecayChannel); - Partition reconstructedCandDplusBkg = fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); - - // Matched MC, with ML - Partition reconstructedCandDsSigWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == decayChannel; - Partition reconstructedCandDplusSigWithMl = fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == (decayChannel + offsetDplusDecayChannel); - Partition reconstructedCandDplusBkgWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == decayChannel; - Partition reconstructedCandBkgWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); - HistogramRegistry registry{"registry", {}}; std::array folders = {"Data/", "MC/Ds/Prompt/", "MC/Ds/NonPrompt/", "MC/Dplus/Prompt/", "MC/Dplus/NonPrompt/", "MC/Dplus/Bkg/", "MC/Bkg/"}; @@ -120,6 +128,12 @@ struct HfTaskDs { std::unordered_map mcDplusBkgHistograms = {}; std::unordered_map mcBkgHistograms = {}; + std::map, PresliceUnsorted, PresliceUnsorted, PresliceUnsorted>> colPerMcCollisionMap{ + {CentralityEstimator::None, colPerMcCollision}, + {CentralityEstimator::FT0C, colPerMcCollisionWithFT0C}, + {CentralityEstimator::FT0M, colPerMcCollisionWithFT0M}, + {CentralityEstimator::NTracksPV, colPerMcCollisionWithNTracksPV}}; + std::array, DataType::kDataTypes> histosPtr = {dataHistograms, mcDsPromptHistograms, mcDsNonPromptHistograms, mcDplusPromptHistograms, mcDplusNonPromptHistograms, mcDplusBkgHistograms, mcBkgHistograms}; void init(InitContext&) @@ -138,18 +152,25 @@ struct HfTaskDs { AxisSpec massbins = {600, 1.67, 2.27, "inv. mass (KK#pi) (GeV/#it{c}^{2})"}; AxisSpec centralitybins = {100, 0., 100., "Centrality"}; + histosPtr[DataType::Data]["hNPvContribAll"] = registry.add((folders[DataType::Data] + "hNPvContribAll").c_str(), "3-prong candidates;NPvContributors;Centrality;Entries", HistType::kTH2F, {axisNPvContributors, {100, 0., 100}}); + for (auto i = 0; i < DataType::kDataTypes; ++i) { - if (doprocessDataWithCentFT0C || doprocessDataWithCentFT0M || doprocessDataWithCentNTracksPV || - doprocessMcWithCentFT0C || doprocessMcWithCentFT0M || doprocessMcWithCentNTracksPV) { - histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, centralitybins}); - } else if (doprocessDataWithMlAndCentFT0C || doprocessDataWithMlAndCentFT0M || doprocessDataWithMlAndCentNTracksPV || - doprocessMcWithMlAndCentFT0C || doprocessMcWithMlAndCentFT0M || doprocessMcWithMlAndCentNTracksPV) { - histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, centralitybins, axisMlScore0, axisMlScore1, axisMlScore2}); - } else if (doprocessData || doprocessMc) { - histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins}); - } else if (doprocessDataWithMl || doprocessMcWithMl) { - histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, axisMlScore0, axisMlScore1, axisMlScore2}); + if (doprocessDataWithCentFT0C || doprocessDataWithCentFT0M || doprocessDataWithCentNTracksPV || doprocessData || doprocessMcWithCentFT0C || doprocessMcWithCentFT0M || doprocessMcWithCentNTracksPV || doprocessMc) { + if (i == DataType::Data) { // If data do not fill PV contributors in sparse + histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, centralitybins}); + } else { + histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, centralitybins, axisNPvContributors}); + } + } else if (doprocessDataWithMlAndCentFT0C || doprocessDataWithMlAndCentFT0M || doprocessDataWithMlAndCentNTracksPV || doprocessDataWithMl || doprocessMcWithMlAndCentFT0C || doprocessMcWithMlAndCentFT0M || doprocessMcWithMlAndCentNTracksPV || doprocessMcWithMl) { + if (i == DataType::Data) { // If data do not fill PV contributors in sparse + histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, centralitybins, axisMlScore0, axisMlScore1, axisMlScore2}); + } else { + histosPtr[i]["hSparseMass"] = registry.add((folders[i] + "hSparseMass").c_str(), "THn for Ds", HistType::kTHnSparseF, {massbins, ptbins, centralitybins, axisMlScore0, axisMlScore1, axisMlScore2, axisNPvContributors}); + } } + histosPtr[i]["hNPvContribCands"] = registry.add((folders[i] + "hNPvContribCands").c_str(), "3-prong candidates;NPvContributors;Centrality;Entries", HistType::kTH2F, {axisNPvContributors, centralitybins}); + histosPtr[i]["hNPvContribCandsInSignalRegionDs"] = registry.add((folders[i] + "hNPvContribCandsInSignalRegionDs").c_str(), "3-prong candidates;NPvContributors;Centrality;Entries", HistType::kTH2F, {axisNPvContributors, centralitybins}); + histosPtr[i]["hNPvContribCandsInSignalRegionDplus"] = registry.add((folders[i] + "hNPvContribCandsInSignalRegionDplus").c_str(), "3-prong candidates;NPvContributors;Centrality;Entries", HistType::kTH2F, {axisNPvContributors, centralitybins}); histosPtr[i]["hPt"] = registry.add((folders[i] + "hPt").c_str(), "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); histosPtr[i]["hPtProng0"] = registry.add((folders[i] + "hPtProng0").c_str(), "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); histosPtr[i]["hPtProng1"] = registry.add((folders[i] + "hPtProng1").c_str(), "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); @@ -184,32 +205,80 @@ struct HfTaskDs { if (i == DataType::McDsPrompt || i == DataType::McDsNonPrompt || i == DataType::McDplusPrompt || i == DataType::McDplusNonPrompt || i == DataType::McDplusBkg) { histosPtr[i]["hEtaGen"] = registry.add((folders[i] + "hEtaGen").c_str(), "3-prong candidates (matched);#eta;entries", {HistType::kTH1F, {{100, -2., 2.}}}); - histosPtr[i]["hEtaRecSig"] = registry.add((folders[i] + "hEtaRecSig").c_str(), "3-prong candidates (matched);#eta;entries", {HistType::kTH1F, {{100, -2., 2.}}}); - histosPtr[i]["hCPARecSig"] = registry.add((folders[i] + "hCPARecSig").c_str(), "3-prong candidates (matched);cos. pointing angle;entries", {HistType::kTH1F, {{100, -1., 1.}}}); - histosPtr[i]["hPtRecSig"] = registry.add((folders[i] + "hPtRecSig").c_str(), "3-prong candidates (matched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {ptbins}}); - histosPtr[i]["hPtGenSig"] = registry.add((folders[i] + "hPtGenSig").c_str(), "MC particles (matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {ptbins}}); histosPtr[i]["hPtGen"] = registry.add((folders[i] + "hPtGen").c_str(), "MC particles (unmatched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {ptbins}}); - histosPtr[i]["hPtVsYRecSigRecoPID"] = registry.add((folders[i] + "hPtVsYRecSigRecoPID").c_str(), "3-prong candidates (RecoPID - matched);#it{p}_{T}^{rec.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); - histosPtr[i]["hPtVsYRecSigRecoTopol"] = registry.add((folders[i] + "hPtVsYRecSigRecoTopol").c_str(), "3-prong candidates (RecoTopol - matched);#it{p}_{T}^{rec.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); - histosPtr[i]["hPtVsYRecSigRecoSkim"] = registry.add((folders[i] + "hPtVsYRecSigRecoSkim").c_str(), "3-prong candidates (RecoSkim - matched);#it{p}_{T}^{rec.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); - histosPtr[i]["hPtVsYGen"] = registry.add((folders[i] + "hPtVsYGen").c_str(), "MC particles (unmatched);#it{p}_{T}^{gen.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); + histosPtr[i]["hPtVsYRecoPID"] = registry.add((folders[i] + "hPtVsYRecoPID").c_str(), "3-prong candidates (RecoPID - matched);#it{p}_{T}^{rec.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); + histosPtr[i]["hPtVsYRecoTopol"] = registry.add((folders[i] + "hPtVsYRecoTopol").c_str(), "3-prong candidates (RecoTopol - matched);#it{p}_{T}^{rec.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); + histosPtr[i]["hPtVsYRecoSkim"] = registry.add((folders[i] + "hPtVsYRecoSkim").c_str(), "3-prong candidates (RecoSkim - matched);#it{p}_{T}^{rec.}; #it{y}", {HistType::kTH2F, {ptbins, {ybins}}}); + histosPtr[i]["hPtYNPvContribGen"] = registry.add((folders[i] + "hPtYNPvContribGen").c_str(), "Thn for generated candidates", {HistType::kTHnSparseF, {ptbins, {ybins}, axisNPvContributors}}); } } } } - /// Evaluate multiplicity + template + bool isDsPrompt(const CandDs& candidate) + { + return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel && candidate.originMcRec() == RecoDecay::OriginType::Prompt; + } + + template + bool isDplusPrompt(const CandDs& candidate) + { + return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel + offsetDplusDecayChannel && candidate.originMcRec() == RecoDecay::OriginType::Prompt; + } + + template + bool isDsNonPrompt(const CandDs& candidate) + { + return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel && candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + } + + template + bool isDplusNonPrompt(const CandDs& candidate) + { + return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel + offsetDplusDecayChannel && candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + } + + template + bool isDplusBkg(const CandDs& candidate) + { + return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + } + + /// Checks whether the candidate is in the signal region of either the Ds or D+ decay + /// \param candidate is the candidate + /// \param isDs is true if we check for the Ds signal region, false for the D+ signal region + /// \return true if the candidate is in the signal region, false otherwise + template + bool isCandInSignalRegion(const CandDs& candidate, bool isDs) + { + bool isKKPi = candidate.isSelDsToKKPi() >= selectionFlagDs; + float invMass = isKKPi ? hfHelper.invMassDsToKKPi(candidate) : hfHelper.invMassDsToPiKK(candidate); + if (isDs && (invMass < massDsSignalMin || invMass > massDsSignalMax)) { + return false; + } + if (!isDs && (invMass < massDplusSignalMin || invMass > massDplusSignalMax)) { + return false; + } + return true; + } + + /// Evaluate centrality/multiplicity percentile (centrality estimator is automatically selected based on the used table) /// \param candidate is candidate - /// \return multiplicity of the collision associated to the candidate - template - int evaluateCentrality(const T1& candidate) + /// \return centrality/multiplicity percentile of the collision + template + float evaluateCentralityColl(const Coll& collision) { - if constexpr (centDetector == CentralityEstimator::FT0C) - return candidate.template collision_as().centFT0C(); - else if constexpr (centDetector == CentralityEstimator::FT0M) - return candidate.template collision_as().centFT0M(); - else if constexpr (centDetector == CentralityEstimator::NTracksPV) - return candidate.template collision_as().centNTPV(); + return o2::hf_centrality::getCentralityColl(collision); + } + + /// Evaluate centrality/multiplicity percentile + /// \param candidate is candidate + /// \return centrality/multiplicity percentile of the collision associated to the candidate + template + float evaluateCentralityCand(const T1& candidate) + { + return evaluateCentralityColl(candidate.template collision_as()); } /// Fill histograms of quantities independent from the daugther-mass hypothesis @@ -245,31 +314,62 @@ struct HfTaskDs { return; } - /// Fill histograms of quantities for the KKPi daugther-mass hypothesis + /// Fill mass sparse if ML information is present /// \param candidate is candidate /// \param dataType is data class, as defined in DataType enum - template - void fillHistoKKPi(const T1& candidate, DataType dataType) + /// \param finalState is either KKPi or PiKK, as defined in FinalState enum + template + void fillSparse(const Cand& candidate, DataType dataType, FinalState finalState) { + auto mass = finalState == FinalState::KKPi ? hfHelper.invMassDsToKKPi(candidate) : hfHelper.invMassDsToPiKK(candidate); auto pt = candidate.pt(); - if constexpr (useMl) { - std::vector outputMl = {-999., -999., -999.}; - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { // TODO: add checks for classMl size - outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; - } - if constexpr (centDetector != CentralityEstimator::None) { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToKKPi(candidate), pt, evaluateCentrality(candidate), outputMl[0], outputMl[1], outputMl[2]); - } else { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToKKPi(candidate), pt, outputMl[0], outputMl[1], outputMl[2]); - } - } else { - if constexpr (centDetector != CentralityEstimator::None) { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToKKPi(candidate), pt, evaluateCentrality(candidate)); - } else { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToKKPi(candidate), pt); + auto mlScore = finalState == FinalState::KKPi ? candidate.mlProbDsToKKPi() : candidate.mlProbDsToPiKK(); + + std::vector outputMl = {-999., -999., -999.}; + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { // TODO: add checks for classMl size + if (mlScore.size() == 0) { + continue; } + outputMl[iclass] = mlScore[classMl->at(iclass)]; } + if (dataType == DataType::Data) { // If data do not fill PV contributors in sparse + std::get(histosPtr[dataType]["hSparseMass"])->Fill(mass, pt, evaluateCentralityCand(candidate), outputMl[0], outputMl[1], outputMl[2]); + return; + } + std::get(histosPtr[dataType]["hSparseMass"])->Fill(mass, pt, evaluateCentralityCand(candidate), outputMl[0], outputMl[1], outputMl[2], candidate.template collision_as().numContrib()); + + return; + } + + /// Fill mass sparse if ML information is not present + /// \param candidate is candidate + /// \param dataType is data class, as defined in DataType enum + /// \param finalState is either KKPi or PiKK, as defined in FinalState enum + template + void fillSparse(const Cand& candidate, DataType dataType, FinalState finalState) + { + auto mass = finalState == FinalState::KKPi ? hfHelper.invMassDsToKKPi(candidate) : hfHelper.invMassDsToPiKK(candidate); + auto pt = candidate.pt(); + + if (dataType == DataType::Data) { // If data do not fill PV contributors in sparse + std::get(histosPtr[dataType]["hSparseMass"])->Fill(mass, pt, evaluateCentralityCand(candidate)); + return; + } + std::get(histosPtr[dataType]["hSparseMass"])->Fill(mass, pt, evaluateCentralityCand(candidate), candidate.template collision_as().numContrib()); + + return; + } + + /// Fill histograms of quantities for the KKPi daugther-mass hypothesis + /// \param candidate is candidate + /// \param dataType is data class, as defined in DataType enum + template + void fillHistoKKPi(const T1& candidate, DataType dataType) + { + auto pt = candidate.pt(); + fillSparse(candidate, dataType, FinalState::KKPi); + std::get(histosPtr[dataType]["hCos3PiK"])->Fill(hfHelper.cos3PiKDsToKKPi(candidate), pt); std::get(histosPtr[dataType]["hAbsCos3PiK"])->Fill(hfHelper.absCos3PiKDsToKKPi(candidate), pt); std::get(histosPtr[dataType]["hDeltaMassPhi"])->Fill(hfHelper.deltaMassPhiDsToKKPi(candidate), pt); @@ -281,27 +381,11 @@ struct HfTaskDs { /// Fill histograms of quantities for the PiKK daugther-mass hypothesis /// \param candidate is candidate /// \param dataType is data class, as defined in DataType enum - template + template void fillHistoPiKK(const T1& candidate, DataType dataType) { auto pt = candidate.pt(); - if constexpr (useMl) { - std::vector outputMl = {-999., -999., -999.}; - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { // TODO: add checks for classMl size - outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; - } - if constexpr (centDetector != CentralityEstimator::None) { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToPiKK(candidate), pt, evaluateCentrality(candidate), outputMl[0], outputMl[1], outputMl[2]); - } else { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToPiKK(candidate), pt, outputMl[0], outputMl[1], outputMl[2]); - } - } else { - if constexpr (centDetector != CentralityEstimator::None) { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToPiKK(candidate), pt, evaluateCentrality(candidate)); - } else { - std::get(histosPtr[dataType]["hSparseMass"])->Fill(hfHelper.invMassDsToPiKK(candidate), pt); - } - } + fillSparse(candidate, dataType, FinalState::PiKK); std::get(histosPtr[dataType]["hCos3PiK"])->Fill(hfHelper.cos3PiKDsToPiKK(candidate), pt); std::get(histosPtr[dataType]["hAbsCos3PiK"])->Fill(hfHelper.absCos3PiKDsToPiKK(candidate), pt); @@ -315,229 +399,122 @@ struct HfTaskDs { /// \param candidate is candidate /// \param mcParticles are particles with MC information /// \param whichSpeciesDecay defines which histogram to fill - template - void fillHistoMCRec(const T1& candidate, const CandDsMcGen& mcParticles, SpeciesAndDecay whichSpeciesDecay) + template + void fillHistoMCRec(const T1& candidate, const CandDsMcGen& mcParticles, DataType dataType) { + + SpeciesAndDecay whichSpeciesDecay = SpeciesAndDecay::DsToKKPi; + if (dataType == DataType::McDplusPrompt || dataType == DataType::McDplusNonPrompt) { + whichSpeciesDecay = SpeciesAndDecay::DplusToKKPi; + } else if (dataType == DataType::McDplusBkg) { + whichSpeciesDecay = SpeciesAndDecay::DplusToPiKPi; + } + auto indexMother = RecoDecay::getMother(mcParticles, candidate.template prong0_as().template mcParticle_as(), whichSpeciesDecay == SpeciesAndDecay::DsToKKPi ? o2::constants::physics::Pdg::kDS : o2::constants::physics::Pdg::kDPlus, true); if (indexMother != -1) { - if (yCandRecoMax >= 0. && std::abs(whichSpeciesDecay == SpeciesAndDecay::DsToKKPi ? hfHelper.yDs(candidate) : hfHelper.yDplus(candidate)) > yCandRecoMax) { + auto yCand = whichSpeciesDecay == SpeciesAndDecay::DsToKKPi ? hfHelper.yDs(candidate) : hfHelper.yDplus(candidate); + if (yCandRecoMax >= 0. && std::abs(yCand) > yCandRecoMax) { return; } - auto particleMother = mcParticles.iteratorAt(indexMother); - - int flag = candidate.isCandidateSwapped() ? candidate.isSelDsToPiKK() : candidate.isSelDsToKKPi(); // 0 corresponds to KKPi, 1 to PiKK - auto pt = candidate.pt(); // rec. level pT - // Ds - if (whichSpeciesDecay == SpeciesAndDecay::DsToKKPi) { - - double y = hfHelper.yDs(candidate); - - // prompt - if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { - fillHisto(candidate, DataType::McDsPrompt); - if (candidate.isSelDsToKKPi() >= selectionFlagDs) // KKPi - fillHistoKKPi(candidate, DataType::McDsPrompt); - if (candidate.isSelDsToPiKK() >= selectionFlagDs) // PiKK - fillHistoPiKK(candidate, DataType::McDsPrompt); - - std::get(histosPtr[DataType::McDsPrompt]["hPtRecSig"])->Fill(pt); - std::get(histosPtr[DataType::McDsPrompt]["hPtGenSig"])->Fill(particleMother.pt()); // gen. level pT - std::get(histosPtr[DataType::McDsPrompt]["hPtVsYRecSigRecoSkim"])->Fill(pt, y); - std::get(histosPtr[DataType::McDsPrompt]["hCPARecSig"])->Fill(candidate.cpa()); - std::get(histosPtr[DataType::McDsPrompt]["hEtaRecSig"])->Fill(candidate.eta()); - if (TESTBIT(flag, aod::SelectionStep::RecoTopol)) { - std::get(histosPtr[DataType::McDsPrompt]["hPtVsYRecSigRecoTopol"])->Fill(pt, y); - } - if (TESTBIT(flag, aod::SelectionStep::RecoPID)) { - std::get(histosPtr[DataType::McDsPrompt]["hPtVsYRecSigRecoPID"])->Fill(pt, y); - } - } + if (candidate.isSelDsToKKPi() >= selectionFlagDs) { // KKPi + fillHisto(candidate, dataType); + fillHistoKKPi(candidate, dataType); - // non-prompt - if (candidate.originMcRec() == RecoDecay::OriginType::NonPrompt) { - fillHisto(candidate, DataType::McDsNonPrompt); - if (candidate.isSelDsToKKPi() >= selectionFlagDs) // KKPi - fillHistoKKPi(candidate, DataType::McDsNonPrompt); - if (candidate.isSelDsToPiKK() >= selectionFlagDs) // PiKK - fillHistoPiKK(candidate, DataType::McDsNonPrompt); - - std::get(histosPtr[DataType::McDsNonPrompt]["hPtRecSig"])->Fill(pt); - std::get(histosPtr[DataType::McDsNonPrompt]["hPtGenSig"])->Fill(particleMother.pt()); // gen. level pT - std::get(histosPtr[DataType::McDsNonPrompt]["hPtVsYRecSigRecoSkim"])->Fill(pt, y); - std::get(histosPtr[DataType::McDsNonPrompt]["hCPARecSig"])->Fill(candidate.cpa()); - std::get(histosPtr[DataType::McDsNonPrompt]["hEtaRecSig"])->Fill(candidate.eta()); - if (TESTBIT(flag, aod::SelectionStep::RecoTopol)) { - std::get(histosPtr[DataType::McDsNonPrompt]["hPtVsYRecSigRecoTopol"])->Fill(pt, y); - } - if (TESTBIT(flag, aod::SelectionStep::RecoPID)) { - std::get(histosPtr[DataType::McDsNonPrompt]["hPtVsYRecSigRecoPID"])->Fill(pt, y); - } + if (TESTBIT(candidate.isSelDsToKKPi(), aod::SelectionStep::RecoSkims)) { + std::get(histosPtr[dataType]["hPtVsYRecoSkim"])->Fill(pt, yCand); } - return; - } // end Ds - - // D+→ K± K∓ π± - if (whichSpeciesDecay == SpeciesAndDecay::DplusToKKPi) { - double y = hfHelper.yDplus(candidate); - - // prompt - if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { - fillHisto(candidate, DataType::McDplusPrompt); - if (candidate.isSelDsToKKPi() >= selectionFlagDs) // KKPi - fillHistoKKPi(candidate, DataType::McDplusPrompt); - if (candidate.isSelDsToPiKK() >= selectionFlagDs) // PiKK - fillHistoPiKK(candidate, DataType::McDplusPrompt); - - std::get(histosPtr[DataType::McDplusPrompt]["hPtRecSig"])->Fill(pt); - std::get(histosPtr[DataType::McDplusPrompt]["hPtGenSig"])->Fill(particleMother.pt()); // gen. level pT - std::get(histosPtr[DataType::McDplusPrompt]["hPtVsYRecSigRecoSkim"])->Fill(pt, y); - std::get(histosPtr[DataType::McDplusPrompt]["hCPARecSig"])->Fill(candidate.cpa()); - std::get(histosPtr[DataType::McDplusPrompt]["hEtaRecSig"])->Fill(candidate.eta()); - if (TESTBIT(flag, aod::SelectionStep::RecoTopol)) { - std::get(histosPtr[DataType::McDplusPrompt]["hPtVsYRecSigRecoTopol"])->Fill(pt, y); - } - if (TESTBIT(flag, aod::SelectionStep::RecoPID)) { - std::get(histosPtr[DataType::McDplusPrompt]["hPtVsYRecSigRecoPID"])->Fill(pt, y); - } + if (TESTBIT(candidate.isSelDsToKKPi(), aod::SelectionStep::RecoTopol)) { + std::get(histosPtr[dataType]["hPtVsYRecoTopol"])->Fill(pt, yCand); } - - // non-prompt - if (candidate.originMcRec() == RecoDecay::OriginType::NonPrompt) { - fillHisto(candidate, DataType::McDplusNonPrompt); - if (candidate.isSelDsToKKPi() >= selectionFlagDs) // KKPi - fillHistoKKPi(candidate, DataType::McDplusNonPrompt); - if (candidate.isSelDsToPiKK() >= selectionFlagDs) // PiKK - fillHistoPiKK(candidate, DataType::McDplusNonPrompt); - - std::get(histosPtr[DataType::McDplusNonPrompt]["hPtRecSig"])->Fill(pt); - std::get(histosPtr[DataType::McDplusNonPrompt]["hPtGenSig"])->Fill(particleMother.pt()); // gen. level pT - std::get(histosPtr[DataType::McDplusNonPrompt]["hPtVsYRecSigRecoSkim"])->Fill(pt, y); - std::get(histosPtr[DataType::McDplusNonPrompt]["hCPARecSig"])->Fill(candidate.cpa()); - std::get(histosPtr[DataType::McDplusNonPrompt]["hEtaRecSig"])->Fill(candidate.eta()); - if (TESTBIT(flag, aod::SelectionStep::RecoTopol)) { - std::get(histosPtr[DataType::McDplusNonPrompt]["hPtVsYRecSigRecoTopol"])->Fill(pt, y); - } - if (TESTBIT(flag, aod::SelectionStep::RecoPID)) { - std::get(histosPtr[DataType::McDplusNonPrompt]["hPtVsYRecSigRecoPID"])->Fill(pt, y); - } + if (TESTBIT(candidate.isSelDsToKKPi(), aod::SelectionStep::RecoPID)) { + std::get(histosPtr[dataType]["hPtVsYRecoPID"])->Fill(pt, yCand); } + } + if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK + fillHisto(candidate, dataType); + fillHistoPiKK(candidate, dataType); - return; - } // end D+→ K± K∓ π± - - // D+→ π± K∓ π± - if (whichSpeciesDecay == SpeciesAndDecay::DplusToPiKPi) { - double y = hfHelper.yDplus(candidate); - - // Fill whether it is prompt or non-prompt - fillHisto(candidate, DataType::McDplusBkg); - - if (candidate.isSelDsToKKPi() >= selectionFlagDs) // KKPi - fillHistoKKPi(candidate, DataType::McDplusBkg); - if (candidate.isSelDsToPiKK() >= selectionFlagDs) // PiKK - fillHistoPiKK(candidate, DataType::McDplusBkg); - - std::get(histosPtr[DataType::McDplusBkg]["hPtRecSig"])->Fill(pt); - std::get(histosPtr[DataType::McDplusBkg]["hPtGenSig"])->Fill(particleMother.pt()); // gen. level pT - std::get(histosPtr[DataType::McDplusBkg]["hPtVsYRecSigRecoSkim"])->Fill(pt, y); - std::get(histosPtr[DataType::McDplusBkg]["hCPARecSig"])->Fill(candidate.cpa()); - std::get(histosPtr[DataType::McDplusBkg]["hEtaRecSig"])->Fill(candidate.eta()); - if (TESTBIT(flag, aod::SelectionStep::RecoTopol)) { - std::get(histosPtr[DataType::McDplusBkg]["hPtVsYRecSigRecoTopol"])->Fill(pt, y); + if (TESTBIT(candidate.isSelDsToPiKK(), aod::SelectionStep::RecoSkims)) { + std::get(histosPtr[dataType]["hPtVsYRecoSkim"])->Fill(pt, yCand); } - if (TESTBIT(flag, aod::SelectionStep::RecoPID)) { - std::get(histosPtr[DataType::McDplusBkg]["hPtVsYRecSigRecoPID"])->Fill(pt, y); + if (TESTBIT(candidate.isSelDsToPiKK(), aod::SelectionStep::RecoTopol)) { + std::get(histosPtr[dataType]["hPtVsYRecoTopol"])->Fill(pt, yCand); } - - return; - } // end D+→ π± K∓ π± + if (TESTBIT(candidate.isSelDsToPiKK(), aod::SelectionStep::RecoPID)) { + std::get(histosPtr[dataType]["hPtVsYRecoPID"])->Fill(pt, yCand); + } + } } + return; } - template - void runDataAnalysis(CandsDs const& candidates) + template + void runDataAnalysisPerCandidate(CandDs const& candidate) { - for (const auto& candidate : candidates) { - if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { - continue; - } + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { + return; + } + + if (candidate.isSelDsToKKPi() >= selectionFlagDs) { // KKPi fillHisto(candidate, DataType::Data); - if constexpr (decayChannel == FinalState::KKPi) { // KKPi - fillHistoKKPi(candidate, DataType::Data); - } else if constexpr (decayChannel == FinalState::PiKK) { // PiKK - fillHistoPiKK(candidate, DataType::Data); - } + fillHistoKKPi(candidate, DataType::Data); + } + if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK + fillHisto(candidate, DataType::Data); + fillHistoPiKK(candidate, DataType::Data); } } - template - void runMcAnalysis(CandsDs const& /*candidates*/, - CandDsMcGen const& mcParticles) + template + void runMcAnalysisPerCandidate(CandDs const& candidate, + CandDsMcGen const& mcParticles) { // MC rec. - // Ds± → K± K∓ π± - if constexpr (useMl) { - // Ds - for (const auto& candidate : reconstructedCandDsSigWithMl) - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) - fillHistoMCRec(candidate, mcParticles, SpeciesAndDecay::DsToKKPi); - // D+→ K± K∓ π± - for (const auto& candidate : reconstructedCandDplusSigWithMl) - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) - fillHistoMCRec(candidate, mcParticles, SpeciesAndDecay::DplusToKKPi); - // D+→ π± K∓ π± - for (const auto& candidate : reconstructedCandDplusBkgWithMl) - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) - fillHistoMCRec(candidate, mcParticles, SpeciesAndDecay::DplusToPiKPi); - // Bkg - for (const auto& candidate : reconstructedCandBkgWithMl) { - if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { - continue; - } + std::array, 5> isOfType = {// Contains the functions to check if the candidate is of a certain type + &HfTaskDs::isDsPrompt, + &HfTaskDs::isDsNonPrompt, + &HfTaskDs::isDplusPrompt, + &HfTaskDs::isDplusNonPrompt, + &HfTaskDs::isDplusBkg}; + + bool isBkg = true; + for (int i = DataType::McDsPrompt; i <= DataType::McDplusBkg; i++) { // Check what type of MC signal candidate it is, and fill the corresponding histograms + if ((this->*isOfType[i - DataType::McDsPrompt])(candidate)) { + isBkg = false; + fillHistoMCRec(candidate, mcParticles, static_cast(i)); + break; + } + } + if (isBkg) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { + return; + } - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) + if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) { + if (candidate.isSelDsToKKPi() >= selectionFlagDs) { // KKPi fillHisto(candidate, DataType::McBkg); - } - } else { - // Ds - for (const auto& candidate : reconstructedCandDsSig) - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) - fillHistoMCRec(candidate, mcParticles, SpeciesAndDecay::DsToKKPi); - - // D+→ K± K∓ π± - for (const auto& candidate : reconstructedCandDplusSig) - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) - fillHistoMCRec(candidate, mcParticles, SpeciesAndDecay::DplusToKKPi); - - // D+→ π± K∓ π± - for (const auto& candidate : reconstructedCandDplusBkg) - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) - fillHistoMCRec(candidate, mcParticles, SpeciesAndDecay::DplusToPiKPi); - - // Bkg - for (const auto& candidate : reconstructedCandBkg) { - if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { - continue; + fillHistoKKPi(candidate, DataType::McBkg); } - - if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) { + if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK fillHisto(candidate, DataType::McBkg); - if (candidate.isSelDsToKKPi() >= selectionFlagDs) // KKPi - fillHistoKKPi(candidate, DataType::McDsPrompt); - if (candidate.isSelDsToPiKK() >= selectionFlagDs) // PiKK - fillHistoPiKK(candidate, DataType::McDsPrompt); + fillHistoPiKK(candidate, DataType::McBkg); } } } // TODO: add histograms for reflections + } + template + void fillMcGenHistos(CandDsMcGen const& mcParticles, + Coll const& recoCollisions) + { // MC gen. for (const auto& particle : mcParticles) { if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { @@ -545,20 +522,27 @@ struct HfTaskDs { auto pt = particle.pt(); double y{0.f}; + unsigned maxNumContrib = 0; + const auto& recoCollsPerMcColl = recoCollisions.sliceBy(std::get>(colPerMcCollisionMap.at(centDetector)), particle.mcCollision().globalIndex()); + for (const auto& recCol : recoCollisions) { + maxNumContrib = recCol.numContrib() > maxNumContrib ? recCol.numContrib() : maxNumContrib; + } + if (particle.flagMcDecayChanGen() == decayChannel) { y = RecoDecay::y(particle.pVector(), o2::constants::physics::MassDS); if (yCandGenMax >= 0. && std::abs(y) > yCandGenMax) { continue; } + if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { - std::get(histosPtr[DataType::McDsPrompt]["hPtGen"])->Fill(pt); // gen. level pT - std::get(histosPtr[DataType::McDsPrompt]["hPtVsYGen"])->Fill(pt, y); // gen. level pT - std::get(histosPtr[DataType::McDsPrompt]["hEtaGen"])->Fill(particle.eta()); // gen. level pT + std::get(histosPtr[DataType::McDsPrompt]["hPtGen"])->Fill(pt); // gen. level pT + std::get(histosPtr[DataType::McDsPrompt]["hEtaGen"])->Fill(particle.eta()); + std::get(histosPtr[DataType::McDsPrompt]["hPtYNPvContribGen"])->Fill(pt, y, maxNumContrib); // gen. level pT } if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) { - std::get(histosPtr[DataType::McDsNonPrompt]["hPtGen"])->Fill(pt); // gen. level pT - std::get(histosPtr[DataType::McDsNonPrompt]["hPtVsYGen"])->Fill(pt, y); // gen. level pT - std::get(histosPtr[DataType::McDsNonPrompt]["hEtaGen"])->Fill(particle.eta()); // gen. level pT + std::get(histosPtr[DataType::McDsNonPrompt]["hPtGen"])->Fill(pt); // gen. level pT + std::get(histosPtr[DataType::McDsNonPrompt]["hEtaGen"])->Fill(particle.eta()); // gen. level pT + std::get(histosPtr[DataType::McDsNonPrompt]["hPtYNPvContribGen"])->Fill(pt, y, maxNumContrib); // gen. level pT } } else if (fillDplusMc) { y = RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus); @@ -566,14 +550,14 @@ struct HfTaskDs { continue; } if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { - std::get(histosPtr[DataType::McDplusPrompt]["hPtGen"])->Fill(pt); // gen. level pT - std::get(histosPtr[DataType::McDplusPrompt]["hPtVsYGen"])->Fill(pt, y); // gen. level pT + std::get(histosPtr[DataType::McDplusPrompt]["hPtGen"])->Fill(pt); // gen. level pT std::get(histosPtr[DataType::McDplusPrompt]["hEtaGen"])->Fill(particle.eta()); + std::get(histosPtr[DataType::McDplusPrompt]["hPtYNPvContribGen"])->Fill(pt, y, maxNumContrib); // gen. level pT } if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) { std::get(histosPtr[DataType::McDplusNonPrompt]["hPtGen"])->Fill(pt); // gen. level pT - std::get(histosPtr[DataType::McDplusNonPrompt]["hPtVsYGen"])->Fill(pt, y); std::get(histosPtr[DataType::McDplusNonPrompt]["hEtaGen"])->Fill(particle.eta()); + std::get(histosPtr[DataType::McDplusNonPrompt]["hPtYNPvContribGen"])->Fill(pt, y, maxNumContrib); // gen. level pT } } } @@ -581,155 +565,258 @@ struct HfTaskDs { } } - void processDataWithCentFT0C(CollisionsWithFT0C const&, - CandDsData const&) + template + void fillNPvContribHisto(const Coll& collision, + std::array& nCandsPerType, + std::array& nCandsInSignalRegionDsPerType, + std::array& nCandsInSignalRegionDplusPerType) + { + int numPvContributors = collision.numContrib(); + float centrality = evaluateCentralityColl(collision); + std::get(histosPtr[DataType::Data]["hNPvContribAll"])->Fill(numPvContributors, centrality); + for (int i = 0; i < DataType::kDataTypes; i++) { + if (nCandsPerType[i]) { + std::get(histosPtr[i]["hNPvContribCands"])->Fill(numPvContributors, centrality); + } + if (nCandsInSignalRegionDsPerType[i]) { + std::get(histosPtr[i]["hNPvContribCandsInSignalRegionDs"])->Fill(numPvContributors, centrality); + } + if (nCandsInSignalRegionDplusPerType[i]) { + std::get(histosPtr[i]["hNPvContribCandsInSignalRegionDplus"])->Fill(numPvContributors, centrality); + } + } + } + + template + void runDataAnalysisPerCollision(const Coll& collisions, const CandsDs& candsDs, Preslice candDsPerCollision) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + std::array nCandsPerType{0}; + std::array nCandsInSignalRegionDsPerType{0}; + std::array nCandsInSignalRegionDplusPerType{0}; + + auto groupedDsCandidates = candsDs.sliceBy(candDsPerCollision, thisCollId); + for (const auto& candidate : groupedDsCandidates) { + if (candidate.isSelDsToKKPi() < selectionFlagDs && candidate.isSelDsToPiKK() < selectionFlagDs) { + continue; + } + runDataAnalysisPerCandidate(candidate); + + ++nCandsPerType[DataType::Data]; + if (isCandInSignalRegion(candidate, true)) { + ++nCandsInSignalRegionDsPerType[DataType::Data]; + } + if (isCandInSignalRegion(candidate, false)) { + ++nCandsInSignalRegionDplusPerType[DataType::Data]; + } + } + fillNPvContribHisto(collision, nCandsPerType, nCandsInSignalRegionDsPerType, nCandsInSignalRegionDplusPerType); + } + } + + template + void runMcAnalysisPerCollision(const Coll& collisions, + const CandsDs& candsDs, + const CandDsMcGen& mcParticles, + Preslice candDsPerCollision) + { + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + std::array nCandsPerType{0}; + std::array nCandsInSignalRegionDsPerType{0}; + std::array nCandsInSignalRegionDplusPerType{0}; + + auto groupedDsCandidates = candsDs.sliceBy(candDsPerCollision, thisCollId); + for (const auto& candidate : groupedDsCandidates) { + if (candidate.isSelDsToKKPi() < selectionFlagDs && candidate.isSelDsToPiKK() < selectionFlagDs) { + continue; + } + runDataAnalysisPerCandidate(candidate); + runMcAnalysisPerCandidate(candidate, mcParticles); + + // Increase the number of candidates of the corresponding type to fill the NPvContrib histos + std::array, 4> isOfType = {// Contains the functions to check if the candidate is of a certain type + &HfTaskDs::isDsPrompt, + &HfTaskDs::isDsNonPrompt, + &HfTaskDs::isDplusPrompt, + &HfTaskDs::isDplusNonPrompt}; + bool isBkg = true; + for (int i = DataType::McDsPrompt; i <= DataType::McDplusNonPrompt; i++) { // Check what type of MC signal candidate it is, and fill the corresponding arrays + if ((this->*isOfType[i - DataType::McDsPrompt])(candidate)) { + isBkg = false; + ++nCandsPerType[i]; + if (isCandInSignalRegion(candidate, true)) { + ++nCandsInSignalRegionDsPerType[i]; + } + if (isCandInSignalRegion(candidate, false)) { + ++nCandsInSignalRegionDplusPerType[i]; + } + break; + } + } + if (isBkg) { + ++nCandsPerType[DataType::McBkg]; + if (isCandInSignalRegion(candidate, true)) { + ++nCandsInSignalRegionDsPerType[DataType::McBkg]; + } + if (isCandInSignalRegion(candidate, false)) { + ++nCandsInSignalRegionDplusPerType[DataType::McBkg]; + } + } + + nCandsPerType[DataType::Data] = nCandsPerType[DataType::McDsPrompt] + nCandsPerType[DataType::McDsNonPrompt] + nCandsPerType[DataType::McDplusPrompt] + nCandsPerType[DataType::McDplusNonPrompt] + nCandsPerType[DataType::McBkg]; + + nCandsInSignalRegionDsPerType[DataType::Data] = nCandsInSignalRegionDsPerType[DataType::McDsPrompt] + nCandsInSignalRegionDsPerType[DataType::McDsNonPrompt] + nCandsInSignalRegionDsPerType[DataType::McDplusPrompt] + nCandsInSignalRegionDsPerType[DataType::McDplusNonPrompt] + nCandsInSignalRegionDsPerType[DataType::McBkg]; + + nCandsInSignalRegionDplusPerType[DataType::Data] = nCandsInSignalRegionDplusPerType[DataType::McDsPrompt] + nCandsInSignalRegionDplusPerType[DataType::McDsNonPrompt] + nCandsInSignalRegionDplusPerType[DataType::McDplusPrompt] + nCandsInSignalRegionDplusPerType[DataType::McDplusNonPrompt] + nCandsInSignalRegionDplusPerType[DataType::McBkg]; + } + fillNPvContribHisto(collision, nCandsPerType, nCandsInSignalRegionDsPerType, nCandsInSignalRegionDplusPerType); + } + fillMcGenHistos(mcParticles, collisions); + } + + void processDataWithCentFT0C(CollisionsWithFT0C const& collisions, + CandDsData const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandData); - runDataAnalysis(selectedDsToPiKKCandData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithCentFT0C, "Process data w/o ML information on Ds, with information on centrality from FT0C", false); - void processDataWithCentFT0M(CollisionsWithFT0M const&, - CandDsData const&) + void processDataWithCentFT0M(CollisionsWithFT0M const& collisions, + CandDsData const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandData); - runDataAnalysis(selectedDsToPiKKCandData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithCentFT0M, "Process data w/o ML information on Ds, with information on centrality from FT0M", false); - void processDataWithCentNTracksPV(CollisionsWithNTracksPV const&, - CandDsData const&) + void processDataWithCentNTracksPV(CollisionsWithNTracksPV const& collisions, + CandDsData const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandData); - runDataAnalysis(selectedDsToPiKKCandData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithCentNTracksPV, "Process data w/o ML information on Ds, with information on centrality from NTracksPV", false); - void processData(aod::Collisions const&, - CandDsData const&) + void processData(soa::Join const& collisions, + CandDsData const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandData); - runDataAnalysis(selectedDsToPiKKCandData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataPerCollision); } PROCESS_SWITCH(HfTaskDs, processData, "Process data w/o ML information on Ds, w/o information on centrality", true); - void processDataWithMlAndCentFT0C(CollisionsWithFT0C const&, - CandDsDataWithMl const&) + void processDataWithMlAndCentFT0C(CollisionsWithFT0C const& collisions, + CandDsDataWithMl const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandWithMlData); - runDataAnalysis(selectedDsToPiKKCandWithMlData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithMlAndCentFT0C, "Process data with ML information on Ds, with information on centrality from FT0C", false); - void processDataWithMlAndCentFT0M(CollisionsWithFT0M const&, - CandDsDataWithMl const&) + void processDataWithMlAndCentFT0M(CollisionsWithFT0M const& collisions, + CandDsDataWithMl const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandWithMlData); - runDataAnalysis(selectedDsToPiKKCandWithMlData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithMlAndCentFT0M, "Process data with ML information on Ds, with information on centrality from FT0M", false); - void processDataWithMlAndCentNTracksPV(CollisionsWithNTracksPV const&, - CandDsDataWithMl const&) + void processDataWithMlAndCentNTracksPV(CollisionsWithNTracksPV const& collisions, + CandDsDataWithMl const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandWithMlData); - runDataAnalysis(selectedDsToPiKKCandWithMlData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithMlAndCentNTracksPV, "Process data with ML information on Ds, with information on centrality", false); - void processDataWithMl(aod::Collisions const&, - CandDsDataWithMl const&) + void processDataWithMl(soa::Join const& collisions, + CandDsDataWithMl const& candsDs, + aod::Tracks const&) { - runDataAnalysis(selectedDsToKKPiCandWithMlData); - runDataAnalysis(selectedDsToPiKKCandWithMlData); + runDataAnalysisPerCollision(collisions, candsDs, candDsDataWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processDataWithMl, "Process data with ML information on Ds, w/o information on centrality", false); - void processMcWithCentFT0C(CollisionsWithFT0C const&, - CandDsMcReco const& candidates, + void processMcWithCentFT0C(CollisionsMcWithFT0C const& collisions, + CandDsMcReco const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandMc); - runDataAnalysis(selectedDsToPiKKCandMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithCentFT0C, "Process MC w/o ML information on Ds, with information on centrality from FT0C", false); - void processMcWithCentFT0M(CollisionsWithFT0M const&, - CandDsMcReco const& candidates, + void processMcWithCentFT0M(CollisionsMcWithFT0M const& collisions, + CandDsMcReco const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandMc); - runDataAnalysis(selectedDsToPiKKCandMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithCentFT0M, "Process MC w/o ML information on Ds, with information on centrality from FT0M", false); - void processMcWithCentNTracksPV(CollisionsWithNTracksPV const&, - CandDsMcReco const& candidates, + void processMcWithCentNTracksPV(CollisionsMcWithNTracksPV const& collisions, + CandDsMcReco const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandMc); - runDataAnalysis(selectedDsToPiKKCandMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithCentNTracksPV, "Process MC w/o ML information on Ds, with information on centrality from NTracksPV", false); - void processMc(aod::Collisions const&, - CandDsMcReco const& candidates, + void processMc(CollisionsMc const& collisions, + CandDsMcReco const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandMc); - runDataAnalysis(selectedDsToPiKKCandMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoPerCollision); } PROCESS_SWITCH(HfTaskDs, processMc, "Process MC w/o ML information on Ds, w/o information on centrality", false); - void processMcWithMlAndCentFT0C(CollisionsWithFT0C const&, - CandDsMcRecoWithMl const& candidates, + void processMcWithMlAndCentFT0C(CollisionsMcWithFT0C const& collisions, + CandDsMcRecoWithMl const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandWithMlMc); - runDataAnalysis(selectedDsToPiKKCandWithMlMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithMlAndCentFT0C, "Process MC with ML information on Ds, with information on centrality from FT0C", false); - void processMcWithMlAndCentFT0M(CollisionsWithFT0M const&, - CandDsMcRecoWithMl const& candidates, + void processMcWithMlAndCentFT0M(CollisionsMcWithFT0M const& collisions, + CandDsMcRecoWithMl const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandWithMlMc); - runDataAnalysis(selectedDsToPiKKCandWithMlMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithMlAndCentFT0M, "Process MC with ML information on Ds, with information on centrality from FT0M", false); - void processMcWithMlAndCentNTracksPV(CollisionsWithNTracksPV const&, - CandDsMcRecoWithMl const& candidates, + void processMcWithMlAndCentNTracksPV(CollisionsMcWithNTracksPV const& collisions, + CandDsMcRecoWithMl const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandWithMlMc); - runDataAnalysis(selectedDsToPiKKCandWithMlMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithMlAndCentNTracksPV, "Process MC with ML information on Ds, with information on centrality from NTracksPV", false); - void processMcWithMl(aod::Collisions const&, - CandDsMcRecoWithMl const& candidates, + void processMcWithMl(CollisionsMc const& collisions, + CandDsMcRecoWithMl const& candsDs, CandDsMcGen const& mcParticles, + aod::McCollisions const&, aod::TracksWMc const&) { - runMcAnalysis(candidates, mcParticles); - runDataAnalysis(selectedDsToKKPiCandWithMlMc); - runDataAnalysis(selectedDsToPiKKCandWithMlMc); + runMcAnalysisPerCollision(collisions, candsDs, mcParticles, candDsMcRecoWithMlPerCollision); } PROCESS_SWITCH(HfTaskDs, processMcWithMl, "Process MC with ML information on Ds, w/o information on centrality", false); }; diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index 07c5f63efa9..35a6ce4c74b 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -17,6 +17,7 @@ #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" #include "Framework/runDataProcessing.h" #include "PWGHF/Core/SelectorCuts.h" @@ -27,6 +28,7 @@ using namespace o2; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::soa; /// Dstar analysis task struct HfTaskDstarToD0Pi { @@ -42,12 +44,19 @@ struct HfTaskDstarToD0Pi { using CandDstarWSelFlagMcRec = soa::Join; using CandDstarMcGen = soa::Join; + using CollisionsWCent = soa::Join; + using CollisionsWCentMcLabel = soa::Join; + + PresliceUnsorted colsPerMcCollision = aod::mccollisionlabel::mcCollisionId; + SliceCache cache; + Partition rowsSelectedCandDstar = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; Partition rowsSelectedCandDstarMcRec = aod::hf_sel_candidate_dstar::isRecoD0Flag == selectionFlagHfD0ToPiK; ConfigurableAxis binningImpactParam{"binningImpactParam", {1000, 0.1, -0.1}, " Bins of Impact Parameter"}; ConfigurableAxis binningDecayLength{"binningDecayLength", {1000, 0.0, 0.7}, "Bins of Decay Length"}; ConfigurableAxis binningNormDecayLength{"binningNormDecayLength", {1000, 0.0, 40.0}, "Bins of Normalised Decay Length"}; + ConfigurableAxis binningCentrality{"binningCentrality", {VARIABLE_WIDTH, 0.0, 10.0, 20.0, 30.0, 60.0, 100.0}, "centrality binning"}; HistogramRegistry registry{ "registry", @@ -57,7 +66,8 @@ struct HfTaskDstarToD0Pi { {"QA/hPtProng1D0", "Prong1 of D0 Candidates; Prong1 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, {"QA/hPtProng0D0Bar", "Prong0 of D0Bar Candidates; Prong0 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, {"QA/hPtProng1D0Bar", "Prong1 of D0Bar Candidates; Prong1 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtSoftPi", "Soft Pi ; Soft Pi #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{100, 0., 1.}}}}}}; + {"QA/hPtSoftPi", "Soft Pi ; Soft Pi #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"QA/hDeltaCentGen", "#{Delta}Cent % distribution of Collisions having same MC Collision;FT0M #{Delta}Cent %; Counts", {HistType::kTH1F, {{100, 0.0, 100.0}}}}}}; void init(InitContext&) { @@ -66,7 +76,9 @@ struct HfTaskDstarToD0Pi { AxisSpec axisImpactParam = {binningImpactParam, "impact parameter (cm)"}; AxisSpec axisDecayLength = {binningDecayLength, " decay length (cm)"}; AxisSpec axisNormDecayLength = {binningNormDecayLength, "normalised decay length (cm)"}; + AxisSpec axisCentrality = {binningCentrality, "centrality (%)"}; + registry.add("Yield/hDeltaInvMassDstar3D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c}); FT0M centrality", {HistType::kTH3F, {{100, 0.13, 0.16}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); registry.add("Yield/hDeltaInvMassDstar2D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, 0.13, 0.16}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); registry.add("Yield/hDeltaInvMassDstar1D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2}); entries", {HistType::kTH1F, {{100, 0.13, 0.16}}}, true); registry.add("Yield/hInvMassDstar", "#Delta #it{M}_{inv} D* Candidate; inv. mass (#pi #pi k) (GeV/#it{c}^{2}); entries", {HistType::kTH1F, {{500, 0., 5.0}}}, true); @@ -94,7 +106,8 @@ struct HfTaskDstarToD0Pi { registry.add("QA/hEtaSkimD0RecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{#eta} of D0 Prong", {HistType::kTH1F, {{100, -2., 2.}}}); registry.add("QA/hEtaSkimDstarRecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{#eta} of D* Candidate", {HistType::kTH1F, {{100, -2., 2.}}}); // pt vs y - registry.add("QA/hPtSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hPtSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); + registry.add("Efficiency/hPtVsCentSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c}); Centrality (%)", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); registry.add("QA/hPtVsYSkimDstarRecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); registry.add("QA/hPtVsYRecoTopolDstarRecSig", "MC Matched RecoTopol D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); registry.add("QA/hPtVsYRecoPidDstarRecSig", "MC Matched RecoPid D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); @@ -118,6 +131,7 @@ struct HfTaskDstarToD0Pi { // MC Matching at Generator level Successful registry.add("QA/hEtaDstarGen", "MC Matched D* Candidates at Generator Level; #it{#eta}", {HistType::kTH1F, {{100, -2., 2.}}}); registry.add("QA/hPtDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Efficiency/hPtVsCentDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*;Centrality (%) ", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); registry.add("QA/hPtVsYDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); // Prompt Gen registry.add("QA/hPtPromptDstarGen", "MC Matched Prompt D* Candidates at Generator Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -127,7 +141,7 @@ struct HfTaskDstarToD0Pi { registry.add("QA/hPtVsYNonPromptDstarGen", "MC Matched Non-Prompt D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); } - void process(CandDstarWSelFlag const&) + void process(CollisionsWCent const&, CandDstarWSelFlag const&) { for (const auto& candDstar : rowsSelectedCandDstar) { auto yDstar = candDstar.y(constants::physics::MassDStar); @@ -162,8 +176,12 @@ struct HfTaskDstarToD0Pi { auto invD0 = candDstar.invMassD0(); auto invD0Bar = candDstar.invMassD0Bar(); + auto collision = candDstar.collision_as(); + auto centrality = collision.centFT0M(); // 0-100% + auto signDstar = candDstar.signSoftPi(); if (signDstar > 0) { + registry.fill(HIST("Yield/hDeltaInvMassDstar3D"), (invDstar - invD0), candDstar.pt(), centrality); registry.fill(HIST("Yield/hDeltaInvMassDstar2D"), (invDstar - invD0), candDstar.pt()); registry.fill(HIST("Yield/hInvMassD0"), invD0, candDstar.ptD0()); registry.fill(HIST("Yield/hDeltaInvMassDstar1D"), (invDstar - invD0)); @@ -172,6 +190,7 @@ struct HfTaskDstarToD0Pi { registry.fill(HIST("QA/hPtProng0D0"), candDstar.ptProng0()); registry.fill(HIST("QA/hPtProng1D0"), candDstar.ptProng1()); } else if (signDstar < 0) { + registry.fill(HIST("Yield/hDeltaInvMassDstar3D"), (invAntiDstar - invD0Bar), candDstar.pt(), centrality); registry.fill(HIST("Yield/hDeltaInvMassDstar2D"), (invAntiDstar - invD0Bar), candDstar.pt()); registry.fill(HIST("Yield/hInvMassD0"), invD0Bar, candDstar.ptD0()); registry.fill(HIST("Yield/hDeltaInvMassDstar1D"), (invAntiDstar - invD0Bar)); @@ -183,10 +202,11 @@ struct HfTaskDstarToD0Pi { } } - void processMC(CandDstarWSelFlagMcRec const&, + void processMC(aod::McCollisions const&, CollisionsWCentMcLabel const& collisions, CandDstarWSelFlagMcRec const&, CandDstarMcGen const& rowsMcPartilces, aod::TracksWMc const&) { + rowsSelectedCandDstarMcRec.bindExternalIndices(&collisions); int8_t signDstar = 0; // MC at Reconstruction level @@ -196,11 +216,18 @@ struct HfTaskDstarToD0Pi { if (yCandDstarRecoMax >= 0. && std::abs(yDstarRecSig) > yCandDstarRecoMax) { continue; } + auto collision = candDstarMcRec.collision_as(); + auto centrality = collision.centFT0M(); // 0-100% if (TESTBIT(std::abs(candDstarMcRec.flagMcMatchRec()), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { // if MC matching is successful at Reconstruction Level // get MC Mother particle auto indexMother = RecoDecay::getMother(rowsMcPartilces, candDstarMcRec.prong0_as().mcParticle_as(), o2::constants::physics::Pdg::kDStar, true, &signDstar, 2); auto particleMother = rowsMcPartilces.rawIteratorAt(indexMother); // What is difference between rawIterator() or iteratorAt() methods? registry.fill(HIST("QA/hPtSkimDstarGenSig"), particleMother.pt()); // generator level pt + registry.fill(HIST("Efficiency/hPtVsCentSkimDstarGenSig"), particleMother.pt(), centrality); + + // auto recCollision = candDstarMcRec.collision_as(); + // float centFT0M = recCollision.centFT0M(); + // LOGF(info, "centFT0M: %f", centFT0M); registry.fill(HIST("QA/hPtVsYSkimDstarRecSig"), ptDstarRecSig, yDstarRecSig); // Skimed at level of trackIndexSkimCreator if (candDstarMcRec.isRecoTopol()) { // if Topological selection are passed @@ -253,15 +280,48 @@ struct HfTaskDstarToD0Pi { // MC at Generator Level for (const auto& mcParticle : rowsMcPartilces) { if (TESTBIT(std::abs(mcParticle.flagMcMatchGen()), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { // MC Matching is successful at Generator Level + auto ptGen = mcParticle.pt(); // auto yGen = mcParticle.y(); // Can we use this definition? auto yGen = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDStar); if (yCandDstarGenMax >= 0. && std::abs(yGen) > yCandDstarGenMax) { continue; } + + auto mcCollision = mcParticle.mcCollision_as(); + auto recCollisions = collisions.sliceBy(colsPerMcCollision, mcCollision.globalIndex()); + // auto recCollisions = collisions.sliceByCached(aod::mccollisionlabel::mcCollisionId, mcCollision.globalIndex(), cache); + // auto recCollisions = collisions.sliceByCachedUnsorted(aod::mccollisionlabel::mcCollisionId, mcCollision.globalIndex(), cache); + + // looking if a generated collision reconstructed more than a times. + if (recCollisions.size() > 1) { + for (const auto& [c1, c2] : combinations(CombinationsStrictlyUpperIndexPolicy(recCollisions, recCollisions))) { + auto deltaCent = abs(c1.centFT0M() - c2.centFT0M()); + registry.fill(HIST("QA/hDeltaCentGen"), deltaCent); + } + } + + float centFT0MGen; + // assigning centrality to MC Collision using max FT0M amplitute from Reconstructed collisions + if (recCollisions.size()) { + std::vector::iterator, int>> tempRecCols; + + for (const auto& recCol : recCollisions) { + // if(recCollisions.size()>1) LOGF(info, "cuurent cent: %f",recCol.centFT0M()); + tempRecCols.push_back(std::make_pair(recCol, recCol.numContrib())); + } + std::sort(tempRecCols.begin(), tempRecCols.end(), compare); + centFT0MGen = tempRecCols.at(0).first.centFT0M(); + // if(recCollisions.size()>1) LOGF(info, "assigned cent: %f",centFT0MGen); + } else { + centFT0MGen = -999.; + } + registry.fill(HIST("QA/hEtaDstarGen"), mcParticle.eta()); registry.fill(HIST("QA/hPtDstarGen"), ptGen); registry.fill(HIST("QA/hPtVsYDstarGen"), ptGen, yGen); + registry.fill(HIST("Efficiency/hPtVsCentDstarGen"), ptGen, centFT0MGen); + // only promt Dstar candidate at Generator level if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { registry.fill(HIST("QA/hPtPromptDstarGen"), ptGen); @@ -274,6 +334,12 @@ struct HfTaskDstarToD0Pi { } } PROCESS_SWITCH(HfTaskDstarToD0Pi, processMC, "Process MC Data", false); + + // Comparator function to sort based on the second argument of a tuple + static bool compare(const std::pair::iterator, int>& a, const std::pair::iterator, int>& b) + { + return a.second > b.second; + } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 4b808f5dfb1..7941890d40a 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -15,6 +15,7 @@ /// \author S. PolitanĂČ, INFN Torino, Italy /// \author Wu Chuntai, CUG, China +#include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" @@ -26,12 +27,14 @@ #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::hf_centrality; +using namespace o2::hf_evsel; enum DecayChannel { DplusToPiKPi = 0, DsToKKPi, @@ -46,16 +49,17 @@ enum QvecEstimator { FV0A = 0, FT0A, FT0C, TPCPos, - TPCNeg }; + TPCNeg, + TPCTot }; struct HfTaskFlowCharmHadrons { - Configurable zVtxMax{"zVtxMax", 10., "Max vertex coordinate z"}; Configurable harmonic{"harmonic", 2, "harmonic number"}; - Configurable qvecDetector{"qvecDetector", 3, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3, TPC Pos: 4, TPC Neg: 5)"}; + Configurable qvecDetector{"qvecDetector", 3, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3, TPC Pos: 4, TPC Neg: 5, TPC Tot: 6)"}; Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; Configurable storeMl{"storeMl", false, "Flag to store ML scores"}; Configurable saveEpResoHisto{"saveEpResoHisto", false, "Flag to save event plane resolution histogram"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable> classMl{"classMl", {0, 2}, "Indexes of BDT scores to be stored. Two indexes max."}; ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""}; @@ -75,7 +79,7 @@ struct HfTaskFlowCharmHadrons { using CandLcDataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; Filter filterSelectDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlag; @@ -98,6 +102,8 @@ struct HfTaskFlowCharmHadrons { SliceCache cache; HfHelper hfHelper; EventPlaneHelper epHelper; + HfEventSelection hfEvSel; // event selection and monitoring + o2::framework::Service ccdb; HistogramRegistry registry{"registry", {}}; @@ -121,14 +127,18 @@ struct HfTaskFlowCharmHadrons { registry.add("spReso/hSpResoFT0cFV0a", "hSpResoFT0cFV0a; centrality; Q_{FT0c} #bullet Q_{FV0a}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0cTPCpos", "hSpResoFT0cTPCpos; centrality; Q_{FT0c} #bullet Q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0cTPCneg", "hSpResoFT0cTPCneg; centrality; Q_{FT0c} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); + registry.add("spReso/hSpResoFT0cTPCtot", "hSpResoFT0cTPCtot; centrality; Q_{FT0c} #bullet Q_{TPCtot}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0aFV0a", "hSpResoFT0aFV0a; centrality; Q_{FT0a} #bullet Q_{FV0a}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0aTPCpos", "hSpResoFT0aTPCpos; centrality; Q_{FT0a} #bullet Q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0aTPCneg", "hSpResoFT0aTPCneg; centrality; Q_{FT0a} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); + registry.add("spReso/hSpResoFT0aTPCtot", "hSpResoFT0aTPCtot; centrality; Q_{FT0m} #bullet Q_{TPCtot}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0mFV0a", "hSpResoFT0mFV0a; centrality; Q_{FT0m} #bullet Q_{FV0a}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0mTPCpos", "hSpResoFT0mTPCpos; centrality; Q_{FT0m} #bullet Q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0mTPCneg", "hSpResoFT0mTPCneg; centrality; Q_{FT0m} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); + registry.add("spReso/hSpResoFT0mTPCtot", "hSpResoFT0mTPCtot; centrality; Q_{FV0a} #bullet Q_{TPCtot}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFV0aTPCpos", "hSpResoFV0aTPCpos; centrality; Q_{FV0a} #bullet Q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFV0aTPCneg", "hSpResoFV0aTPCneg; centrality; Q_{FV0a} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); + registry.add("spReso/hSpResoFV0aTPCtot", "hSpResoFV0aTPCtot; centrality; Q_{FV0a} #bullet Q_{TPCtot}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoTPCposTPCneg", "hSpResoTPCposTPCneg; centrality; Q_{TPCpos} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); if (saveEpResoHisto) { @@ -136,16 +146,25 @@ struct HfTaskFlowCharmHadrons { registry.add("epReso/hEpResoFT0cFV0a", "hEpResoFT0cFV0a; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0cTPCpos", "hEpResoFT0cTPCpos; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0cTPCneg", "hEpResoFT0cTPCneg; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); + registry.add("epReso/hEpResoFT0cTPCtot", "hEpResoFT0cTPCtot; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0aFV0a", "hEpResoFT0aFV0a; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0aTPCpos", "hEpResoFT0aTPCpos; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0aTPCneg", "hEpResoFT0aTPCneg; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); + registry.add("epReso/hEpResoFT0aTPCtot", "hEpResoFT0aTPCtot; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0mFV0a", "hEpResoFT0mFV0a; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0mTPCpos", "hEpResoFT0mTPCpos; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0mTPCneg", "hEpResoFT0mTPCneg; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); + registry.add("epReso/hEpResoFT0mTPCtot", "hEpResoFT0mTPCtot; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFV0aTPCpos", "hEpResoFV0aTPCpos; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFV0aTPCneg", "hEpResoFV0aTPCneg; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); + registry.add("epReso/hEpResoFV0aTPCtot", "hEpResoFV0aTPCtot; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoTPCposTPCneg", "hEpResoTPCposTPCneg; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); } + + hfEvSel.addHistograms(registry); // collision monitoring + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); }; // end init /// Compute the Q vector for the candidate's tracks @@ -249,6 +268,22 @@ struct HfTaskFlowCharmHadrons { return cent; } + /// Check if the collision is selected + /// \param collision is the collision with the Q vector information + /// \param bc is the bunch crossing with timestamp information + /// \return true if the collision is selected, false otherwise + template + bool isCollSelected(CollsWithQvecs::iterator const& collision, + aod::BCsWithTimestamps const&) + { + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + /// monitor the satisfied event selections + hfEvSel.fillHistograms(collision, rejectionMask, centrality); + return rejectionMask == 0; + } + /// Get the Q vector /// \param collision is the collision with the Q vector information std::vector getQvec(CollsWithQvecs::iterator const& collision) @@ -283,6 +318,11 @@ struct HfTaskFlowCharmHadrons { yQVec = collision.qvecBNegIm(); amplQVec = collision.nTrkBNeg(); break; + case QvecEstimator::TPCTot: + xQVec = collision.qvecBTotRe(); + yQVec = collision.qvecBTotIm(); + amplQVec = collision.nTrkBTot(); + break; default: LOG(warning) << "Q vector estimator not valid. Please choose between FV0A, FT0M, FT0A, FT0C, TPC Pos, TPC Neg. Fallback to FV0A"; xQVec = collision.qvecFV0ARe(); @@ -485,14 +525,15 @@ struct HfTaskFlowCharmHadrons { PROCESS_SWITCH(HfTaskFlowCharmHadrons, processLc, "Process Lc candidates", false); // Resolution - void processResolution(CollsWithQvecs::iterator const& collision) + void processResolution(CollsWithQvecs::iterator const& collision, + aod::BCsWithTimestamps const& bcs) { - - if (!collision.sel8() || std::abs(collision.posZ()) > zVtxMax) { + if (!isCollSelected(collision, bcs)) { + // no selection on the centrality is applied on purpose to allow for the resolution study in post-processing return; } - float centrality = getCentrality(collision); + float centrality = getCentrality(collision); // centrality not updated in the rejection mask function float xQVecFT0a = collision.qvecFT0ARe(); float yQVecFT0a = collision.qvecFT0AIm(); float xQVecFT0c = collision.qvecFT0CRe(); @@ -505,19 +546,25 @@ struct HfTaskFlowCharmHadrons { float yQVecBPos = collision.qvecBPosIm(); float xQVecBNeg = collision.qvecBNegRe(); float yQVecBNeg = collision.qvecBNegIm(); + float xQVecBTot = collision.qvecBTotRe(); + float yQVecBTot = collision.qvecBTotIm(); registry.fill(HIST("spReso/hSpResoFT0cFT0a"), centrality, xQVecFT0c * xQVecFT0a + yQVecFT0c * yQVecFT0a); registry.fill(HIST("spReso/hSpResoFT0cFV0a"), centrality, xQVecFT0c * xQVecFV0a + yQVecFT0c * yQVecFV0a); registry.fill(HIST("spReso/hSpResoFT0cTPCpos"), centrality, xQVecFT0c * xQVecBPos + yQVecFT0c * yQVecBPos); registry.fill(HIST("spReso/hSpResoFT0cTPCneg"), centrality, xQVecFT0c * xQVecBNeg + yQVecFT0c * yQVecBNeg); + registry.fill(HIST("spReso/hSpResoFT0cTPCtot"), centrality, xQVecFT0c * xQVecBTot + yQVecFT0c * yQVecBTot); registry.fill(HIST("spReso/hSpResoFT0aFV0a"), centrality, xQVecFT0a * xQVecFV0a + yQVecFT0a * yQVecFV0a); registry.fill(HIST("spReso/hSpResoFT0aTPCpos"), centrality, xQVecFT0a * xQVecBPos + yQVecFT0a * yQVecBPos); registry.fill(HIST("spReso/hSpResoFT0aTPCneg"), centrality, xQVecFT0a * xQVecBNeg + yQVecFT0a * yQVecBNeg); + registry.fill(HIST("spReso/hSpResoFT0aTPCtot"), centrality, xQVecFT0a * xQVecBTot + yQVecFT0a * yQVecBTot); registry.fill(HIST("spReso/hSpResoFT0mFV0a"), centrality, xQVecFT0m * xQVecFV0a + yQVecFT0m * yQVecFV0a); registry.fill(HIST("spReso/hSpResoFT0mTPCpos"), centrality, xQVecFT0m * xQVecBPos + yQVecFT0m * yQVecBPos); registry.fill(HIST("spReso/hSpResoFT0mTPCneg"), centrality, xQVecFT0m * xQVecBNeg + yQVecFT0m * yQVecBNeg); + registry.fill(HIST("spReso/hSpResoFT0mTPCtot"), centrality, xQVecFT0m * xQVecBTot + yQVecFT0m * yQVecBTot); registry.fill(HIST("spReso/hSpResoFV0aTPCpos"), centrality, xQVecFV0a * xQVecBPos + yQVecFV0a * yQVecBPos); registry.fill(HIST("spReso/hSpResoFV0aTPCneg"), centrality, xQVecFV0a * xQVecBNeg + yQVecFV0a * yQVecBNeg); + registry.fill(HIST("spReso/hSpResoFV0aTPCtot"), centrality, xQVecFV0a * xQVecBTot + yQVecFV0a * yQVecBTot); registry.fill(HIST("spReso/hSpResoTPCposTPCneg"), centrality, xQVecBPos * xQVecBNeg + yQVecBPos * yQVecBNeg); if (saveEpResoHisto) { @@ -527,19 +574,24 @@ struct HfTaskFlowCharmHadrons { float epFV0a = epHelper.GetEventPlane(xQVecFV0a, yQVecFV0a, harmonic); float epBPoss = epHelper.GetEventPlane(xQVecBPos, yQVecBPos, harmonic); float epBNegs = epHelper.GetEventPlane(xQVecBNeg, yQVecBNeg, harmonic); + float epBTots = epHelper.GetEventPlane(xQVecBTot, yQVecBTot, harmonic); registry.fill(HIST("epReso/hEpResoFT0cFT0a"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epFT0a))); registry.fill(HIST("epReso/hEpResoFT0cFV0a"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epFV0a))); registry.fill(HIST("epReso/hEpResoFT0cTPCpos"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epBPoss))); registry.fill(HIST("epReso/hEpResoFT0cTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epBNegs))); + registry.fill(HIST("epReso/hEpResoFT0cTPCtot"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epBTots))); registry.fill(HIST("epReso/hEpResoFT0aFV0a"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0a, epFV0a))); registry.fill(HIST("epReso/hEpResoFT0aTPCpos"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0a, epBPoss))); registry.fill(HIST("epReso/hEpResoFT0aTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0a, epBNegs))); + registry.fill(HIST("epReso/hEpResoFT0aTPCtot"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0a, epBTots))); registry.fill(HIST("epReso/hEpResoFT0mFV0a"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0m, epFV0a))); registry.fill(HIST("epReso/hEpResoFT0mTPCpos"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0m, epBPoss))); registry.fill(HIST("epReso/hEpResoFT0mTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0m, epBNegs))); + registry.fill(HIST("epReso/hEpResoFT0mTPCtot"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0m, epBTots))); registry.fill(HIST("epReso/hEpResoFV0aTPCpos"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFV0a, epBPoss))); registry.fill(HIST("epReso/hEpResoFV0aTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFV0a, epBNegs))); + registry.fill(HIST("epReso/hEpResoFV0aTPCtot"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFV0a, epBTots))); registry.fill(HIST("epReso/hEpResoTPCposTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epBPoss, epBNegs))); } } diff --git a/PWGHF/D2H/Tasks/taskLb.cxx b/PWGHF/D2H/Tasks/taskLb.cxx index a74b5ec7f11..025c525b35c 100644 --- a/PWGHF/D2H/Tasks/taskLb.cxx +++ b/PWGHF/D2H/Tasks/taskLb.cxx @@ -58,6 +58,9 @@ struct HfTaskLb { Filter filterSelectCandidates = (aod::hf_sel_candidate_lb::isSelLbToLcPi >= selectionFlagLb); using TracksWExt = soa::Join; + using TracksWExtMc = soa::Join; + + PresliceUnsorted McPartID = aod::mctracklabel::mcParticleId; bool passesImpactParameterResolution(float pT, float d0Resolution) { @@ -294,7 +297,7 @@ struct HfTaskLb { void processMc(soa::Filtered> const& candidates, soa::Join const& mcParticles, - aod::TracksWMc const&, + TracksWExtMc const&, aod::HfCand3Prong const&) { // MC rec @@ -306,9 +309,10 @@ struct HfTaskLb { continue; } auto candLc = candidate.prong0_as(); + if (std::abs(candidate.flagMcMatchRec()) == 1 << hf_cand_lb::DecayType::LbToLcPi) { - auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kLambdaB0, true); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kLambdaB0, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("MC/hPtGenSig"), particleMother.pt()); registry.fill(HIST("MC/hPtRecSig"), candidate.pt()); @@ -362,7 +366,7 @@ struct HfTaskLb { float ptProngs[2], yProngs[2], etaProngs[2]; int counter = 0; - for (const auto& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as>()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); diff --git a/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx b/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx new file mode 100644 index 00000000000..821379003d7 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx @@ -0,0 +1,204 @@ +// Copyright 2019-2020 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. + +/// \file taskSigmacToCascade.cxx +/// \brief Task for ÎŁc0,++ → Λc(→ K0sP) + π-,+ analysis +/// \note Here the Lc from the cascade channel is obtained using the task taskLcToK0sP.cxx +/// \author Rutuparna Rath , INFN BOLOGNA and GSI Darmstadt +/// In collaboration with Andrea Alici , INFN BOLOGNA + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct HfTaskSigmacToCascade { + + Configurable enableTHn{"enableTHn", false, "enable the usage of THn for ÎŁc0, ÎŁc++ and ÎŁc0,++"}; + Configurable selectionFlagLcToK0sP{"selectionFlagLcToK0sP", 1, "Selection Flag for Lc"}; + Configurable selectionFlagLcbarToK0sP{"selectionFlagLcbarToK0sP", 1, "Selection Flag for Lcbar"}; + Configurable etaCandMax{"etaCandMax", -1., "max. cand. pseudorapidity"}; + Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_k0s_p::vecBinsPt}, "pT bin limits"}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {16, 0, 16}, ""}; + ConfigurableAxis thnConfigAxisDecLength{"thnConfigAxisDecLength", {10, 0, 0.05}, ""}; + ConfigurableAxis thnConfigAxisDecLengthXY{"thnConfigAxisDecLengthXY", {10, 0, 0.05}, ""}; + ConfigurableAxis thnConfigAxisCPA{"thnConfigAxisCPA", {20, 0.8, 1}, ""}; + ConfigurableAxis thnConfigAxisCPAXY{"thnConfigAxisCPAXY", {20, 0.8, 1}, ""}; + ConfigurableAxis configAxisMassLambdaC{"configAxisMassLambdaC", {600, 1.98, 2.58}, ""}; + ConfigurableAxis configAxisDeltaMassSigmaC{"configAxisDeltaMassSigmaC", {200, 0.13, 0.23}, ""}; + Configurable nSigmaSoftPi{"pionNSigma", 3., "NSigma TPC selection"}; + ConfigurableAxis configAxisChargeSigmaC{"configAxisChargeSigmaC", {3, 0, 3}, "charge of SigmaC"}; + + /// Filter the candidate Λc+ used for the ÎŁc0,++ creation + Filter filterSelectCandidateLc = (aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcToK0sP || + aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcbarToK0sP); + + using RecoLc = soa::Filtered>; + + HistogramRegistry registry{"registry"}; + HfHelper hfHelper; + + void init(InitContext&) + { + // axes + AxisSpec axisBinsPt = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisPt = {300, 0.0f, 30.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta = {500, -2.0f, 2.0f, "#it{#eta}"}; + AxisSpec axisY = {500, -2.0f, 2.0f, "y"}; + AxisSpec axisPhi = {100, 0.f, 6.3f, "#it{#phi}"}; + AxisSpec axisMassCand = {600, 1.98f, 2.58f, "inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2})"}; + AxisSpec axisd0 = {500, -0.5f, 0.5f, "DCAxy (cm)"}; + AxisSpec axisd0V0Daughters = {1000, -5.0f, 5.0f, "DCAxy (cm)"}; + AxisSpec axisV0CPA = {500, 0.98f, 1.0001f, "v0 cos pointing angle"}; + AxisSpec axisV0Radius = {1000, 0.f, 40.f, "V0 radius (cm)"}; + AxisSpec axisV0DCADaughters = {200, 0.f, 2.f, "DCA (cm)"}; + AxisSpec axisMassK0Short = {500, 0.4f, 0.6f, "#it{m}(K_{S}^{0}) (GeV/#it{c}^{2})"}; + AxisSpec axisMassLambda = {500, 1.0f, 1.2f, "#it{m}(#Lambda) (GeV/#it{c}^{2})"}; + AxisSpec axisMassGamma = {500, 0.0f, 0.4f, "#it{m}(#gamma) (GeV/#it{c}^{2})"}; + AxisSpec axisCPACand = {110, -1.1f, 1.1f, "candiate cos pointing angle"}; + AxisSpec axisDecLength = {200, 0.f, 2.0f, "decay length (cm)"}; + AxisSpec axisProperLifetime = {100, 0.f, 0.2f, "#it{c#tau} (cm)"}; + AxisSpec axisProperLifetimeV0 = {1000, 0.f, 80.f, "#it{c#tau} (cm)"}; + AxisSpec axisNSigma = {100, -6.f, 6.f, "n#it{#sigma}_{p}"}; + AxisSpec axisPidP = {100, 0.f, 10.0f, "#it{p} (GeV/#it{c})"}; + const AxisSpec axisDeltaMassSigmaC{configAxisDeltaMassSigmaC, "#it{M}(pK_{S}^{0}#pi) - #it{M}(pK_{S}^{0}) (GeV/#it{c}^{2})"}; + + // data + //////////////////////////////////////////////////////////////////////////// + /// Declare histograms related to Sigma_C analysis from LcToK0sP channel/// + /////////////////////////////////////////////////////////////////////////// + + registry.add("Data/hDeltaMassSc0", "#Sigma_{c}^{0} candidates; #it{M}(K0sP #pi) - #it{M}(K0sP) (GeV/#it{c}^{2}); counts;", {HistType::kTH1D, {{200, 0.13, 0.23}}}); /// ÎŁc0 + registry.add("Data/hDeltaMassScPlusPlus", "#Sigma_{c}^{++} candidates; #it{M}(K0sP#pi) - #it{M}(K0sP) (GeV/#it{c}^{2}); counts;", {HistType::kTH1D, {{200, 0.13, 0.23}}}); /// ÎŁc++ + registry.add("Data/hDeltaMassSc0PlusPlus", "#Sigma_{c}^{0, ++} candidates; #it{M}(K0sP#pi) - #it{M}(K0sP) (GeV/#it{c}^{2}); counts;", {HistType::kTH1D, {{200, 0.13, 0.23}}}); /// ÎŁc0,++ + registry.add("Data/hDeltaMassSc0VsPt", "#Sigma_{c}^{0} candidates; #it{M}(K0sP #pi) - #it{M}(K0sP) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{0}) (GeV/#it{c});", {HistType::kTH2D, {{200, 0.13, 0.23}, {36, 0., 36.}}}); /// ÎŁc0 + registry.add("Data/hDeltaMassScPlusPlusVsPt", "#Sigma_{c}^{++} candidates; #it{M}(K0sP #pi) - #it{M}(K0sP) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{++}) (GeV/#it{c});", {HistType::kTH2D, {{200, 0.13, 0.23}, {36, 0., 36.}}}); /// ÎŁc++ + registry.add("Data/hDeltaMassSc0PlusPlusVsPt", "#Sigma_{c}^{0, ++} candidates; #it{M}(K0sP #pi) - #it{M}(K0sP) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{++}) (GeV/#it{c});", {HistType::kTH2D, {{200, 0.13, 0.23}, {36, 0., 36.}}}); /// ÎŁc0, ++ + registry.add("Data/hEtaSc0", "#Sigma_{c}^{0} candidates; #eta ; counts;", {HistType::kTH1D, {axisEta}}); /// ÎŁc0 + registry.add("Data/hEtaScPlusPlus", "#Sigma_{c}^{++} candidates; #eta ; counts;", {HistType::kTH1D, {axisEta}}); /// ÎŁc++ + registry.add("Data/hEtaSc0PlusPlus", "#Sigma_{c}^{0, ++} candidates; #eta ; counts;", {HistType::kTH1D, {axisEta}}); /// ÎŁc0,++ + registry.add("Data/hEtaSc0PlusPlusVsPt", "#Sigma_{c}^{0, ++} candidates; #eta; #it{p}_{T}(#Sigma_{c}^{0}) (GeV/#it{c});", {HistType::kTH2D, {axisEta, axisPt}}); /// ÎŁc0,++ + registry.add("Data/hYSc0PlusPlusVsPt", "#Sigma_{c}^{0, ++} candidates; y (rapidity); #it{p}_{T}(#Sigma_{c}^{0}) (GeV/#it{c});", {HistType::kTH2D, {axisY, axisPt}}); /// ÎŁc0,++ + registry.add("Data/hPhiSc0", "#Sigma_{c}^{0} candidates; #Phi ; counts;", {HistType::kTH1D, {axisPhi}}); /// ÎŁc0 + registry.add("Data/hPhiScPlusPlus", "#Sigma_{c}^{++} candidates; #Phi ; counts;", {HistType::kTH1D, {axisPhi}}); /// ÎŁc++ + registry.add("Data/hPhiSc0PlusPlus", "#Sigma_{c}^{0, ++} candidates; #Phi ; counts;", {HistType::kTH1D, {axisPhi}}); /// ÎŁc0,++ + + /// softPions + registry.add("Data/hPtSoftPiSc0", "#pi^{-} #leftarrow #Sigma_{c}^{0} candidates; #it{p}_{T}(#pi^{-} #leftarrow #Sigma_{c}^{0}) (GeV/#it{c}); counts;", {HistType::kTH1D, {axisPt}}); /// ÎŁc0 + registry.add("Data/hPtSoftPiScPlusPlus", "#pi^{+} #leftarrow #Sigma_{c}^{++} candidates; #it{p}_{T}(#pi^{+} #leftarrow #Sigma_{c}^{0}) (GeV/#it{c}); counts;", {HistType::kTH1D, {axisPt}}); /// ÎŁc++ + registry.add("Data/hPtSoftPiSc0PlusPlus", "#pi^{#pm} #leftarrow #Sigma_{c}^{0, ++} candidates; #it{p}_{T}(#pi^{#pm} #leftarrow #Sigma_{c}^{0}) (GeV/#it{c}); counts;", {HistType::kTH1D, {axisPt}}); /// ÎŁc0,++ + registry.add("Data/hEtaSoftPiSc0", "#pi^{-} #leftarrow #Sigma_{c}^{0} candidates; #eta ; counts;", {HistType::kTH1D, {axisEta}}); /// ÎŁc0 + registry.add("Data/hEtaSoftPiScPlusPlus", "#pi^{+} #leftarrow #Sigma_{c}^{++} candidates; #eta ; counts;", {HistType::kTH1D, {axisEta}}); /// ÎŁc++ + registry.add("Data/hEtaSoftPiSc0PlusPlus", "#pi^{#pm} #leftarrow #Sigma_{c}^{0, ++} candidates; #eta ; counts;", {HistType::kTH1D, {axisEta}}); /// ÎŁc0,++ + registry.add("Data/hPhiSoftPiSc0", "#pi^{-} #leftarrow #Sigma_{c}^{0} candidates; #Phi ; counts;", {HistType::kTH1D, {axisPhi}}); /// ÎŁc0 + registry.add("Data/hPhiSoftPiScPlusPlus", "#pi^{+} #leftarrow #Sigma_{c}^{++} candidates; #Phi ; counts;", {HistType::kTH1D, {axisPhi}}); /// ÎŁc++ + registry.add("Data/hPhiSoftPiSc0PlusPlus", "#pi^{#pm} #leftarrow #Sigma_{c}^{0, ++} candidates; #Phi ; counts;", {HistType::kTH1D, {axisPhi}}); /// ÎŁc0,++ + + /// THn for candidate Λc+ and ÎŁc0,++ cut variation + if (enableTHn) { + const AxisSpec thnAxisChargeSigmaC{configAxisChargeSigmaC, "charge of SigmaC"}; + const AxisSpec thnAxisMassLambdaC{configAxisMassLambdaC, "inv. mass (K0s p) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPtLambdaC{thnConfigAxisPt, "#it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})"}; + const AxisSpec thnAxisPtSigmaC{thnConfigAxisPt, "#it{p}_{T}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; + const AxisSpec thnAxisDecLength{thnConfigAxisDecLength, "decay length #Lambda_{c}^{+} (cm)"}; + const AxisSpec thnAxisDecLengthXY{thnConfigAxisDecLengthXY, "decay length XY #Lambda_{c}^{+} (cm)"}; + const AxisSpec thnAxisCPA{thnConfigAxisCPA, "cosine of pointing angle #Lambda_{c}^{+}"}; + const AxisSpec thnAxisCPAXY{thnConfigAxisCPAXY, "cosine of pointing angle XY #Lambda_{c}^{+}"}; + registry.add("hnSigmaC0PlusPlus", "THn for Sigmac from Cascade channel", HistType::kTHnSparseF, {thnAxisChargeSigmaC, thnAxisMassLambdaC, thnAxisPtLambdaC, axisDeltaMassSigmaC, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisCPAXY, thnAxisPtSigmaC}); + } + } + + void processSigmacToLcPi(aod::HfCandScCascades const& candScs, + RecoLc const&, + aod::Tracks const&) + { + for (const auto& candSc : candScs) { + const auto& candidateLc = candSc.prongLc_as(); + float massSc(-1.), massLc(-1.), deltaMass(-1.); + float ptSc(candSc.pt()), ptLc(candidateLc.pt()); + float etaSc(candSc.eta()) /*, etaLc(candidateLc.eta())*/; + float phiSc(candSc.phi()) /*, phiLc(candidateLc.phi())*/; + float ptSoftPi(candSc.prong1().pt()), etaSoftPi(candSc.prong1().eta()), phiSoftPi(candSc.prong1().phi()); + double decLengthLc(candidateLc.decayLength()), decLengthXYLc(candidateLc.decayLengthXY()); + float cpaLc(candidateLc.cpa()), cpaXYLc(candidateLc.cpaXY()); + float y(-1.); + + massLc = hfHelper.invMassLcToK0sP(candidateLc); + massSc = hfHelper.invMassScRecoLcToK0sP(candSc, candidateLc); + deltaMass = massSc - massLc; + if (candSc.charge() == 0) { + y = hfHelper.ySc0(candSc); + } else if (candSc.charge() == 2) { + y = hfHelper.yScPlusPlus(candSc); + } + registry.fill(HIST("Data/hDeltaMassSc0PlusPlus"), deltaMass); /// ÎŁc(0,++) for both charges + registry.fill(HIST("Data/hDeltaMassSc0PlusPlusVsPt"), deltaMass, ptSc); /// ÎŁc(0,++) for both charges + registry.fill(HIST("Data/hEtaSc0PlusPlus"), etaSc); /// ÎŁc(0,++) for both charges + registry.fill(HIST("Data/hEtaSc0PlusPlusVsPt"), etaSc, ptSc); /// ÎŁc(0,++) for both charges + registry.fill(HIST("Data/hYSc0PlusPlusVsPt"), y, ptSc); /// ÎŁc(0,++) for both charges + registry.fill(HIST("Data/hPhiSc0PlusPlus"), phiSc); /// ÎŁc(0,++) for both charges + + /// fill histograms for softpion from ÎŁc(0,++) + registry.fill(HIST("Data/hPtSoftPiSc0PlusPlus"), ptSoftPi); + registry.fill(HIST("Data/hEtaSoftPiSc0PlusPlus"), etaSoftPi); + registry.fill(HIST("Data/hPhiSoftPiSc0PlusPlus"), phiSoftPi); // π ← ÎŁc0,++ + + if (candSc.charge() == 0) { + registry.fill(HIST("Data/hDeltaMassSc0"), deltaMass); /// ÎŁc0 + registry.fill(HIST("Data/hDeltaMassSc0VsPt"), deltaMass, ptSc); /// ÎŁc0 + registry.fill(HIST("Data/hEtaSc0"), etaSc); /// ÎŁc0 + registry.fill(HIST("Data/hPhiSc0"), phiSc); /// ÎŁc0 + + /// fill histograms for softpion + registry.fill(HIST("Data/hPtSoftPiSc0"), ptSoftPi); + registry.fill(HIST("Data/hEtaSoftPiSc0"), etaSoftPi); + registry.fill(HIST("Data/hPhiSoftPiSc0"), phiSoftPi); // π ← ÎŁc0 + + if (enableTHn) { + registry.get(HIST("hnSigmaC0PlusPlus"))->Fill(candSc.charge(), massLc, ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, ptSc); + } + /// ÎŁc0 + } else if (candSc.charge() == 2) { + registry.fill(HIST("Data/hDeltaMassScPlusPlus"), deltaMass); /// ÎŁc++ + registry.fill(HIST("Data/hDeltaMassScPlusPlusVsPt"), deltaMass, ptSc); /// ÎŁc++ + registry.fill(HIST("Data/hEtaScPlusPlus"), etaSc); /// ÎŁc++ + registry.fill(HIST("Data/hPhiScPlusPlus"), phiSc); /// ÎŁc++ + + /// fill histograms for softpion + registry.fill(HIST("Data/hPtSoftPiScPlusPlus"), ptSoftPi); + registry.fill(HIST("Data/hEtaSoftPiScPlusPlus"), etaSoftPi); + registry.fill(HIST("Data/hPhiSoftPiScPlusPlus"), phiSoftPi); // π ← ÎŁc++ + + if (enableTHn) { + registry.get(HIST("hnSigmaC0PlusPlus"))->Fill(candSc.charge(), massLc, ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, ptSc); + } + } + } + } + PROCESS_SWITCH(HfTaskSigmacToCascade, processSigmacToLcPi, "Process Data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index fa337ff6265..df164fb9a77 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -56,6 +56,7 @@ struct HfTaskXic { ConfigurableAxis thnConfigAxisCPA{"thnConfigAxisCPA", {20, 0.8, 1}, ""}; ConfigurableAxis thnConfigAxisBdtScoreBkg{"thnConfigAxisBdtScoreBkg", {100, 0., 1.}, ""}; ConfigurableAxis thnConfigAxisBdtScoreSignal{"thnConfigAxisBdtScoreSignal", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisYMC{"thnConfigAxisYMC", {100, -2., 2.}, ""}; // Service pdg; HfHelper hfHelper; @@ -86,7 +87,6 @@ struct HfTaskXic { {"MC/generated/hEtaGen", "MC particles; #it{eta}^{gen} ;#it{p}_{T}^{gen.};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"MC/generated/hYGen", "MC particles; #it{y}^{gen} ;#it{p}_{T}^{gen.} ;entries", {HistType::kTH1F, {{100, -2., 2.}}}}, // add generated in acceptance!! - }}; void init(InitContext&) @@ -198,6 +198,8 @@ struct HfTaskXic { if (enableTHn) { const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T}(#Xi_{c}^{+}) (GeV/#it{c})"}; + const AxisSpec thnAxisPtMC{thnConfigAxisPt, "#it{p}_{T}(#Xi_{c}^{+} MC) (GeV/#it{c})"}; + const AxisSpec thnAxisYMC{thnConfigAxisYMC, "#it{y}_{MC}(#Xi_{c}^{+} MC)"}; const AxisSpec thnAxisChi2PCA{thnConfigAxisChi2PCA, "Chi2PCA to sec. vertex (cm)"}; const AxisSpec thnAxisDecLength{thnConfigAxisDecLength, "decay length (cm)"}; const AxisSpec thnAxisDecLengthXY{thnConfigAxisDecLengthXY, "decay length (cm)"}; @@ -206,11 +208,12 @@ struct HfTaskXic { const AxisSpec thnAxisBdtScoreXicPrompt{thnConfigAxisBdtScoreSignal, "BDT prompt score (Xic)"}; const AxisSpec thnAxisBdtScoreXicNonPrompt{thnConfigAxisBdtScoreSignal, "BDT non-prompt score (Xic)"}; const AxisSpec thnAxisMcOrigin{3, -0.5, 2.5, "MC origin"}; + const AxisSpec thnAxisMCAllProngAccepted{2, -0.5, 1.5, "All MC prongs accepted"}; if (doprocessDataWithMl || doprocessMcWithMl) { // with ML - registry.add("hnXicVarsWithBdt", "THn for Xic candidates with BDT scores", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisBdtScoreXicBkg, thnAxisBdtScoreXicPrompt, thnAxisBdtScoreXicNonPrompt, thnAxisMcOrigin}); + registry.add("hnXicVarsWithBdt", "THn for Xic candidates with BDT scores", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisBdtScoreXicBkg, thnAxisBdtScoreXicPrompt, thnAxisBdtScoreXicNonPrompt, thnAxisMcOrigin, thnAxisPtMC, thnAxisYMC, thnAxisMCAllProngAccepted}); } else { - registry.add("hnXicVars", "THn for Xic candidates", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisChi2PCA, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisMcOrigin}); + registry.add("hnXicVars", "THn for Xic candidates", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisChi2PCA, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisMcOrigin, thnAxisPtMC, thnAxisYMC, thnAxisMCAllProngAccepted}); } } } // end init @@ -334,9 +337,9 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPKPi()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate Xic - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0, 0.0, 0.0, false); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0); + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0, 0.0, 0.0, false); } } if (candidate.isSelXicToPiKP() >= selectionFlagXic) { @@ -348,9 +351,9 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPiKP()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0, 0.0, 0.0, false); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0); + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0, 0.0, 0.0, false); } } } // thn for Xic @@ -403,6 +406,9 @@ struct HfTaskXic { // Get the corresponding MC particle. auto mcParticleProng0 = candidate.template prong0_as().template mcParticle_as>(); auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); + auto yProng0 = RecoDecay::y(mcParticleProng0.pVector(), o2::constants::physics::MassXiCPlus); + std::array ptProngs; + std::array etaProngs; // Signal registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), ptCandidate); // rec. level pT @@ -434,8 +440,16 @@ struct HfTaskXic { if (enableTHn) { double massXic(-1); double outputBkg(-1), outputPrompt(-1), outputFD(-1); + bool allProngsInAcceptance = false; if ((candidate.isSelXicToPKPi() >= selectionFlagXic) && pdgCodeProng0 == kProton) { massXic = hfHelper.invMassXicToPKPi(candidate); + int counter = 0; + for (const auto& daught : mcParticleProng0.template daughters_as>()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + counter++; + } + allProngsInAcceptance = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]) && isProngInAcceptance(etaProngs[2], ptProngs[2]); if constexpr (useMl) { if (candidate.mlProbXicToPKPi().size() == 3) { outputBkg = candidate.mlProbXicToPKPi()[0]; /// bkg score @@ -443,13 +457,20 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPKPi()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec()); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec()); + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); } } if ((candidate.isSelXicToPiKP() >= selectionFlagXic) && pdgCodeProng0 == kPiPlus) { massXic = hfHelper.invMassXicToPiKP(candidate); + int counter = 0; + for (const auto& daught : mcParticleProng0.template daughters_as>()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + counter++; + } + allProngsInAcceptance = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]) && isProngInAcceptance(etaProngs[2], ptProngs[2]); if constexpr (useMl) { if (candidate.mlProbXicToPiKP().size() == 3) { outputBkg = candidate.mlProbXicToPiKP()[0]; /// bkg score @@ -457,9 +478,10 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPiKP()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec()); + // add here the pT_Mother, y_Mother, level (reco, Gen, Gen + Acc) + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec()); + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); } } } // enable THn @@ -512,7 +534,6 @@ struct HfTaskXic { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - registry.fill(HIST("MC/generated/hPtGen"), ptParticle); registry.fill(HIST("MC/generated/hEtaGen"), particle.eta(), ptParticle); registry.fill(HIST("MC/generated/hYGen"), yParticle, ptParticle); @@ -526,7 +547,6 @@ struct HfTaskXic { } } } - void processMcStd(soa::Filtered> const& selectedCandidatesMc, soa::Join const& mcParticles, aod::TracksWMc const& tracksWithMc) diff --git a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx new file mode 100644 index 00000000000..a5a14c734cc --- /dev/null +++ b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx @@ -0,0 +1,510 @@ +// Copyright 2019-2020 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. + +/// \file taskXicToXiPiPi.cxx +/// \brief Ξc± → (Ξ∓ → (Λ → p π∓) π∓) π± π± analysis task +/// \note adapted from taskBs.cxx +/// +/// \author Phil Lennart Stahlhut , Heidelberg University +/// \author Carolina Reetz , Heidelberg University + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// Xic analysis task +struct HfTaskXicToXiPiPi { + Configurable selectionFlagXic{"selectionFlagXic", 1, "Selection Flag for Xic"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_xi_pi_pi::vecBinsPt}, "pT bin limits"}; + // MC checks + Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "Flag to enable DecayType histogram"}; + + // Axis + ConfigurableAxis binsDecLength{"binsDecLength", {200, 0., 0.5}, ""}; + ConfigurableAxis binsErrDecLength{"binsErrDecLength", {100, 0., 1.}, ""}; + ConfigurableAxis binsDCA{"binsDCA", {100, -0.05, 0.05}, ""}; + ConfigurableAxis binsImpParErr{"binsImpParErr", {200, -0.1, 0.1}, ""}; + ConfigurableAxis binsSV{"binsSV", {200, -5., 5.}, ""}; + ConfigurableAxis binsChi2{"binsChi2", {200, 0., 0.1}, ""}; + + Service pdg; + + Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic); + + HistogramRegistry registry{ + "registry", + {{"hPtCand", "#Xi^{#plus}_{c} candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{400, 0., 40.}}}}, + {"hPtProng0", "#Xi^{#plus}_{c} candidates;prong 0 (#Xi^{#minus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}}, + {"hPtProng1", "#Xi^{#plus}_{c} candidates;prong 1 (#pi^{#plus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 20.}}}}, + {"hPtProng2", "#Xi^{#plus}_{c} candidates;prong 2 (#pi^{#plus}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 20.}}}}}}; + + void init(InitContext const&) + { + if (!doprocessWithKFParticle && !doprocessWithDCAFitter && !doprocessMcWithKFParticle && !doprocessMcWithDCAFitter) { + LOGF(fatal, "No process function enabled. Please enable one."); + } + if (doprocessWithKFParticle && doprocessWithDCAFitter) { + LOGF(fatal, "Cannot enable doprocessWithKFParticle and doprocessWithDCAFitter at the same time. Please choose one."); + } + if (doprocessMcWithKFParticle && doprocessMcWithDCAFitter) { + LOGF(fatal, "Cannot enable doprocessMcWithKFParticle and doprocessMcWithDCAFitter at the same time. Please choose one."); + } + if (doprocessWithKFParticle && doprocessMcWithDCAFitter) { + LOGF(fatal, "Cannot enable doprocessWithKFParticle and doprocessMcWithDCAFitter at the same time. Please choose one."); + } + if (doprocessWithDCAFitter && doprocessMcWithKFParticle) { + LOGF(fatal, "Cannot enable doprocessWithDCAFitter and doprocessMcWithKFParticle at the same time. Please choose one."); + } + + static const AxisSpec axisMassXic = {300, 1.8, 3.0, "inv. mass (GeV/#it{c}^{2})"}; + static const AxisSpec axisMassXiRes = {300, 1.0, 2.0, "inv. mass (GeV/#it{c}^{2})"}; + static const AxisSpec axisPt = {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}; + static const AxisSpec axisDecLength = {binsDecLength}; + static const AxisSpec axisErrDecLength = {binsErrDecLength}; + static const AxisSpec axisDCA = {binsDCA}; + static const AxisSpec axisImpParErr = {binsImpParErr}; + static const AxisSpec axisSV = {binsSV}; + static const AxisSpec axisChi2 = {binsChi2}; + + // candidate + registry.add("hPt", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 20.}}}); + registry.add("hEta", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hRapidity", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hCPA", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxy", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hMass", "#Xi^{#plus}_{c} candidates;inv. mass #Xi^{#mp} #pi^{#pm} #pi^{#pm} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisMassXic, axisPt}}); + registry.add("hDecLength", "#Xi^{#plus}_{c} candidates;decay length (cm);entries", {HistType::kTH2F, {axisDecLength, axisPt}}); + registry.add("hErrDecLength", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate decay length error (cm);entries", {HistType::kTH2F, {axisErrDecLength, axisPt}}); + registry.add("hDecLengthXY", "#Xi^{#plus}_{c} candidates;decay length xy (cm);entries", {HistType::kTH2F, {axisDecLength, axisPt}}); + registry.add("hErrDecLengthXY", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate decay length xy error (cm);entries", {HistType::kTH2F, {axisErrDecLength, axisPt}}); + registry.add("hSVx", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate secondary vertex position x (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVy", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate secondary vertex position y (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVz", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate secondary vertex position z (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + // daughters + registry.add("hCPAXi", "#Xi^{#plus}_{c} candidates;#Xi^{#minus} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyXi", "#Xi^{#plus}_{c} candidates;#Xi^{#minus} candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPALambda", "#Xi^{#plus}_{c} candidates;#Lambda candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyLambda", "#Xi^{#plus}_{c} candidates;#Lambda candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hPtProng0vsPt", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng1vsPt", "#Xi^{#plus}_{c} candidates;prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng2vsPt", "#Xi^{#plus}_{c} candidates;prong 2 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hd0Prong0", "#Xi^{#plus}_{c} candidates;prong 0 (#Xi^{#mp}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong1", "#Xi^{#plus}_{c} candidates;prong 1 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong2", "#Xi^{#plus}_{c} candidates;prong 2 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hImpParErr", "#Xi^{#plus}_{c} candidates;prongs impact parameter error (cm);entries", {HistType::kTH2F, {axisImpParErr, axisPt}}); + registry.add("hChi2PCA", "#Xi^{#plus}_{c} candidates (matched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.5}, axisPt}}); + registry.add("hMassXiPi1", "#Xi^{#plus}_{c} candidates;inv. mass #Xi^{#mp} #pi^{#pm} (prong 1) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisMassXiRes, axisPt}}); + registry.add("hMassXiPi2", "#Xi^{#plus}_{c} candidates;inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisMassXiRes, axisPt}}); + + if (doprocessWithKFParticle) { + registry.add("hChi2geoXi", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2geoLam", "#Xi^{#plus}_{c} candidates;#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2topoToPV", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2topoXiToXicPlus", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + } + + if (doprocessMcWithKFParticle || doprocessMcWithDCAFitter) { + // MC reconstructed + registry.add("hPtGenSig", "#Xi^{#plus}_{c} candidates (gen+rec);candidate #it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtRecSig", "#Xi^{#plus}_{c} candidates (matched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtRecBg", "#Xi^{#plus}_{c} candidates (unmatched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtProng0RecSig", "#Xi^{#plus}_{c} candidates (matched);prong 0 (#Xi^{#mp}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtProng0RecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 0 (#Xi^{#mp}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtProng1RecSig", "#Xi^{#plus}_{c} candidates (matched);prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 20.}}}); + registry.add("hPtProng1RecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 20.}}}); + registry.add("hPtProng2RecSig", "#Xi^{#plus}_{c} candidates (matched);prong 2 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 20.}}}); + registry.add("hPtProng2RecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 2 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 20.}}}); + registry.add("hPtProng0vsPtRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng0vsPtRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng1vsPtRecSig", "#Xi^{#plus}_{c} candidates (matched);prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng1vsPtRecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng2vsPtRecSig", "#Xi^{#plus}_{c} candidates (matched);prong 2 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng2vsPtRecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 2 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hEtaRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hEtaRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hRapidityRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hRapidityRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hSVxRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate secondary vertex position x (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVxRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate secondary vertex position x (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVyRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate secondary vertex position y (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVyRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate secondary vertex position y (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVzRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate secondary vertex position z (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVzRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate secondary vertex position z (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hCPARecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{220, -1.1, 1.1}, axisPt}}); + registry.add("hCPARecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{220, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate CPAxy;entries", {HistType::kTH2F, {{220, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate CPAxy;entries", {HistType::kTH2F, {{220, -1.1, 1.1}, axisPt}}); + registry.add("hMassRecSig", "#Xi^{#plus}_{c} candidates (matched);inv. mass #Xi^{#mp} #pi^{#pm} #pi^{#pm} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.8, 3.0}, axisPt}}); + registry.add("hMassRecBg", "#Xi^{#plus}_{c} candidates (unmatched);inv. mass #Xi^{#mp} #pi^{#pm} #pi^{#pm} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.8, 3.0}, axisPt}}); + registry.add("hDecLengthRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate decay length (cm);entries", {HistType::kTH2F, {axisDecLength, axisPt}}); + registry.add("hDecLengthRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate decay length (cm);entries", {HistType::kTH2F, {axisDecLength, axisPt}}); + registry.add("hErrDecLengthRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate decay length (cm);entries", {HistType::kTH2F, {axisErrDecLength, axisPt}}); + registry.add("hErrDecLengthRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate decay length (cm);entries", {HistType::kTH2F, {axisErrDecLength, axisPt}}); + registry.add("hDecLengthXYRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate decay length xy (cm);entries", {HistType::kTH2F, {axisDecLength, axisPt}}); + registry.add("hDecLengthXYRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate decay length xy(cm);entries", {HistType::kTH2F, {axisDecLength, axisPt}}); + registry.add("hErrDecLengthXYRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate decay length xy (cm);entries", {HistType::kTH2F, {axisErrDecLength, axisPt}}); + registry.add("hErrDecLengthXYRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate decay length xy(cm);entries", {HistType::kTH2F, {axisErrDecLength, axisPt}}); + registry.add("hd0Prong0RecSig", "#Xi^{#plus}_{c} candidates (matched);prong 0 (#Xi^{#mp}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong0RecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 0 (#Xi^{#mp}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong1RecSig", "#Xi^{#plus}_{c} candidates (matched);prong 1 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong1RecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 1 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong2RecSig", "#Xi^{#plus}_{c} candidates (matched);prong 2 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hd0Prong2RecBg", "#Xi^{#plus}_{c} candidates (unmatched);prong 2 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisDCA, axisPt}}); + registry.add("hImpParErrRecSig", "#Xi^{#plus}_{c} candidates (matched);prongs impact parameter error (cm);entries", {HistType::kTH2F, {axisImpParErr, axisPt}}); + registry.add("hImpParErrRecBg", "#Xi^{#plus}_{c} candidates (unmatched);prongs impact parameter error (cm);entries", {HistType::kTH2F, {axisImpParErr, axisPt}}); + registry.add("hChi2PCARecSig", "#Xi^{#plus}_{c} candidates (matched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.1}, axisPt}}); + registry.add("hChi2PCARecBg", "#Xi^{#plus}_{c} candidates (unmatched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.1}, axisPt}}); + registry.add("hCPAXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#minus} cosine of pointing angle;entries", {HistType::kTH2F, {{220, -1.1, 1.1}, axisPt}}); + registry.add("hCPAXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#minus} cosine of pointing angle;entries", {HistType::kTH2F, {{220, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#minus} candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#minus} candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPALambdaRecSig", "#Xi^{#plus}_{c} candidates (matched);#Lambda candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPALambdaRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Lambda candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyLambdaRecSig", "#Xi^{#plus}_{c} candidates (matched);#Lambda candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hCPAxyLambdaRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Lambda candidate cosine of pointing angle xy;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hMassXiPi1RecSig", "#Xi^{#plus}_{c} candidates (matched);inv. mass #Xi^{#mp} #pi^{#pm} (prong 1) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.0, 2.0}, axisPt}}); + registry.add("hMassXiPi1RecBg", "#Xi^{#plus}_{c} candidates (unmatched);inv. mass #Xi^{#mp} #pi^{#pm} (prong 1) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.0, 2.0}, axisPt}}); + registry.add("hMassXiPi2RecSig", "#Xi^{#plus}_{c} candidates (matched);inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.0, 2.0}, axisPt}}); + registry.add("hMassXiPi2RecBg", "#Xi^{#plus}_{c} candidates (unmatched);inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.0, 2.0}, axisPt}}); + + if (doprocessMcWithKFParticle) { + registry.add("hChi2topoToPVRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2topoToPVRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2geoXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2geoXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2geoLamRecSig", "#Xi^{#plus}_{c} candidates (matched);#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2geoLamRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2topoXiToXicPlusRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2topoXiToXicPlusRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + } + + // MC generated + registry.add("hPtProng0Gen", "MC particles (generated);prong 0 (#Xi^{#mp}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{300, 0., 30.}, axisPt}}); + registry.add("hPtProng1Gen", "MC particles (generated);prong 1 (#pi^{#pm}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hPtProng2Gen", "MC particles (generated);prong 2 (#pi^{#pm}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{200, 0., 20.}, axisPt}}); + registry.add("hEtaProng0Gen", "MC particles (generated);prong 0 (#Xi^{#mp}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hEtaProng1Gen", "MC particles (generated);prong 1 (#pi^{#pm}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hEtaProng2Gen", "MC particles (generated);prong 2 (#pi^{#pm}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hYProng0Gen", "MC particles (generated);prong 0 (#Xi^{#mp}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hYProng1Gen", "MC particles (generated);prong 1 (#pi^{#pm}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hYProng2Gen", "MC particles (generated);prong 2 (#pi^{#pm}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hPtGen", "MC particles (generated);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaGen", "MC particles (generated);#Xi^{#plus}_{c} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hYGen", "MC particles (generated);#Xi^{#plus}_{c} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hSVxGen", "#Xi^{#plus}_{c} candidates (generated);#Xi^{#plus}_{c} candidate secondary vertex position x (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVyGen", "#Xi^{#plus}_{c} candidates (generated);#Xi^{#plus}_{c} candidate secondary vertex position y (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hSVzGen", "#Xi^{#plus}_{c} candidates (generated);#Xi^{#plus}_{c} candidate secondary vertex position z (cm);entries", {HistType::kTH2F, {axisSV, axisPt}}); + registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);#Xi^{#plus}_{c} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);#Xi^{#plus}_{c} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + } + + if (checkDecayTypeMc) { + constexpr uint8_t kNBinsDecayTypeMc = hf_cand_xic_to_xi_pi_pi::DecayType::NDecayType + 1; + TString labels[kNBinsDecayTypeMc]; + labels[hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi] = "#Xi^{+}_{c} #rightarrow #Xi^{#minus} #pi^{#plus}) #pi^{#plus}"; + labels[hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi] = "#Xi^{+}_{c} #rightarrow #Xi(1530)^{0} #pi^{#plus} #rightarrow #Xi^{#minus} #pi^{#plus}) #pi^{#plus}"; + labels[hf_cand_xic_to_xi_pi_pi::DecayType::NDecayType] = "Other decays"; + static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; + registry.add("hDecayTypeMc", "DecayType", {HistType::kTH3F, {axisDecayType, axisMassXic, axisPt}}); + for (uint8_t iBin = 0; iBin < kNBinsDecayTypeMc; ++iBin) { + registry.get(HIST("hDecayTypeMc"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin]); + } + } + } + + /// Selection of Xic daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of Xic prong + /// \param ptProng is the pT of Xic prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Function to fill histograms + template + void fillHistograms(TCanTable const& candidates) + { + for (const auto& candidate : candidates) { + auto yCandXic = candidate.y(o2::constants::physics::MassXiCPlus); + if (yCandRecoMax >= 0. && std::abs(yCandXic) > yCandRecoMax) { + continue; + } + + auto ptCandXic = candidate.pt(); + + registry.fill(HIST("hPtCand"), ptCandXic); + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("hPtProng2"), candidate.ptProng2()); + registry.fill(HIST("hEta"), candidate.eta(), ptCandXic); + registry.fill(HIST("hRapidity"), yCandXic, ptCandXic); + registry.fill(HIST("hCPA"), candidate.cpa(), ptCandXic); + registry.fill(HIST("hCPAxy"), candidate.cpaXY(), ptCandXic); + registry.fill(HIST("hMass"), candidate.invMassXic(), ptCandXic); + registry.fill(HIST("hDecLength"), candidate.decayLength(), ptCandXic); + registry.fill(HIST("hErrDecLength"), candidate.errorDecayLength(), ptCandXic); + registry.fill(HIST("hDecLengthXY"), candidate.decayLengthXY(), ptCandXic); + registry.fill(HIST("hErrDecLengthXY"), candidate.errorDecayLengthXY(), ptCandXic); + registry.fill(HIST("hSVx"), candidate.xSecondaryVertex(), ptCandXic); + registry.fill(HIST("hSVy"), candidate.ySecondaryVertex(), ptCandXic); + registry.fill(HIST("hSVz"), candidate.zSecondaryVertex(), ptCandXic); + registry.fill(HIST("hPtProng0vsPt"), candidate.ptProng0(), ptCandXic); + registry.fill(HIST("hPtProng1vsPt"), candidate.ptProng1(), ptCandXic); + registry.fill(HIST("hPtProng2vsPt"), candidate.ptProng2(), ptCandXic); + registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), ptCandXic); + registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandXic); + registry.fill(HIST("hd0Prong2"), candidate.impactParameter2(), ptCandXic); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandXic); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandXic); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter2(), ptCandXic); + registry.fill(HIST("hChi2PCA"), candidate.chi2PCA(), ptCandXic); + registry.fill(HIST("hCPAXi"), candidate.cosPaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXi"), candidate.cosPaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambda"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambda"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hMassXiPi1"), candidate.invMassXiPi0(), ptCandXic); + registry.fill(HIST("hMassXiPi2"), candidate.invMassXiPi1(), ptCandXic); + + // fill KFParticle specific histograms + if constexpr (useKfParticle) { + registry.fill(HIST("hChi2topoToPV"), candidate.chi2TopoXicPlusToPV(), ptCandXic); + registry.fill(HIST("hChi2topoXiToXicPlus"), candidate.chi2TopoXiToXicPlus(), ptCandXic); + registry.fill(HIST("hChi2geoXi"), candidate.kfCascadeChi2(), ptCandXic); + registry.fill(HIST("hChi2geoLam"), candidate.kfV0Chi2(), ptCandXic); + } + } // candidate loop + } + + /// Function for MC analysis and histogram filling + template + void fillHistogramsMc(TCandTable const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&) + { + std::vector arrDaughIndex; + + // MC rec + for (const auto& candidate : candidates) { + auto yCandXic = candidate.y(o2::constants::physics::MassXiCPlus); + if (yCandRecoMax >= 0. && std::abs(yCandXic) > yCandRecoMax) { + continue; + } + + auto ptCandXic = candidate.pt(); + int flagMcMatchRecXic = std::abs(candidate.flagMcMatchRec()); + + if (TESTBIT(flagMcMatchRecXic, hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi) || TESTBIT(flagMcMatchRecXic, hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi)) { + auto indexMother = RecoDecay::getMother(mcParticles, candidate.template pi0_as().template mcParticle_as>(), o2::constants::physics::Pdg::kXiCPlus, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); + + registry.fill(HIST("hPtGenSig"), particleMother.pt()); + registry.fill(HIST("hPtRecSig"), ptCandXic); + registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1()); + registry.fill(HIST("hPtProng2RecSig"), candidate.ptProng2()); + registry.fill(HIST("hPtProng0vsPtRecSig"), candidate.ptProng0(), ptCandXic); + registry.fill(HIST("hPtProng1vsPtRecSig"), candidate.ptProng1(), ptCandXic); + registry.fill(HIST("hPtProng2vsPtRecSig"), candidate.ptProng2(), ptCandXic); + registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandXic); + registry.fill(HIST("hRapidityRecSig"), yCandXic, ptCandXic); + registry.fill(HIST("hSVxRecSig"), candidate.xSecondaryVertex(), ptCandXic); + registry.fill(HIST("hSVyRecSig"), candidate.ySecondaryVertex(), ptCandXic); + registry.fill(HIST("hSVzRecSig"), candidate.zSecondaryVertex(), ptCandXic); + registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandXic); + registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandXic); + registry.fill(HIST("hMassRecSig"), candidate.invMassXic(), ptCandXic); + registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandXic); + registry.fill(HIST("hErrDecLengthRecSig"), candidate.errorDecayLength(), ptCandXic); + registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandXic); + registry.fill(HIST("hErrDecLengthXYRecSig"), candidate.errorDecayLengthXY(), ptCandXic); + registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandXic); + registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandXic); + registry.fill(HIST("hd0Prong2RecSig"), candidate.impactParameter2(), ptCandXic); + registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter0(), ptCandXic); + registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter1(), ptCandXic); + registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter2(), ptCandXic); + registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandXic); + registry.fill(HIST("hCPAXiRecSig"), candidate.cosPaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXiRecSig"), candidate.cosPaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambdaRecSig"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambdaRecSig"), candidate.cosPaLambda(), ptCandXic); + + // fill KFParticle specific histograms + if constexpr (useKfParticle) { + registry.fill(HIST("hChi2topoToPVRecSig"), candidate.chi2TopoXicPlusToPV(), ptCandXic); + registry.fill(HIST("hChi2topoXiToXicPlusRecSig"), candidate.chi2TopoXiToXicPlus(), ptCandXic); + registry.fill(HIST("hChi2geoXiRecSig"), candidate.kfCascadeChi2(), ptCandXic); + registry.fill(HIST("hChi2geoLamRecSig"), candidate.kfV0Chi2(), ptCandXic); + } + } else { + registry.fill(HIST("hPtRecBg"), ptCandXic); + registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1()); + registry.fill(HIST("hPtProng2RecBg"), candidate.ptProng2()); + registry.fill(HIST("hPtProng0vsPtRecBg"), candidate.ptProng0(), ptCandXic); + registry.fill(HIST("hPtProng1vsPtRecBg"), candidate.ptProng1(), ptCandXic); + registry.fill(HIST("hPtProng2vsPtRecBg"), candidate.ptProng2(), ptCandXic); + registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandXic); + registry.fill(HIST("hRapidityRecBg"), yCandXic, ptCandXic); + registry.fill(HIST("hSVxRecBg"), candidate.xSecondaryVertex(), ptCandXic); + registry.fill(HIST("hSVyRecBg"), candidate.ySecondaryVertex(), ptCandXic); + registry.fill(HIST("hSVzRecBg"), candidate.zSecondaryVertex(), ptCandXic); + registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandXic); + registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandXic); + registry.fill(HIST("hMassRecBg"), candidate.invMassXic(), ptCandXic); + registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandXic); + registry.fill(HIST("hErrDecLengthRecBg"), candidate.errorDecayLength(), ptCandXic); + registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandXic); + registry.fill(HIST("hErrDecLengthXYRecBg"), candidate.errorDecayLengthXY(), ptCandXic); + registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandXic); + registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandXic); + registry.fill(HIST("hd0Prong2RecBg"), candidate.impactParameter2(), ptCandXic); + registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter0(), ptCandXic); + registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter1(), ptCandXic); + registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter2(), ptCandXic); + registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandXic); + registry.fill(HIST("hCPAXiRecBg"), candidate.cosPaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXiRecBg"), candidate.cosPaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambdaRecBg"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambdaRecBg"), candidate.cosPaLambda(), ptCandXic); + + // fill KFParticle specific histograms + if constexpr (useKfParticle) { + registry.fill(HIST("hChi2topoToPVRecBg"), candidate.chi2TopoXicPlusToPV(), ptCandXic); + registry.fill(HIST("hChi2topoXiToXicPlusRecBg"), candidate.chi2TopoXiToXicPlus(), ptCandXic); + registry.fill(HIST("hChi2geoXiRecBg"), candidate.kfCascadeChi2(), ptCandXic); + registry.fill(HIST("hChi2geoLamRecBg"), candidate.kfV0Chi2(), ptCandXic); + } + } + + if (checkDecayTypeMc) { + if (TESTBIT(flagMcMatchRecXic, hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi)) { + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi, candidate.invMassXic(), ptCandXic); + } else if (TESTBIT(flagMcMatchRecXic, hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi)) { + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi, candidate.invMassXic(), ptCandXic); + } else { + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_xic_to_xi_pi_pi::DecayType::NDecayType, candidate.invMassXic(), ptCandXic); + } + } + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi) || TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi)) { + arrDaughIndex.clear(); + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassXiCPlus); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + + // get kinematic variables of Ξ π π + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + std::array prodVtxXProngs; + std::array prodVtxYProngs; + std::array prodVtxZProngs; + int counter = 0; + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + ptProngs[counter] = daughI.pt(); + etaProngs[counter] = daughI.eta(); + yProngs[counter] = RecoDecay::y(daughI.pVector(), pdg->Mass(daughI.pdgCode())); + prodVtxXProngs[counter] = daughI.vx(); + prodVtxYProngs[counter] = daughI.vy(); + prodVtxZProngs[counter] = daughI.vz(); + counter++; + } + + registry.fill(HIST("hPtProng0Gen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtProng1Gen"), ptProngs[1], ptParticle); + registry.fill(HIST("hPtProng2Gen"), ptProngs[2], ptParticle); + registry.fill(HIST("hEtaProng0Gen"), etaProngs[0], ptParticle); + registry.fill(HIST("hEtaProng1Gen"), etaProngs[1], ptParticle); + registry.fill(HIST("hEtaProng2Gen"), etaProngs[2], ptParticle); + registry.fill(HIST("hYProng0Gen"), yProngs[0], ptParticle); + registry.fill(HIST("hYProng1Gen"), yProngs[1], ptParticle); + registry.fill(HIST("hYProng2Gen"), yProngs[2], ptParticle); + registry.fill(HIST("hPtGen"), ptParticle); + registry.fill(HIST("hYGen"), yParticle, ptParticle); + registry.fill(HIST("hEtaGen"), particle.eta(), ptParticle); + registry.fill(HIST("hSVxGen"), prodVtxXProngs[0], ptParticle); + registry.fill(HIST("hSVyGen"), prodVtxYProngs[0], ptParticle); + registry.fill(HIST("hSVzGen"), prodVtxZProngs[0], ptParticle); + + // reject Xic daughters that are not in geometrical acceptance + if (!isProngInAcceptance(etaProngs[0], ptProngs[0]) || !isProngInAcceptance(etaProngs[1], ptProngs[1]) || !isProngInAcceptance(etaProngs[2], ptProngs[2])) { + continue; + } + registry.fill(HIST("hPtGenWithProngsInAcceptance"), ptParticle); + registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); + registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); + } + } // gen + } + + void processWithDCAFitter(soa::Filtered> const& candidates) + { + fillHistograms(candidates); + } + PROCESS_SWITCH(HfTaskXicToXiPiPi, processWithDCAFitter, "Process data with DCAFitter", true); + + void processWithKFParticle(soa::Filtered> const& candidates) + { + fillHistograms(candidates); + } + PROCESS_SWITCH(HfTaskXicToXiPiPi, processWithKFParticle, "Process data with KFParticle", false); + + /// MC analysis and fill histograms + void processMcWithDCAFitter(soa::Filtered> const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const& tracksWMc) + { + fillHistogramsMc(candidates, mcParticles, tracksWMc); + } + PROCESS_SWITCH(HfTaskXicToXiPiPi, processMcWithDCAFitter, "Process MC with DCAFitter", false); + + /// MC analysis and fill histograms with KFParticle + void processMcWithKFParticle(soa::Filtered> const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const& tracksWMc) + { + fillHistogramsMc(candidates, mcParticles, tracksWMc); + } + PROCESS_SWITCH(HfTaskXicToXiPiPi, processMcWithKFParticle, "Process MC with KFParticle", false); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Utils/utilsRedDataFormat.h b/PWGHF/D2H/Utils/utilsRedDataFormat.h index 64d1931e06b..2d99105e474 100644 --- a/PWGHF/D2H/Utils/utilsRedDataFormat.h +++ b/PWGHF/D2H/Utils/utilsRedDataFormat.h @@ -16,6 +16,8 @@ #ifndef PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ #define PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ +#include "Framework/HistogramRegistry.h" + #include "CCDB/BasicCCDBManager.h" #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Utils/utilsEvSelHf.h" @@ -27,10 +29,10 @@ namespace o2::hf_evsel /// \tparam centEstimator centrality estimator /// \param collision collision to test against the selection criteria template -void checkEvSel(Coll const& collision, o2::hf_evsel::HfEventSelection& hfEvSel, int& zvtxColl, int& sel8Coll, int& zvtxAndSel8Coll, int& zvtxAndSel8CollAndSoftTrig, int& allSelColl, o2::framework::Service const& ccdb) +void checkEvSel(Coll const& collision, o2::hf_evsel::HfEventSelection& hfEvSel, int& zvtxColl, int& sel8Coll, int& zvtxAndSel8Coll, int& zvtxAndSel8CollAndSoftTrig, int& allSelColl, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry) { float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (!TESTBIT(rejectionMask, o2::hf_evsel::EventRejection::Trigger)) { sel8Coll++; } diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 6c1b4d50356..27716aee943 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1164,6 +1164,48 @@ DECLARE_SOA_COLUMN(DecLenV0, decLenV0, float); DECLARE_SOA_COLUMN(ErrorDecayLengthCharmBaryon, errorDecayLengthCharmBaryon, float); DECLARE_SOA_COLUMN(ErrorDecayLengthXYCharmBaryon, errorDecayLengthXYCharmBaryon, float); +// KFParticle results +DECLARE_SOA_COLUMN(KfDcaXYPiFromOmegac, kfDcaXYPiFromOmegac, float); +DECLARE_SOA_COLUMN(KfDcaXYCascToPv, kfDcaXYCascToPv, float); +DECLARE_SOA_COLUMN(Chi2GeoV0, chi2GeoV0, float); +DECLARE_SOA_COLUMN(Chi2GeoCasc, chi2GeoCasc, float); +DECLARE_SOA_COLUMN(Chi2GeoOmegac, chi2GeoOmegac, float); +DECLARE_SOA_COLUMN(Chi2MassV0, chi2MassV0, float); +DECLARE_SOA_COLUMN(Chi2MassCasc, chi2MassCasc, float); +DECLARE_SOA_COLUMN(V0ldl, v0ldl, float); +DECLARE_SOA_COLUMN(Cascldl, cascldl, float); +DECLARE_SOA_COLUMN(Omegacldl, omegacldl, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToPv, chi2TopoV0ToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToPv, chi2TopoCascToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoPiFromOmegacToPv, chi2TopoPiFromOmegacToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoOmegacToPv, chi2TopoOmegacToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToCasc, chi2TopoV0ToCasc, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToOmegac, chi2TopoCascToOmegac, float); +DECLARE_SOA_COLUMN(DecayLenXYLambda, decayLenXYLambda, float); +DECLARE_SOA_COLUMN(DecayLenXYCasc, decayLenXYCasc, float); +DECLARE_SOA_COLUMN(DecayLenXYOmegac, decayLenXYOmegac, float); +DECLARE_SOA_COLUMN(CosPaV0ToCasc, cosPaV0ToCasc, float); +DECLARE_SOA_COLUMN(CosPaCascToOmegac, cosPaCascToOmegac, float); +DECLARE_SOA_COLUMN(CosPaXYV0ToCasc, cosPaXYV0ToCasc, float); +DECLARE_SOA_COLUMN(CosPaXYCascToOmegac, cosPaXYCascToOmegac, float); +DECLARE_SOA_COLUMN(KfMassV0, kfMassV0, float); +DECLARE_SOA_COLUMN(KfMassCasc, kfMassCasc, float); +DECLARE_SOA_COLUMN(KfMassOmegac, kfMassOmegac, float); +DECLARE_SOA_COLUMN(KfRapOmegac, kfRapOmegac, float); +DECLARE_SOA_COLUMN(KfptPiFromOmegac, kfptPiFromOmegac, float); +DECLARE_SOA_COLUMN(KfptOmegac, kfptOmegac, float); +DECLARE_SOA_COLUMN(CosThetaStarPiFromOmegac, cosThetaStarPiFromOmegac, float); +DECLARE_SOA_COLUMN(V0Ndf, v0Ndf, float); +DECLARE_SOA_COLUMN(CascNdf, cascNdf, float); +DECLARE_SOA_COLUMN(OmegacNdf, omegacNdf, float); +DECLARE_SOA_COLUMN(MassV0Ndf, massV0Ndf, float); +DECLARE_SOA_COLUMN(MassCascNdf, massCascNdf, float); +DECLARE_SOA_COLUMN(V0Chi2OverNdf, v0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(CascChi2OverNdf, cascChi2OverNdf, float); +DECLARE_SOA_COLUMN(OmegacChi2OverNdf, omegacChi2OverNdf, float); +DECLARE_SOA_COLUMN(MassV0Chi2OverNdf, massV0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(MassCascChi2OverNdf, massCascChi2OverNdf, float); + // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level @@ -1177,6 +1219,18 @@ DECLARE_SOA_COLUMN(OriginGen, originGen, int8_t); DECLARE_SOA_COLUMN(PtCharmBaryonGen, ptCharmBaryonGen, float); DECLARE_SOA_COLUMN(RapidityCharmBaryonGen, rapidityCharmBaryonGen, float); +// dynamic columns +DECLARE_SOA_DYNAMIC_COLUMN(PtCharmBaryon, ptCharmBaryon, + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtCasc, ptCasc, + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtLambda, ptLambda, + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtPiFromCharmBaryon, ptPiFromCharmBaryon, + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtKaFromCasc, ptKaFromCasc, + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); + // mapping of decay types enum DecayType { XiczeroToXiPi = 0, OmegaczeroToXiPi, @@ -1229,6 +1283,13 @@ DECLARE_SOA_TABLE(HfCandToOmegaPi, "AOD", "HFCANDTOOMEGAPI", hf_cand_xic0_omegac0::PxBachFromCasc, hf_cand_xic0_omegac0::PyBachFromCasc, hf_cand_xic0_omegac0::PzBachFromCasc, hf_cand_xic0_omegac0::PxPosV0Dau, hf_cand_xic0_omegac0::PyPosV0Dau, hf_cand_xic0_omegac0::PzPosV0Dau, hf_cand_xic0_omegac0::PxNegV0Dau, hf_cand_xic0_omegac0::PyNegV0Dau, hf_cand_xic0_omegac0::PzNegV0Dau, + // dynamic + hf_cand_xic0_omegac0::PtCharmBaryon, + hf_cand_xic0_omegac0::PtCasc, + hf_cand_xic0_omegac0::PtPiFromCharmBaryon, + hf_cand_xic0_omegac0::PtLambda, + hf_cand_xic0_omegac0::PtKaFromCasc, + hf_cand_xic0_omegac0::ImpactParCascXY, hf_cand_xic0_omegac0::ImpactParBachFromCharmBaryonXY, hf_cand_xic0_omegac0::ImpactParCascZ, hf_cand_xic0_omegac0::ImpactParBachFromCharmBaryonZ, hf_cand_xic0_omegac0::ErrImpactParCascXY, hf_cand_xic0_omegac0::ErrImpactParBachFromCharmBaryonXY, hf_cand_xic0_omegac0::V0Id, v0data::PosTrackId, v0data::NegTrackId, hf_cand_xic0_omegac0::CascadeId, hf_cand_xic0_omegac0::BachelorFromCharmBaryonId, cascdata::BachelorId, @@ -1272,6 +1333,24 @@ DECLARE_SOA_TABLE(HfCandToOmegaK, "AOD", "HFCANDTOOMEGAK", hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon, o2::soa::Marker<2>); +// table with results of KFParticle +DECLARE_SOA_TABLE(HfOmegacKf, "AOD", "HFOMEGACKF", //! + hf_cand_xic0_omegac0::KfDcaXYPiFromOmegac, hf_cand_xic0_omegac0::KfDcaXYCascToPv, + hf_cand_xic0_omegac0::Chi2GeoV0, hf_cand_xic0_omegac0::Chi2GeoCasc, hf_cand_xic0_omegac0::Chi2GeoOmegac, + hf_cand_xic0_omegac0::Chi2MassV0, hf_cand_xic0_omegac0::Chi2MassCasc, + hf_cand_xic0_omegac0::V0ldl, hf_cand_xic0_omegac0::Cascldl, hf_cand_xic0_omegac0::Omegacldl, + hf_cand_xic0_omegac0::Chi2TopoV0ToPv, hf_cand_xic0_omegac0::Chi2TopoCascToPv, hf_cand_xic0_omegac0::Chi2TopoPiFromOmegacToPv, hf_cand_xic0_omegac0::Chi2TopoOmegacToPv, + hf_cand_xic0_omegac0::Chi2TopoV0ToCasc, hf_cand_xic0_omegac0::Chi2TopoCascToOmegac, + hf_cand_xic0_omegac0::DecayLenXYLambda, hf_cand_xic0_omegac0::DecayLenXYCasc, hf_cand_xic0_omegac0::DecayLenXYOmegac, + hf_cand_xic0_omegac0::CosPaV0ToCasc, hf_cand_xic0_omegac0::CosPaCascToOmegac, hf_cand_xic0_omegac0::CosPaXYV0ToCasc, hf_cand_xic0_omegac0::CosPaXYCascToOmegac, + hf_cand_xic0_omegac0::KfRapOmegac, + hf_cand_xic0_omegac0::KfptPiFromOmegac, hf_cand_xic0_omegac0::KfptOmegac, + hf_cand_xic0_omegac0::CosThetaStarPiFromOmegac, + hf_cand_xic0_omegac0::V0Ndf, hf_cand_xic0_omegac0::CascNdf, hf_cand_xic0_omegac0::OmegacNdf, + hf_cand_xic0_omegac0::MassV0Ndf, hf_cand_xic0_omegac0::MassCascNdf, + hf_cand_xic0_omegac0::V0Chi2OverNdf, hf_cand_xic0_omegac0::CascChi2OverNdf, hf_cand_xic0_omegac0::OmegacChi2OverNdf, + hf_cand_xic0_omegac0::MassV0Chi2OverNdf, hf_cand_xic0_omegac0::MassCascChi2OverNdf); + // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfXicToXiPiMCRec, "AOD", "HFXICXIPIMCREC", //! hf_cand_xic0_omegac0::FlagMcMatchRec, @@ -1320,6 +1399,127 @@ DECLARE_SOA_TABLE(HfToOmegaKMCGen, "AOD", "HFTOOMEKMCGEN", //! hf_cand_xic0_omegac0::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<4>); +// specific Xic to Xi Pi Pi candidate properties +namespace hf_cand_xic_to_xi_pi_pi +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Pi0, pi0, int, Tracks, "_pi0"); +DECLARE_SOA_INDEX_COLUMN_FULL(Pi1, pi1, int, Tracks, "_pi1"); +DECLARE_SOA_COLUMN(XPvErr, xPvErr, float); +DECLARE_SOA_COLUMN(YPvErr, yPvErr, float); +DECLARE_SOA_COLUMN(ZPvErr, zPvErr, float); +DECLARE_SOA_COLUMN(XSvErr, xSvErr, float); +DECLARE_SOA_COLUMN(YSvErr, ySvErr, float); +DECLARE_SOA_COLUMN(ZSvErr, zSvErr, float); +DECLARE_SOA_COLUMN(XDecayVtxXi, xDecayVtxXi, float); +DECLARE_SOA_COLUMN(YDecayVtxXi, yDecayVtxXi, float); +DECLARE_SOA_COLUMN(ZDecayVtxXi, zDecayVtxXi, float); +DECLARE_SOA_COLUMN(XDecayVtxLambda, xDecayVtxLambda, float); +DECLARE_SOA_COLUMN(YDecayVtxLambda, yDecayVtxLambda, float); +DECLARE_SOA_COLUMN(ZDecayVtxLambda, zDecayVtxLambda, float); +DECLARE_SOA_COLUMN(CosPaXi, cosPaXi, float); +DECLARE_SOA_COLUMN(CosPaXYXi, cosPaXYXi, float); +DECLARE_SOA_COLUMN(CosPaLambda, cosPaLambda, float); +DECLARE_SOA_COLUMN(CosPaXYLambda, cosPaXYLambda, float); +DECLARE_SOA_COLUMN(InvMassXic, invMassXic, float); +DECLARE_SOA_COLUMN(Sign, sign, float); +DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); +DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); +// KF specific columns +DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); +DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); +DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); +DECLARE_SOA_COLUMN(DcaPi0Pi1, dcaPi0Pi1, float); +DECLARE_SOA_COLUMN(DcaPi0Xi, dcaPi0Xi, float); +DECLARE_SOA_COLUMN(DcaPi1Xi, dcaPi1Xi, float); +DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); +DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlus, chi2TopoXiToXicPlus, float); +// MC matching result: +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_COLUMN(DebugMcGen, debugMcGen, int8_t); +DECLARE_SOA_COLUMN(OriginRec, originRec, int8_t); +DECLARE_SOA_COLUMN(OriginGen, originGen, int8_t); + +// mapping of decay types +enum DecayType { XicToXiPiPi = 0, // Ξc± → Ξ∓ π± π± + XicToXiResPiToXiPiPi, // Ξc± → Ξ(1530) π± → Ξ∓ π± π± + NDecayType }; +} // end of namespace hf_cand_xic_to_xi_pi_pi + +// declare dedicated Xic to Xi Pi Pi candidate table +DECLARE_SOA_TABLE(HfCandXicBase, "AOD", "HFCANDXICBASE", + hf_cand::CollisionId, + collision::PosX, collision::PosY, collision::PosZ, + hf_cand_xic_to_xi_pi_pi::XPvErr, hf_cand_xic_to_xi_pi_pi::YPvErr, hf_cand_xic_to_xi_pi_pi::ZPvErr, + // 3-prong specific columns + cascdata::CascadeId, hf_cand_xic_to_xi_pi_pi::Pi0Id, hf_cand_xic_to_xi_pi_pi::Pi1Id, + cascdata::BachelorId, cascdata::PosTrackId, cascdata::NegTrackId, + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_cand_xic_to_xi_pi_pi::XSvErr, hf_cand_xic_to_xi_pi_pi::YSvErr, hf_cand_xic_to_xi_pi_pi::ZSvErr, + hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, hf_cand_xic_to_xi_pi_pi::InvMassXic, hf_cand_xic_to_xi_pi_pi::Sign, + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, + // cascade specific columns + hf_cand_xic_to_xi_pi_pi::XDecayVtxXi, hf_cand_xic_to_xi_pi_pi::YDecayVtxXi, hf_cand_xic_to_xi_pi_pi::ZDecayVtxXi, + hf_cand_xic_to_xi_pi_pi::XDecayVtxLambda, hf_cand_xic_to_xi_pi_pi::YDecayVtxLambda, hf_cand_xic_to_xi_pi_pi::ZDecayVtxLambda, + hf_cand_xic_to_xi_pi_pi::CosPaXi, hf_cand_xic_to_xi_pi_pi::CosPaXYXi, hf_cand_xic_to_xi_pi_pi::CosPaLambda, hf_cand_xic_to_xi_pi_pi::CosPaXYLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + /* dynamic columns */ + hf_cand::RSecondaryVertex, + hf_cand::DecayLength, + hf_cand::DecayLengthXY, + hf_cand::DecayLengthNormalised, + hf_cand::DecayLengthXYNormalised, + hf_cand::ImpactParameterNormalised0, + hf_cand::ImpactParameterNormalised1, + hf_cand::ImpactParameterNormalised2, + /* dynamic columns that use daughter momentum components */ + hf_cand::PtProng0, + hf_cand::PtProng1, + hf_cand::PtProng2, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt, + hf_cand::P, + hf_cand::PVector, + hf_cand::CPA, + hf_cand::CPAXY, + hf_cand::Ct, + hf_cand::ImpactParameterXY, + hf_cand_3prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandXicExt, HfCandXicBase, "HFCANDXICEXT", + hf_cand_3prong::Px, hf_cand_3prong::Py, hf_cand_3prong::Pz); + +using HfCandXic = HfCandXicExt; + +DECLARE_SOA_TABLE(HfCandXicKF, "AOD", "HFCANDXICKF", + cascdata::KFCascadeChi2, cascdata::KFV0Chi2, hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, hf_cand_xic_to_xi_pi_pi::Chi2TopoXiToXicPlus, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + cascdata::DCACascDaughters); + +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfCandXicMcRec, "AOD", "HFCANDXICMCREC", //! + hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, + hf_cand_xic_to_xi_pi_pi::DebugMcRec, + hf_cand_xic_to_xi_pi_pi::OriginRec); + +// table with results of generator level MC matching +DECLARE_SOA_TABLE(HfCandXicMcGen, "AOD", "HFCANDXICMCGEN", //! + hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, + hf_cand_xic_to_xi_pi_pi::DebugMcGen, + hf_cand_xic_to_xi_pi_pi::OriginGen); + // specific chic candidate properties namespace hf_cand_chic { @@ -1672,6 +1872,67 @@ DECLARE_SOA_TABLE(HfCandScMcGen, "AOD", "HFCANDSCMCGEN", //! hf_cand_sigmac::OriginMcGen, hf_cand::IdxBhadMotherPart); +// specific ÎŁc0,++ candidate properties in cascade channel +namespace hf_cand_sigmac_to_cascade +{ +DECLARE_SOA_INDEX_COLUMN_FULL(ProngLc, prongLc, int, HfCandCascade, ""); //! Index to a Lc prong +DECLARE_SOA_COLUMN(Charge, charge, int8_t); //! // ÎŁc charge(either 0 or ++) +DECLARE_SOA_COLUMN(ChargeLc, chargelc, int8_t); //! // Λc charge(+) +DECLARE_SOA_COLUMN(ChargeSoftPi, chargesoftpi, int8_t); //! // pion charge(either - or +) +DECLARE_SOA_COLUMN(StatusSpreadLcMinvKs0PFromPDG, statusSpreadLcMinvKs0PFromPDG, int); //! // Λc Minv spread from PDG Λc mass +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCandCascade, "_0"); //! Λc index +// MC matching result: +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level +} // namespace hf_cand_sigmac_to_cascade + +// declare dedicated ÎŁc0,++ decay candidate table +// NB: no topology for ÎŁc0,++ (strong decay) +DECLARE_SOA_TABLE(HfCandScCasBase, "AOD", "HFCANDSCCASBASE", + o2::soa::Index<>, + // general columns + hf_cand::CollisionId, + // 2-prong specific columns + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand_sigmac_to_cascade::ProngLcId, hf_track_index::Prong1Id, + hf_cand_sigmac_to_cascade::ChargeLc, + hf_cand_sigmac_to_cascade::ChargeSoftPi, + // hf_track_index::HFflag, + /* ÎŁc0,++ specific columns */ + hf_cand_sigmac_to_cascade::Charge, + // hf_cand_sigmac_to_cascade::StatusSpreadLcMinvKs0PFromPDG, + /* prong 0 */ + hf_cand::PtProng0, + hf_cand::Pt2Prong0, + hf_cand::PVectorProng0, + /* prong 1 */ + hf_cand::PtProng1, + hf_cand::Pt2Prong1, + hf_cand::PVectorProng1, + /* dynamic columns */ + hf_cand_2prong::M, + hf_cand_2prong::M2, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt, + hf_cand::Pt2, + hf_cand::P, + hf_cand::P2, + hf_cand::PVector, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandScCasExt, HfCandScCasBase, "HFCANDSCCASEXT", + hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); +using HfCandScCascades = HfCandScCasExt; +using HfCandScCascade = HfCandScCascades::iterator; + /// D*± → D0(bar) π± namespace hf_cand_dstar { @@ -1777,11 +2038,11 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtSoftPi, ptSoftPi, [](float pxSoftPi, float pySoftPi DECLARE_SOA_DYNAMIC_COLUMN(PVecSoftPi, pVecSoftPi, [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level enum DecayType { DstarToD0Pi = 0, diff --git a/PWGHF/DataModel/CandidateSelectionTables.h b/PWGHF/DataModel/CandidateSelectionTables.h index fa9bc07a981..071ad7c0431 100644 --- a/PWGHF/DataModel/CandidateSelectionTables.h +++ b/PWGHF/DataModel/CandidateSelectionTables.h @@ -301,16 +301,22 @@ DECLARE_SOA_TABLE(HfSelChicToJpsiGamma, "AOD", "HFSELCHIC", //! namespace hf_sel_candidate_xic { +// XicPlus to P K Pi DECLARE_SOA_COLUMN(IsSelXicToPKPi, isSelXicToPKPi, int); //! DECLARE_SOA_COLUMN(IsSelXicToPiKP, isSelXicToPiKP, int); //! DECLARE_SOA_COLUMN(MlProbXicToPKPi, mlProbXicToPKPi, std::vector); //! DECLARE_SOA_COLUMN(MlProbXicToPiKP, mlProbXicToPiKP, std::vector); //! +// XicPlus to Xi Pi Pi +DECLARE_SOA_COLUMN(IsSelXicToXiPiPi, isSelXicToXiPiPi, int); //! } // namespace hf_sel_candidate_xic DECLARE_SOA_TABLE(HfSelXicToPKPi, "AOD", "HFSELXIC", //! hf_sel_candidate_xic::IsSelXicToPKPi, hf_sel_candidate_xic::IsSelXicToPiKP); DECLARE_SOA_TABLE(HfMlXicToPKPi, "AOD", "HFMLXIC", //! hf_sel_candidate_xic::MlProbXicToPKPi, hf_sel_candidate_xic::MlProbXicToPiKP); +// XicPlus to Xi Pi Pi +DECLARE_SOA_TABLE(HfSelXicToXiPiPi, "AOD", "HFSELXICTOXI2PI", //! + hf_sel_candidate_xic::IsSelXicToXiPiPi); namespace hf_sel_candidate_xicc { @@ -369,6 +375,9 @@ DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); DECLARE_SOA_COLUMN(PidTofInfoStored, pidTofInfoStored, int); +// Machine learning column for omegac0 to omega pi +DECLARE_SOA_COLUMN(MlProbOmegac, mlProbOmegac, std::vector); +DECLARE_SOA_COLUMN(MlProbOmegacBar, mlProbOmegacBar, std::vector); } // namespace hf_sel_toomegapi DECLARE_SOA_TABLE(HfSelToOmegaPi, "AOD", "HFSELTOOMEPI", @@ -378,6 +387,8 @@ DECLARE_SOA_TABLE(HfSelToOmegaPi, "AOD", "HFSELTOOMEPI", hf_sel_toomegapi::TpcNSigmaPiFromCharmBaryon, hf_sel_toomegapi::TpcNSigmaKaFromCasc, hf_sel_toomegapi::TpcNSigmaPiFromLambda, hf_sel_toomegapi::TpcNSigmaPrFromLambda, hf_sel_toomegapi::TofNSigmaPiFromCharmBaryon, hf_sel_toomegapi::TofNSigmaKaFromCasc, hf_sel_toomegapi::TofNSigmaPiFromLambda, hf_sel_toomegapi::TofNSigmaPrFromLambda); +DECLARE_SOA_TABLE(HfMlSelOmegacToOmegaPi, "AOD", "HFMLOMEGAC", //! + hf_sel_toomegapi::MlProbOmegac, hf_sel_toomegapi::MlProbOmegacBar); namespace hf_sel_toomegaka { DECLARE_SOA_COLUMN(StatusPidLambda, statusPidLambda, bool); diff --git a/PWGHF/DataModel/DerivedTables.h b/PWGHF/DataModel/DerivedTables.h index 9fb45596145..30bc06c3bc6 100644 --- a/PWGHF/DataModel/DerivedTables.h +++ b/PWGHF/DataModel/DerivedTables.h @@ -206,9 +206,13 @@ DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); +DECLARE_SOA_COLUMN(NSigTofKaExpPi, nSigTofKaExpPi, float); +DECLARE_SOA_COLUMN(NSigTofKaExpKa, nSigTofKaExpKa, float); DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); +DECLARE_SOA_COLUMN(NSigTofPiExpPi, nSigTofPiExpPi, float); +DECLARE_SOA_COLUMN(NSigTofPiExpKa, nSigTofPiExpKa, float); DECLARE_SOA_COLUMN(NSigTofPr0, nSigTofPr0, float); DECLARE_SOA_COLUMN(NSigTofPr1, nSigTofPr1, float); DECLARE_SOA_COLUMN(NSigTofPr2, nSigTofPr2, float); @@ -216,9 +220,13 @@ DECLARE_SOA_COLUMN(NSigTofPr2, nSigTofPr2, float); DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); +DECLARE_SOA_COLUMN(NSigTpcKaExpPi, nSigTpcKaExpPi, float); +DECLARE_SOA_COLUMN(NSigTpcKaExpKa, nSigTpcKaExpKa, float); DECLARE_SOA_COLUMN(NSigTpcPi0, nSigTpcPi0, float); DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); +DECLARE_SOA_COLUMN(NSigTpcPiExpPi, nSigTpcPiExpPi, float); +DECLARE_SOA_COLUMN(NSigTpcPiExpKa, nSigTpcPiExpKa, float); DECLARE_SOA_COLUMN(NSigTpcPr0, nSigTpcPr0, float); DECLARE_SOA_COLUMN(NSigTpcPr1, nSigTpcPr1, float); DECLARE_SOA_COLUMN(NSigTpcPr2, nSigTpcPr2, float); @@ -226,9 +234,13 @@ DECLARE_SOA_COLUMN(NSigTpcPr2, nSigTpcPr2, float); DECLARE_SOA_COLUMN(NSigTpcTofKa0, nSigTpcTofKa0, float); DECLARE_SOA_COLUMN(NSigTpcTofKa1, nSigTpcTofKa1, float); DECLARE_SOA_COLUMN(NSigTpcTofKa2, nSigTpcTofKa2, float); +DECLARE_SOA_COLUMN(NSigTpcTofKaExpPi, nSigTpcTofKaExpPi, float); +DECLARE_SOA_COLUMN(NSigTpcTofKaExpKa, nSigTpcTofKaExpKa, float); DECLARE_SOA_COLUMN(NSigTpcTofPi0, nSigTpcTofPi0, float); DECLARE_SOA_COLUMN(NSigTpcTofPi1, nSigTpcTofPi1, float); DECLARE_SOA_COLUMN(NSigTpcTofPi2, nSigTpcTofPi2, float); +DECLARE_SOA_COLUMN(NSigTpcTofPiExpPi, nSigTpcTofPiExpPi, float); +DECLARE_SOA_COLUMN(NSigTpcTofPiExpKa, nSigTpcTofPiExpKa, float); DECLARE_SOA_COLUMN(NSigTpcTofPr0, nSigTpcTofPr0, float); DECLARE_SOA_COLUMN(NSigTpcTofPr1, nSigTpcTofPr1, float); DECLARE_SOA_COLUMN(NSigTpcTofPr2, nSigTpcTofPr2, float); @@ -287,18 +299,18 @@ DECLARE_SOA_TABLE(HfD0Pars, "AOD", "HFD0PAR", //! Table with candidate propertie hf_cand::ImpactParameter1, hf_cand_par::ImpactParameterNormalised0, hf_cand_par::ImpactParameterNormalised1, - hf_cand_par::NSigTpcPi0, - hf_cand_par::NSigTpcKa0, - hf_cand_par::NSigTofPi0, - hf_cand_par::NSigTofKa0, - hf_cand_par::NSigTpcTofPi0, - hf_cand_par::NSigTpcTofKa0, - hf_cand_par::NSigTpcPi1, - hf_cand_par::NSigTpcKa1, - hf_cand_par::NSigTofPi1, - hf_cand_par::NSigTofKa1, - hf_cand_par::NSigTpcTofPi1, - hf_cand_par::NSigTpcTofKa1, + hf_cand_par::NSigTpcPiExpPi, + hf_cand_par::NSigTofPiExpPi, + hf_cand_par::NSigTpcTofPiExpPi, + hf_cand_par::NSigTpcKaExpPi, + hf_cand_par::NSigTofKaExpPi, + hf_cand_par::NSigTpcTofKaExpPi, + hf_cand_par::NSigTpcPiExpKa, + hf_cand_par::NSigTofPiExpKa, + hf_cand_par::NSigTpcTofPiExpKa, + hf_cand_par::NSigTpcKaExpKa, + hf_cand_par::NSigTofKaExpKa, + hf_cand_par::NSigTpcTofKaExpKa, hf_cand_par::MaxNormalisedDeltaIP, hf_cand_par::ImpactParameterProduct, soa::Marker); diff --git a/PWGHF/DataModel/DerivedTablesStored.h b/PWGHF/DataModel/DerivedTablesStored.h index 95d5cc0438f..991ef61a9b8 100644 --- a/PWGHF/DataModel/DerivedTablesStored.h +++ b/PWGHF/DataModel/DerivedTablesStored.h @@ -161,18 +161,18 @@ DECLARE_SOA_TABLE(StoredHfD0Pars, "AOD1", "HFD0PAR", //! Table with candidate pr hf_cand::ImpactParameter1, hf_cand_par::ImpactParameterNormalised0, hf_cand_par::ImpactParameterNormalised1, - hf_cand_par::NSigTpcPi0, - hf_cand_par::NSigTpcKa0, - hf_cand_par::NSigTofPi0, - hf_cand_par::NSigTofKa0, - hf_cand_par::NSigTpcTofPi0, - hf_cand_par::NSigTpcTofKa0, - hf_cand_par::NSigTpcPi1, - hf_cand_par::NSigTpcKa1, - hf_cand_par::NSigTofPi1, - hf_cand_par::NSigTofKa1, - hf_cand_par::NSigTpcTofPi1, - hf_cand_par::NSigTpcTofKa1, + hf_cand_par::NSigTpcPiExpPi, + hf_cand_par::NSigTofPiExpPi, + hf_cand_par::NSigTpcTofPiExpPi, + hf_cand_par::NSigTpcKaExpPi, + hf_cand_par::NSigTofKaExpPi, + hf_cand_par::NSigTpcTofKaExpPi, + hf_cand_par::NSigTpcPiExpKa, + hf_cand_par::NSigTofPiExpKa, + hf_cand_par::NSigTpcTofPiExpKa, + hf_cand_par::NSigTpcKaExpKa, + hf_cand_par::NSigTofKaExpKa, + hf_cand_par::NSigTpcTofKaExpKa, hf_cand_par::MaxNormalisedDeltaIP, hf_cand_par::ImpactParameterProduct, soa::Marker); diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h index 0069d6b2161..e486e7bb33b 100644 --- a/PWGHF/HFC/DataModel/CorrelationTables.h +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -216,13 +216,23 @@ DECLARE_SOA_TABLE(Hadron, "AOD", "HADRON", //! Associated hadron properties // definition of columns and tables for Dplus-Hadron correlation pairs namespace hf_correlation_dplus_hadron { -DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between D+ and Hadrons -DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between D+ and Hadrons -DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of D+ -DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron -DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of D+ -DECLARE_SOA_COLUMN(SignalStatus, signalStatus, bool); //! Used in MC-Rec, D+ Signal -DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin of event defined using zvtx and multiplicity +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between D+ and Hadrons +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between D+ and Hadrons +DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of D+ +DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron +DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of D+ +DECLARE_SOA_COLUMN(MlScoreBkg, mlScoreBkg, float); //! ML background score for D+ selection +DECLARE_SOA_COLUMN(MlScorePrompt, mlScorePrompt, float); //! ML prompt score for D+ selection +DECLARE_SOA_COLUMN(SignalStatus, signalStatus, bool); //! Used in MC-Rec, D+ Signal +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin of event defined using zvtx and multiplicity +DECLARE_SOA_COLUMN(TrackDcaXY, trackDcaXY, float); //! DCA xy of the track +DECLARE_SOA_COLUMN(TrackDcaZ, trackDcaZ, float); //! DCA z of the track +DECLARE_SOA_COLUMN(TrackTPCNClsCrossedRows, trackTPCNClsCrossedRows, int); //! Number of crossed TPC Rows +DECLARE_SOA_COLUMN(TrackOrigin, trackOrigin, int); //! Number of crossed TPC Rows +DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); //! Used in MC-Rec, D+ Signal +DECLARE_SOA_COLUMN(IsDecayChan, isDecayChan, bool); //! Used in MC-Rec, D+ decay channel check +DECLARE_SOA_COLUMN(IsPrompt, isPrompt, bool); //! Used in MC-Rec, D+ Prompt or Non-Prompt +DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); //! Used in MC-Rec, primary associated particles } // namespace hf_correlation_dplus_hadron DECLARE_SOA_TABLE(DplusHadronPair, "AOD", "DPLUSHPAIR", //! D+-Hadrons pairs Informations @@ -236,6 +246,29 @@ DECLARE_SOA_TABLE(DplusHadronRecoInfo, "AOD", "DPLUSHRECOINFO", //! D+-Hadrons p aod::hf_correlation_dplus_hadron::MD, aod::hf_correlation_dplus_hadron::SignalStatus); +DECLARE_SOA_TABLE(DplusHadronGenInfo, "AOD", "DPLUSHGENINFO", //! Ds-Hadrons pairs Generated Information + aod::hf_correlation_dplus_hadron::IsPrompt, + aod::hf_correlation_dplus_hadron::IsPhysicalPrimary, + aod::hf_correlation_dplus_hadron::TrackOrigin); + +DECLARE_SOA_TABLE(DplusHadronMlInfo, "AOD", "DPLUSHMLINFO", //! D+-Hadrons pairs Machine Learning Information + aod::hf_correlation_dplus_hadron::MlScoreBkg, + aod::hf_correlation_dplus_hadron::MlScorePrompt); + +DECLARE_SOA_TABLE(DplusRecoInfo, "AOD", "DPLUSRECOINFO", //! D+ candidates Reconstructed Information + aod::hf_correlation_dplus_hadron::MD, + aod::hf_correlation_dplus_hadron::PtD, + aod::hf_correlation_dplus_hadron::MlScoreBkg, + aod::hf_correlation_dplus_hadron::MlScorePrompt); + +DECLARE_SOA_TABLE(DplusGenInfo, "AOD", "DPLUSGENOINFO", //! D+ candidates Generated Information + aod::hf_correlation_dplus_hadron::IsPrompt); + +DECLARE_SOA_TABLE(TrkRecInfoDplus, "AOD", "TRKRECINFODPLUS", //! Tracks Reconstructed Information + aod::hf_correlation_dplus_hadron::TrackDcaXY, + aod::hf_correlation_dplus_hadron::TrackDcaZ, + aod::hf_correlation_dplus_hadron::TrackTPCNClsCrossedRows); + // definition of columns and tables for Dstar-Hadron correlation pair namespace hf_correlation_dstar_hadron { @@ -314,6 +347,22 @@ DECLARE_SOA_COLUMN(DmesonSel, dmesonSel, bool); //! Selection flag for D meson i DECLARE_SOA_TABLE(DmesonSelection, "AOD", "DINCOLL", // Selection of D meson in collisions aod::hf_selection_dmeson_collision::DmesonSel); + +// Note: definition of columns and tables for Electron Hadron correlation pairs +namespace hf_correlation_electron_hadron +{ +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between Electron and Hadrons +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between Electron and Hadrons +DECLARE_SOA_COLUMN(PtElectron, ptElectron, float); //! Transverse momentum of Electron +DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron; +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin of event defined using zvtx and multiplicity +} // namespace hf_correlation_electron_hadron +DECLARE_SOA_TABLE(HfEHadronPair, "AOD", "HFEHADRONPAIR", //! Hfe-Hadrons pairs Informations + hf_correlation_electron_hadron::DeltaPhi, + hf_correlation_electron_hadron::DeltaEta, + hf_correlation_electron_hadron::PtElectron, + hf_correlation_electron_hadron::PtHadron, + hf_correlation_electron_hadron::PoolBin); } // namespace o2::aod #endif // PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ diff --git a/PWGHF/HFC/TableProducer/CMakeLists.txt b/PWGHF/HFC/TableProducer/CMakeLists.txt index 1a888dfc1d7..2b01aad32c6 100644 --- a/PWGHF/HFC/TableProducer/CMakeLists.txt +++ b/PWGHF/HFC/TableProducer/CMakeLists.txt @@ -49,6 +49,11 @@ o2physics_add_dpl_workflow(correlator-dstar-hadrons PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(correlator-hfe-hadrons + SOURCES correlatorHfeHadrons.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(correlator-lc-hadrons SOURCES correlatorLcHadrons.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 63827f2b89c..6288d7388b5 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -62,6 +62,7 @@ struct HfCorrelatorDMesonPairs { Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + Configurable selectionFlagHf{"selectionFlagHf", 1, "Selection Flag for HF flagged candidates"}; Configurable yCandMax{"yCandMax", 0.8, "maxmum |y| of D0 candidates"}; Configurable ptCandMin{"ptCandMin", -1., "minimum pT of D0 candidates"}; Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for candidate mass plots"}; @@ -74,7 +75,7 @@ struct HfCorrelatorDMesonPairs { using TracksWPid = soa::Join; Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isRecoHfFlag >= selectionFlagHf; HistogramConfigSpec hTH1Pt{HistType::kTH1F, {{180, 0., 36.}}}; HistogramConfigSpec hTH1Y{HistType::kTH1F, {{100, -5., 5.}}}; @@ -370,11 +371,9 @@ struct HfCorrelatorDMesonPairs { } /// Fill selection status histogram - /// \param candidate1 is the first candidate of the pair - /// \param candidate2 is the second candidate of the pair - template - void fillEntry(const T& candidate1, const T& candidate2, const bool& isDCand1, const bool& isDbarCand1, - const bool& isDCand2, const bool& isDbarCand2, const uint8_t& candidateType1, const uint8_t& candidateType2) + void fillEntry(const bool& isDCand1, const bool& isDbarCand1, const bool& isDCand2, const bool& isDbarCand2, + const uint8_t& candidateType1, const uint8_t& candidateType2, float yCand1, float yCand2, + double ptCand1, double ptCand2, float massDCand1, float massDbarCand1, float massDCand2, float massDbarCand2) { /// Fill information on the D candidates @@ -399,12 +398,6 @@ struct HfCorrelatorDMesonPairs { /// Collect information on the D pairs uint8_t pairType(0); registry.fill(HIST("hSelectionStatus"), 1); - float yCand1 = hfHelper.yD0(candidate1); - float yCand2 = hfHelper.yD0(candidate2); - float massDCand1 = hfHelper.invMassD0ToPiK(candidate1); - float massDbarCand1 = hfHelper.invMassD0barToKPi(candidate1); - float massDCand2 = hfHelper.invMassD0ToPiK(candidate2); - float massDbarCand2 = hfHelper.invMassD0barToKPi(candidate2); if (isDCand1 && isDCand2) { SETBIT(pairType, DD); registry.fill(HIST("hSelectionStatus"), 14); @@ -434,7 +427,7 @@ struct HfCorrelatorDMesonPairs { } } - entryD0Pair(candidate1.pt(), candidate2.pt(), yCand1, yCand2, massDCand1, massDbarCand1, massDCand2, massDbarCand2, pairType, candidateType1, candidateType2); + entryD0Pair(ptCand1, ptCand2, yCand1, yCand2, massDCand1, massDbarCand1, massDCand2, massDbarCand2, pairType, candidateType1, candidateType2); } /// D0(bar)-D0(bar) correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) @@ -493,7 +486,9 @@ struct HfCorrelatorDMesonPairs { bool isDCand2 = isD(candidateType2); bool isDbarCand2 = isDbar(candidateType2); - fillEntry(candidate1, candidate2, isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2); + fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, hfHelper.yD0(candidate1), hfHelper.yD0(candidate2), + candidate1.pt(), candidate2.pt(), hfHelper.invMassD0ToPiK(candidate1), hfHelper.invMassD0barToKPi(candidate1), + hfHelper.invMassD0ToPiK(candidate2), hfHelper.invMassD0barToKPi(candidate2)); } // end inner loop (Cand2) } // end outer loop (Cand1) } @@ -512,20 +507,27 @@ struct HfCorrelatorDMesonPairs { return; } for (const auto& candidate1 : selectedD0CandidatesGroupedMc) { + auto ptCandidate1 = candidate1.pt(); + auto yCandidate1 = hfHelper.yD0(candidate1); + float massD0Cand1 = hfHelper.invMassD0ToPiK(candidate1); + float massD0barCand1 = hfHelper.invMassD0barToKPi(candidate1); + auto prong0Cand1 = candidate1.template prong0_as(); + auto prong1Cand1 = candidate1.template prong1_as(); + if (abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { continue; } - auto prong0Cand1 = candidate1.template prong0_as(); - auto prong1Cand1 = candidate1.template prong1_as(); - - bool isSignalD0Cand1 = std::abs(hfHelper.invMassD0ToPiK(candidate1) - MassD0) < massCut; - bool isSignalD0barCand1 = std::abs(hfHelper.invMassD0barToKPi(candidate1) - MassD0Bar) < massCut; + bool isSignalD0Cand1 = std::abs(massD0Cand1 - MassD0) < massCut; + bool isSignalD0barCand1 = std::abs(massD0barCand1 - MassD0Bar) < massCut; if (selectSignalRegionOnly && !(isSignalD0Cand1 || isSignalD0barCand1)) { continue; } + if (!(candidate1.isSelD0() >= selectionFlagD0 || candidate1.isSelD0bar() >= selectionFlagD0bar)) { + continue; + } auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution @@ -544,21 +546,28 @@ struct HfCorrelatorDMesonPairs { } for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGroupedMc.end(); ++candidate2) { + auto ptCandidate2 = candidate2.pt(); + auto yCandidate2 = hfHelper.yD0(candidate2); + float massD0Cand2 = hfHelper.invMassD0ToPiK(candidate2); + float massD0barCand2 = hfHelper.invMassD0barToKPi(candidate2); + auto prong0Cand2 = candidate2.template prong0_as(); + auto prong1Cand2 = candidate2.template prong1_as(); + if (abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { continue; } - auto prong0Cand2 = candidate2.template prong0_as(); - auto prong1Cand2 = candidate2.template prong1_as(); - if (daughterTracksCutFlag && ((prong0Cand1 == prong0Cand2) || (prong1Cand1 == prong1Cand2) || (prong0Cand1 == prong1Cand2) || (prong1Cand1 == prong0Cand2))) { + bool isSignalD0Cand2 = std::abs(massD0Cand2 - MassD0) < massCut; + bool isSignalD0barCand2 = std::abs(massD0barCand2 - MassD0Bar) < massCut; + if (selectSignalRegionOnly && !(isSignalD0Cand2 || isSignalD0barCand2)) { continue; } - - bool isSignalD0Cand2 = std::abs(hfHelper.invMassD0ToPiK(candidate2) - MassD0) < massCut; - bool isSignalD0barCand2 = std::abs(hfHelper.invMassD0barToKPi(candidate2) - MassD0Bar) < massCut; - if (selectSignalRegionOnly && !(isSignalD0Cand2 || isSignalD0barCand2)) { + if (!(candidate2.isSelD0() >= selectionFlagD0 || candidate2.isSelD0bar() >= selectionFlagD0bar)) { + continue; + } + if (daughterTracksCutFlag && ((prong0Cand1 == prong0Cand2) || (prong1Cand1 == prong1Cand2) || (prong0Cand1 == prong1Cand2) || (prong1Cand1 == prong0Cand2))) { continue; } auto candidateType2 = assignCandidateTypeD0(candidate2); // Candidate type attribution @@ -609,7 +618,8 @@ struct HfCorrelatorDMesonPairs { } else if (isTrueDbarCand1 && isTrueDCand2) { registry.fill(HIST("hSelectionStatus"), 25); } - fillEntry(candidate1, candidate2, isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2); + fillEntry(isDCand1, isDbarCand1, isDCand2, isDbarCand2, candidateType1, candidateType2, yCandidate1, yCandidate2, + ptCandidate1, ptCandidate2, massD0Cand1, massD0barCand1, massD0Cand2, massD0barCand2); entryD0PairMcInfo(originRec1, originRec2, matchedRec1, matchedRec2); } // end inner loop (Cand2) } // end outer loop (Cand1) diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index a079552b749..166ebb7eab8 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -31,6 +31,7 @@ using namespace o2; using namespace o2::analysis; using namespace o2::constants::physics; +using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; @@ -45,61 +46,68 @@ double getDeltaPhi(double phiD, double phiHadron) const int npTBinsMassAndEfficiency = o2::analysis::hf_cuts_dplus_to_pi_k_pi::nBinsPt; std::vector efficiencyDmeson(npTBinsMassAndEfficiency + 1); -// histogram binning definition -const int massAxisBins = 350; -const double massAxisMin = 1.7; -const double massAxisMax = 2.05; -const int phiAxisBins = 32; -const double phiAxisMin = -o2::constants::math::PIHalf; -const double phiAxisMax = 3. * o2::constants::math::PIHalf; -const int yAxisBins = 100; -const double yAxisMin = -2.; -const double yAxisMax = 2.; -const int ptDAxisBins = 180; -const double ptDAxisMin = 0.; -const double ptDAxisMax = 36.; - // definition of ME variables using BinningType = ColumnBinningPolicy>; +using BinningTypeMcGen = ColumnBinningPolicy; // Code to select a Dmeson in a collision struct HfCorrelatorDplusHadronsDplusSelection { Produces dplusSel; - Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for Dplus"}; // 7 corresponds to topo+PID cuts + Configurable useSel8{"useSel8", true, "Flag for applying sel8 for collision selection"}; + Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; + Configurable doSelDplusCollision{"doSelDplusCollision", true, "Select collisions with at least one D+"}; + Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; HfHelper hfHelper; SliceCache cache; + using SelCollisions = soa::Join; using CandidatesDplusData = soa::Filtered>; using CandidatesDplusMcRec = soa::Filtered>; + using CandDplusMcGen = soa::Join; + // filter on selection of Dplus meson and decay channel Dplus->KPiPi Filter dplusFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) != static_cast(0)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - void processDplusSelectionData(aod::Collision const& /*collision*/, + void processDplusSelectionData(SelCollisions::iterator const& collision, CandidatesDplusData const& candidates) { - bool isDplusFound = 0; - if (candidates.size() > 0) { + bool isSelColl = true; + bool isDplusFound = true; + bool isSel8 = true; + bool isNosameBunchPileUp = true; + if (doSelDplusCollision) { for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yDplus(candidate)) >= yCandMax || candidate.pt() <= ptCandMin) { + if (std::abs(hfHelper.yDplus(candidate)) > yCandMax || candidate.pt() < ptCandMin) { + isDplusFound = false; continue; } - isDplusFound = 1; + isDplusFound = true; break; } } - dplusSel(isDplusFound); + if (useSel8) { + isSel8 = collision.sel8(); + } + if (selNoSameBunchPileUpColl) { + isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); + } + isSelColl = isDplusFound && isSel8 && isNosameBunchPileUp; + dplusSel(isSelColl); } PROCESS_SWITCH(HfCorrelatorDplusHadronsDplusSelection, processDplusSelectionData, "Process Dplus Selection Data", false); - void processDplusSelectionMcRec(aod::Collision const& /*collision*/, + void processDplusSelectionMcRec(SelCollisions::iterator const& collision, CandidatesDplusMcRec const& candidates) { - bool isDplusFound = 0; - if (candidates.size() > 0) { + bool isSelColl = true; + bool isDplusFound = false; + bool isSel8 = true; + bool isNosameBunchPileUp = true; + if (doSelDplusCollision) { for (const auto& candidate : candidates) { if (std::abs(hfHelper.yDplus(candidate)) >= yCandMax || candidate.pt() <= ptCandMin) { continue; @@ -108,12 +116,20 @@ struct HfCorrelatorDplusHadronsDplusSelection { break; } } - dplusSel(isDplusFound); + if (useSel8) { + isSel8 = collision.sel8(); + } + if (selNoSameBunchPileUpColl) { + isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); + } + isSelColl = isDplusFound && isSel8 && isNosameBunchPileUp; + dplusSel(isSelColl); } + PROCESS_SWITCH(HfCorrelatorDplusHadronsDplusSelection, processDplusSelectionMcRec, "Process Dplus Selection MCRec", false); void processDplusSelectionMcGen(aod::McCollision const&, - aod::McParticles const& mcParticles) + CandDplusMcGen const& mcParticles) { bool isDplusFound = 0; for (const auto& particle1 : mcParticles) { @@ -136,103 +152,155 @@ struct HfCorrelatorDplusHadronsDplusSelection { struct HfCorrelatorDplusHadrons { Produces entryDplusHadronPair; Produces entryDplusHadronRecoInfo; + Produces entryDplusHadronMlInfo; + Produces entryDplusCandRecoInfo; + Produces entryDplusHadronGenInfo; + Produces entryDplusCandGenInfo; + Produces entryTrackRecoInfo; Produces entryDplus; Produces entryHadron; Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for Dplus"}; // 7 corresponds to topo+PID cuts - Configurable applyEfficiency{"applyEfficiency", 1, "Flag for applying D-meson efficiency weights"}; - Configurable> binsPtEfficiencyD{"binsPtEfficiencyD", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for efficiency"}; - Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for D+ meson"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; + Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying D-meson efficiency weights"}; + Configurable removeDaughters{"removeDaughters", true, "Flag for removing D-meson daughters from correlations"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; + Configurable ptCandMax{"ptCandMax", 50., "max. cand pT"}; Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; Configurable ptTrackMax{"ptTrackMax", 100., "max. track pT"}; Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; - Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; + Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; + Configurable> binsPtD{"binsPtD", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots"}; + Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle"}; + Configurable> binsPtEfficiencyD{"binsPtEfficiencyD", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for efficiency"}; + Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for D+ meson"}; ConfigurableAxis binsMultiplicity{"binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 2000.0f, 6000.0f, 100000.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; ConfigurableAxis binsMultiplicityMc{"binsMultiplicityMc", {VARIABLE_WIDTH, 0.0f, 20.0f, 50.0f, 500.0f}, "Mixing bins - MC multiplicity"}; // In MCGen multiplicity is defined by counting tracks + ConfigurableAxis binsBdtScore{"binsBdtScore", {100, 0., 1.}, "Bdt output scores"}; + ConfigurableAxis binsEta{"binsEta", {50, -2., 2.}, "#it{#eta}"}; + ConfigurableAxis binsPhi{"binsPhi", {64, -PIHalf, 3. * PIHalf}, "#it{#varphi}"}; + ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; + ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 6000.}, "Multiplicity as FT0M signal amplitude"}; + ConfigurableAxis binsMassD{"binsMassD", {200, 1.7, 2.10}, "inv. mass (#pi^{+}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; HfHelper hfHelper; SliceCache cache; BinningType corrBinning{{binsZVtx, binsMultiplicity}, true}; // Event Mixing for the Data Mode - using SelCollisionsWithDplus = soa::Filtered>; - using TracksWithDca = soa::Filtered>; // track Selection applied - using CandidatesDplusData = soa::Filtered>; + using SelCollisionsWithDplus = soa::Filtered>; + using SelCollisionsWithDplusMc = soa::Filtered>; // collisionFilter applied + using CandidatesDplusData = soa::Filtered>; // Event Mixing for the MCRec Mode - using CandidatesDplusMcRec = soa::Filtered>; + using CandidatesDplusMcRec = soa::Filtered>; + using CandDplusMcGen = soa::Join; // flagDplusFilter applied // Event Mixing for the MCGen Mode using McCollisionsSel = soa::Filtered>; using McParticlesSel = soa::Filtered; + // Tracks used in Data and MC + using TracksData = soa::Filtered>; // trackFilter applied + using TracksWithMc = soa::Filtered>; // trackFilter applied Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; // filter on selection of Dplus meson and decay channel Dplus->KPiPi Filter dplusFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) != static_cast(0)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); + // Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); Preslice perCol = aod::hf_cand::collisionId; - HistogramRegistry registry{ - "registry", - {{"hPtCand", "Dplus,Hadron candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hPtProng0", "Dplus,Hadron candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hPtProng1", "Dplus,Hadron candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hPtProng2", "Dplus,Hadron candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hSelectionStatus", "Dplus,Hadron candidates;selection status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}}, - {"hEta", "Dplus,Hadron candidates;candidate #it{#eta};entries", {HistType::kTH1F, {{yAxisBins, yAxisMin, yAxisMax}}}}, - {"hPhi", "Dplus,Hadron candidates;candidate #it{#varphi};entries", {HistType::kTH1F, {{phiAxisBins, phiAxisMin, phiAxisMax}}}}, - {"hY", "Dplus,Hadron candidates;candidate #it{#y};entries", {HistType::kTH1F, {{yAxisBins, yAxisMin, yAxisMax}}}}, - {"hPtCandMCRec", "Dplus,Hadron candidates - MC reco;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hPtProng0MCRec", "Dplus,Hadron candidates - MC reco;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hPtProng1MCRec", "Dplus,Hadron candidates - MC reco;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hPtProng2MCRec", "Dplus,Hadron candidates - MC reco;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hSelectionStatusMCRec", "Dplus,Hadron candidates - MC reco;selection status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}}, - {"hEtaMCRec", "Dplus,Hadron candidates - MC reco;candidate #it{#eta};entries", {HistType::kTH1F, {{yAxisBins, yAxisMin, yAxisMax}}}}, - {"hPhiMCRec", "Dplus,Hadron candidates - MC reco;candidate #it{#varphi};entries", {HistType::kTH1F, {{phiAxisBins, phiAxisMin, phiAxisMax}}}}, - {"hYMCRec", "Dplus,Hadron candidates - MC reco;candidate #it{#y};entries", {HistType::kTH1F, {{yAxisBins, yAxisMin, yAxisMax}}}}, - {"hMCEvtCount", "Event counter - MC gen;;entries", {HistType::kTH1F, {{1, -0.5, 0.5}}}}, - {"hPtCandMCGen", "Dplus,Hadron particles - MC gen;particle #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisBins, ptDAxisMin, ptDAxisMax}}}}, - {"hEtaMCGen", "Dplus,Hadron particles - MC gen;particle #it{#eta};entries", {HistType::kTH1F, {{yAxisBins, yAxisMin, yAxisMax}}}}, - {"hPhiMCGen", "Dplus,Hadron particles - MC gen;particle #it{#varphi};entries", {HistType::kTH1F, {{phiAxisBins, phiAxisMin, phiAxisMax}}}}, - {"hYMCGen", "Dplus,Hadron candidates - MC gen;candidate #it{#y};entries", {HistType::kTH1F, {{yAxisBins, yAxisMin, yAxisMax}}}}, - {"hcountDplusHadronPerEvent", "Dplus,Hadron particles - MC gen;Number per event;entries", {HistType::kTH1F, {{20, 0., 20.}}}}, - {"hMultiplicityPreSelection", "multiplicity prior to selection;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}}, - {"hMultiplicity", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}}, - {"hMultFT0M", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}}, - {"hZvtx", "z vertex;z vertex;entries", {HistType::kTH1F, {{200, -20., 20.}}}}, - {"hDplusBin", "Dplus selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}}, - {"hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}}}}; + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { - auto vbins = (std::vector)binsPt; - registry.add("hMassDplus_2D", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDplusData", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{massAxisBins, massAxisMin, massAxisMax}}}); - registry.add("hMassDplusMCRec", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{massAxisBins, massAxisMin, massAxisMax}}}); - registry.add("hMassDplusMCRecSig", "Dplus signal candidates - MC reco;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDplusMCRecBkg", "Dplus background candidates - MC reco;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hcountDplustriggersMCGen", "Dplus trigger particles - MC gen;;N of trigger Dplus", {HistType::kTH2F, {{1, -0.5, 0.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + AxisSpec axisMassD = {binsMassD, "inv. mass (pi^{+}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; + AxisSpec axisEta = {binsEta, "#it{#eta}"}; + AxisSpec axisPhi = {binsPhi, "#it{#varphi}"}; + AxisSpec axisPtD = {(std::vector)binsPtD, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisPtHadron = {(std::vector)binsPtHadron, "#it{p}_{T} Hadron (GeV/#it{c})"}; + AxisSpec axisMultiplicity = {binsMultiplicity, "Multiplicity"}; + AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; + AxisSpec axisPosZ = {binsZVtx, "PosZ"}; + AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; + AxisSpec axisPoolBin = {binsPoolBin, "PoolBin"}; + AxisSpec axisStatus = {15, 0.5, 15.5, "Selection status"}; + AxisSpec axisRapidity = {100, -2, 2, "Rapidity"}; + + registry.add("hPtCand", "Dplus,Hadron candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtProng0", "Dplus,Hadron candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtProng1", "Dplus,Hadron candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtProng2", "Dplus,Hadron candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hSelectionStatus", "Dplus,Hadron candidates;selection status;entries", {HistType::kTH1F, {{10, -0.5, 9.5}}}); + registry.add("hEta", "Dplus,Hadron candidates;candidate #it{#eta};entries", {HistType::kTH1F, {axisEta}}); + registry.add("hPhi", "Dplus,Hadron candidates;candidate #it{#varphi};entries", {HistType::kTH1F, {axisPhi}}); + registry.add("hY", "Dplus,Hadron candidates;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); + registry.add("hcountDplusHadronPerEvent", "Dplus,Hadron particles - MC gen;Number per event;entries", {HistType::kTH1F, {{20, 0., 20.}}}); + registry.add("hMultiplicityPreSelection", "multiplicity prior to selection;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}); + registry.add("hMultiplicity", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}); + registry.add("hMultFT0M", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}); + registry.add("hZvtx", "z vertex;z vertex;entries", {HistType::kTH1F, {{200, -20., 20.}}}); + registry.add("hDplusBin", "Dplus selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); + registry.add("hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); + registry.add("hMassDplus_2D", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassDplusData", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{axisMassD}}}); + registry.add("hDplusPoolBin", "D+ candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); + registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); + // Histograms for MC Reco analysis + registry.add("hSelectionStatusMCRec", "Dplus,Hadron candidates - MC reco;selection status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}); + registry.add("hMCEvtCount", "Event counter - MC gen;;entries", {HistType::kTH1F, {{1, -0.5, 0.5}}}); + registry.add("hPtProng0MCRec", "Dplus,Hadron candidates - MC reco;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtProng1MCRec", "Dplus,Hadron candidates - MC reco;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtProng2MCRec", "Dplus,Hadron candidates - MC reco;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hMassDplusMcRec", "D+ candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{axisMassD}}}); + registry.add("hMassDplusVsPtMcRec", "D+ signal candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassDplusMcRecSig", "D+ signal candidates - MC reco;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassDplusMcRecBkg", "D+ background candidates - MC reco;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hPtCandMcRecSig", "D+,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecSigPrompt", "D+,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecSigNonPrompt", "D+,Hadron candidates Non Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecBkg", "D+,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hEtaMcRecSig", "D+,Hadron candidates - MC Reco", {HistType::kTH1F, {axisEta}}); + registry.add("hPhiMcRecSig", "D+,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPhi}}); + registry.add("hYMCRecSig", "D+,Hadron candidates - MC reco;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); + registry.add("hEtaMcRecBkg", "D+,Hadron candidates - MC Reco", {HistType::kTH1F, {axisEta}}); + registry.add("hPhiMcRecBkg", "D+,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPhi}}); + registry.add("hYMCRecBkg", "Dplus,Hadron candidates - MC reco;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); + registry.add("hFakeTracksMcRec", "Fake tracks - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtParticleAssocVsCandMcRec", "Associated Particle - MC Rec", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); + registry.add("hPtPrimaryParticleAssocVsCandMcRec", "Associated Particle - MC Rec", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); + registry.add("hPtVsMultiplicityMcRecPrompt", "Multiplicity FT0M - MC Rec Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); + registry.add("hPtVsMultiplicityMcRecNonPrompt", "Multiplicity FT0M - MC Rec Non Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); + // Histograms for MC Gen analysis + registry.add("hcountDplustriggersMCGen", "D+ trigger particles - MC gen;;N of trigger Dplus", {HistType::kTH2F, {{1, -0.5, 0.5}, {axisPtD}}}); + registry.add("hPtCandMCGen", "Dplus,Hadron particles - MC gen;particle #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); + registry.add("hYMCGen", "Dplus,Hadron candidates - MC gen;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); + registry.add("hPtCandMcGenPrompt", "D+,Hadron particles - MC Gen Prompt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenNonPrompt", "D+,Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hEtaMcGen", "D+,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); + registry.add("hPhiMcGen", "D+,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); + registry.add("hMultFT0AMcGen", "D+,Hadron multiplicity FT0A - MC Gen", {HistType::kTH1F, {axisMultiplicity}}); corrBinning = {{binsZVtx, binsMultiplicity}, true}; } /// Dplus-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) void processData(SelCollisionsWithDplus::iterator const& collision, - TracksWithDca const& tracks, + TracksData const& tracks, CandidatesDplusData const& candidates, aod::BCsWithTimestamps const&) { auto bc = collision.bc_as(); int gCollisionId = collision.globalIndex(); int64_t timeStamp = bc.timestamp(); + + int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); if (candidates.size() > 0) { - int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); int nTracks = 0; if (collision.numContrib() > 1) { for (const auto& track : tracks) { @@ -240,10 +308,8 @@ struct HfCorrelatorDplusHadrons { continue; } nTracks++; - registry.fill(HIST("hTracksBin"), poolBin); } } - registry.fill(HIST("hMultiplicityPreSelection"), nTracks); if (nTracks < multMin || nTracks > multMax) { return; @@ -251,18 +317,19 @@ struct HfCorrelatorDplusHadrons { registry.fill(HIST("hMultiplicity"), nTracks); int cntDplus = 0; + std::vector outputMl = {-1., -1., -1.}; for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yDplus(candidate)) >= yCandMax || candidate.pt() <= ptCandMin || candidate.pt() >= ptTrackMax) { + if (std::abs(hfHelper.yDplus(candidate)) >= yCandMax || candidate.pt() <= ptCandMin || candidate.pt() >= ptCandMax) { continue; } int effBinD = o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()); - double efficiencyWeight = 1.; + double efficiencyWeightD = 1.; if (applyEfficiency) { - efficiencyWeight = 1. / efficiencyD->at(effBinD); + efficiencyWeightD = 1. / efficiencyD->at(effBinD); } // fill invariant mass plots and generic info from all Dplus candidates - registry.fill(HIST("hMassDplus_2D"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDplusData"), hfHelper.invMassDplusToPiKPi(candidate), efficiencyWeight); + registry.fill(HIST("hMassDplus_2D"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeightD); + registry.fill(HIST("hMassDplusData"), hfHelper.invMassDplusToPiKPi(candidate), efficiencyWeightD); registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -272,7 +339,12 @@ struct HfCorrelatorDplusHadrons { registry.fill(HIST("hY"), hfHelper.yDplus(candidate)); registry.fill(HIST("hSelectionStatus"), candidate.isSelDplusToPiKPi()); registry.fill(HIST("hDplusBin"), poolBin); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; + } + entryDplusCandRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1]); // 0: BkgBDTScore, 1:PromptBDTScore entryDplus(candidate.phi(), candidate.eta(), candidate.pt(), hfHelper.invMassDplusToPiKPi(candidate), poolBin, gCollisionId, timeStamp); + // Dplus-Hadron correlation dedicated section // if the candidate is a Dplus, search for Hadrons and evaluate correlations for (const auto& track : tracks) { @@ -281,16 +353,23 @@ struct HfCorrelatorDplusHadrons { continue; } // Removing Dplus daughters by checking track indices - if ((candidate.prong0Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex()) || (candidate.prong2Id() == track.globalIndex())) { - continue; + if (removeDaughters) { + if ((candidate.prong0Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex()) || (candidate.prong2Id() == track.globalIndex())) { + continue; + } } entryDplusHadronPair(getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), track.pt(), poolBin); - entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), 0); - if (cntDplus == 0) + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), false); + entryDplusHadronGenInfo(false, false, 0); + entryDplusHadronMlInfo(outputMl[0], outputMl[1]); + entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); + if (cntDplus == 0) { entryHadron(track.phi(), track.eta(), track.pt(), poolBin, gCollisionId, timeStamp); + registry.fill(HIST("hTracksBin"), poolBin); + } } // Hadron Tracks loop cntDplus++; } // end outer Dplus loop @@ -302,11 +381,12 @@ struct HfCorrelatorDplusHadrons { /// Dplus-Hadron correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) void processMcRec(SelCollisionsWithDplus::iterator const& collision, - TracksWithDca const& tracks, - CandidatesDplusMcRec const& candidates) + TracksWithMc const& tracks, + CandidatesDplusMcRec const& candidates, + aod::McParticles const& mcParticles) { + int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); if (candidates.size() > 0) { - int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFT0M())); int nTracks = 0; if (collision.numContrib() > 1) { for (const auto& track : tracks) { @@ -314,7 +394,6 @@ struct HfCorrelatorDplusHadrons { continue; } nTracks++; - registry.fill(HIST("hTracksBin"), poolBin); } } registry.fill(HIST("hMultiplicityPreSelection"), nTracks); @@ -323,55 +402,105 @@ struct HfCorrelatorDplusHadrons { } registry.fill(HIST("hMultiplicity"), nTracks); + float multiplicityFT0M = collision.multFT0M(); + // MC reco level - bool flagDplusSignal = false; + bool isDplusPrompt = false; + bool isDplusNonPrompt = false; + bool isDplusSignal = false; for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yDplus(candidate)) >= yCandMax || candidate.pt() <= ptCandMin || candidate.pt() >= ptTrackMax) { + // rapidity and pT selections + if (std::abs(hfHelper.yDplus(candidate)) >= yCandMax || candidate.pt() <= ptCandMin || candidate.pt() >= ptCandMax) { continue; } + // efficiency weight determination int effBinD = o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()); - double efficiencyWeight = 1.; + double efficiencyWeightD = 1.; if (applyEfficiency) { - efficiencyWeight = 1. / efficiencyD->at(effBinD); + efficiencyWeightD = 1. / efficiencyD->at(effBinD); } + // Dplus flag + isDplusSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::DplusToPiKPi); + // prompt and non-prompt division + isDplusPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; + isDplusNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + + std::vector outputMl = {-1., -1., -1.}; + + // fill invariant mass plots from Dplus signal and background candidates + registry.fill(HIST("hMassDplusMcRec"), hfHelper.invMassDplusToPiKPi(candidate), efficiencyWeightD); + registry.fill(HIST("hDplusBin"), poolBin); - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (isDplusSignal) { // fill per-candidate distributions from Dplus true candidates - registry.fill(HIST("hPtCandMCRec"), candidate.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate.ptProng0()); registry.fill(HIST("hPtProng1MCRec"), candidate.ptProng1()); registry.fill(HIST("hPtProng2MCRec"), candidate.ptProng2()); - registry.fill(HIST("hEtaMCRec"), candidate.eta()); - registry.fill(HIST("hPhiMCRec"), RecoDecay::constrainAngle(candidate.phi(), -o2::constants::math::PIHalf)); - registry.fill(HIST("hYMCRec"), hfHelper.yDplus(candidate)); + registry.fill(HIST("hMassDplusVsPtMcRec"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeightD); registry.fill(HIST("hSelectionStatusMCRec"), candidate.isSelDplusToPiKPi()); - } - // fill invariant mass plots from Dplus signal and background candidates - registry.fill(HIST("hMassDplusMCRec"), hfHelper.invMassDplusToPiKPi(candidate), efficiencyWeight); - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { // also matched as Dplus - registry.fill(HIST("hMassDplusMCRecSig"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hPtCandMcRecSig"), candidate.pt()); + registry.fill(HIST("hEtaMcRecSig"), candidate.eta()); + registry.fill(HIST("hYMCRecSig"), hfHelper.yDplus(candidate)); + registry.fill(HIST("hPhiMcRecSig"), RecoDecay::constrainAngle(candidate.phi(), -PIHalf)); + + // prompt and non-prompt division + if (isDplusPrompt) { + registry.fill(HIST("hPtCandMcRecSigPrompt"), candidate.pt()); + registry.fill(HIST("hPtVsMultiplicityMcRecPrompt"), candidate.pt(), multiplicityFT0M); + } else if (isDplusNonPrompt) { + registry.fill(HIST("hPtCandMcRecSigNonPrompt"), candidate.pt()); + registry.fill(HIST("hPtVsMultiplicityMcRecNonPrompt"), candidate.pt(), multiplicityFT0M); + } + // Storing ML scores for signal reco candidates and charm/beauty origin + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; + } + registry.fill(HIST("hMassDplusMcRecSig"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeightD); + entryDplusCandRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1]); + entryDplusCandGenInfo(isDplusPrompt); } else { - registry.fill(HIST("hMassDplusMCRecBkg"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hPtCandMcRecBkg"), candidate.pt()); + registry.fill(HIST("hEtaMcRecBkg"), candidate.eta()); + registry.fill(HIST("hPhiMcRecBkg"), RecoDecay::constrainAngle(candidate.phi(), -PIHalf)); + registry.fill(HIST("hMassDplusMcRecBkg"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), efficiencyWeightD); } - registry.fill(HIST("hDplusBin"), poolBin); + // Dplus-Hadron correlation dedicated section // if the candidate is selected as Dplus, search for Hadron and evaluate correlations - flagDplusSignal = candidate.flagMcMatchRec() == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; - for (const auto& track : tracks) { + bool isPhysicalPrimary = false; + int trackOrigin = -1; // apply track selection if (!track.isGlobalTrackWoDCA()) { continue; } // Removing Dplus daughters by checking track indices - if ((candidate.prong0Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex()) || (candidate.prong2Id() == track.globalIndex())) { - continue; + if (removeDaughters) { + if ((candidate.prong0Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex()) || (candidate.prong2Id() == track.globalIndex())) { + continue; + } } entryDplusHadronPair(getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), track.pt(), poolBin); - entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), flagDplusSignal); + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), isDplusSignal); + entryDplusHadronMlInfo(outputMl[0], outputMl[1]); + if (track.has_mcParticle()) { + auto mcParticle = track.template mcParticle_as(); + isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); + entryDplusHadronGenInfo(isDplusPrompt, isPhysicalPrimary, trackOrigin); + } else { + entryDplusHadronGenInfo(isDplusPrompt, false, 0); + registry.fill(HIST("hFakeTracksMcRec"), track.pt()); + } + // for secondary particle fraction estimation + registry.fill(HIST("hPtParticleAssocVsCandMcRec"), track.pt(), candidate.pt()); + if (isPhysicalPrimary) { + registry.fill(HIST("hPtPrimaryParticleAssocVsCandMcRec"), track.pt(), candidate.pt()); + } + entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); } // end inner loop (Tracks) } // end outer Dplus loop @@ -382,81 +511,103 @@ struct HfCorrelatorDplusHadrons { PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcRec, "Process MC Reco mode", true); /// Dplus-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(aod::McCollision const& mcCollision, - aod::McParticles const& mcParticles) + void processMcGen(SelCollisionsWithDplusMc::iterator const& mcCollision, + CandDplusMcGen const& mcParticles) { int counterDplusHadron = 0; registry.fill(HIST("hMCEvtCount"), 0); - auto getTracksSize = [&mcParticles](aod::McCollision const&) { - int nTracks = 0; - for (const auto& track : mcParticles) { - if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { - nTracks++; - } - } - return nTracks; - }; - using BinningTypeMCGen = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; - BinningTypeMCGen corrBinningMcGen{{getTracksSize}, {binsZVtx, binsMultiplicityMc}, true}; + BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; + int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); + registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); + bool isDplusPrompt = false; + bool isDplusNonPrompt = false; // MC gen level for (const auto& particle1 : mcParticles) { // check if the particle is Dplus (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! if (std::abs(particle1.pdgCode()) != Pdg::kDPlus) { continue; } + if (!TESTBIT(std::abs(particle1.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + continue; + } double yD = RecoDecay::y(particle1.pVector(), MassDPlus); if (std::abs(yD) >= yCandMax || particle1.pt() <= ptCandMin) { continue; } + registry.fill(HIST("hDplusBin"), poolBin); registry.fill(HIST("hPtCandMCGen"), particle1.pt()); - registry.fill(HIST("hEtaMCGen"), particle1.eta()); - registry.fill(HIST("hPhiMCGen"), RecoDecay::constrainAngle(particle1.phi(), -o2::constants::math::PIHalf)); + registry.fill(HIST("hEtaMcGen"), particle1.eta()); + registry.fill(HIST("hPhiMcGen"), RecoDecay::constrainAngle(particle1.phi(), -PIHalf)); registry.fill(HIST("hYMCGen"), yD); + + // prompt and non-prompt division + isDplusPrompt = particle1.originMcGen() == RecoDecay::OriginType::Prompt; + isDplusNonPrompt = particle1.originMcGen() == RecoDecay::OriginType::NonPrompt; + if (isDplusPrompt) { + registry.fill(HIST("hPtCandMcGenPrompt"), particle1.pt()); + } else if (isDplusNonPrompt) { + registry.fill(HIST("hPtCandMcGenNonPrompt"), particle1.pt()); + } + + // prompt and non-prompt division + std::vector listDaughters{}; + std::array arrDaughDplusPDG = {+kPiPlus, -kKPlus, kPiPlus}; + std::array prongsId; + listDaughters.clear(); + RecoDecay::getDaughters(particle1, &listDaughters, arrDaughDplusPDG, 2); + int counterDaughters = 0; + if (listDaughters.size() == 3) { + for (const auto& dauIdx : listDaughters) { + auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); + counterDaughters += 1; + prongsId[counterDaughters - 1] = daughI.globalIndex(); + } + } counterDplusHadron++; // Dplus Hadron correlation dedicated section // if it's a Dplus particle, search for Hadron and evaluate correlations - if (std::abs(particle1.pdgCode()) != Pdg::kDPlus) { // just checking the particle PDG, not the decay channel (differently from Reco: you have a BR factor btw such levels!) - continue; - } registry.fill(HIST("hcountDplustriggersMCGen"), 0, particle1.pt()); // to count trigger Dplus for normalisation) - for (const auto& particle2 : mcParticles) { - - // Check Mother of particle 2 - bool flagMotherFound = false; - for (const auto& m : particle2.mothers_as()) { - if (m.globalIndex() == particle1.globalIndex()) { - flagMotherFound = true; - break; + for (const auto& particleAssoc : mcParticles) { + if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { + continue; + } + if (removeDaughters) { + if (particleAssoc.globalIndex() == prongsId[0] || particleAssoc.globalIndex() == prongsId[1] || particleAssoc.globalIndex() == prongsId[2]) { + continue; } } - if (flagMotherFound || std::abs(particle2.eta()) >= etaTrackMax || particle2.pt() <= ptTrackMin) { + if ((std::abs(particleAssoc.pdgCode()) != kElectron) && (std::abs(particleAssoc.pdgCode()) != kMuonMinus) && (std::abs(particleAssoc.pdgCode()) != kPiPlus) && (std::abs(particleAssoc.pdgCode()) != kKPlus) && (std::abs(particleAssoc.pdgCode()) != kProton)) { continue; } - if ((std::abs(particle2.pdgCode()) != 11) && (std::abs(particle2.pdgCode()) != 13) && (std::abs(particle2.pdgCode()) != 211) && (std::abs(particle2.pdgCode()) != 321) && (std::abs(particle2.pdgCode()) != 2212)) { + if (!particleAssoc.isPhysicalPrimary()) { continue; } - int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), getTracksSize(mcCollision))); - entryDplusHadronPair(getDeltaPhi(particle2.phi(), particle1.phi()), - particle2.eta() - particle1.eta(), - particle1.pt(), - particle2.pt(), poolBin); - } // end inner loop - } // end outer loop + int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); + registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); + entryDplusHadronPair(getDeltaPhi(particleAssoc.phi(), particle1.phi()), + particleAssoc.eta() - particle1.eta(), + particle1.pt(), + particleAssoc.pt(), + poolBin); + entryDplusHadronRecoInfo(MassDPlus, true); + entryDplusHadronGenInfo(isDplusPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); + } // end associated loop + } // end trigger registry.fill(HIST("hcountDplusHadronPerEvent"), counterDplusHadron); registry.fill(HIST("hZvtx"), mcCollision.posZ()); - registry.fill(HIST("hMultiplicity"), getTracksSize(mcCollision)); + // registry.fill(HIST("hMultiplicity"), getTracksSize(mcCollision)); } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcGen, "Process MC Gen mode", false); void processDataMixedEvent(SelCollisionsWithDplus const& collisions, CandidatesDplusData const& candidates, - TracksWithDca const& tracks) + TracksData const& tracks) { auto tracksTuple = std::make_tuple(candidates, tracks); - Pair pairData{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + Pair pairData{corrBinning, 5, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairData) { // LOGF(info, "Mixed event collisions: Index = (%d, %d), tracks Size: (%d, %d), Z Vertex: (%f, %f), Pool Bin: (%d, %d)", c1.globalIndex(), c2.globalIndex(), tracks1.size(), tracks2.size(), c1.posZ(), c2.posZ(), corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFT0M())),corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFT0M()))); // For debug @@ -475,61 +626,114 @@ struct HfCorrelatorDplusHadrons { void processMcRecMixedEvent(SelCollisionsWithDplus const& collisions, CandidatesDplusMcRec const& candidates, - TracksWithDca const& tracks) + TracksWithMc const& tracks, + aod::McParticles const& mcParticles) { + BinningType corrBinning{{binsZVtx, binsMultiplicityMc}, true}; + for (const auto& candidate : candidates) { + if (std::abs(hfHelper.yDplus(candidate)) > yCandMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { + continue; + } + // Dplus flag + bool isDplusSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::DplusToPiKPi); + // prompt and non-prompt division + bool isDplusPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; + bool isDplusNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + if (isDplusSignal) { + if (isDplusPrompt) { + registry.fill(HIST("hPtCandMcRecSigPrompt"), candidate.pt()); + registry.fill(HIST("hPtVsMultiplicityMcRecPrompt"), candidate.pt(), 0); + } else if (isDplusNonPrompt) { + registry.fill(HIST("hPtCandMcRecSigNonPrompt"), candidate.pt()); + registry.fill(HIST("hPtVsMultiplicityMcRecNonPrompt"), candidate.pt(), 0); + } + } else { + registry.fill(HIST("hPtCandMcRecBkg"), candidate.pt()); + registry.fill(HIST("hEtaMcRecBkg"), candidate.eta()); + registry.fill(HIST("hPhiMcRecBkg"), RecoDecay::constrainAngle(candidate.phi(), -PIHalf)); + } + } auto tracksTuple = std::make_tuple(candidates, tracks); - Pair pairMcRec{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + Pair pairMcRec{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairMcRec) { int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFT0M())); - for (const auto& [trigDplus, assocParticle] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - - if (!assocParticle.isGlobalTrackWoDCA() || std::abs(hfHelper.yDplus(trigDplus)) >= yCandMax) { + int poolBinDplus = corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFT0M())); + registry.fill(HIST("hMultFT0M"), c1.multFT0M()); + registry.fill(HIST("hZVtx"), c1.posZ()); + registry.fill(HIST("hTracksPoolBin"), poolBin); // note that the selections here are not yet applied + registry.fill(HIST("hDplusPoolBin"), poolBinDplus); // note that the selections here are not yet applied + for (const auto& [candidate, pAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (std::abs(hfHelper.yDplus(candidate)) > yCandMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { continue; } - entryDplusHadronPair(getDeltaPhi(trigDplus.phi(), assocParticle.phi()), trigDplus.eta() - assocParticle.eta(), trigDplus.pt(), assocParticle.pt(), poolBin); - entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(trigDplus), 0); + if (!pAssoc.isGlobalTrackWoDCA()) { + continue; + } + std::vector outputMl = {-1., -1., -1.}; + bool isPhysicalPrimary = false; + int trackOrigin = -1; + bool isDplusSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; + // prompt and non-prompt division + bool isDplusPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; + if (pAssoc.has_mcParticle()) { + auto mcParticle = pAssoc.template mcParticle_as(); + isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); + } else { + registry.fill(HIST("hFakeTracksMcRec"), pAssoc.pt()); + } + entryDplusHadronPair(getDeltaPhi(pAssoc.phi(), candidate.phi()), + pAssoc.eta() - candidate.eta(), + candidate.pt(), + pAssoc.pt(), + poolBin); + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate), isDplusSignal); + entryDplusHadronGenInfo(isDplusPrompt, isPhysicalPrimary, trackOrigin); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; + } + entryDplusHadronMlInfo(outputMl[0], outputMl[1]); + entryTrackRecoInfo(pAssoc.dcaXY(), pAssoc.dcaZ(), pAssoc.tpcNClsCrossedRows()); } } } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcRecMixedEvent, "Process Mixed Event MCRec", false); - void processMcGenMixedEvent(McCollisionsSel const& collisions, - McParticlesSel const& mcParticles) + void processMcGenMixedEvent(SelCollisionsWithDplusMc const& collisions, + CandDplusMcGen const& mcParticles) { - - auto getTracksSize = [&mcParticles, this](McCollisionsSel::iterator const& collision) { - int nTracks = 0; - auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, collision.globalIndex(), this->cache); - for (const auto& track : associatedTracks) { - if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { - nTracks++; - } - } - return nTracks; - }; - - using BinningTypeMcGen = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; - BinningTypeMcGen corrBinningMcGen{{getTracksSize}, {binsZVtx, binsMultiplicityMc}, true}; - + BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pairMcGen{corrBinningMcGen, 5, -1, collisions, tracksTuple, &cache}; - + Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { - for (const auto& [trigDplus, assocParticle] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - - // Check track trigDplus is Dplus - if (std::abs(trigDplus.pdgCode()) != Pdg::kDPlus) { + int poolBin = corrBinningMcGen.getBin(std::make_tuple(c1.posZ(), c1.multMCFT0A())); + for (const auto& [candidate, particleAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (std::abs(candidate.pdgCode()) != Pdg::kDPlus) { continue; } - - double yD = RecoDecay::y(trigDplus.pVector(), MassDPlus); - if (std::abs(yD) >= yCandMax || trigDplus.pt() <= ptCandMin || std::abs(assocParticle.eta()) >= etaTrackMax || assocParticle.pt() <= ptTrackMin) { + double yD = RecoDecay::y(candidate.pVector(), MassDPlus); + if (std::abs(yD) > yCandGenMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { + continue; + } + if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { + continue; + } + if ((std::abs(particleAssoc.pdgCode()) != kElectron) && (std::abs(particleAssoc.pdgCode()) != kMuonMinus) && (std::abs(particleAssoc.pdgCode()) != kPiPlus) && (std::abs(particleAssoc.pdgCode()) != kKPlus) && (std::abs(particleAssoc.pdgCode()) != kProton)) { + continue; + } + if (!particleAssoc.isPhysicalPrimary()) { continue; } - int poolBin = corrBinningMcGen.getBin(std::make_tuple(c2.posZ(), getTracksSize(c2))); - // LOGF(info, "Mixed event collisions: Index = (%d,%d), tracks Size: (%d,%d), Z Vertex: (%f), Pool Bin: (%d)", c1.globalIndex(), c2.globalIndex(), getTracksSize(c1), getTracksSize(c2), c2.posZ(), poolBin); // For debug - entryDplusHadronPair(getDeltaPhi(assocParticle.phi(), trigDplus.phi()), assocParticle.eta() - trigDplus.eta(), trigDplus.pt(), assocParticle.pt(), poolBin); + int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); + bool isDplusPrompt = candidate.originMcGen() == RecoDecay::OriginType::Prompt; + entryDplusHadronPair(getDeltaPhi(particleAssoc.phi(), candidate.phi()), + particleAssoc.eta() - candidate.eta(), + candidate.pt(), + particleAssoc.pt(), + poolBin); + entryDplusHadronRecoInfo(MassDPlus, true); + entryDplusHadronGenInfo(isDplusPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); } } } diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 2800c2911fe..016c672f50e 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -64,7 +64,6 @@ struct HfCorrelatorDsHadronsSelCollision { using SelCollisions = soa::Join; using CandDsData = soa::Filtered>; using CandDsMcReco = soa::Filtered>; - using CandDsMcGen = soa::Join; Filter dsFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) != static_cast(0)) && (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); @@ -97,15 +96,15 @@ struct HfCorrelatorDsHadronsSelCollision { } PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsData, "Process Ds Collision Selection Data", true); - /// Code to select collisions with at least one Ds meson - for MC reco-level analysis - void processDsSelCollisionsMcRec(SelCollisions::iterator const& collision, - CandDsMcReco const& candidates) + /// Code to select collisions with at least one Ds meson - for MC-level analysis + void processDsSelCollisionsMc(SelCollisions::iterator const& collision, + CandDsMcReco const& candidates) { bool isSelColl = true; bool isDsFound = true; bool isSel8 = true; bool isNosameBunchPileUp = true; - if (doSelDsCollision) { + if (doSelDsCollision) { // to enable only for the MC reco part for (const auto& candidate : candidates) { if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin) { isDsFound = false; @@ -124,33 +123,7 @@ struct HfCorrelatorDsHadronsSelCollision { isSelColl = isDsFound && isSel8 && isNosameBunchPileUp; collisionsWithSelDs(isSelColl); } - PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsMcRec, "Process Ds Collision Selection MCRec", false); - - /// Code to select collisions with at least one Ds meson - for MC gen-level analysis - void processDsSelCollisionsMcGen(aod::McCollision const&, - CandDsMcGen const& mcParticles) - { - bool isSelColl = true; - bool isDsFound = true; - if (doSelDsCollision) { - for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kDS) { - isDsFound = false; - continue; - } - double yD = RecoDecay::y(particle.pVector(), MassDS); - if (std::abs(yD) > yCandMax || particle.pt() < ptCandMin) { - isDsFound = false; - continue; - } - isDsFound = true; - break; - } - } - isSelColl = isDsFound; - collisionsWithSelDs(isSelColl); - } - PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsMcGen, "Process Ds Collision Selection MCGen", false); + PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsMc, "Process Ds Collision Selection MCRec", false); }; /// Ds-Hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) @@ -163,15 +136,21 @@ struct HfCorrelatorDsHadrons { Produces entryDsCandGenInfo; Produces entryTrackRecoInfo; - Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; + Configurable fillHistoData{"fillHistoData", true, "Flag for filling histograms in data processes"}; + Configurable fillHistoMcRec{"fillHistoMcRec", true, "Flag for filling histograms in MC Rec processes"}; + Configurable fillHistoMcGen{"fillHistoMcGen", true, "Flag for filling histograms in MC Gen processes"}; + Configurable removeCollWSplitVtx{"removeCollWSplitVtx", false, "Flag for rejecting the splitted collisions"}; + Configurable useSel8{"useSel8", true, "Flag for applying sel8 for collision selection"}; + Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; + Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds (avoid the case of flag = 0, no outputMlScore)"}; Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; Configurable decayChannel{"decayChannel", 1, "Decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying D-meson efficiency weights"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; - Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; - Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; + Configurable dcaXYTrackMax{"dcaXYTrackMax", 2., "max. DCA_xy of tracks"}; + Configurable dcaZTrackMax{"dcaZTrackMax", 2., "max. DCA_z of tracks"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; Configurable ptCandMax{"ptCandMax", 50., "max. cand pT"}; Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; @@ -189,14 +168,14 @@ struct HfCorrelatorDsHadrons { ConfigurableAxis binsMultiplicity{"binsMultiplicity", {200, 0., 800.}, "Multiplicity"}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 6000.}, "Multiplicity as FT0M signal amplitude"}; ConfigurableAxis binsPosZ{"binsPosZ", {100, -10., 10.}, "primary vertex z coordinate"}; - ConfigurableAxis binsBdtScore{"binsBdtScore", {100, 0., 1.}, "Bdt output scores"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; HfHelper hfHelper; SliceCache cache; - using SelCollisionsWithDs = soa::Filtered>; // collisionFilter applied - using SelCollisionsWithDsMc = soa::Filtered>; // collisionFilter applied + using SelCollisionsWithDs = soa::Filtered>; // collisionFilter applied + // using SelCollisionsWithDsWithMc = soa::Filtered>; // collisionFilter applied + using SelCollisionsMc = soa::Join; using CandDsData = soa::Filtered>; // flagDsFilter applied using CandDsMcReco = soa::Filtered>; // flagDsFilter applied using CandDsMcGen = soa::Join; // flagDsFilter applied @@ -219,57 +198,64 @@ struct HfCorrelatorDsHadrons { AxisSpec axisMultiplicity = {binsMultiplicity, "Multiplicity"}; AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; AxisSpec axisPosZ = {binsPosZ, "PosZ"}; - AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisPoolBin = {binsPoolBin, "PoolBin"}; AxisSpec axisStatus = {15, 0.5, 15.5, "Selection status"}; // Histograms for data analysis - registry.add("hPtCand", "Ds candidates pt", {HistType::kTH1F, {axisPtD}}); - registry.add("hSelectionStatusDsToKKPi", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); - registry.add("hSelectionStatusDsToPiKK", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); - registry.add("hCountSelectionStatusDsToKKPiAndToPiKK", "Ds candidates selection", {HistType::kTH1F, {{1, -0.5, 0.5}}}); - registry.add("hEta", "Ds candidates eta", {HistType::kTH1F, {axisEta}}); - registry.add("hEtaVsPtCand", "Ds candidates etaVsPt", {HistType::kTH2F, {{axisEta}, {axisPtD}}}); - registry.add("hEtaVsPtPartAssoc", "Particles associated etaVsPt", {HistType::kTH2F, {{axisEta}, {axisPtHadron}}}); - registry.add("hPhi", "Ds candidates phi", {HistType::kTH1F, {axisPhi}}); - registry.add("hPhiVsPtCand", "Ds candidates phiVsPt", {HistType::kTH2F, {{axisPhi}, {axisPtD}}}); - registry.add("hPhiVsPtPartAssoc", "Particles associated phiVsPt", {HistType::kTH2F, {{axisPhi}, {axisPtHadron}}}); - registry.add("hMultiplicity", "Multiplicity", {HistType::kTH1F, {axisMultiplicity}}); - registry.add("hMultFT0M", "Multiplicity FT0M", {HistType::kTH1F, {axisMultFT0M}}); - registry.add("hZVtx", "z vertex", {HistType::kTH1F, {axisPosZ}}); - registry.add("hMassDsVsPt", "Ds candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); - registry.add("hMassDsData", "Ds candidates mass", {HistType::kTH1F, {axisMassD}}); - registry.add("hCollisionPoolBin", "Ds candidates collision pool bin", {HistType::kTH1F, {axisPoolBin}}); - registry.add("hDsPoolBin", "Ds candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); - registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); - registry.add("hCorrelSystematics", "Ds-h correlations systematic error evaluation", {HistType::kTHnSparseD, {{axisPhi}, {axisEta}, {axisPtD}, {axisPtHadron}, {axisMassD}, {axisBdtScore}, {axisBdtScore}}}); + if (fillHistoData) { + registry.add("hPtCand", "Ds candidates pt", {HistType::kTH1F, {axisPtD}}); + registry.add("hSelectionStatusDsToKKPi", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); + registry.add("hSelectionStatusDsToPiKK", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); + registry.add("hCountSelectionStatusDsToKKPiAndToPiKK", "Ds candidates selection", {HistType::kTH1F, {{1, -0.5, 0.5}}}); + registry.add("hEta", "Ds candidates eta", {HistType::kTH1F, {axisEta}}); + registry.add("hEtaVsPtCand", "Ds candidates etaVsPt", {HistType::kTH2F, {{axisEta}, {axisPtD}}}); + registry.add("hEtaVsPtPartAssoc", "Particles associated etaVsPt", {HistType::kTH2F, {{axisEta}, {axisPtHadron}}}); + registry.add("hPhi", "Ds candidates phi", {HistType::kTH1F, {axisPhi}}); + registry.add("hPhiVsPtCand", "Ds candidates phiVsPt", {HistType::kTH2F, {{axisPhi}, {axisPtD}}}); + registry.add("hPhiVsPtPartAssoc", "Particles associated phiVsPt", {HistType::kTH2F, {{axisPhi}, {axisPtHadron}}}); + registry.add("hMultiplicity", "Multiplicity", {HistType::kTH1F, {axisMultiplicity}}); + registry.add("hMultFT0M", "Multiplicity FT0M", {HistType::kTH1F, {axisMultFT0M}}); + registry.add("hZVtx", "z vertex", {HistType::kTH1F, {axisPosZ}}); + registry.add("hMassDsVsPt", "Ds candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassDsData", "Ds candidates mass", {HistType::kTH1F, {axisMassD}}); + registry.add("hCollisionPoolBin", "Ds candidates collision pool bin", {HistType::kTH1F, {axisPoolBin}}); + registry.add("hDsPoolBin", "Ds candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); + registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); + } // Histograms for MC Reco analysis - registry.add("hPtCandMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcRecSigPrompt", "Ds,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcRecSigNonPrompt", "Ds,Hadron candidates Non Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcRecBkg", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtParticleAssocVsCandMcRec", "Associated Particle - MC Rec", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); - registry.add("hPtPrimaryParticleAssocVsCandMcRec", "Associated Particle - MC Rec", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); - registry.add("hEtaMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisEta}}); - registry.add("hPhiMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPhi}}); - registry.add("hEtaMcRecBkg", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisEta}}); - registry.add("hPhiMcRecBkg", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPhi}}); - registry.add("hPtVsMultiplicityMcRecPrompt", "Multiplicity FT0M - MC Rec Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); - registry.add("hPtVsMultiplicityMcRecNonPrompt", "Multiplicity FT0M - MC Rec Non Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); - registry.add("hMassDsMcRec", "Ds candidates", {HistType::kTH1F, {axisMassD}}); - registry.add("hMassDsVsPtMcRec", "Ds signal candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); - registry.add("hMassDsMcRecSig", "Ds signal candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); - registry.add("hMassDsMcRecBkg", "Ds background candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); - registry.add("hFakeTracksMcRec", "Fake tracks - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + if (fillHistoMcRec) { + registry.add("hPtCandMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecSigPrompt", "Ds,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecSigNonPrompt", "Ds,Hadron candidates Non Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecBkg", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hSelectionStatusDsToKKPiMcRec", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); + registry.add("hSelectionStatusDsToPiKKMcRec", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); + registry.add("hCountSelectionStatusDsToKKPiAndToPiKKMcRec", "Ds candidates selection", {HistType::kTH1F, {{1, -0.5, 0.5}}}); + registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtParticleAssocVsCandMcRec", "Associated Particle - MC Rec", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); + registry.add("hPtPrimaryParticleAssocVsCandMcRec", "Associated Particle - MC Rec", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); + registry.add("hEtaMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisEta}}); + registry.add("hPhiMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPhi}}); + registry.add("hEtaMcRecBkg", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisEta}}); + registry.add("hPhiMcRecBkg", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPhi}}); + registry.add("hPtVsMultiplicityMcRecPrompt", "Multiplicity FT0M - MC Rec Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); + registry.add("hPtVsMultiplicityMcRecNonPrompt", "Multiplicity FT0M - MC Rec Non Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); + registry.add("hMassDsMcRec", "Ds candidates", {HistType::kTH1F, {axisMassD}}); + registry.add("hMassDsVsPtMcRec", "Ds signal candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassDsMcRecSig", "Ds signal candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassDsMcRecBkg", "Ds background candidates - MC Reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hFakeTracksMcRec", "Fake tracks - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + } // Histograms for MC Gen analysis - registry.add("hPtCandMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles - MC Gen Prompt", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hEtaMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); - registry.add("hPhiMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); - registry.add("hMultFT0AMcGen", "Ds,Hadron multiplicity FT0A - MC Gen", {HistType::kTH1F, {axisMultiplicity}}); + if (fillHistoMcGen) { + registry.add("hPtCandMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles - MC Gen Prompt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hEtaMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); + registry.add("hPhiMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); + registry.add("hMultFT0AMcGen", "Ds,Hadron multiplicity FT0A - MC Gen", {HistType::kTH1F, {axisMultiplicity}}); + } } /// Fill histograms of quantities independent from the daugther-mass hypothesis for data @@ -339,7 +325,7 @@ struct HfCorrelatorDsHadrons { /// Fill histograms of quantities for the Ds signal for MC reco-level /// \param particle is particle, Ds template - void fillHistoMcGen(const T1& particle) + void fillMcGenHisto(const T1& particle) { registry.fill(HIST("hPtCandMcGen"), particle.pt()); registry.fill(HIST("hEtaMcGen"), particle.eta()); @@ -447,6 +433,7 @@ struct HfCorrelatorDsHadrons { // MC reco level bool isDsPrompt = false; bool isDsSignal = false; + bool isCorrectInvMassHypo = false; bool isDecayChan = false; bool isAlreadyFilledEvent = false; float multiplicityFT0M = collision.multFT0M(); @@ -461,6 +448,9 @@ struct HfCorrelatorDsHadrons { continue; } + auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); + isCorrectInvMassHypo = ((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs)); + double efficiencyWeightD = 1.; if (applyEfficiency) { efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())); @@ -468,7 +458,7 @@ struct HfCorrelatorDsHadrons { std::vector outputMl = {-1., -1., -1.}; - if (isDsSignal && isDecayChan) { + if (isDsSignal && isDecayChan && isCorrectInvMassHypo) { fillHistoMcRecSig(candidate, multiplicityFT0M); if (candidate.isSelDsToKKPi() >= selectionFlagDs) { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { @@ -477,7 +467,7 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hMassDsMcRec"), hfHelper.invMassDsToKKPi(candidate), efficiencyWeightD); registry.fill(HIST("hMassDsMcRecSig"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeightD); registry.fill(HIST("hMassDsVsPtMcRec"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeightD); - registry.fill(HIST("hSelectionStatusDsToKKPi"), candidate.isSelDsToKKPi()); + registry.fill(HIST("hSelectionStatusDsToKKPiMcRec"), candidate.isSelDsToKKPi()); entryDsCandRecoInfo(hfHelper.invMassDsToKKPi(candidate), candidate.pt(), outputMl[0], outputMl[2]); entryDsCandGenInfo(isDsPrompt); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { @@ -487,7 +477,7 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hMassDsMcRec"), hfHelper.invMassDsToPiKK(candidate), efficiencyWeightD); registry.fill(HIST("hMassDsMcRecSig"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeightD); registry.fill(HIST("hMassDsVsPtMcRec"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeightD); - registry.fill(HIST("hSelectionStatusDsToPiKK"), candidate.isSelDsToPiKK()); + registry.fill(HIST("hSelectionStatusDsToPiKKMcRec"), candidate.isSelDsToPiKK()); entryDsCandRecoInfo(hfHelper.invMassDsToPiKK(candidate), candidate.pt(), outputMl[0], outputMl[2]); entryDsCandGenInfo(isDsPrompt); } @@ -525,7 +515,7 @@ struct HfCorrelatorDsHadrons { bool isPhysicalPrimary = false; int trackOrigin = -1; // DsToKKPi and DsToPiKK division - if (candidate.isSelDsToKKPi() >= selectionFlagDs) { + if (isCorrectInvMassHypo && candidate.isSelDsToKKPi() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), @@ -550,7 +540,7 @@ struct HfCorrelatorDsHadrons { } } entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); - } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { + } else if (isCorrectInvMassHypo && candidate.isSelDsToPiKK() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), @@ -582,71 +572,111 @@ struct HfCorrelatorDsHadrons { } PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcRec, "Process MC Reco mode", false); + Preslice perCollisionCandMc = o2::aod::mcparticle::mcCollisionId; + PresliceUnsorted> collPerCollMc = o2::aod::mccollisionlabel::mcCollisionId; + /// Ds-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(SelCollisionsWithDsMc::iterator const& mcCollision, + void processMcGen(SelCollisionsMc const& mcCollisions, + soa::Join const& collisions, CandDsMcGen const& mcParticles) { BinningTypeMcGen corrBinningMcGen{{zPoolBins, multPoolBins}, true}; - int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); - registry.fill(HIST("hCollisionPoolBin"), poolBin); - registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); - bool isDsPrompt = false; - bool isDecayChan = false; - int trackOrigin = -1; - // MC gen level - for (const auto& particle : mcParticles) { - // check if the particle is Ds - if (std::abs(particle.pdgCode()) != Pdg::kDS) { + + for (const auto& mcCollision : mcCollisions) { + + // auto mcCollision = collision.template mcCollision_as>(); + + int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); + registry.fill(HIST("hCollisionPoolBin"), poolBin); + registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); + + const auto groupedMcParticles = mcParticles.sliceBy(perCollisionCandMc, mcCollision.globalIndex()); + const auto groupedCollisions = collisions.sliceBy(collPerCollMc, mcCollision.globalIndex()); + + if (groupedCollisions.size() < 1) { // Skipping MC events that have no reconstructed collisions continue; } - if ((std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (particle.flagMcDecayChanGen() == decayChannel)) { - double yD = RecoDecay::y(particle.pVector(), MassDS); - if (std::abs(yD) > yCandGenMax || particle.pt() < ptCandMin || particle.pt() > ptCandMax) { + if (groupedCollisions.size() > 1 && removeCollWSplitVtx) { // Skipping MC events that have more than one reconstructed collision + continue; + } + + /// loop over reconstructed collisions + for (const auto& collision : groupedCollisions) { + + // reco collision selection + if (useSel8 && !collision.sel8()) { continue; } - fillHistoMcGen(particle); - // prompt and non-prompt division - isDsPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; - isDecayChan = particle.flagMcDecayChanGen() == decayChannel; - std::vector listDaughters{}; - std::array arrDaughDsPDG = {+kKPlus, -kKPlus, kPiPlus}; - std::array prongsId; - listDaughters.clear(); - RecoDecay::getDaughters(particle, &listDaughters, arrDaughDsPDG, 2); - int counterDaughters = 0; - if (listDaughters.size() == 3) { - for (const auto& dauIdx : listDaughters) { - auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); - counterDaughters += 1; - prongsId[counterDaughters - 1] = daughI.globalIndex(); - } + if (std::abs(collision.posZ()) > 10.) { + continue; } - // Ds Hadron correlation dedicated section - for (const auto& particleAssoc : mcParticles) { - if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { - continue; - } - if (particleAssoc.globalIndex() == prongsId[0] || particleAssoc.globalIndex() == prongsId[1] || particleAssoc.globalIndex() == prongsId[2]) { - continue; - } - if ((std::abs(particleAssoc.pdgCode()) != kElectron) && (std::abs(particleAssoc.pdgCode()) != kMuonMinus) && (std::abs(particleAssoc.pdgCode()) != kPiPlus) && (std::abs(particleAssoc.pdgCode()) != kKPlus) && (std::abs(particleAssoc.pdgCode()) != kProton)) { - continue; - } - if (!particleAssoc.isPhysicalPrimary()) { - continue; + if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (!collision.has_mcCollision()) { + registry.fill(HIST("hFakeCollision"), 0.); + continue; + } + + bool isDsPrompt = false; + bool isDecayChan = false; + int trackOrigin = -1; + + // MC gen level + for (const auto& particle : groupedMcParticles) { + // check if the particle is Ds + if ((std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (particle.flagMcDecayChanGen() == decayChannel)) { + double yD = RecoDecay::y(particle.pVector(), MassDS); + if (std::abs(yD) > yCandGenMax || particle.pt() < ptCandMin || particle.pt() > ptCandMax) { + continue; + } + fillMcGenHisto(particle); + // prompt and non-prompt division + isDsPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; + isDecayChan = particle.flagMcDecayChanGen() == decayChannel; + std::vector listDaughters{}; + std::array arrDaughDsPDG = {+kKPlus, -kKPlus, kPiPlus}; + std::array prongsId; + listDaughters.clear(); + RecoDecay::getDaughters(particle, &listDaughters, arrDaughDsPDG, 2); + int counterDaughters = 0; + if (listDaughters.size() == 3) { + for (const auto& dauIdx : listDaughters) { + // auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); + auto daughI = groupedMcParticles.rawIteratorAt(dauIdx - groupedMcParticles.offset()); + counterDaughters += 1; + prongsId[counterDaughters - 1] = daughI.globalIndex(); + } + } + // Ds Hadron correlation dedicated section + for (const auto& particleAssoc : groupedMcParticles) { + if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { + continue; + } + if (particleAssoc.globalIndex() == prongsId[0] || particleAssoc.globalIndex() == prongsId[1] || particleAssoc.globalIndex() == prongsId[2]) { + continue; + } + if ((std::abs(particleAssoc.pdgCode()) != kElectron) && (std::abs(particleAssoc.pdgCode()) != kMuonMinus) && (std::abs(particleAssoc.pdgCode()) != kPiPlus) && (std::abs(particleAssoc.pdgCode()) != kKPlus) && (std::abs(particleAssoc.pdgCode()) != kProton)) { + continue; + } + if (!particleAssoc.isPhysicalPrimary()) { + continue; + } + // trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); + trackOrigin = RecoDecay::getCharmHadronOrigin(groupedMcParticles, particleAssoc, true); + registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); + entryDsHadronPair(getDeltaPhi(particleAssoc.phi(), particle.phi()), + particleAssoc.eta() - particle.eta(), + particle.pt(), + particleAssoc.pt(), + poolBin); + entryDsHadronRecoInfo(MassDS, true, isDecayChan); + entryDsHadronGenInfo(isDsPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); + } } - trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); - registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); - entryDsHadronPair(getDeltaPhi(particleAssoc.phi(), particle.phi()), - particleAssoc.eta() - particle.eta(), - particle.pt(), - particleAssoc.pt(), - poolBin); - entryDsHadronRecoInfo(MassDS, true, isDecayChan); - entryDsHadronGenInfo(isDsPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); } - } - } + } // end loop reconstructed collision + } // end loop generated collision } PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcGen, "Process MC Gen mode", false); @@ -809,18 +839,15 @@ struct HfCorrelatorDsHadrons { } PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcRecME, "Process Mixed Event MC Rec", false); - void processMcGenME(SelCollisionsWithDsMc const& collisions, + void processMcGenME(SelCollisionsMc const& collisions, CandDsMcGen const& mcParticles) { BinningTypeMcGen corrBinningMcGen{{zPoolBins, multPoolBins}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { int poolBin = corrBinningMcGen.getBin(std::make_tuple(c1.posZ(), c1.multMCFT0A())); for (const auto& [candidate, particleAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (std::abs(candidate.pdgCode()) != Pdg::kDS) { - continue; - } if ((std::abs(candidate.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (candidate.flagMcDecayChanGen() == decayChannel)) { double yD = RecoDecay::y(candidate.pVector(), MassDS); if (std::abs(yD) > yCandGenMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { diff --git a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx new file mode 100644 index 00000000000..91bc73c3edd --- /dev/null +++ b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx @@ -0,0 +1,251 @@ +// Copyright 2019-2020 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. + +/// \file correlatorHfeHadrons.cxx +/// \brief Heavy Flavour electron-Hadron correaltor task - data-like, MC-reco and MC-Kine analyses. +/// \author Rashi Gupta , IIT Indore +/// \author Ravindra Singh , IIT Indore + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::hf_sel_electron; + +// definition of ME variables and new types +std::vector zBins{VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}; +std::vector multBins{VARIABLE_WIDTH, 0., 200., 500.0, 5000.}; +std::vector multBinsMcGen{VARIABLE_WIDTH, 0., 20., 50.0, 500.}; // In MCGen multiplicity is defined by counting primaries +using BinningType = ColumnBinningPolicy>; +BinningType corrBinning{{zBins, multBins}, true}; + +struct HfCorrelatorHfeHadrons { + SliceCache cache; + Produces entryElectronHadronPair; + // Configurables + // Event Selection + Configurable zPvPosMax{"zPvPosMax", 10., "Maximum z of the primary vertex (cm)"}; + Configurable isRun3{"isRun3", true, "Data is from Run3 or Run2"}; + + // Associated Hadron selection + Configurable ptTrackMin{"ptTrackMin", 0.1f, "Transverse momentum range for associated hadron tracks"}; + Configurable etaTrackMax{"etaTrackMax", 0.8f, "Eta range for associated hadron tracks"}; + Configurable etaTrackMin{"etaTrackMin", -0.8f, "Eta range for associated hadron tracks"}; + Configurable dcaXYTrackMax{"dcaXYTrackMax", 0.5f, "DCA XY cut"}; + Configurable dcaZTrackMax{"dcaZTrackMax", 1.0f, "DCA Z cut"}; + + // Electron hadron correlation condition + Configurable ptCondition{"ptCondition", true, "Electron pT should be greater than associate particle pT"}; + + using TableCollisions = o2::soa::Filtered>; + using TableCollision = TableCollisions::iterator; + using TableTracks = o2::soa::Join; + + using McTableCollisions = o2::soa::Filtered>; + using McTableCollision = McTableCollisions::iterator; + using McTableTracks = soa::Join; + + Filter CollisionFilter = nabs(aod::collision::posZ) < zPvPosMax && aod::collision::numContrib > (uint16_t)1; + Preslice perCol = aod::track::collisionId; + Preslice perCollision = aod::hf_sel_electron::collisionId; + HistogramConfigSpec hCorrelSpec{HistType::kTHnSparseD, {{30, 0., 30.}, {20, 0., 20.}, {32, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf}, {50, -1.8, 1.8}}}; + + HistogramRegistry registry{ + "registry", + {{"hInclusiveEHCorrel", "Sparse for Delta phi and Delta eta Inclusive Electron with Hadron;p_{T}^{e} (GeV#it{/c});p_{T}^{h} (GeV#it{/c});#Delta#varphi;#Delta#eta;", hCorrelSpec}, + {"hptElectron", "hptElectron", {HistType::kTH1F, {{100, 0, 100}}}}, + {"hMixEventInclusiveEHCorrl", "Sparse for mix event Delta phi and Delta eta Inclusive Electron with Hadron;p_{T}^{e} (GeV#it{/c});p_{T}^{h} (GeV#it{/c});#Delta#varphi;#Delta#eta;", hCorrelSpec}}}; + + void init(InitContext&) + { + registry.get(HIST("hInclusiveEHCorrel"))->Sumw2(); + registry.get(HIST("hMixEventInclusiveEHCorrl"))->Sumw2(); + } + + // Associated Hadron Selection Cut + template + bool selAssoHadron(T const& track) + { + if (!track.isGlobalTrackWoDCA()) { + return false; + } + + if (std::abs(track.dcaXY()) > dcaXYTrackMax || std::abs(track.dcaZ()) > dcaZTrackMax) { + return false; + } + if (track.eta() < etaTrackMin || track.eta() > etaTrackMax) { + return false; + } + if (track.pt() < ptTrackMin) { + return false; + } + return true; + } + + // Electron-hadron Correlation + template + void fillCorrelation(CollisionType const& collision, ElectronType const& electron, TracksType const& tracks) + { + if (!(isRun3 ? collision.sel8() : (collision.sel7() && collision.alias_bit(kINT7)))) + return; + int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFV0M())); + + // Construct Deta Phi between electrons and hadrons + + double ptElectron = -999; + double phiElectron = -999; + double etaElectron = -999; + + for (const auto& eTrack : electron) { + ptElectron = eTrack.ptTrack(); + phiElectron = eTrack.phiTrack(); + etaElectron = eTrack.etaTrack(); + double deltaPhi = -999; + double deltaEta = -999; + double ptHadron = -999; + double etaHadron = -999; + double phiHadron = -999; + if (!eTrack.isEmcal()) + continue; + + registry.fill(HIST("hptElectron"), ptElectron); + for (const auto& hTrack : tracks) { + + if (hTrack.globalIndex() == eTrack.globalIndex()) + continue; + // Apply Hadron cut + if (!selAssoHadron(hTrack)) + continue; + ptHadron = hTrack.pt(); + phiHadron = hTrack.phi(); + etaHadron = hTrack.eta(); + + if (ptCondition && (ptElectron < ptHadron)) + continue; + deltaPhi = RecoDecay::constrainAngle(phiElectron - phiHadron, -o2::constants::math::PIHalf); + deltaEta = etaElectron - etaHadron; + registry.fill(HIST("hInclusiveEHCorrel"), ptElectron, ptHadron, deltaPhi, deltaEta); + entryElectronHadronPair(deltaPhi, deltaEta, ptElectron, ptHadron, poolBin); + } + } + } + + // mix event electron-hadron correlation + + template + void fillMixCorrelation(CollisionType1 const& c1, CollisionType2 const& c2, ElectronType const& tracks1, TracksType const& tracks2) + { + if (!(isRun3 ? c2.sel8() : (c2.sel7() && c2.alias_bit(kINT7)))) + return; + double ptElectronMix = -999; + double phiElectronMix = -999; + double etaElectronMix = -999; + double deltaPhiMix = -999; + double deltaEtaMix = -999; + double ptHadronMix = -999; + double etaHadronMix = -999; + double phiHadronMix = -999; + int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); + for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!t1.isEmcal()) + continue; + ptHadronMix = t2.pt(); + ptElectronMix = t1.ptTrack(); + phiElectronMix = t1.phiTrack(); + phiHadronMix = t2.phi(); + etaElectronMix = t1.etaTrack(); + etaHadronMix = t2.eta(); + if (!selAssoHadron(t2)) + continue; + if (ptCondition && (ptElectronMix < ptHadronMix)) + continue; + deltaPhiMix = RecoDecay::constrainAngle(phiElectronMix - phiHadronMix, -o2::constants::math::PIHalf); + deltaEtaMix = etaElectronMix - etaHadronMix; + + registry.fill(HIST("hMixEventInclusiveEHCorrl"), ptElectronMix, ptHadronMix, deltaPhiMix, deltaEtaMix); + entryElectronHadronPair(deltaPhiMix, deltaEtaMix, ptElectronMix, ptHadronMix, poolBin); + } + } + + // ======= Process starts for Data, Same event ============ + + void processData(TableCollision const& collision, + aod::HfSelEl const& electron, + TableTracks const& tracks) + { + fillCorrelation(collision, electron, tracks); + } + + PROCESS_SWITCH(HfCorrelatorHfeHadrons, processData, "Process for Data", true); + + // ======= Process starts for McRec, Same event ============ + + void processMcRec(McTableCollision const& mcCollision, + aod::HfSelEl const& mcElectron, + McTableTracks const& mcTracks) + { + fillCorrelation(mcCollision, mcElectron, mcTracks); + } + + PROCESS_SWITCH(HfCorrelatorHfeHadrons, processMcRec, "Process MC Reco mode", false); + + // ====================== Implement Event mixing on Data =================================== + + void processDataMixedEvent(TableCollisions const& collision, aod::HfSelEl const& electron, TableTracks const& tracks) + { + auto tracksTuple = std::make_tuple(electron, tracks); + Pair pair{corrBinning, 5, -1, collision, tracksTuple, &cache}; + + // loop over the rows of the new table + for (auto& [c1, tracks1, c2, tracks2] : pair) { + + fillMixCorrelation(c1, c2, tracks1, tracks2); + } + } + PROCESS_SWITCH(HfCorrelatorHfeHadrons, processDataMixedEvent, "Process Mixed Event Data", false); + + // ====================== Implement Event mixing on McRec =================================== + + void processMcRecMixedEvent(McTableCollisions const& mccollision, aod::HfSelEl const& electron, McTableTracks const& mcTracks) + { + auto tracksTuple = std::make_tuple(electron, mcTracks); + Pair pairMcRec{corrBinning, 5, -1, mccollision, tracksTuple, &cache}; + + // loop over the rows of the new table + for (auto& [c1, tracks1, c2, tracks2] : pairMcRec) { + + fillMixCorrelation(c1, c2, tracks1, tracks2); + } + } + PROCESS_SWITCH(HfCorrelatorHfeHadrons, processMcRecMixedEvent, "Process Mixed Event MC Reco mode", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx index aeb92144fa9..3a2bd3434e8 100644 --- a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx +++ b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx @@ -43,73 +43,80 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::analysis::femtoDream; -struct femtoDreamProducer { +struct HfFemtoDreamProducer { Produces outputCollision; Produces rowCandCharmHad; - Produces rowCandMCCharmHad; + Produces rowCandMcCharmHad; Produces rowCandCharmHadGen; Produces outputPartsIndex; - Produces outputMCCollision; - Produces outputCollsMCLabels; + Produces outputMcCollision; + Produces outputCollsMcLabels; Produces outputParts; - Produces outputPartsMC; + Produces outputPartsMc; Produces outputDebugParts; - Produces outputPartsMCLabels; - Produces outputDebugPartsMC; - Produces outputPartsExtMCLabels; + Produces outputPartsMcLabels; + Produces outputDebugPartsMc; + Produces outputPartsExtMcLabels; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; - Configurable isDebug{"isDebug", true, "Enable Debug tables"}; - Configurable isRun3{"isRun3", true, "Running on Run3 or pilot"}; - Configurable isForceGRP{"isForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; + // Configurable isForceGRP{"isForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; /// Event selection - Configurable doPvRefit{"doPvRefit", false, "do PV refit excluding the considered track"}; - Configurable evtZvtx{"evtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + // Configurable evtZvtx{"evtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + // Configurable evtTriggerCheck{"evtTriggerCheck", true, "Evt sel: check for trigger"}; + // Configurable evtTriggerSel{"evtTriggerSel", kINT7, "Evt sel: trigger"}; + // Configurable evtOfflineCheck{"evtOfflineCheck", false, "Evt sel: check for offline selection"}; + // Configurable evtAddOfflineCheck{"evtAddOfflineCheck", false, "Evt sel: additional checks for offline selection (not part of sel8 yet)"}; + + Configurable evtAddOfflineCheck{"evtAddOfflineCheck", false, "Evt sel: additional checks for offline selection (not part of sel8 yet)"}; + Configurable evtOfflineCheck{"evtOfflineCheck", false, "Evt sel: check for offline selection"}; Configurable evtTriggerCheck{"evtTriggerCheck", true, "Evt sel: check for trigger"}; Configurable evtTriggerSel{"evtTriggerSel", kINT7, "Evt sel: trigger"}; - Configurable evtOfflineCheck{"evtOfflineCheck", false, "Evt sel: check for offline selection"}; - Configurable evtAddOfflineCheck{"evtAddOfflineCheck", false, "Evt sel: additional checks for offline selection (not part of sel8 yet)"}; + Configurable evtZvtx{"evtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + + Configurable isDebug{"isDebug", true, "Enable Debug tables"}; + Configurable isRun3{"isRun3", true, "Running on Run3 or pilot"}; /// Lc table - Configurable useCent{"useCent", false, "Enable centrality for lc"}; Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable useCent{"useCent", false, "Enable centrality for lc"}; - Configurable trkRejectNotPropagated{"trkRejectNotPropagated", false, "True: reject not propagated tracks"}; Configurable trkPDGCode{"trkPDGCode", 2212, "PDG code of the selected track for Monte Carlo truth"}; Configurable> trkCharge{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kSign, "trk"), std::vector{-1, 1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kSign, "Track selection: ")}; - Configurable> trkPtmin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMin, "trk"), std::vector{0.5f, 0.4f, 0.6f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "Track selection: ")}; - Configurable> trkPtmax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMax, "trk"), std::vector{5.4f, 5.6f, 5.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMax, "Track selection: ")}; - Configurable> trkEta{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "trk"), std::vector{0.8f, 0.7f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Track selection: ")}; - Configurable> trkTPCnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCnClsMin, "trk"), std::vector{80.f, 70.f, 60.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCnClsMin, "Track selection: ")}; - Configurable> trkTPCfCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCfClsMin, "trk"), std::vector{0.7f, 0.83f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCfClsMin, "Track selection: ")}; - Configurable> trkTPCcRowsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCcRowsMin, "trk"), std::vector{70.f, 60.f, 80.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCcRowsMin, "Track selection: ")}; - Configurable> trkTPCsCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCsClsMax, "trk"), std::vector{0.1f, 160.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCsClsMax, "Track selection: ")}; - Configurable> trkITSnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsMin, "trk"), std::vector{-1.f, 2.f, 4.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsMin, "Track selection: ")}; - Configurable> trkITSnclsIbMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsIbMin, "trk"), std::vector{-1.f, 1.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsIbMin, "Track selection: ")}; Configurable> trkDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "trk"), std::vector{0.1f, 3.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Track selection: ")}; Configurable> trkDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "trk"), std::vector{0.2f, 3.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Track selection: ")}; + Configurable> trkEta{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "trk"), std::vector{0.8f, 0.7f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Track selection: ")}; + Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID"}; Configurable> trkPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "trk"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; Configurable trkPIDnSigmaOffsetTPC{"trkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; Configurable trkPIDnSigmaOffsetTOF{"trkPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; - Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID"}; + Configurable> trkPtmax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMax, "trk"), std::vector{5.4f, 5.6f, 5.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMax, "Track selection: ")}; + Configurable> trkPtmin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMin, "trk"), std::vector{0.5f, 0.4f, 0.6f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "Track selection: ")}; + Configurable> trkTPCcRowsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCcRowsMin, "trk"), std::vector{70.f, 60.f, 80.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCcRowsMin, "Track selection: ")}; + Configurable> trkTPCfCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCfClsMin, "trk"), std::vector{0.7f, 0.83f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCfClsMin, "Track selection: ")}; + Configurable> trkTPCnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCnClsMin, "trk"), std::vector{80.f, 70.f, 60.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCnClsMin, "Track selection: ")}; + Configurable> trkTPCsCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCsClsMax, "trk"), std::vector{0.1f, 160.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCsClsMax, "Track selection: ")}; + Configurable> trkITSnclsIbMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsIbMin, "trk"), std::vector{-1.f, 1.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsIbMin, "Track selection: ")}; + Configurable> trkITSnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsMin, "trk"), std::vector{-1.f, 2.f, 4.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsMin, "Track selection: ")}; using CandidateLc = soa::Join; - using CandidateLcMC = soa::Join; + using CandidateLcMc = soa::Join; using FemtoFullCollision = soa::Join::iterator; - using FemtoFullCollisionMC = soa::Join::iterator; - using FemtoFullMCgenCollisions = soa::Join; - using FemtoFullMCgenCollision = FemtoFullMCgenCollisions::iterator; + using FemtoFullCollisionMc = soa::Join::iterator; + using FemtoFullMcgenCollisions = soa::Join; + using FemtoFullMcgenCollision = FemtoFullMcgenCollisions::iterator; using FemtoHFTracks = soa::Join; using FemtoHFTrack = FemtoHFTracks::iterator; + using FemtoHFMcTracks = soa::Join; + using FemtoHFMcTrack = FemtoHFMcTracks::iterator; - using GeneratedMC = soa::Filtered>; + using GeneratedMc = soa::Filtered>; FemtoDreamCollisionSelection colCuts; FemtoDreamTrackSelection trackCuts; @@ -120,15 +127,17 @@ struct femtoDreamProducer { HistogramRegistry TrackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; HfHelper hfHelper; - int runNumber; + float magField; + int runNumber; + Service ccdb; /// Accessing the CCDB o2::base::MatLayerCylSet* lut; // if (doPvRefit){ lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut));} //! may be it useful, will check later void init(InitContext&) { - std::array processes = {doprocessDataCharmHad, doprocessMCCharmHad, doprocessDataCharmHadWithML, doprocessMCCharmHadWithML, doprocessMCCharmHadGen}; + std::array processes = {doprocessDataCharmHad, doprocessMcCharmHad, doprocessDataCharmHadWithML, doprocessMcCharmHadWithML, doprocessMcCharmHadGen}; if (std::accumulate(processes.begin(), processes.end(), 0) != 1) { LOGP(fatal, "One and only one process function must be enabled at a time."); } @@ -170,41 +179,7 @@ struct femtoDreamProducer { /// Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T void getMagneticFieldTesla(aod::BCsWithTimestamps::iterator bc) { - // auto bc = col.bc_as(); initCCDB(bc, runNumber, ccdb, !isRun3 ? ccdbPathGrp : ccdbPathGrpMag, lut, !isRun3); - - // // TODO done only once (and not per run). Will be replaced by CCDBConfigurable - // // get magnetic field for run - // if (runNumber == bc.runNumber()) - // return; - // auto timestamp = bc.timestamp(); - // float output = -999; - // - // if (isRun3 && !isForceGRP) { - // static o2::parameters::GRPMagField* grpo = nullptr; - // grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); - // if (grpo == nullptr) { - // LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); - // return; - // } - // LOGF(info, "Retrieved GRP for timestamp %llu with L3 ", timestamp, grpo->getL3Current()); - // // taken from GRP onject definition of getNominalL3Field; update later to something smarter (mNominalL3Field = std::lround(5.f * mL3Current / 30000.f);) - // auto NominalL3Field = std::lround(5.f * grpo->getL3Current() / 30000.f); - // output = 0.1 * (NominalL3Field); - // - // } else { - // - // static o2::parameters::GRPObject* grpo = nullptr; - // grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); - // if (grpo == nullptr) { - // LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); - // return; - // } - // LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); - // output = 0.1 * (grpo->getNominalL3Field()); - // } - // magField = output; - // runNumber = bc.runNumber(); } template @@ -231,67 +206,77 @@ struct femtoDreamProducer { } template - void fillMCParticle(CollisionType const& col, ParticleType const& particle, o2::aod::femtodreamparticle::ParticleType fdparttype) + void fillMcParticle(CollisionType const& col, ParticleType const& particle, o2::aod::femtodreamparticle::ParticleType fdparttype) { if (particle.has_mcParticle()) { // get corresponding MC particle and its info - auto particleMC = particle.mcParticle(); - auto pdgCode = particleMC.pdgCode(); + auto particleMc = particle.mcParticle(); + auto pdgCode = particleMc.pdgCode(); int particleOrigin = 99; int pdgCodeMother = -1; - // get list of mothers - // could be empty (for example in case of injected light nuclei) - auto motherparticlesMC = particleMC.template mothers_as(); + // get list of mothers, but it could be empty (for example in case of injected light nuclei) + auto motherparticlesMc = particleMc.template mothers_as(); // check pdg code - if (std::abs(pdgCode) == abs(trkPDGCode.value)) { - if ((col.has_mcCollision() && (particleMC.mcCollisionId() != col.mcCollisionId())) || !col.has_mcCollision()) { + // if this fails, the particle is a fake + if (abs(pdgCode) == abs(trkPDGCode.value)) { + // check first if particle is from pile up + // check if the collision associated with the particle is the same as the analyzed collision by checking their Ids + if ((col.has_mcCollision() && (particleMc.mcCollisionId() != col.mcCollisionId())) || !col.has_mcCollision()) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kWrongCollision; - } else if (particleMC.isPhysicalPrimary()) { + // check if particle is primary + } else if (particleMc.isPhysicalPrimary()) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kPrimary; - } else if (particleMC.getGenStatusCode() == -1) { + // check if particle is secondary + // particle is from a decay -> getProcess() == 4 + // particle is generated during transport -> getGenStatusCode() == -1 + // list of mothers is not empty + } else if (particleMc.getProcess() == 4 && particleMc.getGenStatusCode() == -1 && !motherparticlesMc.empty()) { + // get direct mother + auto motherparticleMc = motherparticlesMc.front(); + pdgCodeMother = motherparticleMc.pdgCode(); + particleOrigin = checkDaughterType(fdparttype, motherparticleMc.pdgCode()); + // check if particle is material + // particle is from inelastic hadronic interaction -> getProcess() == 23 + // particle is generated during transport -> getGenStatusCode() == -1 + } else if (particleMc.getProcess() == 23 && particleMc.getGenStatusCode() == -1) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kMaterial; - } else if (!motherparticlesMC.empty()) { - // get direct mother of the particle - auto motherparticleMC = motherparticlesMC.front(); - pdgCodeMother = motherparticleMC.pdgCode(); - if (motherparticleMC.isPhysicalPrimary() && particleMC.getProcess() == 4) { - particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); - } + // cross check to see if we missed a case } else { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kElse; } + // if pdg code is wrong, particle is fake } else { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kFake; } - outputPartsMC(particleOrigin, pdgCode, particleMC.pt(), particleMC.eta(), particleMC.phi()); - outputPartsMCLabels(outputPartsMC.lastIndex()); + outputPartsMc(particleOrigin, pdgCode, particleMc.pt(), particleMc.eta(), particleMc.phi()); + outputPartsMcLabels(outputPartsMc.lastIndex()); if (isDebug) { - outputPartsExtMCLabels(outputPartsMC.lastIndex()); - outputDebugPartsMC(pdgCodeMother); + outputPartsExtMcLabels(outputPartsMc.lastIndex()); + outputDebugPartsMc(pdgCodeMother); } } else { - outputPartsMCLabels(-1); + outputPartsMcLabels(-1); if (isDebug) { - outputPartsExtMCLabels(-1); + outputPartsExtMcLabels(-1); } } } template - void fillMCCollision(CollisionType const& col) + void fillMcCollision(CollisionType const& col) { if (col.has_mcCollision()) { - auto genMCcol = col.template mcCollision_as(); - outputMCCollision(genMCcol.multMCNParticlesEta08()); - outputCollsMCLabels(outputMCCollision.lastIndex()); + // auto genMCcol = col.template mcCollision_as(); + // outputMcCollision(genMCcol.multMCNParticlesEta08()); + outputCollsMcLabels(outputMcCollision.lastIndex()); } else { - outputCollsMCLabels(-1); + outputCollsMcLabels(-1); } } - template - bool fillTracksForCharmHadron(TrackType const& tracks, FemtoHFTrack const& prong0, FemtoHFTrack const& prong1, FemtoHFTrack const& prong2, int candSize) + template + bool fillTracksForCharmHadron(CollisionType const& col, TrackType const& tracks, ProngType const& prong0, ProngType const& prong1, ProngType const& prong2, int candSize) { std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children @@ -330,17 +315,14 @@ struct femtoDreamProducer { fillDebugParticle(track); } - if constexpr (isMC) { - fillMCParticle(track, o2::aod::femtodreamparticle::ParticleType::kTrack); - // if constexpr (isMC) { - // fillMCParticle(col, track, o2::aod::femtodreamparticle::ParticleType::kTrack); - // } + if constexpr (isMc) { + fillMcParticle(col, track, o2::aod::femtodreamparticle::ParticleType::kTrack); } } return fIsTrackFilled; } - template + template void fillCharmHadronTable(CollisionType const& col, TrackType const& tracks, CandType const& candidates) { const auto vtxZ = col.posZ(); @@ -394,9 +376,9 @@ struct femtoDreamProducer { outputMlPiKP.at(2) = candidate.mlProbLcToPiKP()[2]; /// non-prompt score } } - auto trackPos1 = candidate.template prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.template prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.template prong2_as(); // positive daughter (negative for the antiparticles) + auto trackPos1 = candidate.template prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.template prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.template prong2_as(); // positive daughter (negative for the antiparticles) auto fillTable = [&](int CandFlag, int FunctionSelection, @@ -406,12 +388,15 @@ struct femtoDreamProducer { if (FunctionSelection >= 1){ // Fill tracks if it is not filled for Lc Candidate in an event if (!isTrackFilled) { - isTrackFilled = fillTracksForCharmHadron(tracks, trackPos1, trackNeg, trackPos2, sizeCand); + isTrackFilled = fillTracksForCharmHadron(col, tracks, trackPos1, trackNeg, trackPos2, sizeCand); - // If track filling was successful, fill the collision table - if (isTrackFilled) { - outputCollision(vtxZ, mult, multNtr, spher, magField); + // If track filling was successful, fill the collision table + if (isTrackFilled) { + outputCollision(vtxZ, mult, multNtr, spher, magField); + if constexpr (isMc) { + fillMcCollision(col); } + } } // fill collision table if track table is filled, i.e., there is at least one Lc-p pair @@ -437,11 +422,11 @@ struct femtoDreamProducer { BDTScorePrompt, BDTScoreFD); - // Row for MC candidate charm hadron (if constexpr isMC) - if constexpr (isMC) { - rowCandMCCharmHad( - candidate.flagMcMatchRec(), - candidate.originMcRec()); + // Row for MC candidate charm hadron (if constexpr isMc) + if constexpr (isMc) { + rowCandMcCharmHad( + candidate.flagMcMatchRec(), + candidate.originMcRec()); } } } }; @@ -476,7 +461,7 @@ struct femtoDreamProducer { fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(femtoDreamProducer, processDataCharmHad, + PROCESS_SWITCH(HfFemtoDreamProducer, processDataCharmHad, "Provide experimental data for charm hadron femto", false); void processDataCharmHadWithML(FemtoFullCollision const& col, @@ -491,47 +476,45 @@ struct femtoDreamProducer { fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(femtoDreamProducer, processDataCharmHadWithML, + PROCESS_SWITCH(HfFemtoDreamProducer, processDataCharmHadWithML, "Provide experimental data for charm hadron femto with ml", false); - void processMCCharmHad(FemtoFullCollisionMC const& col, + void processMcCharmHad(FemtoFullCollisionMc const& col, aod::BCsWithTimestamps const&, - soa::Join const& tracks, - soa::Filtered const& candidates, - GeneratedMC const& particles) + FemtoHFMcTracks const& tracks, + aod::McParticles const&, + CandidateLcMc const& candidates) { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(femtoDreamProducer, processMCCharmHad, "Provide MC for charm hadron", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processMcCharmHad, "Provide Mc for charm hadron", false); - void processMCCharmHadWithML(FemtoFullCollisionMC const& col, + void processMcCharmHadWithML(FemtoFullCollisionMc const& col, aod::BCsWithTimestamps const&, - soa::Join const& tracks, - soa::Filtered> const& candidates, - GeneratedMC const& particles) + FemtoHFMcTracks const& tracks, + aod::McParticles const&, + soa::Join const& candidates) { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(femtoDreamProducer, processMCCharmHadWithML, "Provide MC for charm hadron with ml", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processMcCharmHadWithML, "Provide Mc for charm hadron with ml", false); - void processMCCharmHadGen(GeneratedMC const& particles) + void processMcCharmHadGen(GeneratedMc const& particles) { fillCharmHadMcGen(particles); } - PROCESS_SWITCH(femtoDreamProducer, processMCCharmHadGen, "Provide MC Generated charm hadron", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processMcCharmHadGen, "Provide Mc Generated charm hadron", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/HFC/Tasks/CMakeLists.txt b/PWGHF/HFC/Tasks/CMakeLists.txt index af150b89849..ec2e1779ebf 100644 --- a/PWGHF/HFC/Tasks/CMakeLists.txt +++ b/PWGHF/HFC/Tasks/CMakeLists.txt @@ -9,8 +9,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(femtodream-pair-charm-hadrons - SOURCES femtoDreamPairTaskCharmHadrons.cxx +o2physics_add_dpl_workflow(task-charm-hadrons-femto-dream + SOURCES taskCharmHadronsFemtoDream.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -44,6 +44,11 @@ o2physics_add_dpl_workflow(task-correlation-dstar-hadrons PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-correlation-hfe-hadrons + SOURCES taskCorrelationHfeHadrons.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-correlation-lc-hadrons SOURCES taskCorrelationLcHadrons.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFC/Tasks/femtoDreamPairTaskCharmHadrons.cxx b/PWGHF/HFC/Tasks/femtoDreamPairTaskCharmHadrons.cxx deleted file mode 100644 index df35f7ca105..00000000000 --- a/PWGHF/HFC/Tasks/femtoDreamPairTaskCharmHadrons.cxx +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2019-2022 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. - -/// \file femtoDreamPairTaskCharmHadrons.cxx -/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks -/// \author Ravindra SIngh, GSI, ravindra.singh@cern.ch - -#include - -#include "Framework/Expressions.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" - -#include "PWGCF/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" -#include "PWGCF/FemtoDream/Core/femtoDreamContainer.h" -#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" -#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" - -using namespace o2; -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::analysis::femtoDream; - -struct femtoDreamPairTaskCharmHadrons { - - enum PairCharge { - positiveCharge = 1, - negativeCharge = -1 - }; - - /// General options - Configurable ConfOptCPRPlotPerRadii{"ConfOptCPRPlotPerRadii", false, "Plot CPR per radii"}; - Configurable ConfOptUseCPR{"ConfOptUseCPR", false, "Close Pair Rejection"}; - Configurable ConfOptCPRdeltaEtaMax{"ConfOptCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; - Configurable ConfOptCPRdeltaPhiMax{"ConfOptCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; - Configurable ConfOptExtendedPlots{"ConfOptExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; - Configurable ConfOptHighkstarCut{"ConfOptHighkstarCut", 100000., "Set a cut for high k*, above which the pairs are rejected"}; - Configurable ConfOptisMc{"ConfOptisMc", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; - Configurable ConfOptsmearingByOrigin{"ConfOptsmearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption. Use with care!"}; - Configurable ConfOptUse4D{"ConfOptUse4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; - ConfigurableAxis ConfOptDummy{"ConfOptDummy", {1, 0, 1}, "Dummy axis"}; - - /// Event selection - Configurable ConfEvent_maxMult{"ConfEvent_maxMult", 99999, "Maximum Multiplicity (MultNtr)"}; - Configurable ConfEvent_maxMultPercentile{"ConfEvent_maxMultPercentile", 100, "Maximum Multiplicity Percentile"}; - Configurable ConfEvent_minMult{"ConfEvent_minMult", 0, "Minimum Multiplicity (MultNtr)"}; - Configurable ConfEvent_minMultPercentile{"ConfEvent_minMultPercentile", 0, "Minimum Multiplicity Percentile"}; - - /// Particle 1 (track) - Configurable ConfTrk1_CutBit{"ConfTrk1_CutBit", 5542474, "Particle 1 (Track) - Selection bit from cutCulator"}; - Configurable ConfTrk1_PDGCode{"ConfTrk1_PDGCode", 2212, "PDG code of Particle 1 (Track)"}; - Configurable ConfTrk1_PIDThres{"ConfTrk1_PIDThres", 0.75, "Momentum threshold for PID selection for particle 1 (Track)"}; - Configurable ConfTrk1_TPCBit{"ConfTrk1_TPCBit", 4, "PID TPC bit from cutCulator for particle 1 (Track)"}; - Configurable ConfTrk1_TPCTOFBit{"ConfTrk1_TPCTOFBit", 2, "PID TPCTOF bit from cutCulator for particle 1 (Track)"}; - Configurable ConfTrk1_maxEta{"ConfTrk1_maxEta", 10., "Maximum eta of partricle 1 (Track)"}; - Configurable ConfTrk1_maxPt{"ConfTrk1_maxPt", 999., "Maximum pT of partricle 1 (Track)"}; - Configurable ConfTrk1_minEta{"ConfTrk1_minEta", -10., "Minimum eta of partricle 1 (Track)"}; - Configurable ConfTrk1_minPt{"ConfTrk1_minPt", 0., "Minimum pT of partricle 1 (Track)"}; - - /// Particle 2 (Charm Hadrons) - Configurable ConfHF_bkgBDT{"ConfHF_bkgBDT", 1., "Maximum background bdt score for Charm Hadron (particle 2)"}; - Configurable ConfHF_CandSel{"ConfHF_CandSel", 1, "candidate selection for charm hadron"}; - Configurable ConfHF_fdBDT{"ConfHF_fdBDT", 0., "Minimum feed-down bdt score Charm Hadron (particle 2)"}; - Configurable ConfHF_maxInvMass{"ConfHF_maxInvMass", 2.45, "Maximum invariant mass of Charm Hadron (particle 2)"}; - Configurable ConfHF_maxPt{"ConfHF_maxPt", 999., "Maximum pT of Charm Hadron (particle 2)"}; - Configurable ConfHF_minInvMass{"ConfHF_minInvMass", 2.15, "Minimum invariant mass of Charm Hadron (particle 2)"}; - Configurable ConfHF_minPt{"ConfHF_minPt", 0., "Minimum pT of Charm Hadron (particle 2)"}; - Configurable ConfHF_PDGCode{"ConfHF_PDGCode", 4122, "PDG code of particle 2 Charm Hadron"}; - Configurable ConfHF_promptBDT{"ConfHF_promptBDT", 0., "Minimum prompt bdt score Charm Hadron (particle 2)"}; - - /// Binning configurables - ConfigurableAxis ConfBin4Dkstar{"ConfBin4Dkstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis ConfBin4DMult{"ConfBin4Dmult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis ConfBin4DmT{"ConfBin4DmT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis ConfBin4DmultPercentile{"ConfBin4DmultPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis ConfBinInvMass{"ConfBinInvMass", {300, 2.15, 2.45}, "InvMass binning"}; - ConfigurableAxis ConfBinTempFitVarHF{"ConfBinTempFitVarHF", {300, 0.9, 1}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis ConfBinTempFitVarHFChild{"ConfBinTempFitVarHFChild", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0 child)"}; - ConfigurableAxis ConfBinTempFitVarTrack{"ConfBinTempFitVarTrack", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Track)"}; - ConfigurableAxis ConfBinmT{"ConfBinmT", {225, 0., 7.5}, "binning mT"}; - ConfigurableAxis ConfBinmultTempFit{"ConfBinmultTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; - ConfigurableAxis ConfBinpT{"ConfBinpT", {20, 0.5, 4.05}, "pT binning"}; - ConfigurableAxis ConfBinpTHF{"ConfBinpTHF", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis ConfBinpTHFChild{"ConfBinpTHFChild", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis ConfBinpTTrack{"ConfBinpTTrack", {50, 0.5, 10.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; - ConfigurableAxis ConfBinkT{"ConfBinkT", {150, 0., 9.}, "binning kT"}; - ConfigurableAxis ConfBinkstar{"ConfBinkstar", {1500, 0., 6.}, "binning kstar"}; - - // Mixing configurables - ConfigurableAxis ConfMixingBinMult{"ConfMixingBinMult", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Mixing bins - multiplicity"}; - ConfigurableAxis ConfMixingBinMultPercentile{"ConfMixingBinMultPercentile", {VARIABLE_WIDTH, 0.0f, 100.f}, "Mixing bins - multiplicity percentile"}; - ConfigurableAxis ConfMixingBinVztx{"ConfMixingBinVztx", {VARIABLE_WIDTH, -10.0f, -4.f, 0.f, 4.f, 10.f}, "Mixing bins - z-vertex"}; - Configurable ConfMixingDepth{"ConfMixingDepth", 5, "Number of events for mixing"}; - Configurable ConfMixingPolicy{"ConfMixingBinPolicy", 0, "Binning policy for mixing - 0: multiplicity, 1: multipliciy percentile, 2: both"}; - - ColumnBinningPolicy colBinningMult{{ConfMixingBinVztx, ConfMixingBinMult}, true}; - ColumnBinningPolicy colBinningMultPercentile{{ConfMixingBinVztx, ConfMixingBinMultPercentile}, true}; - ColumnBinningPolicy colBinningMultMultPercentile{{ConfMixingBinVztx, ConfMixingBinMult, ConfMixingBinMultPercentile}, true}; - - FemtoDreamContainer sameEventCont; - FemtoDreamContainer mixedEventCont; - FemtoDreamPairCleaner pairCleaner; - FemtoDreamDetaDphiStar pairCloseRejection; - - Filter trackEtaFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta < ConfTrk1_maxEta, true); - Filter trackEtaFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta > ConfTrk1_minEta, true); - Filter trackPtFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt < ConfTrk1_maxPt, true); - Filter trackPtFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt > ConfTrk1_minPt, true); - Filter hfCandSelFilter = aod::fdhf::candidateSelFlag >= ConfHF_CandSel.value; - - using FilteredCharmCands = soa::Filtered; - using FilteredCharmCand = FilteredCharmCands::iterator; - - using FilteredCharmMCCands = soa::Filtered>; - using FilteredCharmMCCand = FilteredCharmMCCands::iterator; - - using FilteredColisions = FDCollisions; - using FilteredColision = FilteredColisions::iterator; - - using FilteredFDMCParts = soa::Filtered>; - using FilteredFDMCPart = FilteredFDMCParts::iterator; - - using FilteredFDParticles = soa::Filtered>; - using FilteredFDParticle = FilteredFDParticles::iterator; - - /// Histogramming for particle 1 - FemtoDreamParticleHisto trackHistoPartOne; - - /// Partition for particle 1 - - Partition PartitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)); - - Partition PartitionMCTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && - (ncheckbit(aod::femtodreamparticle::cut, ConfTrk1_CutBit)) && - ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfTrk1_PIDThres, ncheckbit(aod::femtodreamparticle::pidcut, ConfTrk1_TPCBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTrk1_TPCTOFBit)); - - /// Partition for particle 2 - Partition PartitionHF = aod::fdhf::bdtBkg < ConfHF_bkgBDT && aod::fdhf::bdtPrompt > ConfHF_promptBDT; - /// Histogramming for Event - FemtoDreamEventHisto eventHisto; - - /// Histogram output - HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry resultRegistry{"CorrelationsHF", {}, OutputObjHandlingPolicy::AnalysisObject}; - - float MassOne = o2::analysis::femtoDream::getMass(ConfTrk1_PDGCode); - float MassTwo = o2::analysis::femtoDream::getMass(ConfHF_PDGCode); - int8_t partSign = 0; - int64_t processType = 0; - - SliceCache cache; - Preslice perCol = aod::femtodreamparticle::fdCollisionId; - Produces fillFemtoResult; - - void init(InitContext& context) - { - eventHisto.init(&qaRegistry); - trackHistoPartOne.init(&qaRegistry, ConfBinmultTempFit, ConfOptDummy, ConfBinpTTrack, ConfOptDummy, ConfOptDummy, ConfBinTempFitVarTrack, ConfOptDummy, ConfOptDummy, ConfOptDummy, ConfOptDummy, ConfOptDummy, ConfOptisMc, ConfTrk1_PDGCode); - - sameEventCont.init(&resultRegistry, - ConfBinkstar, ConfBinpT, ConfBinkT, ConfBinmT, ConfMixingBinMult, ConfMixingBinMultPercentile, - ConfBin4Dkstar, ConfBin4DmT, ConfBin4DMult, ConfBin4DmultPercentile, - ConfOptisMc, ConfOptUse4D, ConfOptExtendedPlots, - ConfOptHighkstarCut, - ConfOptsmearingByOrigin, ConfBinInvMass); - - sameEventCont.setPDGCodes(ConfTrk1_PDGCode, ConfHF_PDGCode); - mixedEventCont.init(&resultRegistry, - ConfBinkstar, ConfBinpT, ConfBinkT, ConfBinmT, ConfMixingBinMult, ConfMixingBinMultPercentile, - ConfBin4Dkstar, ConfBin4DmT, ConfBin4DMult, ConfBin4DmultPercentile, - ConfOptisMc, ConfOptUse4D, ConfOptExtendedPlots, - ConfOptHighkstarCut, - ConfOptsmearingByOrigin, ConfBinInvMass); - - mixedEventCont.setPDGCodes(ConfTrk1_PDGCode, ConfHF_PDGCode); - pairCleaner.init(&qaRegistry); - if (ConfOptUseCPR.value) { - pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfOptCPRdeltaPhiMax.value, ConfOptCPRdeltaEtaMax.value, ConfOptCPRPlotPerRadii.value); - } - } - - /// This function processes the same event and takes care of all the histogramming - template - void doSameEvent(PartitionType& SliceTrk1, CandType& SliceCharmHad, TableTracks const& parts, TableCandidates const& candidates, Collision const& col) - { - processType = 1; // for same event - /// Histogramming same event - for (auto const& part : SliceTrk1) { - - trackHistoPartOne.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); - } - for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(SliceTrk1, SliceCharmHad))) { - // proton track charge - float chargeTrack = 0.; - if ((p1.cut() & 1) == 1) { - chargeTrack = positiveCharge; - } else { - chargeTrack = negativeCharge; - } - - if (chargeTrack != p2.charge()) - continue; - float kstar = FemtoDreamMath::getkstar(p1, MassOne, p2, MassTwo); - if (kstar > ConfOptHighkstarCut) - continue; - - if (chargeTrack == 1) { - partSign = 1; - } else { - partSign = 1 << 1; - } - - if (ConfOptUseCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, col.magField())) { - continue; - } - } - - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } - float invMass; - if (p2.candidateSelFlag() == 1) { - invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); - } else { - invMass = p2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); - } - - if (invMass < ConfHF_minInvMass || invMass > ConfHF_maxInvMass) - continue; - if (p2.pt() < ConfHF_minPt || p2.pt() > ConfHF_maxPt) - continue; - - fillFemtoResult( - invMass, - p2.pt(), - p1.pt(), - p2.bdtBkg(), - p2.bdtPrompt(), - p2.bdtFD(), - kstar, - FemtoDreamMath::getkT(p1, MassOne, p2, MassTwo), - FemtoDreamMath::getmT(p1, MassOne, p2, MassTwo), - col.multNtr(), - col.multV0M(), - partSign, - processType); - - sameEventCont.setPair(p1, p2, col.multNtr(), col.multV0M(), ConfOptUse4D, ConfOptExtendedPlots, ConfOptsmearingByOrigin); - } - } - - void processSameEvent(FilteredColision const& col, FilteredFDParticles const& parts, FilteredCharmCands const& candidates) - { - eventHisto.fillQA(col); - auto SliceTrk1 = PartitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto SliceCharmHad = PartitionHF->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - doSameEvent(SliceTrk1, SliceCharmHad, parts, candidates, col); - } - PROCESS_SWITCH(femtoDreamPairTaskCharmHadrons, processSameEvent, "Enable processing same event", true); - - template - void doMixedEvent(CollisionType const& cols, PartType const& parts, PartitionType1& part1, PartitionType2& part2, BinningType policy) - { - processType = 1 << 1; // for mixed event - - for (auto const& [collision1, collision2] : soa::selfCombinations(policy, ConfMixingDepth.value, -1, cols, cols)) { - - auto SliceTrk1 = part1->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); - auto SliceCharmHad = PartitionHF->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); - for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(SliceTrk1, SliceCharmHad))) { - - float chargeTrack = 0.; - if ((p1.cut() & 1) == 1) { - chargeTrack = positiveCharge; - } else { - chargeTrack = negativeCharge; - } - - if (chargeTrack != p2.charge()) - continue; - float kstar = FemtoDreamMath::getkstar(p1, MassOne, p2, MassTwo); - if (kstar > ConfOptHighkstarCut) - continue; - - if (chargeTrack == 1) { - partSign = 1; - } else { - partSign = 1 << 1; - } - - float invMass; - if (p2.candidateSelFlag() == 1) { - invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); - } else { - invMass = p2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); - } - fillFemtoResult( - invMass, - p2.pt(), - p1.pt(), - p2.bdtBkg(), - p2.bdtPrompt(), - p2.bdtFD(), - kstar, - FemtoDreamMath::getkT(p1, MassOne, p2, MassTwo), - FemtoDreamMath::getmT(p1, MassOne, p2, MassTwo), - collision1.multNtr(), - collision1.multV0M(), - partSign, - processType); - - if (ConfOptUseCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, collision1.magField())) { - continue; - } - } - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } - mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), ConfOptUse4D, ConfOptExtendedPlots, ConfOptsmearingByOrigin); - } - } - } - - void processMixedEvent(FilteredColisions const& cols, FilteredFDParticles const& parts, FilteredCharmCands const& candidates) - { - switch (ConfMixingPolicy.value) { - case femtodreamcollision::kMult: - doMixedEvent(cols, parts, PartitionTrk1, PartitionHF, colBinningMult); - break; - case femtodreamcollision::kMultPercentile: - doMixedEvent(cols, parts, PartitionTrk1, PartitionHF, colBinningMultPercentile); - break; - case femtodreamcollision::kMultMultPercentile: - doMixedEvent(cols, parts, PartitionTrk1, PartitionHF, colBinningMultMultPercentile); - break; - default: - LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; - } - } - PROCESS_SWITCH(femtoDreamPairTaskCharmHadrons, processMixedEvent, "Enable processing mixed events", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx new file mode 100644 index 00000000000..f1d3e5aaf70 --- /dev/null +++ b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx @@ -0,0 +1,457 @@ +// Copyright 2019-2022 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. + +/// \file taskCharmHadronsFemtoDream.cxx.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Ravindra SIngh, GSI, ravindra.singh@cern.ch + +#include + +#include "Framework/Expressions.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamContainer.h" +#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femtoDream; + +struct HfTaskCharmHadronsFemtoDream { + + enum TrackCharge { + PositiveCharge = 1, + NegativeCharge = -1 + }; + + enum PairSign { + PairNotDefined = 0, + LikeSignPair = 1, + UnLikeSignPair = 2 + }; + + /// Binning configurables + ConfigurableAxis bin4Dkstar{"bin4Dkstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis bin4DMult{"bin4Dmult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis bin4DmT{"bin4DmT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis bin4DmultPercentile{"bin4DmultPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis binInvMass{"binInvMass", {300, 2.15, 2.45}, "InvMass binning"}; + ConfigurableAxis binTempFitVarTrack{"binTempFitVarTrack", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis binmT{"binmT", {225, 0., 7.5}, "binning mT"}; + ConfigurableAxis binmultTempFit{"binmultTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; + ConfigurableAxis binpT{"binpT", {20, 0.5, 4.05}, "pT binning"}; + ConfigurableAxis binpTTrack{"binpTTrack", {50, 0.5, 10.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis binkT{"binkT", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis binkstar{"binkstar", {1500, 0., 6.}, "binning kstar"}; + + /// Particle 2 (Charm Hadrons) + Configurable charmHadBkgBDTmax{"charmHadBkgBDTmax", 1., "Maximum background bdt score for Charm Hadron (particle 2)"}; + Configurable charmHadCandSel{"charmHadCandSel", 1, "candidate selection for charm hadron"}; + Configurable charmHadMcSel{"charmHadMcSel", 2, "charm hadron selection for mc, partDplusToPiKPi (1), partLcToPKPi (2), partDsToKKPi (4), partXicToPKPi (8)"}; + Configurable charmHadFdBDTmin{"charmHadFdBDTmin", 0., "Minimum feed-down bdt score Charm Hadron (particle 2)"}; + Configurable charmHadFdBDTmax{"charmHadFdBDTmax", 1., "Maximum feed-down bdt score Charm Hadron (particle 2)"}; + Configurable charmHadMaxInvMass{"charmHadMaxInvMass", 2.45, "Maximum invariant mass of Charm Hadron (particle 2)"}; + Configurable charmHadMaxPt{"charmHadMaxPt", 999., "Maximum pT of Charm Hadron (particle 2)"}; + Configurable charmHadMinInvMass{"charmHadMinInvMass", 2.15, "Minimum invariant mass of Charm Hadron (particle 2)"}; + Configurable charmHadMinPt{"charmHadMinPt", 0., "Minimum pT of Charm Hadron (particle 2)"}; + Configurable charmHadPDGCode{"charmHadPDGCode", 4122, "PDG code of particle 2 Charm Hadron"}; + Configurable charmHadPromptBDTmin{"charmHadPromptBDTmin", 0., "Minimum prompt bdt score Charm Hadron (particle 2)"}; + Configurable charmHadPromptBDTmax{"charmHadPromptBDTmax", 1., "Maximum prompt bdt score Charm Hadron (particle 2)"}; + + /// General options + Configurable cprDeltaEtaMax{"cprDeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable cprDeltaPhiMax{"cprDeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable cprPlotPerRadii{"cprPlotPerRadii", false, "Plot CPR per radii"}; + Configurable extendedPlots{"extendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; + Configurable highkstarCut{"highkstarCut", 100000., "Set a cut for high k*, above which the pairs are rejected"}; + Configurable isMc{"isMc", false, "Set true in the case of a MonteCarlo Run"}; + Configurable smearingByOrigin{"smearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption. Use with care!"}; + Configurable use4D{"use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; + Configurable useCPR{"useCPR", false, "Close Pair Rejection"}; + ConfigurableAxis dummy{"dummy", {1, 0, 1}, "dummy axis"}; + + // Mixing configurables + ConfigurableAxis mixingBinMult{"mixingBinMult", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis mixingBinMultPercentile{"mixingBinMultPercentile", {VARIABLE_WIDTH, 0.0f, 100.f}, "Mixing bins - multiplicity percentile"}; + ConfigurableAxis mixingBinVztx{"mixingBinVztx", {VARIABLE_WIDTH, -10.0f, -4.f, 0.f, 4.f, 10.f}, "Mixing bins - z-vertex"}; + Configurable mixingDepth{"mixingDepth", 5, "Number of events for mixing"}; + Configurable mixingPolicy{"mixingBinPolicy", 0, "Binning policy for mixing - 0: multiplicity, 1: multipliciy percentile, 2: both"}; + + /// Event selection + struct : ConfigurableGroup { + std::string prefix = "eventSel"; + Configurable multMin{"multMin", 0, "Minimum Multiplicity (MultNtr)"}; + Configurable multMax{"multMax", 99999, "Maximum Multiplicity (MultNtr)"}; + Configurable multPercentileMin{"multPercentileMin", 0, "Maximum Multiplicity Percentile"}; + Configurable multPercentileMax{"multPercentileMax", 100, "Minimum Multiplicity Percentile"}; + } eventSel; + + /// Particle 1 (track) + Configurable cutBitTrack1{"cutBitTrack1", 5542474, "Particle 1 (Track) - Selection bit from cutCulator"}; + Configurable pdgCodeTrack1{"pdgCodeTrack1", 2212, "PDG code of Particle 1 (Track)"}; + Configurable pidThresTrack1{"pidThresTrack1", 0.75, "Momentum threshold for PID selection for particle 1 (Track)"}; + Configurable tpcBitTrack1{"tpcBitTrack1", 4, "PID TPC bit from cutCulator for particle 1 (Track)"}; + Configurable tpcTofBitTrack1{"tpcTofBitTrack1", 2, "PID TPCTOF bit from cutCulator for particle 1 (Track)"}; + Configurable etaTrack1Max{"etaTrack1Max", 10., "Maximum eta of partricle 1 (Track)"}; + Configurable ptTrack1Max{"ptTrack1Max", 999., "Maximum pT of partricle 1 (Track)"}; + Configurable etaTrack1Min{"etaTrack1Min", -10., "Minimum eta of partricle 1 (Track)"}; + Configurable ptTrack1Min{"ptTrack1Min", 0., "Minimum pT of partricle 1 (Track)"}; + + ColumnBinningPolicy colBinningMult{{mixingBinVztx, mixingBinMult}, true}; + ColumnBinningPolicy colBinningMultPercentile{{mixingBinVztx, mixingBinMultPercentile}, true}; + ColumnBinningPolicy colBinningMultMultPercentile{{mixingBinVztx, mixingBinMult, mixingBinMultPercentile}, true}; + + FemtoDreamContainer sameEventCont; + FemtoDreamContainer mixedEventCont; + FemtoDreamPairCleaner pairCleaner; + FemtoDreamDetaDphiStar pairCloseRejection; + + Filter eventMultiplicity = aod::femtodreamcollision::multNtr >= eventSel.multMin && aod::femtodreamcollision::multNtr <= eventSel.multMax; + Filter eventMultiplicityPercentile = aod::femtodreamcollision::multV0M >= eventSel.multPercentileMin && aod::femtodreamcollision::multV0M <= eventSel.multPercentileMax; + Filter hfCandSelFilter = aod::fdhf::candidateSelFlag >= charmHadCandSel.value; + Filter hfMcSelFilter = nabs(aod::fdhf::flagMc) == charmHadMcSel.value; + Filter trackEtaFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta < etaTrack1Max, true); + Filter trackEtaFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta > etaTrack1Min, true); + Filter trackPtFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt < ptTrack1Max, true); + Filter trackPtFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt > ptTrack1Min, true); + + using FilteredCharmCands = soa::Filtered; + using FilteredCharmCand = FilteredCharmCands::iterator; + + using FilteredCharmMcCands = soa::Filtered>; + using FilteredCharmMcCand = FilteredCharmMcCands::iterator; + + using FilteredColisions = FDCollisions; + using FilteredColision = FilteredColisions::iterator; + + using FilteredMcColisions = soa::Filtered>; + using FilteredMcColision = FilteredMcColisions::iterator; + + using FilteredFDMcParts = soa::Filtered>; + using FilteredFDMcPart = FilteredFDMcParts::iterator; + + using FilteredFDParticles = soa::Filtered>; + using FilteredFDParticle = FilteredFDParticles::iterator; + + /// Histogramming for particle 1 + FemtoDreamParticleHisto trackHistoPartOne; + /// Histogramming for Event + FemtoDreamEventHisto eventHisto; + /// Histogram output + HistogramRegistry registry{"CorrelationsAndQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + + /// Partition for particle 1 + + Partition partitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)); + + Partition partitionMcTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + (ncheckbit(aod::femtodreamparticle::cut, cutBitTrack1)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, tpcTofBitTrack1)); + + /// Partition for particle 2 + Partition partitionCharmHadron = aod::fdhf::bdtBkg < charmHadBkgBDTmax && aod::fdhf::bdtFD < charmHadFdBDTmax && aod::fdhf::bdtFD > charmHadFdBDTmin&& aod::fdhf::bdtPrompt charmHadPromptBDTmin; + Partition partitionMcCharmHadron = aod::fdhf::originMcRec == 1 || aod::fdhf::originMcRec == 2; + + float massOne = o2::analysis::femtoDream::getMass(pdgCodeTrack1); + float massTwo = o2::analysis::femtoDream::getMass(charmHadPDGCode); + int8_t partSign = 0; + int64_t processType = 0; + + SliceCache cache; + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + Produces fillFemtoResult; + + void init(InitContext& /*context*/) + { + eventHisto.init(®istry); + trackHistoPartOne.init(®istry, binmultTempFit, dummy, binpTTrack, dummy, dummy, binTempFitVarTrack, dummy, dummy, dummy, dummy, dummy, isMc, pdgCodeTrack1); + + sameEventCont.init(®istry, + binkstar, binpT, binkT, binmT, mixingBinMult, mixingBinMultPercentile, + bin4Dkstar, bin4DmT, bin4DMult, bin4DmultPercentile, + isMc, use4D, extendedPlots, + highkstarCut, + smearingByOrigin, binInvMass); + + sameEventCont.setPDGCodes(pdgCodeTrack1, charmHadPDGCode); + mixedEventCont.init(®istry, + binkstar, binpT, binkT, binmT, mixingBinMult, mixingBinMultPercentile, + bin4Dkstar, bin4DmT, bin4DMult, bin4DmultPercentile, + isMc, use4D, extendedPlots, + highkstarCut, + smearingByOrigin, binInvMass); + + mixedEventCont.setPDGCodes(pdgCodeTrack1, charmHadPDGCode); + pairCleaner.init(®istry); + if (useCPR.value) { + pairCloseRejection.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value); + } + } + + /// This function processes the same event and takes care of all the histogramming + template + void doSameEvent(PartitionType& sliceTrk1, CandType& sliceCharmHad, TableTracks const& parts, Collision const& col) + { + processType = 1; // for same event + /// Histogramming same event + for (auto const& part : sliceTrk1) { + + trackHistoPartOne.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + + for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { + // proton track charge + float chargeTrack = 0.; + if ((p1.cut() & 2) == 2) { + chargeTrack = PositiveCharge; + } else { + chargeTrack = NegativeCharge; + } + + int pairSign = 0; + if (chargeTrack == p2.charge()) { + pairSign = LikeSignPair; + } else { + pairSign = UnLikeSignPair; + } + + float kstar = FemtoDreamMath::getkstar(p1, massOne, p2, massTwo); + if (kstar > highkstarCut) { + continue; + } + + // if (chargeTrack == 1) { + // partSign = 1; + // } else { + // partSign = 1 << 1; + // } + + if (useCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, col.magField())) { + continue; + } + } + + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + float invMass; + if (p2.candidateSelFlag() == 1) { + invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + } else { + invMass = p2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); + } + + if (invMass < charmHadMinInvMass || invMass > charmHadMaxInvMass) { + continue; + } + + if (p2.pt() < charmHadMinPt || p2.pt() > charmHadMaxPt) { + continue; + } + + int charmHadMc = 0; + int originType = 0; + if constexpr (isMc) { + charmHadMc = p2.flagMc(); + originType = p2.originMcRec(); + } + fillFemtoResult( + invMass, + p2.pt(), + p1.pt(), + p2.bdtBkg(), + p2.bdtPrompt(), + p2.bdtFD(), + kstar, + FemtoDreamMath::getkT(p1, massOne, p2, massTwo), + FemtoDreamMath::getmT(p1, massOne, p2, massTwo), + col.multNtr(), + col.multV0M(), + p2.charge(), + pairSign, + processType, + charmHadMc, + originType); + + sameEventCont.setPair(p1, p2, col.multNtr(), col.multV0M(), use4D, extendedPlots, smearingByOrigin); + } + } + + template + void doMixedEvent(CollisionType const& cols, PartType const& parts, PartitionType1& part1, PartitionType2& part2, BinningType policy) + { + processType = 1 << 1; // for mixed event + + for (auto const& [collision1, collision2] : soa::selfCombinations(policy, mixingDepth.value, -1, cols, cols)) { + + auto sliceTrk1 = part1->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto sliceCharmHad = part2->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { + + float chargeTrack = 0.; + if ((p1.cut() & 2) == 2) { + chargeTrack = PositiveCharge; + } else { + chargeTrack = NegativeCharge; + } + + int pairSign = 0; + if (chargeTrack == p2.charge()) { + pairSign = LikeSignPair; + } else { + pairSign = UnLikeSignPair; + } + + float kstar = FemtoDreamMath::getkstar(p1, massOne, p2, massTwo); + if (kstar > highkstarCut) { + continue; + } + + float invMass; + if (p2.candidateSelFlag() == 1) { + invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + } else { + invMass = p2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); + } + + int charmHadMc = 0; + int originType = 0; + if constexpr (isMc) { + charmHadMc = p2.flagMc(); + originType = p2.originMcRec(); + } + fillFemtoResult( + invMass, + p2.pt(), + p1.pt(), + p2.bdtBkg(), + p2.bdtPrompt(), + p2.bdtFD(), + kstar, + FemtoDreamMath::getkT(p1, massOne, p2, massTwo), + FemtoDreamMath::getmT(p1, massOne, p2, massTwo), + collision1.multNtr(), + collision1.multV0M(), + p2.charge(), + pairSign, + processType, + charmHadMc, + originType); + + if (useCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, collision1.magField())) { + continue; + } + } + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + // if constexpr (!isMc) mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); + mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); + } + } + } + + void processSameEvent(FilteredColision const& col, + FilteredFDParticles const& parts, + FilteredCharmCands const&) + { + eventHisto.fillQA(col); + auto sliceTrk1 = partitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto sliceCharmHad = partitionCharmHadron->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + doSameEvent(sliceTrk1, sliceCharmHad, parts, col); + } + PROCESS_SWITCH(HfTaskCharmHadronsFemtoDream, processSameEvent, "Enable processing same event", false); + + void processMixedEvent(FilteredColisions const& cols, + FilteredFDParticles const& parts, + FilteredCharmCands const&) + { + switch (mixingPolicy.value) { + case femtodreamcollision::kMult: + doMixedEvent(cols, parts, partitionTrk1, partitionCharmHadron, colBinningMult); + break; + case femtodreamcollision::kMultPercentile: + doMixedEvent(cols, parts, partitionTrk1, partitionCharmHadron, colBinningMultPercentile); + break; + case femtodreamcollision::kMultMultPercentile: + doMixedEvent(cols, parts, partitionTrk1, partitionCharmHadron, colBinningMultMultPercentile); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + PROCESS_SWITCH(HfTaskCharmHadronsFemtoDream, processMixedEvent, "Enable processing mixed events", false); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// \param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processSameEventMc(FilteredMcColision const& col, + FilteredFDMcParts const& parts, + o2::aod::FDMCParticles const&, + FilteredCharmMcCands const&) + { + auto sliceMcTrk1 = partitionMcTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto sliceMcCharmHad = partitionMcCharmHadron->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + if (sliceMcTrk1.size() == 0 && sliceMcCharmHad.size() == 0) { + return; + } + doSameEvent(sliceMcTrk1, sliceMcCharmHad, parts, col); + } + PROCESS_SWITCH(HfTaskCharmHadronsFemtoDream, processSameEventMc, "Enable processing same event for Monte Carlo", false); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// @param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMc(FilteredMcColisions const& cols, + FilteredFDMcParts const& parts, + o2::aod::FDMCParticles const&, + FilteredCharmMcCands const&) + { + switch (mixingPolicy.value) { + case femtodreamcollision::kMult: + doMixedEvent(cols, parts, partitionMcTrk1, partitionMcCharmHadron, colBinningMult); + break; + case femtodreamcollision::kMultPercentile: + doMixedEvent(cols, parts, partitionMcTrk1, partitionMcCharmHadron, colBinningMultPercentile); + break; + case femtodreamcollision::kMultMultPercentile: + doMixedEvent(cols, parts, partitionMcTrk1, partitionMcCharmHadron, colBinningMultMultPercentile); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + PROCESS_SWITCH(HfTaskCharmHadronsFemtoDream, processMixedEventMc, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx index 353328e4a88..9ac7c6ae3de 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx @@ -52,8 +52,8 @@ AxisSpec axisDeltaPhi = {64, -o2::constants::math::PIHalf, 3. * o2::constants::m AxisSpec axisPtD = {10, 0., 10., ""}; AxisSpec axisPtHadron = {11, 0., 11., ""}; AxisSpec axisPoolBin = {9, 0., 9., ""}; -AxisSpec axisInvmass = {200, 1.3848, 2.3848, ""}; AxisSpec axisCorrelationState = {2, 0., 1., ""}; +ConfigurableAxis axisMass{"axisMass", {250, 1.65f, 2.15f}, ""}; // definition of vectors for standard ptbin and invariant mass configurables const int nPtBinsCorrelations = 12; @@ -90,8 +90,17 @@ struct HfTaskCorrelationD0Hadrons { Configurable> sidebandRightInner{"sidebandRightInner", std::vector{vecSidebandRightInner}, "Inner values of right sideband vs pT"}; Configurable> sidebandRightOuter{"sidebandRightOuter", std::vector{vecSidebandRightOuter}, "Outer values of right sideband vs pT"}; Configurable> efficiencyDmeson{"efficiencyDmeson", std::vector{vecEfficiencyDmeson}, "Efficiency values for D meson specie under study"}; + Configurable isTowardTransverseAway{"isTowardTransverseAway", false, "Divide into three regions: toward, transverse, and away"}; + Configurable leadingParticlePtMin{"leadingParticlePtMin", 0., "Min for leading particle pt"}; Configurable applyEfficiency{"efficiencyFlagD", 1, "Flag for applying efficiency weights"}; + enum Region { + Default = 0, // é»˜èź€ć€Œ + Toward, + Away, + Transverse + }; + HistogramRegistry registry{ "registry", {{"hDeltaEtaPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, @@ -169,7 +178,9 @@ struct HfTaskCorrelationD0Hadrons { {"hDeltaEtaPtIntGen", stringMcParticles + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, {"hDeltaPhiPtIntGen", stringMcParticles + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, // Toward Transverse Away - {"hCorInfoWithCorrelationState", stringDHadron + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}, {axisInvmass}, {axisCorrelationState}}}}}}; + {"hToward", "Toward invmass; ptD; correlationState;entries", {HistType::kTH3F, {{axisMass}, {axisPtD}, {axisCorrelationState}}}}, + {"hTransverse", "Transverse invmass; ptD; correlationState;entries", {HistType::kTH3F, {{axisMass}, {axisPtD}, {axisCorrelationState}}}}, + {"hAway", "Away invmass; ptD; correlationState;entries", {HistType::kTH3F, {{axisMass}, {axisPtD}, {axisCorrelationState}}}}}}; void init(InitContext&) { int nBinsPtAxis = binsCorrelations->size() - 1; @@ -214,6 +225,16 @@ struct HfTaskCorrelationD0Hadrons { registry.get(HIST("hCorrel2DVsPtGen"))->Sumw2(); } + Region getRegion(double deltaPhi) + { + if (std::abs(deltaPhi) < o2::constants::math::PI / 3.) { + return Toward; + } else if (deltaPhi > 2. * o2::constants::math::PI / 3. && deltaPhi < 4. * o2::constants::math::PI / 3.) { + return Away; + } else { + return Transverse; + } + } /// D-h correlation pair filling task, from pair tables - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) /// Works on both USL and LS analyses pair tables void processData(aod::DHadronPairFull const& pairEntries) @@ -231,7 +252,6 @@ struct HfTaskCorrelationD0Hadrons { int ptBinD = o2::analysis::findBin(binsCorrelations, ptD); int poolBin = pairEntry.poolBin(); bool isAutoCorrelated = pairEntry.isAutoCorrelated(); - // reject entries outside pT ranges of interest if (ptBinD < 0 || effBinD < 0) { continue; @@ -249,11 +269,42 @@ struct HfTaskCorrelationD0Hadrons { continue; } //============================================================================================================== - if (signalStatus == ParticleTypeData::D0Only || (signalStatus == ParticleTypeData::D0D0barBoth)) { - registry.fill(HIST("hCorInfoWithCorrelationState"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, massD, isAutoCorrelated, efficiencyWeight); - } - if (signalStatus == ParticleTypeData::D0barOnly || (signalStatus == ParticleTypeData::D0D0barBoth)) { - registry.fill(HIST("hCorInfoWithCorrelationState"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, massDbar, isAutoCorrelated, efficiencyWeight); + if (isTowardTransverseAway) { + // Divide into three regions: toward, transverse, and away + if (ptHadron < leadingParticlePtMin) { + continue; + } + Region region = getRegion(deltaPhi); + if (signalStatus == ParticleTypeData::D0Only || signalStatus == ParticleTypeData::D0D0barBoth) { + switch (region) { + case Toward: + registry.fill(HIST("hToward"), massD, ptD, isAutoCorrelated, efficiencyWeight); + break; + case Away: + registry.fill(HIST("hAway"), massD, ptD, isAutoCorrelated, efficiencyWeight); + break; + case Transverse: + registry.fill(HIST("hTransverse"), massD, ptD, isAutoCorrelated, efficiencyWeight); + break; + default: + break; + } + } + if (signalStatus == ParticleTypeData::D0barOnly || signalStatus == ParticleTypeData::D0D0barBoth) { + switch (region) { + case Toward: + registry.fill(HIST("hToward"), massD, ptD, isAutoCorrelated, efficiencyWeight); + break; + case Away: + registry.fill(HIST("hAway"), massD, ptD, isAutoCorrelated, efficiencyWeight); + break; + case Transverse: + registry.fill(HIST("hTransverse"), massD, ptD, isAutoCorrelated, efficiencyWeight); + break; + default: + break; + } + } } // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0Only) || (signalStatus == ParticleTypeData::D0D0barBoth))) { diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index 271c1284e46..7bbcc0dbcd2 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -12,6 +12,7 @@ /// \file taskCorrelationDplusHadrons.cxx /// \author Shyam Kumar +#include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" @@ -28,11 +29,6 @@ using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; -namespace o2::aod -{ -using DplusHadronPairFull = soa::Join; -} // namespace o2::aod - // string definitions, used for histogram axis labels const TString stringPtD = "#it{p}_{T}^{D} (GeV/#it{c});"; const TString stringPtHadron = "#it{p}_{T}^{Hadron} (GeV/#it{c});"; @@ -68,14 +64,24 @@ std::vector efficiencyDmeson(npTBinsEfficiency + 1); /// Dplus-Hadron correlation pair filling task, from pair tables - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) struct HfTaskCorrelationDplusHadrons { + Configurable fillHistoData{"fillHistoData", true, "Flag for filling histograms in data processes"}; + Configurable fillHistoMcRec{"fillHistoMcRec", true, "Flag for filling histograms in MC Rec processes"}; + Configurable fillHistoMcGen{"fillHistoMcGen", true, "Flag for filling histograms in MC Gen processes"}; + Configurable fillHistoMcEff{"fillHistoMcEff", true, "Flag for filling histograms in efficiency processes"}; Configurable applyEfficiency{"applyEfficiency", 1, "Flag for applying efficiency weights"}; + Configurable loadAccXEffFromCCDB{"loadAccXEffFromCCDB", false, "Flag for loading efficiency distributions from CCDB"}; Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; // 7 corresponds to topo+PID cuts + Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; + Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; + Configurable> mlOutputPrompt{"mlScorePrompt", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for prompt"}; + Configurable> mlOutputBkg{"mlScoreBkg", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for bkg"}; // pT ranges for correlation plots: the default values are those embedded in hf_cuts_dplus_to_pi_k_pi (i.e. the mass pT bins), but can be redefined via json files Configurable> binsPtCorrelations{"binsPtCorrelations", std::vector{pTBinsCorrelations_v}, "pT bin limits for correlation plots"}; Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle efficiency"}; Configurable> binsPtEfficiencyD{"binsPtEfficiencyD", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for efficiency"}; Configurable> binsPtEfficiencyHad{"binsPtEfficiencyHad", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for associated particle efficiency"}; - Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for D+ meson"}; + Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for prompt D+ meson"}; + Configurable> efficiencyFdD{"efficiencyFdD", {1., 1., 1., 1., 1., 1.}, "efficiency values for beauty feed-down D+ meson"}; Configurable> efficiencyHad{"efficiencyHad", {1., 1., 1., 1., 1., 1.}, "efficiency values for associated particles"}; // signal and sideband region edges, to be defined via json file (initialised to empty) Configurable> signalRegionInner{"signalRegionInner", std::vector{signalRegionInner_v}, "Inner values of signal region vs pT"}; @@ -84,6 +90,8 @@ struct HfTaskCorrelationDplusHadrons { Configurable> sidebandLeftOuter{"sidebandLeftOuter", std::vector{sidebandLeftOuter_v}, "Outer values of left sideband vs pT"}; Configurable> sidebandRightInner{"sidebandRightInner", std::vector{sidebandRightInner_v}, "Inner values of right sideband vs pT"}; Configurable> sidebandRightOuter{"sidebandRightOuter", std::vector{sidebandRightOuter_v}, "Outer values of right sideband vs pT"}; + Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; + Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; Configurable ptCandMax{"ptCandMax", 50., "max. cand pT"}; @@ -93,12 +101,28 @@ struct HfTaskCorrelationDplusHadrons { Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; Configurable ptDaughterMin{"ptDaughterMin", 0.1, "min. daughter pT"}; Configurable activateQA{"activateQA", false, "Flag to enable debug histogram"}; - + Configurable nTpcCrossedRaws{"nTpcCrossedRaws", 70, "Number of crossed TPC Rows"}; + Configurable cutCollPosZMc{"cutCollPosZMc", 10., "max z-vertex position for collision acceptance"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable associatedEffCcdbPath{"associatedEffCcdbPath", "", "CCDB path for associated efficiency"}; + Configurable promptEffCcdbPath{"promptEffCcdbPath", "", "CCDB path for trigger efficiency"}; + Configurable fdEffCcdbPath{"fdEffCcdbPath", "", "CCDB path for trigger efficiency"}; + Configurable timestampCcdb{"timestampCcdb", -1, "timestamp of the efficiency files used to query in CCDB"}; + Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + // configurable axis definition + ConfigurableAxis binsMassD{"binsMassD", {200, 1.7, 2.10}, "inv. mass (#pi^{+}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; + ConfigurableAxis binsBdtScore{"binsBdtScore", {100, 0., 1.}, "Bdt output scores"}; ConfigurableAxis binsEta{"binsEta", {100, -2., 2.}, "#it{#eta}"}; ConfigurableAxis binsPhi{"binsPhi", {64, -PIHalf, 3. * PIHalf}, "#it{#varphi}"}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 8000.}, "Multiplicity as FT0M signal amplitude"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; + Service ccdb; + std::shared_ptr mEfficiencyPrompt = nullptr; + std::shared_ptr mEfficiencyFD = nullptr; + std::shared_ptr mEfficiencyAssociated = nullptr; + HfHelper hfHelper; enum CandidateStep { kCandidateStepMcGenAll = 0, @@ -109,16 +133,21 @@ struct HfTaskCorrelationDplusHadrons { kCandidateStepMcRecoInAcceptance, kCandidateNSteps }; - using CandDplusMcReco = soa::Filtered>; + using DplusHadronPair = soa::Join; + using DplusHadronPairFullWithMl = soa::Join; + using CandDplusMcReco = soa::Filtered>; using CandDplusMcGen = soa::Join; + using TracksWithMc = soa::Filtered>; // trackFilter applied Filter dplusFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) != static_cast(0)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin) && (aod::track::pt < ptTrackMax) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { // Axis definition + AxisSpec axisMassD = {binsMassD, "inv. mass (#pi^{+}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; AxisSpec axisPtCorr = {(std::vector)binsPtCorrelations, "#it{p}_{T}^{D} (GeV/#it{c})"}; AxisSpec axisPtD = {(std::vector)binsPtEfficiencyD, "#it{p}_{T}^{D} (GeV/#it{c})"}; AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; @@ -127,31 +156,81 @@ struct HfTaskCorrelationDplusHadrons { AxisSpec axisPtHadron = {(std::vector)binsPtHadron, "#it{p}_{T}^{Hadron} (GeV/#it{c})"}; AxisSpec axisPoolBin = {binsPoolBin, "poolBin"}; AxisSpec axisDplusPrompt = {2, -0.5, 1.5, "Prompt D+"}; + AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; + + // Histograms for data analysis + registry.add("hBdtScorePrompt", "D+ BDT prompt score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hBdtScoreBkg", "D+ BDT bkg score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hMassDplusVsPt", "D+ candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + if (fillHistoData) { + registry.add("hDeltaEtaPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); + registry.add("hCorrel2DVsPtSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hDeltaEtaPtIntSidebands", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); + registry.add("hCorrel2DVsPtSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hDeltaEtaPtIntSidebandLeft", stringDHadron + "Left" + stringSideband + stringDeltaEta, {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSidebandLeft", stringDHadron + "Left" + stringSideband + stringDeltaPhi, {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hDeltaEtaPtIntSidebandRight", stringDHadron + "Right" + stringSideband + stringDeltaEta, {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSidebandRight", stringDHadron + "Right" + stringSideband + stringDeltaPhi, {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DVsPtSidebandLeft", stringDHadron + "Left" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtSidebandRight", stringDHadron + "Right" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); - registry.add("hDeltaEtaPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); - registry.add("hDeltaPhiPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); - registry.add("hCorrel2DPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); - registry.add("hCorrel2DVsPtSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); - registry.add("hDeltaEtaPtIntSidebands", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); - registry.add("hDeltaPhiPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); - registry.add("hCorrel2DPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); - registry.add("hCorrel2DVsPtSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.get(HIST("hCorrel2DVsPtSignalRegion"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebands"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandLeft"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandRight"))->Sumw2(); + } // Histograms for MC Reco analysis - registry.add("hDeltaEtaPtIntSignalRegionMCRec", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); - registry.add("hDeltaPhiPtIntSignalRegionMCRec", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); - registry.add("hDeltaEtaPtIntSidebandsMCRec", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); - registry.add("hCorrel2DPtIntSignalRegionMCRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); - registry.add("hCorrel2DVsPtSignalRegionMCRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); - registry.add("hCorrel2DVsPtSignalMCRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); - registry.add("hCorrel2DVsPtBkgMCRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); - registry.add("hDeltaPhiPtIntSidebandsMCRec", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); - registry.add("hCorrel2DPtIntSidebandsMCRec", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); - registry.add("hCorrel2DVsPtSidebandsMCRec", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + if (fillHistoMcRec) { + registry.add("hMassPromptDplusVsPt", "D+ prompt candidates mass Vs Pt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassNonPromptDplusVsPt", "D+ non prompt candidates mass Vs Pt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hDeltaEtaPtIntSignalRegionMcRec", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSignalRegionMcRec", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hDeltaEtaPtIntSidebandsMcRec", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hCorrel2DPtIntSignalRegionMcRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); + registry.add("hCorrel2DVsPtSignalRegionMcRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisDplusPrompt}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtSignalMcRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtBkgMcRec", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hDeltaPhiPtIntSidebandsMcRec", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DPtIntSidebandsMcRec", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); + registry.add("hCorrel2DVsPtSidebandsMcRec", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtPhysicalPrimaryMcRec", stringDHadron + "(only true primary particles)" + stringSignal, {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisDplusPrompt}, {axisPoolBin}}}); + registry.add("hDeltaEtaPtIntSidebandLeftMcRec", stringDHadron + "Left" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSidebandLeftMcRec", stringDHadron + "Left" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DVsPtSidebandLeftMcRec", stringDHadron + "Left" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hDeltaEtaPtIntSidebandRightMcRec", stringDHadron + "Right" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntSidebandRightMcRec", stringDHadron + "Right" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DVsPtSidebandRightMcRec", stringDHadron + "Right" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtSignalRegionPromptDplusPromptHadronMcRec", stringDHadron + "signal region PromptD - Prompt Track MC reco", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtSignalRegionNonPromptDplusNonPromptHadronMcRec", stringDHadron + " signal region PromptD - NonPrompt Track MC reco", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + + registry.get(HIST("hCorrel2DVsPtSignalRegionMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandsMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtBkgMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandLeftMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandRightMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"))->Sumw2(); + } // Histograms for MC Gen analysis - registry.add("hDeltaEtaPtIntMCGen", stringMCParticles + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); - registry.add("hDeltaPhiPtIntMCGen", stringMCParticles + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); - registry.add("hCorrel2DPtIntMCGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); - registry.add("hCorrel2DVsPtMCGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + if (fillHistoMcGen) { + registry.add("hDeltaEtaPtIntMcGen", stringMCParticles + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}); + registry.add("hDeltaPhiPtIntMcGen", stringMCParticles + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}); + registry.add("hCorrel2DPtIntMcGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); + registry.add("hCorrel2DVsPtMcGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtMcGenPrompt", stringDHadron + " Prompt MC Gen", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtMcGenPromptDPromptHadron", stringDHadron + "prompt D prompt h MC Gen", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtMcGenNonPromptDNonPromptHadron", stringDHadron + " non prompt D non prompt h MC Gen", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtMcGenNonPrompt", stringDHadron + " NonPrompt MC Gen", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + + registry.get(HIST("hCorrel2DVsPtMcGen"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtMcGenPrompt"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtMcGenNonPrompt"))->Sumw2(); + } // Histograms for efficiencies registry.add("Efficiency/hPtCandMcRecPrompt", stringMCRecoDPrompt + stringPtD, {HistType::kTH1F, {axisPtD}}); registry.add("Efficiency/hPtCandMcGenPrompt", stringMCGenDPrompt + stringPtD, {HistType::kTH1F, {axisPtD}}); @@ -159,19 +238,37 @@ struct HfTaskCorrelationDplusHadrons { registry.add("Efficiency/hPtCandMcGenNonPrompt", stringMCGenDFd + stringPtD, {HistType::kTH1F, {axisPtD}}); registry.add("Efficiency/hPtCandMcGenDaughterInAcc", stringMCGenDFd + stringPtD, {HistType::kTH1F, {axisPtD}}); - registry.get(HIST("hCorrel2DVsPtSignalRegion"))->Sumw2(); - registry.get(HIST("hCorrel2DVsPtSidebands"))->Sumw2(); - registry.get(HIST("hCorrel2DVsPtSignalRegionMCRec"))->Sumw2(); - registry.get(HIST("hCorrel2DVsPtSidebandsMCRec"))->Sumw2(); - registry.get(HIST("hCorrel2DVsPtSignalMCRec"))->Sumw2(); - registry.get(HIST("hCorrel2DVsPtBkgMCRec"))->Sumw2(); - registry.get(HIST("hCorrel2DVsPtMCGen"))->Sumw2(); - auto hCandidates = registry.add("hCandidates", "Candidate count at different steps", {HistType::kStepTHnF, {axisPtD, axisMultFT0M, {RecoDecay::OriginType::NonPrompt + 1, +RecoDecay::OriginType::None - 0.5, +RecoDecay::OriginType::NonPrompt + 0.5}}, kCandidateNSteps}); hCandidates->GetAxis(0)->SetTitle("#it{p}_{T} (GeV/#it{c})"); hCandidates->GetAxis(1)->SetTitle("multiplicity"); hCandidates->GetAxis(2)->SetTitle("Charm hadron origin"); + // Loading efficiency histograms from CCDB + if (applyEfficiency && loadAccXEffFromCCDB) { + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + + mEfficiencyPrompt = std::shared_ptr(ccdb->getForTimeStamp(promptEffCcdbPath, timestampCcdb)); + if (mEfficiencyPrompt == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", promptEffCcdbPath.value.c_str()); + } + LOGF(info, "Loaded trigger efficiency (prompt D) histogram from %s", promptEffCcdbPath.value.c_str()); + + mEfficiencyFD = std::shared_ptr(ccdb->getForTimeStamp(fdEffCcdbPath, timestampCcdb)); + if (mEfficiencyFD == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", fdEffCcdbPath.value.c_str()); + } + LOGF(info, "Loaded feed-down D meson efficiency histogram from %s", fdEffCcdbPath.value.c_str()); + + mEfficiencyAssociated = std::shared_ptr(ccdb->getForTimeStamp(associatedEffCcdbPath, timestampCcdb)); + if (mEfficiencyAssociated == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for associated particles from %s", associatedEffCcdbPath.value.c_str()); + } + LOGF(info, "Loaded associated efficiency histogram from %s", associatedEffCcdbPath.value.c_str()); + } + if (activateQA) { const int regionLimits = 6; std::string labels[regionLimits] = {"SigReg Left", "SigReg Right", "Left SB Low", "Left SB Up", "Right SB Low", "Right SB Up"}; @@ -180,7 +277,7 @@ struct HfTaskCorrelationDplusHadrons { for (int iLim = 0; iLim < regionLimits; iLim++) { hSigSidebandLimits->GetXaxis()->SetBinLabel(iLim + 1, labels[iLim].data()); } - for (int iPtD = 0; iPtD < binsPtCorrelations->size() - 1; iPtD++) { + for (size_t iPtD = 0; iPtD < binsPtCorrelations->size() - 1; iPtD++) { hSigSidebandLimits->SetBinContent(1, iPtD + 1, signalRegionInner->at(iPtD)); hSigSidebandLimits->SetBinContent(2, iPtD + 1, signalRegionOuter->at(iPtD)); hSigSidebandLimits->SetBinContent(3, iPtD + 1, sidebandLeftOuter->at(iPtD)); @@ -191,29 +288,68 @@ struct HfTaskCorrelationDplusHadrons { } } - void processData(aod::DplusHadronPairFull const& pairEntries) + void processData(DplusHadronPairFullWithMl const& pairEntries, aod::DplusRecoInfo const& candidates) { + for (const auto& candidate : candidates) { + float massD = candidate.mD(); + float ptD = candidate.ptD(); + float bdtScorePrompt = candidate.mlScorePrompt(); + float bdtScoreBkg = candidate.mlScoreBkg(); + int effBinD = o2::analysis::findBin(binsPtEfficiencyD, ptD); + + // reject entries outside pT ranges of interest + if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) { + continue; + } + + if (bdtScorePrompt < mlOutputPrompt->at(effBinD) || bdtScoreBkg > mlOutputBkg->at(effBinD)) { + continue; + } + double efficiencyWeightD = 1.; + if (applyEfficiency) { + efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); + if (loadAccXEffFromCCDB) { + efficiencyWeightD = 1. / mEfficiencyPrompt->GetBinContent(mEfficiencyPrompt->FindBin(ptD)); + } + } + registry.fill(HIST("hMassDplusVsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); + registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkg); + } + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities - double deltaPhi = pairEntry.deltaPhi(); - double deltaEta = pairEntry.deltaEta(); - double ptD = pairEntry.ptD(); - double ptHadron = pairEntry.ptHadron(); + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); + float bdtScorePrompt = pairEntry.mlScorePrompt(); + float bdtScoreBkg = pairEntry.mlScoreBkg(); + float trackDcaXY = pairEntry.trackDcaXY(); + float trackDcaZ = pairEntry.trackDcaZ(); + int trackTpcCrossedRows = pairEntry.trackTPCNClsCrossedRows(); int poolBin = pairEntry.poolBin(); double massD = pairEntry.mD(); int effBinD = o2::analysis::findBin(binsPtEfficiencyD, ptD); int pTBinD = o2::analysis::findBin(binsPtCorrelations, ptD); // reject entries outside pT ranges of interest - if (pTBinD < 0 || effBinD < 0) { + if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) { + continue; + } + + if (bdtScorePrompt < mlOutputPrompt->at(effBinD) || bdtScoreBkg > mlOutputBkg->at(effBinD)) { continue; } - if (ptHadron > 10.0) { - ptHadron = 10.5; + if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { + continue; } double efficiencyWeight = 1.; if (applyEfficiency) { efficiencyWeight = 1. / (efficiencyD->at(effBinD) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); + if (loadAccXEffFromCCDB) { + efficiencyWeight = 1. / (mEfficiencyPrompt->GetBinContent(mEfficiencyPrompt->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); + } } // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots if (massD > signalRegionInner->at(pTBinD) && massD < signalRegionOuter->at(pTBinD)) { @@ -223,10 +359,21 @@ struct HfTaskCorrelationDplusHadrons { registry.fill(HIST("hDeltaEtaPtIntSignalRegion"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegion"), deltaPhi, efficiencyWeight); } - - if ((massD > sidebandLeftOuter->at(pTBinD) && massD < sidebandLeftInner->at(pTBinD)) || - (massD > sidebandRightInner->at(pTBinD) && massD < sidebandRightOuter->at(pTBinD))) { - // in sideband region + // in sideband left region + if (massD > sidebandLeftOuter->at(pTBinD) && massD < sidebandLeftInner->at(pTBinD)) { + registry.fill(HIST("hCorrel2DVsPtSidebandLeft"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandLeft"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandLeft"), deltaPhi, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebands"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebands"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebands"), deltaPhi, efficiencyWeight); + } + // in sideband right region + if (massD > sidebandRightInner->at(pTBinD) && massD < sidebandRightOuter->at(pTBinD)) { + registry.fill(HIST("hCorrel2DVsPtSidebandRight"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandRight"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandRight"), deltaPhi, efficiencyWeight); registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebands"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebands"), deltaEta, efficiencyWeight); @@ -237,85 +384,174 @@ struct HfTaskCorrelationDplusHadrons { PROCESS_SWITCH(HfTaskCorrelationDplusHadrons, processData, "Process data", false); /// D-Hadron correlation pair filling task, from pair tables - for MC reco-level analysis (candidates matched to true signal only, but also bkg sources are studied) - void processMcRec(aod::DplusHadronPairFull const& pairEntries) + void processMcRec(DplusHadronPairFullWithMl const& pairEntries, + soa::Join const& candidates) { + for (const auto& candidate : candidates) { + float massD = candidate.mD(); + float ptD = candidate.ptD(); + float bdtScorePrompt = candidate.mlScorePrompt(); + float bdtScoreBkg = candidate.mlScoreBkg(); + int effBinD = o2::analysis::findBin(binsPtEfficiencyD, ptD); + bool isDplusPrompt = candidate.isPrompt(); + + // reject entries outside pT ranges of interest + if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) + continue; + + if (bdtScorePrompt < mlOutputPrompt->at(effBinD) || bdtScoreBkg > mlOutputBkg->at(effBinD)) { + continue; + } + double efficiencyWeightD = 1.; + if (applyEfficiency) { + if (isDplusPrompt) { + efficiencyWeightD = 1. / efficiencyD->at(effBinD); + if (loadAccXEffFromCCDB) { + efficiencyWeightD = 1. / mEfficiencyPrompt->GetBinContent(mEfficiencyPrompt->FindBin(ptD)); + } + registry.fill(HIST("hMassDplusVsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hMassPromptDplusVsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); + registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkg); + } else { + efficiencyWeightD = 1. / efficiencyFdD->at(effBinD); + if (loadAccXEffFromCCDB) { + efficiencyWeightD = 1. / mEfficiencyFD->GetBinContent(mEfficiencyFD->FindBin(ptD)); + } + registry.fill(HIST("hMassDplusVsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hMassNonPromptDplusVsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); + registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkg); + } + } + } + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities - double deltaPhi = pairEntry.deltaPhi(); - double deltaEta = pairEntry.deltaEta(); - double ptD = pairEntry.ptD(); - double ptHadron = pairEntry.ptHadron(); + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); + float massD = pairEntry.mD(); + float bdtScorePrompt = pairEntry.mlScorePrompt(); + float bdtScoreBkg = pairEntry.mlScoreBkg(); + bool isPhysicalPrimary = pairEntry.isPhysicalPrimary(); + float trackDcaXY = pairEntry.trackDcaXY(); + float trackDcaZ = pairEntry.trackDcaZ(); + int trackTpcCrossedRows = pairEntry.trackTPCNClsCrossedRows(); + int statusDplusPrompt = static_cast(pairEntry.isPrompt()); + int statusPromptHadron = pairEntry.trackOrigin(); int poolBin = pairEntry.poolBin(); - double massD = pairEntry.mD(); int effBinD = o2::analysis::findBin(binsPtEfficiencyD, ptD); int pTBinD = o2::analysis::findBin(binsPtCorrelations, ptD); - if (pTBinD < 0 || effBinD < 0) { + + // reject entries outside pT ranges of interest + if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) + continue; + + if (bdtScorePrompt < mlOutputPrompt->at(effBinD) || bdtScoreBkg > mlOutputBkg->at(effBinD)) { continue; } - if (ptHadron > 10.0) { - ptHadron = 10.5; + if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { + continue; } double efficiencyWeight = 1.; + if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(effBinD) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); + if (statusDplusPrompt) { + efficiencyWeight = 1. / (efficiencyD->at(effBinD) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); + if (loadAccXEffFromCCDB) { + efficiencyWeight = 1. / (mEfficiencyPrompt->GetBinContent(mEfficiencyPrompt->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); + } + } else { + efficiencyWeight = 1. / (efficiencyFdD->at(effBinD) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); + if (loadAccXEffFromCCDB) { + efficiencyWeight = 1. / (mEfficiencyFD->GetBinContent(mEfficiencyFD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); + } + } } + // fill correlation plots for signal/bagkground correlations if (pairEntry.signalStatus()) { - registry.fill(HIST("hCorrel2DVsPtSignalMCRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSignalMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); } else { - registry.fill(HIST("hCorrel2DVsPtBkgMCRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtBkgMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); } // reject entries outside pT ranges of interest // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots if (massD > signalRegionInner->at(pTBinD) && massD < signalRegionOuter->at(pTBinD)) { // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegionMCRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); - registry.fill(HIST("hCorrel2DPtIntSignalRegionMCRec"), deltaPhi, deltaEta, efficiencyWeight); - registry.fill(HIST("hDeltaEtaPtIntSignalRegionMCRec"), deltaEta, efficiencyWeight); - registry.fill(HIST("hDeltaPhiPtIntSignalRegionMCRec"), deltaPhi, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSignalRegionMcRec"), deltaPhi, deltaEta, ptD, ptHadron, statusDplusPrompt, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSignalRegionMcRec"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegionMcRec"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegionMcRec"), deltaPhi, efficiencyWeight); + if (isPhysicalPrimary) { + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, ptD, ptHadron, statusDplusPrompt, poolBin, efficiencyWeight); + if (statusDplusPrompt == 1 && statusPromptHadron == 1) { + registry.fill(HIST("hCorrel2DVsPtSignalRegionPromptDplusPromptHadronMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + } else if (statusDplusPrompt == 0 && statusPromptHadron == 2) { + registry.fill(HIST("hCorrel2DVsPtSignalRegionNonPromptDplusNonPromptHadronMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + } + } } - - if (((massD > sidebandLeftOuter->at(pTBinD)) && (massD < sidebandLeftInner->at(pTBinD))) || - ((massD > sidebandRightInner->at(pTBinD) && massD < sidebandRightOuter->at(pTBinD)))) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsMCRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); - registry.fill(HIST("hCorrel2DPtIntSidebandsMCRec"), deltaPhi, deltaEta, efficiencyWeight); - registry.fill(HIST("hDeltaEtaPtIntSidebandsMCRec"), deltaEta, efficiencyWeight); - registry.fill(HIST("hDeltaPhiPtIntSidebandsMCRec"), deltaPhi, efficiencyWeight); + // in sideband left region + if (massD > sidebandLeftOuter->at(pTBinD) && massD < sidebandLeftInner->at(pTBinD)) { + registry.fill(HIST("hCorrel2DVsPtSidebandLeftMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandLeftMcRec"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandLeftMcRec"), deltaPhi, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSidebandsMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsMcRec"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsMcRec"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsMcRec"), deltaPhi, efficiencyWeight); + } + // in sideband right region + if (massD > sidebandRightInner->at(pTBinD) && massD < sidebandRightOuter->at(pTBinD)) { + registry.fill(HIST("hCorrel2DVsPtSidebandRightMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandRightMcRec"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandRightMcRec"), deltaPhi, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSidebandsMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsMcRec"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsMcRec"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsMcRec"), deltaPhi, efficiencyWeight); } } // end loop } PROCESS_SWITCH(HfTaskCorrelationDplusHadrons, processMcRec, "Process MC Reco mode", true); /// D-Hadron correlation pair filling task, from pair tables - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(aod::DplusHadronPair const& pairEntries) + void processMcGen(DplusHadronPair const& pairEntries) { for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities - double deltaPhi = pairEntry.deltaPhi(); - double deltaEta = pairEntry.deltaEta(); - double ptD = pairEntry.ptD(); - double ptHadron = pairEntry.ptHadron(); + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); int poolBin = pairEntry.poolBin(); - // reject entries outside pT ranges of interest - if (o2::analysis::findBin(binsPtCorrelations, ptD) < 0) { - continue; - } - if (ptHadron > 10.0) { - ptHadron = 10.5; - } + int statusPromptHadron = pairEntry.trackOrigin(); + bool isDplusPrompt = pairEntry.isPrompt(); - registry.fill(HIST("hCorrel2DVsPtMCGen"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); - registry.fill(HIST("hCorrel2DPtIntMCGen"), deltaPhi, deltaEta); - registry.fill(HIST("hDeltaEtaPtIntMCGen"), deltaEta); - registry.fill(HIST("hDeltaPhiPtIntMCGen"), deltaPhi); - } // end loop + registry.fill(HIST("hCorrel2DVsPtMcGen"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); + registry.fill(HIST("hDeltaEtaPtIntMcGen"), deltaEta); + registry.fill(HIST("hDeltaPhiPtIntMcGen"), deltaPhi); + if (isDplusPrompt) { + registry.fill(HIST("hCorrel2DVsPtMcGenPrompt"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); + if (statusPromptHadron == 1) { + registry.fill(HIST("hCorrel2DVsPtMcGenPromptDPromptHadron"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); + } + } else { + registry.fill(HIST("hCorrel2DVsPtMcGenNonPrompt"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); + if (statusPromptHadron == 2) { + registry.fill(HIST("hCorrel2DVsPtMcGenNonPromptDNonPromptHadron"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); + } + } + } } PROCESS_SWITCH(HfTaskCorrelationDplusHadrons, processMcGen, "Process MC Gen mode", false); /// D-Hadron correlation - reconstruction and selection efficiency - void processMcCandEfficiency(soa::Join const&, + void processMcCandEfficiency(soa::Join const&, soa::Join const&, CandDplusMcGen const& mcParticles, CandDplusMcReco const& candidates, @@ -363,10 +599,20 @@ struct HfTaskCorrelationDplusHadrons { if (candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { continue; } + std::vector outputMl = {-1., -1., -1.}; if (candidate.isSelDplusToPiKPi() < selectionFlagDplus) { continue; } - auto collision = candidate.template collision_as>(); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; + } + if (outputMl[0] > mlOutputBkg->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[1] < mlOutputPrompt->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()))) { + continue; + } + auto collision = candidate.template collision_as>(); + if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } multiplicity = collision.multFT0M(); if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicity, candidate.originMcRec()); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 0661847a2e1..89d8631652e 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -37,12 +37,13 @@ struct HfTaskCorrelationDsHadrons { Configurable fillHistoMcGen{"fillHistoMcGen", true, "Flag for filling histograms in MC Gen processes"}; Configurable fillHistoMcEff{"fillHistoMcEff", true, "Flag for filling histograms in efficiency processes"}; Configurable applyEfficiency{"applyEfficiency", false, "Flag for applying efficiency weights"}; - Configurable useSel8ForTrackEff{"useSel8ForTrackEff", true, "Flag for applying sel8 for collision selection"}; + Configurable useSel8ForEff{"useSel8ForEff", true, "Flag for applying sel8 for collision selection"}; Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; - Configurable doMcCollisionCheck{"doMcCollisionCheck", false, "Flag for applying the collision check and selection based on MC collision info"}; - Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; + Configurable removeCollWSplitVtx{"removeCollWSplitVtx", false, "Flag for rejecting the splitted collisions"}; + // Configurable doMcCollisionCheck{"doMcCollisionCheck", false, "Flag for applying the collision check and selection based on MC collision info"}; + Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds (avoid the case of flag = 0, no outputMlScore)"}; Configurable nTpcCrossedRaws{"nTpcCrossedRaws", 70, "Number of crossed TPC Rows"}; - Configurable eventGeneratorType{"eventGeneratorType", -1, "If positive, enable event selection using subGeneratorId information. The value indicates which events to keep (0 = MB, 4 = charm triggered, 5 = beauty triggered)"}; + // Configurable eventGeneratorType{"eventGeneratorType", -1, "If positive, enable event selection using subGeneratorId information. The value indicates which events to keep (0 = MB, 4 = charm triggered, 5 = beauty triggered)"}; Configurable decayChannel{"decayChannel", 1, "Decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; Configurable cutCollPosZMc{"cutCollPosZMc", 10., "max z-vertex position for collision acceptance"}; Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; @@ -80,13 +81,14 @@ struct HfTaskCorrelationDsHadrons { HfHelper hfHelper; - enum CandidateStep { kCandidateStepMcGenAll = 0, - kCandidateStepMcGenDsToKKPi, - kCandidateStepMcCandInAcceptance, - kCandidateStepMcDaughtersInAcceptance, - kCandidateStepMcReco, - kCandidateStepMcRecoInAcceptance, - kCandidateNSteps }; + enum CandidateStep { + kCandidateStepMcGenDsToKKPi = 0, + kCandidateStepMcCandInAcceptance, + kCandidateStepMcDaughtersInAcceptance, + kCandidateStepMcReco, + kCandidateStepMcRecoInAcceptance, + kCandidateNSteps + }; enum AssocTrackStep { kAssocTrackStepMcGen = 0, kAssocTrackStepMcGenInAcceptance, @@ -94,8 +96,6 @@ struct HfTaskCorrelationDsHadrons { kAssocTrackStepRecoMcMatch, kAssocTrackStepRecoPrimaries, kAssocTrackStepRecoSpecies, - kAssocTrackStepRecoCollMatch, - kAssocTrackStepFake, kAssocTrackNSteps }; using DsHadronPairFull = soa::Join; @@ -188,7 +188,6 @@ struct HfTaskCorrelationDsHadrons { registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtMcParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtParticleAssocCollMatchMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); @@ -204,6 +203,8 @@ struct HfTaskCorrelationDsHadrons { registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtPrmPromptPartMcGen", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hPtPrmNonPromptPartMcGen", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hFakeCollision", "Fake collision counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake coll"}}}); + registry.add("hFakeTracks", "Fake tracks counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake tracks"}}}); auto hCandidates = registry.add("hCandidates", "Candidate count at different steps", {HistType::kStepTHnF, {axisPtD, axisMultFT0M, {RecoDecay::OriginType::NonPrompt + 1, +RecoDecay::OriginType::None - 0.5, +RecoDecay::OriginType::NonPrompt + 0.5}}, kCandidateNSteps}); hCandidates->GetAxis(0)->SetTitle("#it{p}_{T} (GeV/#it{c})"); @@ -523,47 +524,163 @@ struct HfTaskCorrelationDsHadrons { } PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processMcRecME, "Process MC Reco ME", false); + SliceCache cache; + Preslice perCollisionCand = o2::aod::hf_cand::collisionId; + Preslice perCollisionCandMc = o2::aod::mcparticle::mcCollisionId; + PresliceUnsorted> collPerCollMc = o2::aod::mccollisionlabel::mcCollisionId; + /// Ds-Hadron correlation - for calculating candidate reconstruction efficiency using MC reco-level analysis - void processMcCandEfficiency(soa::Join const&, - soa::Join const&, + void processMcCandEfficiency(soa::Join const& collisions, + soa::Join const& mcCollisions, CandDsMcGen const& mcParticles, CandDsMcReco const& candidates, aod::TracksWMc const&) { auto hCandidates = registry.get(HIST("hCandidates")); + /// loop over generated collisions + for (const auto& mcCollision : mcCollisions) { + + const auto groupedCollisions = collisions.sliceBy(collPerCollMc, mcCollision.globalIndex()); + const auto groupedMcParticles = mcParticles.sliceBy(perCollisionCandMc, mcCollision.globalIndex()); + + if (groupedCollisions.size() < 1) { // Skipping MC events that have no reconstructed collisions + continue; + } + if (groupedCollisions.size() > 1 && removeCollWSplitVtx) { // Skipping MC events that have more than one reconstructed collision + continue; + } + + /// loop over reconstructed collisions + for (const auto& collision : groupedCollisions) { + + // reco collision selection + if (useSel8ForEff && !collision.sel8()) { + continue; + } + if (std::abs(collision.posZ()) > cutCollPosZMc) { + continue; + } + if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (!collision.has_mcCollision()) { + registry.fill(HIST("hFakeCollision"), 0.); + continue; + } + + float multiplicityReco = collision.multFT0M(); + float multiplicityGen = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C + + const auto groupedCandidates = candidates.sliceBy(perCollisionCand, collision.globalIndex()); + + // generated candidate loop + for (const auto& mcParticle : groupedMcParticles) { + if ((std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { + hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); + auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); + if (std::abs(yDs) <= yCandGenMax) { + hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); + if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); + } + if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); + } + } + bool isDaughterInAcceptance = true; + auto daughters = mcParticle.template daughters_as(); + for (const auto& daughter : daughters) { + if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { + isDaughterInAcceptance = false; + } + } + if (isDaughterInAcceptance) { + hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); + registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); + } + } + } + + // reconstructed candidate loop + for (const auto& candidate : groupedCandidates) { + if (candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { + continue; + } + std::vector outputMl = {-1., -1., -1.}; + if (candidate.isSelDsToKKPi() >= selectionFlagDs) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; + } + } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; + } + } + if (outputMl[0] < mlOutputPrompt->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[2] > mlOutputBkg->at(o2::analysis::findBin(binsPtD, candidate.pt()))) { + continue; + } + + if ((std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (candidate.flagMcDecayChanRec() == decayChannel)) { + auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); + // DsToKKPi and DsToPiKK division + if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { + hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicityReco, candidate.originMcRec()); + if (std::abs(hfHelper.yDs(candidate)) <= yCandMax) { + hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicityReco, candidate.originMcRec()); + if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); + } + if (candidate.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt()); + } + } + } + } + } + + } // end loop reconstructed collision + } // end loop generated collisions + } + PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processMcCandEfficiency, "Process MC for calculating candidate reconstruction efficiency", false); + + void processMcCandEfficiencyWoColl(soa::Join const&, + soa::Join const&, + CandDsMcGen const& mcParticles, + CandDsMcReco const& candidates, + aod::TracksWMc const&) + { + auto hCandidates = registry.get(HIST("hCandidates")); + /// Gen loop float multiplicity = -1.; for (const auto& mcParticle : mcParticles) { // generated candidates - if (std::abs(mcParticle.pdgCode()) == Pdg::kDS) { + if ((std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { auto mcCollision = mcParticle.template mcCollision_as>(); multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C - hCandidates->Fill(kCandidateStepMcGenAll, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - if ((std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { - hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); - if (std::abs(yDs) <= yCandGenMax) { - hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); - } - if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); - } + hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); + auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); + if (std::abs(yDs) <= yCandGenMax) { + hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); + if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); } - bool isDaughterInAcceptance = true; - auto daughters = mcParticle.template daughters_as(); - for (const auto& daughter : daughters) { - if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { - isDaughterInAcceptance = false; - } + if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); } - if (isDaughterInAcceptance) { - hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); + } + bool isDaughterInAcceptance = true; + auto daughters = mcParticle.template daughters_as(); + for (const auto& daughter : daughters) { + if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { + isDaughterInAcceptance = false; } } + if (isDaughterInAcceptance) { + hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); + registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); + } } } @@ -608,64 +725,37 @@ struct HfTaskCorrelationDsHadrons { } } } - PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processMcCandEfficiency, "Process MC for calculating candidate reconstruction efficiency", false); + PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processMcCandEfficiencyWoColl, "Process MC for calculating candidate reconstruction efficiency", false); + + Preslice perCollision = o2::aod::track::collisionId; + Preslice perCollisionMc = o2::aod::mcparticle::mcCollisionId; /// Ds-Hadron correlation - for calculating associated particle tracking efficiency using MC reco-level analysis - void processMcTrackEfficiency(soa::Join const&, - soa::Join const&, + void processMcTrackEfficiency(soa::Join const& collisions, + soa::Join const& mcCollisions, aod::McParticles const& mcParticles, TracksWithMc const& tracksData) { auto hAssocTracks = registry.get(HIST("hAssocTracks")); - /// Gen loop - float multiplicity = -1.; - float posZ = -20.; - for (const auto& mcParticle : mcParticles) { - // generated tracks - if (mcParticle.isPhysicalPrimary() && ((std::abs(mcParticle.pdgCode()) == kElectron) || (std::abs(mcParticle.pdgCode()) == kMuonMinus) || (std::abs(mcParticle.pdgCode()) == kPiPlus) || (std::abs(mcParticle.pdgCode()) == kKPlus) || (std::abs(mcParticle.pdgCode()) == kProton))) { - auto mcCollision = mcParticle.template mcCollision_as>(); - if (std::abs(mcCollision.posZ()) > cutCollPosZMc) { - continue; - } - multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C - posZ = mcCollision.posZ(); - if (doMcCollisionCheck && eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { - continue; - } - hAssocTracks->Fill(kAssocTrackStepMcGen, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); - if (mcParticle.pt() > ptTrackMin && std::abs(mcParticle.eta()) < etaTrackMax) { - hAssocTracks->Fill(kAssocTrackStepMcGenInAcceptance, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); - registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt()); - if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt()); - } - int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); - if (trackOrigin == 1) { // charm orgin - registry.fill(HIST("hPtPrmPromptPartMcGen"), mcParticle.pt()); - } else if (trackOrigin == 2) { // beauty origin - registry.fill(HIST("hPtPrmNonPromptPartMcGen"), mcParticle.pt()); - } - } + /// loop over generated collisions + for (const auto& mcCollision : mcCollisions) { + + const auto groupedCollisions = collisions.sliceBy(collPerCollMc, mcCollision.globalIndex()); + const auto groupedMcParticles = mcParticles.sliceBy(perCollisionMc, mcCollision.globalIndex()); + + if (groupedCollisions.size() < 1) { // Skipping MC events that have no reconstructed collisions + continue; + } + if (groupedCollisions.size() > 1 && removeCollWSplitVtx) { // Skipping MC events that have more than one reconstructed collision + continue; } - } - // recontructed tracks loop - for (const auto& track : tracksData) { - if (track.has_collision()) { - if (!track.isGlobalTrackWoDCA() || track.dcaXY() > dcaXYTrackMax || track.dcaZ() > dcaZTrackMax || track.tpcNClsCrossedRows() < nTpcCrossedRaws) { - continue; - } - auto collision = track.template collision_as>(); - if (useSel8ForTrackEff && !collision.sel8()) { + /// loop over reconstructed collisions + for (const auto& collision : groupedCollisions) { + + // reco collision selection + if (useSel8ForEff && !collision.sel8()) { continue; } if (std::abs(collision.posZ()) > cutCollPosZMc) { @@ -674,85 +764,92 @@ struct HfTaskCorrelationDsHadrons { if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { continue; } - multiplicity = collision.multFT0M(); - posZ = collision.posZ(); - hAssocTracks->Fill(kAssocTrackStepRecoAll, track.eta(), track.pt(), multiplicity, posZ); - if (track.has_mcParticle()) { - auto mcParticle = track.template mcParticle_as(); - if (doMcCollisionCheck) { - auto mcCollision = track.template mcParticle_as().template mcCollision_as>(); - if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { - continue; - } - hAssocTracks->Fill(kAssocTrackStepRecoMcMatch, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); - if (mcParticle.isPhysicalPrimary()) { - hAssocTracks->Fill(kAssocTrackStepRecoPrimaries, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); - registry.fill(HIST("hPtParticleAssocMcRec"), track.pt()); - if ((std::abs(mcParticle.pdgCode()) == kElectron) || (std::abs(mcParticle.pdgCode()) == kMuonMinus) || (std::abs(mcParticle.pdgCode()) == kPiPlus) || (std::abs(mcParticle.pdgCode()) == kKPlus) || (std::abs(mcParticle.pdgCode()) == kProton)) { - hAssocTracks->Fill(kAssocTrackStepRecoSpecies, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); - registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); - // check if mcParticle pt is equal to the one of the reconstructed track - registry.fill(HIST("hPtMcParticleAssocSpecieMcRec"), mcParticle.pt()); + if (!collision.has_mcCollision()) { + registry.fill(HIST("hFakeCollision"), 0.); + continue; + } + + float multiplicityReco = collision.multFT0M(); + float posZReco = collision.posZ(); + float multiplicityGen = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C + float posZGen = mcCollision.posZ(); + + const auto groupedTracks = tracksData.sliceBy(perCollision, collision.globalIndex()); + + // generated track loop + for (const auto& mcParticle : groupedMcParticles) { + if (mcParticle.isPhysicalPrimary() && ((std::abs(mcParticle.pdgCode()) == kElectron) || (std::abs(mcParticle.pdgCode()) == kMuonMinus) || (std::abs(mcParticle.pdgCode()) == kPiPlus) || (std::abs(mcParticle.pdgCode()) == kKPlus) || (std::abs(mcParticle.pdgCode()) == kProton))) { + if (mcParticle.pt() > ptTrackMin && mcParticle.pt() < ptTrackMax) { + hAssocTracks->Fill(kAssocTrackStepMcGen, mcParticle.eta(), mcParticle.pt(), multiplicityGen, posZGen); + if (std::abs(mcParticle.eta()) < etaTrackMax) { + hAssocTracks->Fill(kAssocTrackStepMcGenInAcceptance, mcParticle.eta(), mcParticle.pt(), multiplicityGen, posZGen); + registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt()); if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt()); } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt()); } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt()); } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt()); } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt()); } int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); if (trackOrigin == 1) { // charm orgin - registry.fill(HIST("hPtPrmPromptPartMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmPromptPartMcGen"), mcParticle.pt()); } else if (trackOrigin == 2) { // beauty origin - registry.fill(HIST("hPtPrmNonPromptPartMcRec"), mcParticle.pt()); - } - if (mcParticle.mcCollisionId() == track.collisionId()) { - hAssocTracks->Fill(kAssocTrackStepRecoCollMatch, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); - registry.fill(HIST("hPtParticleAssocCollMatchMcRec"), track.pt()); + registry.fill(HIST("hPtPrmNonPromptPartMcGen"), mcParticle.pt()); } } } - } else { - hAssocTracks->Fill(kAssocTrackStepRecoMcMatch, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); + } + } + + // reconstructed track loop + for (const auto& track : groupedTracks) { + if (!track.isGlobalTrackWoDCA()) { + continue; + } + if (track.has_mcParticle()) { + hAssocTracks->Fill(kAssocTrackStepRecoMcMatch, track.eta(), track.pt(), multiplicityReco, posZReco); + auto mcParticle = track.template mcParticle_as(); if (mcParticle.isPhysicalPrimary()) { - hAssocTracks->Fill(kAssocTrackStepRecoPrimaries, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); + hAssocTracks->Fill(kAssocTrackStepRecoPrimaries, track.eta(), track.pt(), multiplicityReco, posZReco); registry.fill(HIST("hPtParticleAssocMcRec"), track.pt()); if ((std::abs(mcParticle.pdgCode()) == kElectron) || (std::abs(mcParticle.pdgCode()) == kMuonMinus) || (std::abs(mcParticle.pdgCode()) == kPiPlus) || (std::abs(mcParticle.pdgCode()) == kKPlus) || (std::abs(mcParticle.pdgCode()) == kProton)) { - hAssocTracks->Fill(kAssocTrackStepRecoSpecies, mcParticle.eta(), mcParticle.pt(), multiplicity, posZ); + hAssocTracks->Fill(kAssocTrackStepRecoSpecies, track.eta(), track.pt(), multiplicityReco, posZReco); registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); - // check if mcParticle pt is equal to the one of the reconstructed track + // check the pt spectra of mcParticle registry.fill(HIST("hPtMcParticleAssocSpecieMcRec"), mcParticle.pt()); if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmPionMcRec"), track.pt()); } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmKaonMcRec"), track.pt()); } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmProtonMcRec"), track.pt()); } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmElectronMcRec"), track.pt()); } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmMuonMcRec"), track.pt()); } // check track origin int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); if (trackOrigin == 1) { // charm orgin - registry.fill(HIST("hPtPrmPromptPartMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmPromptPartMcRec"), track.pt()); } else if (trackOrigin == 2) { // beauty origin - registry.fill(HIST("hPtPrmNonPromptPartMcRec"), mcParticle.pt()); + registry.fill(HIST("hPtPrmNonPromptPartMcRec"), track.pt()); } } } + } else { + // fake track + registry.fill(HIST("hFakeTracks"), 0.); } } - } else { - // fake track - hAssocTracks->Fill(kAssocTrackStepFake, track.eta(), track.pt(), multiplicity, posZ); - } - } + + } // end loop reconstructed collision + } // end loop generated collisions } PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processMcTrackEfficiency, "Process MC for calculating associated particle tracking efficiency", false); }; diff --git a/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx new file mode 100644 index 00000000000..5f63948b769 --- /dev/null +++ b/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx @@ -0,0 +1,68 @@ +// Copyright 2019-2020 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. + +/// \file taskCorrelationHfeHadrons.cxx +/// \brief HFE-Hadrons azimuthal correlations analysis task - data-like, MC-reco and MC-Gen analyses +/// \author Rashi Gupta , IIT Indore +/// \author Ravindra Singh , IIT Indore + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/RecoDecay.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::hf_correlation_electron_hadron; + +struct HfTaskCorrelationHfeHadrons { + // Configurables + // Deltaphi binning + Configurable nBinsDeltaPhi{"nBinsDeltaPhi", 32, "Bins for #Delta#varphi bins"}; + + HistogramConfigSpec hCorrelSpec{HistType::kTHnSparseD, {{30, 0., 30.}, {20, 0., 20.}, {nBinsDeltaPhi, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf}, {50, -1.8, 1.8}}}; + + HistogramRegistry registry{ + "registry", + {{"hInclusiveEHCorrel", "Sparse for Delta phi and Delta eta Hadron with Hadron;p_{T}^{e} (GeV#it{/c});p_{T}^{h} (GeV#it{/c});#Delta#varphi;#Delta#eta;", hCorrelSpec}}}; + + void init(InitContext&) + { + registry.get(HIST("hInclusiveEHCorrel"))->Sumw2(); + } + + // correlation for electron hadron + void process(aod::HfEHadronPair const& pairEntries) + { + double deltaPhi = -999; + double deltaEta = -999; + double ptHadron = -999; + double ptElectron = -999; + + for (const auto& pairEntry : pairEntries) { + + deltaPhi = pairEntry.deltaPhi(); + deltaEta = pairEntry.deltaEta(); + ptElectron = pairEntry.ptElectron(); + ptHadron = pairEntry.ptHadron(); + + registry.fill(HIST("hInclusiveEHCorrel"), ptElectron, ptHadron, deltaPhi, deltaEta); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 2053295e740..5f6a5b2a95a 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -100,12 +100,12 @@ struct HfTaskFlow { HistogramRegistry registry{"registry"}; - OutputObj sameTPCTPCCh{"sameEventTPCTPCChHadrons"}; - OutputObj sameTPCMFTCh{"sameEventTPCMFTChHadrons"}; - OutputObj sameHF{"sameEventHFHadrons"}; - OutputObj mixedTPCTPCCh{"mixedEventTPCTPCChHadrons"}; - OutputObj mixedHF{"mixedEventHFHadrons"}; - OutputObj mixedMFT{"mixedEventTPCMFTChHadrons"}; + OutputObj sameTPCTPCChCh{"sameTPCTPCChCh"}; + OutputObj mixedTPCTPCChCh{"mixedTPCTPCChCh"}; + OutputObj sameTPCTPCHfCh{"sameTPCTPCHfCh"}; + OutputObj mixedTPCTPCHfCh{"mixedTPCTPCHfCh"}; + OutputObj sameTPCMFTChCh{"sameTPCMFTChCh"}; + OutputObj mixedTPCMFTChCh{"mixedTPCMFTChCh"}; // ========================= // init() @@ -123,65 +123,65 @@ struct HfTaskFlow { for (int iBin = 0; iBin < kNBinsEvents; iBin++) { registry.get(HIST("Data/hEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } - registry.add("Data/HadronHadron/SameEvent/hMultiplicity", "hMultiplicity", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/HadronHadron/SameEvent/hVtxZ", "hVtxZ", {HistType::kTH1F, {{400, -50, 50}}}); - registry.add("Data/HadronHadron/SameEvent/hNtracks", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hMultiplicity", "hMultiplicity", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hVtxZ", "hVtxZ", {HistType::kTH1F, {{400, -50, 50}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hNtracks", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); // histograms for event mixing const int maxMixBin = axisMultiplicity->size() * 14; // 14 bins for z-vertex - registry.add("Data/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); - registry.add("Data/HadronHf/MixedEvent/hEventCountHFMixing", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); - registry.add("Data/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); - registry.add("Data/HadronHadron/MixedEvent/hMultiplicityMixing", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/HadronHadron/MixedEvent/hVtxZMixing", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); - registry.add("Data/HadronHadron/MixedEvent/hNtracksMixing", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/HadronHf/MixedEvent/hMultiplicityHFMixing", "hMultiplicityHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/HadronHf/MixedEvent/hVtxZHFMixing", "hVtxZHFMixing", {HistType::kTH1F, {{100, -10, 10}}}); - registry.add("Data/HadronHf/MixedEvent/hNtracksHFMixing", "hNtracksHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hMultiplicityHFMixing", "hMultiplicityHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hVtxZHFMixing", "hVtxZHFMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hNtracksHFMixing", "hNtracksHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); // TRACK HISTOGRAMS // histograms for associated particles - registry.add("Data/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); - registry.add("Data/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); - registry.add("Data/HadronHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); - registry.add("Data/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); - registry.add("Data/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); // histograms for particles in event mixing - registry.add("Data/HadronHadron/MixedEvent/hPtMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); - registry.add("Data/HadronHadron/MixedEvent/hEtaMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); - registry.add("Data/HadronHadron/MixedEvent/hPhiMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hPtMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hEtaMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hPhiMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); // histograms for MFT tracks - registry.add("Data/HadronMft/hEtaPhiMFT", "multiplicity vs eta vs phi in MFT", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); - registry.add("Data/HadronMft/hEtaMFT", "etaMFT", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); - registry.add("Data/HadronMft/hPhiMFT", "phiMFT", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/hEtaPhiMFT", "multiplicity vs eta vs phi in MFT", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/hEtaMFT", "etaMFT", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HadronHadron/hPhiMFT", "phiMFT", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); // histograms for candidates auto vbins = (std::vector)binsPt; - registry.add("Data/HadronHf/hPtCand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); - registry.add("Data/HadronHf/hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); - registry.add("Data/HadronHf/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); - registry.add("Data/HadronHf/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0., 5.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hDecLength", "2-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hDecLengthXY", "2-prong candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", {HistType::kTH2F, {{500, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hCPA", "2-prong candidates;cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hEtaCand", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hImpParErr", "2-prong candidates;impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hDecLenErr", "2-prong candidates;decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/HadronHf/hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hPtCand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcTpc/HfHadron/hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcTpc/HfHadron/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcTpc/HfHadron/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0., 5.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hDecLength", "2-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hDecLengthXY", "2-prong candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", {HistType::kTH2F, {{500, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hCPA", "2-prong candidates;cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hEtaCand", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hImpParErr", "2-prong candidates;impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hDecLenErr", "2-prong candidates;decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); // histograms for candidates in event mixing - registry.add("Data/HadronHf/MixedEvent/hPtHFMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); - registry.add("Data/HadronHf/MixedEvent/hEtaHFMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); - registry.add("Data/HadronHf/MixedEvent/hPhiHFMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hPtHFMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEtaHFMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hPhiHFMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); // set axes of the correlation container std::vector corrAxis = {{axisDeltaEta, "#Delta#eta"}, @@ -195,12 +195,12 @@ struct HfTaskFlow { {axisVertexEfficiency, "z-vtx (cm)"}}; std::vector userAxis = {{axisMass, "m_{inv} (GeV/c^{2})"}}; - sameTPCTPCCh.setObject(new CorrelationContainer("sameEventTPCTPCChHadrons", "sameEventTPCTPCChHadrons", corrAxis, effAxis, {})); - sameTPCMFTCh.setObject(new CorrelationContainer("sameEventTPCMFTChHadrons", "sameEventTPCMFTChHadrons", corrAxis, effAxis, {})); - sameHF.setObject(new CorrelationContainer("sameEventHFHadrons", "sameEventHFHadrons", corrAxis, effAxis, userAxis)); - mixedTPCTPCCh.setObject(new CorrelationContainer("mixedEventTPCTPCChHadrons", "mixedEventTPCTPCChHadrons", corrAxis, effAxis, {})); - mixedHF.setObject(new CorrelationContainer("mixedEventHFHadrons", "mixedEventHFHadrons", corrAxis, effAxis, userAxis)); - mixedMFT.setObject(new CorrelationContainer("mixedEventTPCMFTChHadrons", "mixedEventTPCMFTChHadrons", corrAxis, effAxis, {})); + sameTPCTPCChCh.setObject(new CorrelationContainer("sameTPCTPCChCh", "sameTPCTPCChCh", corrAxis, effAxis, {})); + mixedTPCTPCChCh.setObject(new CorrelationContainer("mixedTPCTPCChCh", "mixedTPCTPCChCh", corrAxis, effAxis, {})); + sameTPCTPCHfCh.setObject(new CorrelationContainer("sameTPCTPCHfCh", "sameTPCTPCHfCh", corrAxis, effAxis, userAxis)); + mixedTPCTPCHfCh.setObject(new CorrelationContainer("mixedTPCTPCHfCh", "mixedTPCTPCHfCh", corrAxis, effAxis, userAxis)); + sameTPCMFTChCh.setObject(new CorrelationContainer("sameTPCMFTChCh", "sameTPCMFTChCh", corrAxis, effAxis, {})); + mixedTPCMFTChCh.setObject(new CorrelationContainer("mixedTPCMFTChCh", "mixedTPCMFTChCh", corrAxis, effAxis, {})); } // --------------- @@ -246,56 +246,56 @@ struct HfTaskFlow { int Ntracks = 0; for (const auto& track1 : tracks) { Ntracks++; - registry.fill(HIST("Data/HadronHadron/SameEvent/hPt"), track1.pt()); - registry.fill(HIST("Data/HadronHadron/SameEvent/hEta"), track1.eta()); - registry.fill(HIST("Data/HadronHadron/SameEvent/hPhi"), track1.phi()); - registry.fill(HIST("Data/HadronHadron/SameEvent/hYields"), multiplicity, track1.pt(), track1.eta()); - registry.fill(HIST("Data/HadronHadron/SameEvent/hEtaPhi"), multiplicity, track1.eta(), track1.phi()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hPt"), track1.pt()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hEta"), track1.eta()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hPhi"), track1.phi()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hYields"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hEtaPhi"), multiplicity, track1.eta(), track1.phi()); } - registry.fill(HIST("Data/HadronHadron/SameEvent/hNtracks"), Ntracks); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hNtracks"), Ntracks); } template void fillMixingQA(float multiplicity, float vz, TTracks const& tracks) { - registry.fill(HIST("Data/HadronHadron/MixedEvent/hMultiplicityMixing"), multiplicity); - registry.fill(HIST("Data/HadronHadron/MixedEvent/hVtxZMixing"), vz); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing"), multiplicity); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing"), vz); int Ntracks = 0; for (const auto& track1 : tracks) { Ntracks++; - registry.fill(HIST("Data/HadronHadron/MixedEvent/hPtMixing"), track1.pt()); - registry.fill(HIST("Data/HadronHadron/MixedEvent/hEtaMixing"), track1.eta()); - registry.fill(HIST("Data/HadronHadron/MixedEvent/hPhiMixing"), track1.phi()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hPtMixing"), track1.pt()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEtaMixing"), track1.eta()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hPhiMixing"), track1.phi()); } - registry.fill(HIST("Data/HadronHadron/MixedEvent/hNtracksMixing"), Ntracks); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing"), Ntracks); } template void fillHFMixingQA(float multiplicity, float vz, TTracks const& tracks) { - registry.fill(HIST("Data/HadronHf/MixedEvent/hMultiplicityHFMixing"), multiplicity); - registry.fill(HIST("Data/HadronHf/MixedEvent/hVtxZHFMixing"), vz); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hMultiplicityHFMixing"), multiplicity); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hVtxZHFMixing"), vz); int Ntracks = 0; for (const auto& track1 : tracks) { Ntracks++; - registry.fill(HIST("Data/HadronHf/MixedEvent/hPtHFMixing"), track1.pt()); - registry.fill(HIST("Data/HadronHf/MixedEvent/hEtaHFMixing"), track1.eta()); - registry.fill(HIST("Data/HadronHf/MixedEvent/hPhiHFMixing"), track1.phi()); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hPtHFMixing"), track1.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEtaHFMixing"), track1.eta()); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hPhiHFMixing"), track1.phi()); } - registry.fill(HIST("Data/HadronHf/MixedEvent/hNtracksHFMixing"), Ntracks); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hNtracksHFMixing"), Ntracks); } template void fillMFTQA(float multiplicity, TTracks const& tracks) { for (const auto& track1 : tracks) { - registry.fill(HIST("Data/HadronMft/hEtaMFT"), track1.eta()); + registry.fill(HIST("Data/TpcMft/HadronHadron/hEtaMFT"), track1.eta()); float phi = track1.phi(); o2::math_utils::bringTo02Pi(phi); - registry.fill(HIST("Data/HadronMft/hPhiMFT"), phi); - registry.fill(HIST("Data/HadronMft/hEtaPhiMFT"), multiplicity, track1.eta(), phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/hPhiMFT"), phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/hEtaPhiMFT"), multiplicity, track1.eta(), phi); } } @@ -322,29 +322,29 @@ struct HfTaskFlow { } if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("Data/HadronHf/hMass"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hMass"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("Data/HadronHf/hMass"), hfHelper.invMassD0barToKPi(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hMass"), hfHelper.invMassD0barToKPi(candidate), candidate.pt()); } - registry.fill(HIST("Data/HadronHf/hPtCand"), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hPtProng0"), candidate.ptProng0()); - registry.fill(HIST("Data/HadronHf/hPtProng1"), candidate.ptProng1()); - registry.fill(HIST("Data/HadronHf/hDecLength"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hDecLengthXY"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hd0Prong0"), candidate.impactParameter0(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hd0Prong1"), candidate.impactParameter1(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hd0d0"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hCTS"), hfHelper.cosThetaStarD0(candidate), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hCt"), hfHelper.ctD0(candidate), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hCPA"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hEtaCand"), candidate.eta(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); - registry.fill(HIST("Data/HadronHf/hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hPtCand"), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLength"), candidate.decayLength(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLengthXY"), candidate.decayLengthXY(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hd0Prong0"), candidate.impactParameter0(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hd0Prong1"), candidate.impactParameter1(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hd0d0"), candidate.impactParameterProduct(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hCTS"), hfHelper.cosThetaStarD0(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hCt"), hfHelper.ctD0(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hCPA"), candidate.cpa(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hEtaCand"), candidate.eta(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); } } @@ -420,7 +420,6 @@ struct HfTaskFlow { eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); @@ -453,10 +452,10 @@ struct HfTaskFlow { const auto vz = collision1.posZ(); if constexpr (std::is_same_v) { - registry.fill(HIST("Data/HadronHf/MixedEvent/hEventCountHFMixing"), bin); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing"), bin); fillHFMixingQA(multiplicity, vz, tracks1); } else { - registry.fill(HIST("Data/HadronHadron/MixedEvent/hEventCountMixing"), bin); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); fillMixingQA(multiplicity, vz, tracks1); } @@ -468,8 +467,8 @@ struct HfTaskFlow { // ===================================== // process same event correlations: h-h case // ===================================== - void processSameTpcTpcHH(FilteredCollisionsWSelMult::iterator const& collision, - TracksWDcaSel const& tracks) + void processSameTpcTpcChCh(FilteredCollisionsWSelMult::iterator const& collision, + TracksWDcaSel const& tracks) { if (!(isCollisionSelected(collision, true))) { return; @@ -481,45 +480,45 @@ struct HfTaskFlow { // temporary solution, since other correlation options always have to be ran with h-h, too // TODO: rewrite it in a more intelligent way const auto multiplicity = tracks.size(); - registry.fill(HIST("Data/HadronHadron/SameEvent/hMultiplicity"), multiplicity); - registry.fill(HIST("Data/HadronHadron/SameEvent/hVtxZ"), collision.posZ()); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hMultiplicity"), multiplicity); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hVtxZ"), collision.posZ()); BinningPolicyBase<2> baseBinning{{axisVertex, axisMultiplicity}, true}; int bin = baseBinning.getBin(std::make_tuple(collision.posZ(), multiplicity)); - registry.fill(HIST("Data/HadronHadron/SameEvent/hEventCountSame"), bin); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hEventCountSame"), bin); - sameTPCTPCCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + sameTPCTPCChCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); fillQA(multiplicity, tracks); - fillCorrelations(sameTPCTPCCh, tracks, tracks, multiplicity, collision.posZ()); + fillCorrelations(sameTPCTPCChCh, tracks, tracks, multiplicity, collision.posZ()); } - PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcHH, "Process same-event correlations for h-h case", true); + PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcChCh, "Process same-event correlations for TPC-TPC h-h case", true); // ===================================== // process same event correlations: HF-h case // ===================================== - void processSameHfHadrons(FilteredCollisionsWSelMult::iterator const& collision, - TracksWDcaSel const& tracks, - HfCandidatesSel const& candidates) + void processSameTpcTpcHfCh(FilteredCollisionsWSelMult::iterator const& collision, + TracksWDcaSel const& tracks, + HfCandidatesSel const& candidates) { if (!(isCollisionSelected(collision, true))) { return; } const auto multiplicity = tracks.size(); - sameHF->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + sameTPCTPCHfCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); fillCandidateQA(candidates); - fillCorrelations(sameHF, candidates, tracks, multiplicity, collision.posZ()); + fillCorrelations(sameTPCTPCHfCh, candidates, tracks, multiplicity, collision.posZ()); } - PROCESS_SWITCH(HfTaskFlow, processSameHfHadrons, "Process same-event correlations for HF-h case", true); + PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcHfCh, "Process same-event correlations for TPC-TPC HF-h case", true); // ===================================== // process same event correlations: h-MFT case // ===================================== - void processSameTpcMftHH(FilteredCollisionsWSelMult::iterator const& collision, - TracksWDcaSel const& tracks, - aod::MFTTracks const& mfttracks) + void processSameTpcMftChCh(FilteredCollisionsWSelMult::iterator const& collision, + TracksWDcaSel const& tracks, + aod::MFTTracks const& mfttracks) { if (!(isCollisionSelected(collision, true))) { return; @@ -527,17 +526,17 @@ struct HfTaskFlow { const auto multiplicity = tracks.size(); - sameTPCMFTCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + sameTPCMFTChCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); fillMFTQA(multiplicity, mfttracks); - fillCorrelations(sameTPCMFTCh, tracks, mfttracks, multiplicity, collision.posZ()); + fillCorrelations(sameTPCMFTChCh, tracks, mfttracks, multiplicity, collision.posZ()); } - PROCESS_SWITCH(HfTaskFlow, processSameTpcMftHH, "Process same-event correlations for h-MFT case", true); + PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChCh, "Process same-event correlations for TPC-MFT h-h case", true); // ===================================== // process mixed event correlations: h-h case // ===================================== - void processMixedTpcTpcHH(FilteredCollisionsWSelMult const& collisions, - TracksWDcaSel const& tracks) + void processMixedTpcTpcChCh(FilteredCollisionsWSelMult const& collisions, + TracksWDcaSel const& tracks) { // we want to group collisions based on charged-track multiplicity auto getTracksSize = [&tracks, this](FilteredCollisionsWSelMult::iterator const& col) { @@ -546,16 +545,16 @@ struct HfTaskFlow { return size; }; - mixCollisions(collisions, tracks, tracks, getTracksSize, mixedTPCTPCCh); + mixCollisions(collisions, tracks, tracks, getTracksSize, mixedTPCTPCChCh); } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcHH, "Process mixed-event correlations for h-h case", true); + PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcChCh, "Process mixed-event correlations for TPC-TPC h-h case", true); // ===================================== // process mixed event correlations: h-HF case // ===================================== - void processMixedHfHadrons(FilteredCollisionsWSelMult const& collisions, - TracksWDcaSel const& tracks, - HfCandidatesSel const& candidates) + void processMixedTpcTpcHfCh(FilteredCollisionsWSelMult const& collisions, + TracksWDcaSel const& tracks, + HfCandidatesSel const& candidates) { // we want to group collisions based on charged-track multiplicity auto getTracksSize = [&tracks, this](FilteredCollisionsWSelMult::iterator const& col) { @@ -564,16 +563,16 @@ struct HfTaskFlow { return size; }; - mixCollisions(collisions, candidates, tracks, getTracksSize, mixedHF); + mixCollisions(collisions, candidates, tracks, getTracksSize, mixedTPCTPCHfCh); } - PROCESS_SWITCH(HfTaskFlow, processMixedHfHadrons, "Process mixed-event correlations for HF-h case", true); + PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcHfCh, "Process mixed-event correlations for TPC-TPC HF-h case", true); // ===================================== // process mixed event correlations: h-MFT case // ===================================== - void processMixedTpcMftHH(FilteredCollisionsWSelMult const& collisions, - TracksWDcaSel const& tracks, - aod::MFTTracks const& mfttracks) + void processMixedTpcMftChCh(FilteredCollisionsWSelMult const& collisions, + TracksWDcaSel const& tracks, + aod::MFTTracks const& mfttracks) { // we want to group collisions based on charged-track multiplicity auto getTracksSize = [&tracks, this](FilteredCollisionsWSelMult::iterator const& col) { @@ -582,9 +581,9 @@ struct HfTaskFlow { return size; }; - mixCollisions(collisions, tracks, mfttracks, getTracksSize, mixedMFT); + mixCollisions(collisions, tracks, mfttracks, getTracksSize, mixedTPCMFTChCh); } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftHH, "Process mixed-event correlations for h-MFT case", true); + PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChCh, "Process mixed-event correlations for TPC-MFT h-h case", true); }; // End of struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx index 3823a9e9859..610a9e7a1ff 100644 --- a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx +++ b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx @@ -69,8 +69,10 @@ struct HfElectronSelectionWithTpcEmcal { Configurable phiTrackEMCalMin{"phiTrackEMCalMin", 4.5355f, "phi range for electron tracks associated Emcal"}; // Track and EMCal Cluster matching cut - Configurable deltaEtaMatchMin{"deltaEtaMatchMin", 0.015f, "Eta distance of EMCAL cluster to its closest track"}; - Configurable deltaPhiMatchMin{"deltaPhiMatchMin", 0.025f, "Phi distance of EMCAL cluster to its closest track"}; + Configurable deltaEtaMatchMin{"deltaEtaMatchMin", -0.013f, "Min Eta distance of EMCAL cluster to its closest track"}; + Configurable deltaEtaMatchMax{"deltaEtaMatchMax", 0.0171f, "Max Eta distance of EMCAL cluster to its closest track"}; + Configurable deltaPhiMatchMin{"deltaPhiMatchMin", -0.022f, "Min Phi distance of EMCAL cluster to its closest track"}; + Configurable deltaPhiMatchMax{"deltaPhiMatchMax", 0.028f, "Max Phi distance of EMCAL cluster to its closest track"}; Configurable timeEmcClusterMax{"timeEmcClusterMax", 50.f, "EMCal Cluster time"}; // Inclusive electron selection cut @@ -84,8 +86,11 @@ struct HfElectronSelectionWithTpcEmcal { Configurable tpcNsigmaElectronMax{"tpcNsigmaElectronMax", 3.0f, "max Electron TPCnsigma"}; // Track and EMCal Cluster matching cut for Mc Reco - Configurable mcRecDeltaEtaMatchMin{"mcRecDeltaEtaMatchMin", 0.015f, "McReco Eta distance of EMCAL cluster to its closest track"}; - Configurable mcRecDeltaPhiMatchMin{"mcRecDeltaPhiMatchMin", 0.025f, "McReco Phi distance of EMCAL cluster to its closest track"}; + Configurable mcRecDeltaEtaMatchMin{"mcRecDeltaEtaMatchMin", -0.013f, "McReco Min Eta distance of EMCAL cluster to its closest track"}; + Configurable mcRecDeltaEtaMatchMax{"mcRecDeltaEtaMatchMax", 0.0171f, "McReco Max Eta distance of EMCAL cluster to its closest track"}; + Configurable mcRecDeltaPhiMatchMin{"mcRecDeltaPhiMatchMin", -0.022f, "McReco Min Phi distance of EMCAL cluster to its closest track"}; + Configurable mcRecDeltaPhiMatchMax{"mcRecDeltaPhiMatchMax", 0.028f, "McReco Max Phi distance of EMCAL cluster to its closest track"}; + Configurable mcRecTimeEmcClusterMax{"mcRecTimeEmcClusterMax", 50.f, "McReco EMCal Cluster time"}; // Inclusive electron selection cut for Mc Reco @@ -256,14 +261,14 @@ struct HfElectronSelectionWithTpcEmcal { if (std::abs(timeEmcCluster) > timeEmcClusterMax) { continue; } - if (std::abs(deltaPhiMatch) > deltaPhiMatchMin || std::abs(deltaEtaMatch) > deltaEtaMatchMin) { + if (deltaPhiMatch < deltaPhiMatchMin || deltaPhiMatch > deltaPhiMatchMax || deltaEtaMatch < deltaEtaMatchMin || deltaEtaMatch > deltaEtaMatchMax) { continue; } } else { if (std::abs(timeEmcCluster) > mcRecTimeEmcClusterMax) { continue; } - if (std::abs(deltaPhiMatch) > mcRecDeltaPhiMatchMin || std::abs(deltaEtaMatch) > mcRecDeltaEtaMatchMin) { + if (deltaPhiMatch < mcRecDeltaPhiMatchMin || deltaPhiMatch > mcRecDeltaPhiMatchMax || deltaEtaMatch < mcRecDeltaEtaMatchMin || deltaEtaMatch > mcRecDeltaEtaMatchMax) { continue; } } diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 453a1b6b4eb..609213a5716 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -24,6 +24,11 @@ o2physics_add_dpl_workflow(task-single-muon-reader PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-single-muon-reader-assoc + SOURCES taskSingleMuonReaderAssoc.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-single-muon-source SOURCES taskSingleMuonSource.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx b/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx new file mode 100644 index 00000000000..03fa6efb5a5 --- /dev/null +++ b/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx @@ -0,0 +1,187 @@ +// Copyright 2019-2020 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. + +/// \file taskSingleMuonReaderAssoc.cxx +/// \brief Task used to read the derived table produced by the tableMaker-association of DQ framework and extract observables on single muons needed for the HF-muon analysis. +/// \author Maolin Zhang , CCNU + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/TrackFwd.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using MyCollisions = soa::Join; +using MyMuons = soa::Join; +using MyMcMuons = soa::Join; + +namespace o2::aod +{ +namespace single_muon +{ +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); +DECLARE_SOA_COLUMN(DeltaPt, deltaPt, float); +DECLARE_SOA_COLUMN(Chi2, chi2, float); +} // namespace single_muon +DECLARE_SOA_TABLE(HfSingleMuon, "AOD", "SINGLEMUON", single_muon::Pt, single_muon::DcaXY, single_muon::DeltaPt, single_muon::Chi2); +} // namespace o2::aod + +struct HfTaskSingleMuonReaderAssoc { + Produces singleMuon; + + Configurable trkType{"trkType", 0, "Muon track type, valid values are 0, 1, 2, 3 and 4"}; + Configurable etaMin{"etaMin", -3.6, "eta minimum value"}; + Configurable etaMax{"etaMax", -2.5, "eta maximum value"}; + Configurable pDcaMax{"pDcaMax", 594., "p*DCA maximum value"}; + Configurable rAbsMax{"rAbsMax", 89.5, "R at absorber end maximum value"}; + Configurable rAbsMin{"rAbsMin", 26.5, "R at absorber end minimum value"}; + Configurable fillMcHist{"fillMcHist", false, "fill MC-related histograms"}; + + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + AxisSpec axisPt{200, 0., 100., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{100, -4., -2., "#it{#eta}"}; + AxisSpec axisDCA{2000, 0., 2., "#it{DCA}_{xy} (cm)"}; + AxisSpec axisChi2MatchMCHMFT{100, 0., 100., "MCH-MFT matching #chi^{2}"}; + AxisSpec axisSign{5, -2.5, 2.5, "Charge"}; + AxisSpec axisRabs{1000, 0, 100, "R at Absorber End (cm)"}; + AxisSpec axisDeltaPt{10000, -50, 50, "#Delta #it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisVtxZ{80, -20., 20., "#it{z}_{vtx} (cm)"}; + + HistogramConfigSpec hTHnMu{HistType::kTHnSparseF, {axisPt, axisEta, axisDCA, axisRabs, axisSign, axisChi2MatchMCHMFT, axisDeltaPt}, 7}; + HistogramConfigSpec hVtxZ{HistType::kTH1F, {axisVtxZ}}; + + registry.add("hMuAfterCuts", "", hTHnMu); + if (fillMcHist) { + registry.add("hMuAfterCutsTrue", "", hTHnMu); + registry.add("hMuAfterCutsFake", "", hTHnMu); + } + registry.add("hVtxZ", "", hVtxZ); + } + + template + void runMuonSelAssoc(ReducedMuonsAssoc const& assocs, TCollisions const& collisions, TMuons const&) + { + for (const auto& collision : collisions) { + registry.fill(HIST("hVtxZ"), collision.posZ()); + } + for (const auto& assoc : assocs) { + auto muon = assoc.template reducedmuon_as(); + if (muon.trackType() != trkType) { + continue; + } + + const auto eta(muon.eta()), pDca(muon.pDca()); + const auto rAbs(muon.rAtAbsorberEnd()); + const auto dcaXY(RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())); + const auto pt(muon.pt()); + const auto charge(muon.sign()); + const auto chi2(muon.chi2MatchMCHMFT()); + + if ((eta >= etaMax) || (eta < etaMin)) { + continue; + } + if ((rAbs >= rAbsMax) || (rAbs < rAbsMin)) { + continue; + } + if (pDca >= pDcaMax) { + continue; + } + + // histograms after acceptance cuts + if (muon.has_matchMCHTrack()) { + auto muonType3 = muon.template matchMCHTrack_as(); + auto Dpt = muonType3.pt() - pt; + + singleMuon(pt, dcaXY, Dpt, chi2); + registry.fill(HIST("hMuAfterCuts"), pt, eta, dcaXY, rAbs, charge, chi2, Dpt); + } + } + } + + template + void runMuonSelMcAssoc(ReducedMuonsAssoc const& assocs, TCollisions const& collisions, TMuons const&) + { + for (const auto& collision : collisions) { + registry.fill(HIST("hVtxZ"), collision.posZ()); + } + for (const auto& assoc : assocs) { + auto muon = assoc.template reducedmuon_as(); + if (muon.trackType() != trkType) { + continue; + } + + const auto eta(muon.eta()), pDca(muon.pDca()); + const auto rAbs(muon.rAtAbsorberEnd()); + const auto dcaXY(RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())); + const auto pt(muon.pt()); + const auto charge(muon.sign()); + const auto chi2(muon.chi2MatchMCHMFT()); + + if ((eta >= etaMax) || (eta < etaMin)) { + continue; + } + if ((rAbs >= rAbsMax) || (rAbs < rAbsMin)) { + continue; + } + if (pDca >= pDcaMax) { + continue; + } + + // histograms after acceptance cuts + if (muon.has_matchMCHTrack()) { + auto muonType3 = muon.template matchMCHTrack_as(); + auto Dpt = muonType3.pt() - pt; + + singleMuon(pt, dcaXY, Dpt, chi2); + registry.fill(HIST("hMuAfterCuts"), pt, eta, dcaXY, rAbs, charge, chi2, Dpt); + if (muon.mcMask() == 0) { + registry.fill(HIST("hMuAfterCutsTrue"), pt, eta, dcaXY, rAbs, charge, chi2, Dpt); + } + if (muon.mcMask() == 128) { + registry.fill(HIST("hMuAfterCutsFake"), pt, eta, dcaXY, rAbs, charge, chi2, Dpt); + } + } + } + } + + void processMuon(ReducedMuonsAssoc const& assocs, MyCollisions const& collisions, MyMuons const& muons) + { + runMuonSelAssoc(assocs, collisions, muons); + } + PROCESS_SWITCH(HfTaskSingleMuonReaderAssoc, processMuon, "run muon selection with real data", true); + + void processMuonMc(ReducedMuonsAssoc const& assocs, MyCollisions const& collisions, MyMcMuons const& muons) + { + runMuonSelMcAssoc(assocs, collisions, muons); + } + PROCESS_SWITCH(HfTaskSingleMuonReaderAssoc, processMuonMc, "run muon selection with MC data", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C new file mode 100644 index 00000000000..bdd8f1ca7e2 --- /dev/null +++ b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C @@ -0,0 +1,364 @@ +// Copyright 2019-2020 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. + +/// \file +/// \brief macro for the calculation of FONLL+PYTHIA predictions for non-prompt charm hadrons +/// +/// \author Fabrizio Grosa , CERN + +#if !defined(__CINT__) || defined(__CLING__) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +#include "CommonConstants/MathConstants.h" +#include "Framework/Logger.h" + +#include "Pythia8/Pythia.h" + +#endif + +enum Bhadrons { + Bplus = 0, + Bzero, + Bs, + Lb, + NBeautyHadrons +}; + +enum Chadrons { + Dplus = 0, + Dzero, + Ds, + Lc, + DstarPlus, + NCharmHadrons +}; + +enum BeautyFragFracOptions { + EpEm = 0, + PPbar, + LHCb, + LHCbMin, + LHCbMax, + NBeutyFragFracOptions +}; + +const std::array beautyFragFracEpEm = {0.408, 0.408, 0.100, 0.084}; +const std::array beautyFragFracPPbar = {0.344, 0.344, 0.115, 0.198}; +const std::array charmFragFracEpEm = {0.542, 0.225, 0.092, 0.057, 0.236}; // Values from e+e- ARXIV:1404.3888 (D0, D+, Ds, Lc, D*+) +const std::array beautyHadPdgs = {511, 521, 531, 5122}; +const std::array charmHadPdgs = {411, 421, 431, 4122, 413}; +const std::array beautyHadNames = {"Bzero", "Bplus", "Bs", "Lb"}; +const std::array charmHadNames = {"Dplus", "Dzero", "Ds", "Lc", "DstarPlus"}; +std::array namesFonll = {"Central", "Min", "Max"}; + +// FUNCTION PROTOTYPES +//__________________________________________________________________________________________________ +void computeFonllPlusPythiaPredictions(int nDecays = 10000000, + int seed = 42, + std::string inFileFonllBhad = "fonll_bhadron_5dot5teV_y1.txt", + int fragFracOpt = EpEm, + bool addPromptCharmHadrons = true, + std::string inFileFonllPromptDzero = "fonll_prompt_dzero_5dot5teV_y05.txt", + std::string inFileFonllPromptDplus = "fonll_prompt_dplus_5dot5teV_y05.txt", + std::string inFileFonllPromptDstarPlus = "fonll_prompt_dstar_5dot5teV_y05.txt", + std::string outFileName = "fonll_pythia_beautyFFee_charmhadrons_5dot5tev_y0dot5.root"); +std::vector splitString(const std::string& str, char delimiter); +std::array readFonll(std::string inFile, std::string histName = "hFonllBhadron"); + +// FUNCTION IMPLEMENTATIONS +//__________________________________________________________________________________________________ +std::vector splitString(const std::string& str, char delimiter) +{ + std::vector tokens; + std::stringstream ss(str); + std::string token; + + while (std::getline(ss, token, delimiter)) { + tokens.push_back(token); + } + tokens.erase(std::remove_if(tokens.begin(), tokens.end(), [](const std::string& str) { + return str.find_first_not_of(' ') == std::string::npos; // Check if the string contains only spaces + }), + tokens.end()); + + return tokens; +} + +//__________________________________________________________________________________________________ +std::array readFonll(std::string inFile, std::string histName) +{ + + std::array hFonll{nullptr, nullptr, nullptr}; + + std::ifstream inputFile(inFile); + + if (!inputFile) { + LOGP(fatal, "Error opening file {}", inFile); + return hFonll; + } + + std::string line; + + std::vector ptCent{}; + std::vector crossSecCent{}; + std::vector crossSecMin{}; + std::vector crossSecMax{}; + while (std::getline(inputFile, line)) { + if (line.find("#") != std::string::npos) { + continue; + } + std::vector elements = splitString(line, ' '); + ptCent.push_back(std::stof(elements[0])); + crossSecCent.push_back(std::stof(elements[1])); + crossSecMin.push_back(std::stof(elements[2])); + crossSecMax.push_back(std::stof(elements[3])); + } + inputFile.close(); + + if (ptCent.size() < 2) { + LOGP(fatal, "Only one pT value in FONLL file {}, cannot deduce binning.", inFile); + } + + float ptWidth = ptCent[1] - ptCent[0]; + float ptMin = ptCent.front() - ptWidth / 2; + float ptMax = ptCent.back() + ptWidth / 2; + + hFonll[0] = new TH1D(Form("%sCentral", histName.data()), ";#it{p}_{T} (GeV/#it{c});d#sigma/d#it{p}_{T} (#it{c}/GeV)", ptCent.size(), ptMin, ptMax); + hFonll[1] = new TH1D(Form("%sMin", histName.data()), ";#it{p}_{T} (GeV/#it{c});d#sigma/d#it{p}_{T} (#it{c}/GeV)", ptCent.size(), ptMin, ptMax); + hFonll[2] = new TH1D(Form("%sMax", histName.data()), ";#it{p}_{T} (GeV/#it{c});d#sigma/d#it{p}_{T} (#it{c}/GeV)", ptCent.size(), ptMin, ptMax); + for (auto iPt{0u}; iPt < ptCent.size(); ++iPt) { + hFonll[0]->SetBinContent(iPt + 1, crossSecCent[iPt]); + hFonll[1]->SetBinContent(iPt + 1, crossSecMin[iPt]); + hFonll[2]->SetBinContent(iPt + 1, crossSecMax[iPt]); + } + + return hFonll; +} + +//__________________________________________________________________________________________________ +void computeFonllPlusPythiaPredictions(int nDecays, int seed, std::string inFileFonllBhad, int fragFracOpt, bool addPromptCharmHadrons, std::string inFileFonllPromptDzero, std::string inFileFonllPromptDplus, std::string inFileFonllPromptDstarPlus, std::string outFileName) +{ + + gROOT->SetBatch(true); + gRandom->SetSeed(seed); + + if (fragFracOpt >= NBeutyFragFracOptions) { + LOGP(fatal, "Fragmentation fraction option not supported! Exit"); + } + + // init pythia object for the decayer + Pythia8::Pythia pythia; + pythia.readString("SoftQCD:inelastic = on"); + pythia.readString("Tune:pp = 14"); + pythia.readString("Random:setSeed = on"); + pythia.readString(Form("Random:seed %d", seed)); + pythia.init(); + + // get histograms from FONLL + auto hFonllBhad = readFonll(inFileFonllBhad); + if (!hFonllBhad[0]) { + return; + } + + std::map> hFonllPromptChad{}; + if (addPromptCharmHadrons) { + hFonllPromptChad[411] = readFonll(inFileFonllPromptDplus, "hFonllPromptDplus"); + hFonllPromptChad[421] = readFonll(inFileFonllPromptDzero, "hFonllPromptDzero"); + hFonllPromptChad[413] = readFonll(inFileFonllPromptDstarPlus, "hFonllPromptDstarPlus"); + // TODO: cook something for Ds and Lc + hFonllPromptChad[431] = {nullptr, nullptr, nullptr}; + hFonllPromptChad[4122] = {nullptr, nullptr, nullptr}; + for (auto iChad{0}; iChad < NCharmHadrons; ++iChad) { + if (charmHadPdgs[iChad] == 431 || charmHadPdgs[iChad] == 4122) { + continue; + } + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + hFonllPromptChad[charmHadPdgs[iChad]][iFonll]->Scale(charmFragFracEpEm[iChad]); + } + } + } + + // initialise histograms for non-prompt charm hadrons + std::map, NBeautyHadrons + 1>> hFonllPythiaNonPromptChad{}; + for (auto iChad{0}; iChad < NCharmHadrons; ++iChad) { + for (auto iBhad{0}; iBhad < NBeautyHadrons; ++iBhad) { + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][iBhad][iFonll] = new TH1D( + Form("hFonll%sFrom%s%s", charmHadNames[iChad].data(), beautyHadNames[iBhad].data(), namesFonll[iFonll].data()), + ";#it{p}_{T} (GeV/#it{c});d#sigma/d#it{p}_{T} (#it{c}/GeV)", 1000, 0., 100.); + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][iBhad][iFonll]->Sumw2(); + } + } + } + + // compute fractions for normalisation + std::array fragFracs{}; + std::array, NBeautyHadrons> fragFracFuncs{}; // used in case of LHCb due to the pT dependence + if (fragFracOpt == EpEm) { + fragFracs = beautyFragFracEpEm; + } else if (fragFracOpt == PPbar) { + fragFracs = beautyFragFracPPbar; + } else { // LHCb + for (int iPar{0}; iPar < 15; ++iPar) { + fragFracFuncs[0][iPar] = new TF1(Form("fracBz_%d", iPar), "1 / (2 * (([0] * ([1] + [2] * (x - [3]))) + ([4] * ([5] + exp([6] + [7] * x))) + 1) )", 0.f, 300.f); // B0 + fragFracFuncs[1][iPar] = new TF1(Form("fracBp_%d", iPar), "1 / (2 * (([0] * ([1] + [2] * (x - [3]))) + ([4] * ([5] + exp([6] + [7] * x))) + 1) )", 0.f, 300.f); // B+ + fragFracFuncs[2][iPar] = new TF1(Form("fracBs_%d", iPar), "([0] * ([1] + [2] * (x - [3]))) / (([0] * [1] + [2] * (x - [3])) + ([4] * ([5] + exp([6] + [7] * x))) + 1)", 0.f, 300.f); // Bs0 + fragFracFuncs[3][iPar] = new TF1(Form("fracLb_%d", iPar), "([4] * ([5] + exp([6] + [7] * x))) / (([0] * ([1] + [2] * (x - [3]))) + ([4] * ([5] + exp([6] + [7] * x))) + 1)", 0.f, 300.f); // Lb + + // parameters from https://arxiv.org/pdf/1902.06794.pdf + float sign = (iPar < 8) ? 1.f : -1.f; + float parLbA = 1.f + ((iPar == 1 || iPar == 8) ? sign * 0.061f : 0.f); + float parLbp1 = 0.0793f + ((iPar == 2 || iPar == 9) ? sign * 0.0141f : 0.f); + float parLbp2 = -1.022f + ((iPar == 3 || iPar == 10) ? sign * 0.0047f : 0.f); + float parLbp3 = -0.107f + ((iPar == 4 || iPar == 11) ? sign * 0.002f : 0.f); + float parBsA = 1.f + ((iPar == 5 || iPar == 12) ? sign * 0.043f : 0.f); + float parBsp1 = 0.119f + ((iPar == 6 || iPar == 13) ? sign * 0.001f : 0.f); + float parBsp2 = -0.00091f + ((iPar == 7 || iPar == 14) ? sign * 0.00025f : 0.f); + float parBsAvePt = 10.1f; + + for (int iBhad{0}; iBhad < NBeautyHadrons; ++iBhad) { + fragFracFuncs[iBhad][iPar]->SetParameters(parBsA, parBsp1, parBsp2, parBsAvePt, parLbA, parLbp1, parLbp2, parLbp3); + } + } + } + + std::array beautyHadMasses{}; + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + for (auto iBhad{0}; iBhad < NBeautyHadrons; ++iBhad) { + beautyHadMasses[iBhad] = TDatabasePDG::Instance()->GetParticle(beautyHadPdgs[iBhad])->Mass(); + for (auto iDecay{0}; iDecay < nDecays; ++iDecay) { + auto ptB = hFonllBhad[iFonll]->GetRandom(); + auto yB = gRandom->Uniform(-1., 1.); // we might consider to use more realistic shape from FONLL in the future + auto phiB = gRandom->Rndm() * o2::constants::math::TwoPI; + auto pxB = ptB * std::cos(phiB); + auto pyB = ptB * std::sin(phiB); + auto mtB = std::sqrt(beautyHadMasses[iBhad] * beautyHadMasses[iBhad] + ptB * ptB); + auto pzB = mtB * std::sinh(yB); + auto pB = std::sqrt(ptB * ptB + pzB * pzB); + auto eB = std::sqrt(beautyHadMasses[iBhad] * beautyHadMasses[iBhad] + pB * pB); + + Pythia8::Particle Bhad; + Bhad.id(beautyHadPdgs[iBhad]); + Bhad.status(81); + Bhad.m(beautyHadMasses[iBhad]); + Bhad.xProd(0.); + Bhad.yProd(0.); + Bhad.zProd(0.); + Bhad.tProd(0.); + Bhad.e(eB); + Bhad.px(pxB); + Bhad.py(pyB); + Bhad.pz(pzB); + + pythia.event.reset(); + pythia.event.append(Bhad); + auto idPart = pythia.event[1].id(); + pythia.particleData.mayDecay(idPart, true); + pythia.moreDecays(); + + auto fracB = fragFracs[iBhad]; + if (fragFracOpt == LHCb) { + fracB = fragFracFuncs[iBhad][0]->Eval(ptB > 5.f ? ptB : 5); + } else if (fragFracOpt == LHCbMin) { + fracB = 2.f; + for (int iPar{0}; iPar < 15; ++iPar) { + auto tmpFrac = fragFracFuncs[iBhad][iPar]->Eval(ptB > 5.f ? ptB : 5); + if (tmpFrac < fracB) { + fracB = tmpFrac; + } + } + } else if (fragFracOpt == LHCbMax) { + fracB = -1.f; + for (int iPar{0}; iPar < 15; ++iPar) { + auto tmpFrac = fragFracFuncs[iBhad][iPar]->Eval(ptB > 5.f ? ptB : 5); + if (tmpFrac > fracB) { + fracB = tmpFrac; + } + } + } + + for (int iPart{1}; iPart < pythia.event.size(); ++iPart) { + if (std::abs(pythia.event[iPart].y()) > 0.5) { + continue; + } + auto absPdg = std::abs(pythia.event[iPart].id()); + if (std::find(charmHadPdgs.begin(), charmHadPdgs.end(), absPdg) != charmHadPdgs.end()) { // we found a charm hadron, let's fill the corresponding histogram + hFonllPythiaNonPromptChad[absPdg][iBhad][iFonll]->Fill(pythia.event[iPart].pT(), fracB); + } + } + } + } + } + + std::array normCrossSec{}; + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + normCrossSec[iFonll] = hFonllBhad[iFonll]->Integral(); + for (auto iChad{0}; iChad < NCharmHadrons; ++iChad) { + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][NBeautyHadrons][iFonll] = reinterpret_cast(hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][0][iFonll]->Clone(Form("hFonllNonPrompt%s%s", charmHadNames[iChad].data(), namesFonll[iFonll].data()))); + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][NBeautyHadrons][iFonll]->Reset(); + for (auto iBhad{0}; iBhad < NBeautyHadrons; ++iBhad) { + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][iBhad][iFonll]->Scale(normCrossSec[iFonll] / nDecays); + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][NBeautyHadrons][iFonll]->Add(hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][iBhad][iFonll]); + } + } + } + + TFile outFile(outFileName.data(), "recreate"); + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + hFonllBhad[iFonll]->Write(); + } + auto dirNonPrompt = new TDirectoryFile("NonPrompt", "NonPrompt"); + dirNonPrompt->Write(); + for (auto iChad{0}; iChad < NCharmHadrons; ++iChad) { + dirNonPrompt->cd(); + auto dirCharmHad = new TDirectoryFile(charmHadNames[iChad].data(), charmHadNames[iChad].data()); + dirCharmHad->Write(); + dirCharmHad->cd(); + for (auto iBhad{0}; iBhad < NBeautyHadrons + 1; ++iBhad) { + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + hFonllPythiaNonPromptChad[charmHadPdgs[iChad]][iBhad][iFonll]->Write(); + } + } + } + if (addPromptCharmHadrons) { + outFile.cd(); + auto dirPrompt = new TDirectoryFile("Prompt", "Prompt"); + dirPrompt->Write(); + for (auto iChad{0}; iChad < NCharmHadrons; ++iChad) { + dirPrompt->cd(); + auto dirCharmHad = new TDirectoryFile(charmHadNames[iChad].data(), charmHadNames[iChad].data()); + dirCharmHad->Write(); + dirCharmHad->cd(); + for (auto iFonll{0}; iFonll < 3; ++iFonll) { + if (hFonllPromptChad[charmHadPdgs[iChad]][iFonll]) { + hFonllPromptChad[charmHadPdgs[iChad]][iFonll]->Write(); + } + } + } + } + outFile.Close(); +} diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index cbb9580bbf4..96981187d1f 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -75,9 +75,19 @@ o2physics_add_dpl_workflow(candidate-creator-sigmac0plusplus PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-creator-sigmac0plusplus-cascade + SOURCES candidateCreatorSigmac0plusplusCascade.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-creator-xic0-omegac0 SOURCES candidateCreatorXic0Omegac0.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter O2Physics::EventFilteringUtils KFParticle::KFParticle + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(candidate-creator-xic-to-xi-pi-pi + SOURCES candidateCreatorXicToXiPiPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-xicc @@ -162,6 +172,11 @@ o2physics_add_dpl_workflow(candidate-selector-xic-to-p-k-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-selector-xic-to-xi-pi-pi + SOURCES candidateSelectorXicToXiPiPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-selector-xicc-to-p-k-pi-pi SOURCES candidateSelectorXiccToPKPiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -239,6 +254,11 @@ o2physics_add_dpl_workflow(tree-creator-xic-to-p-k-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tree-creator-xic-to-xi-pi-pi + SOURCES treeCreatorXicToXiPiPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tree-creator-xicc-to-p-k-pi-pi SOURCES treeCreatorXiccToPKPiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index de4c9950fe0..82412417a32 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -171,7 +171,7 @@ struct HfCandidateCreator2Prong { void runCreator2ProngWithDCAFitterN(Coll const&, CandType const& rowsTrackIndexProng2, TTracks const&, - aod::BCsWithTimestamps const& bcWithTimeStamps) + aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { // loop over pairs of track indices for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { @@ -179,7 +179,7 @@ struct HfCandidateCreator2Prong { /// reject candidates not satisfying the event selections auto collision = rowTrackIndexProng2.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -211,7 +211,7 @@ struct HfCandidateCreator2Prong { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } @@ -320,7 +320,7 @@ struct HfCandidateCreator2Prong { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng2.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -596,51 +596,51 @@ struct HfCandidateCreator2Prong { /////////////////////////////////////////////////////////// /// @brief process function to monitor collisions - no centrality - void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreator2Prong, processCollisions, "Collision monitoring - no centrality", true); /// @brief process function to monitor collisions - FT0C centrality - void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreator2Prong, processCollisionsCentFT0C, "Collision monitoring - FT0C centrality", false); /// @brief process function to monitor collisions - FT0M centrality - void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -653,13 +653,30 @@ struct HfCandidateCreator2ProngExpressions { Produces rowMcMatchRec; Produces rowMcMatchGen; + // Configuration + o2::framework::Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; + HfEventSelectionMc hfEvSelMc; // mc event selection and monitoring + + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + using BCsInfo = soa::Join; HistogramRegistry registry{"registry"}; // inspect for which zPvPosMax cut was set for reconstructed void init(InitContext& initContext) { + std::array procCollisions = {doprocessMc, doprocessMcCentFT0C, doprocessMcCentFT0M}; + if (std::accumulate(procCollisions.begin(), procCollisions.end(), 0) > 1) { + LOGP(fatal, "At most one process function for collision study can be enabled at a time."); + } + const auto& workflows = initContext.services().get(); for (const DeviceSpec& device : workflows.devices) { if (device.name.compare("hf-candidate-creator-2prong") == 0) { @@ -671,10 +688,12 @@ struct HfCandidateCreator2ProngExpressions { } /// Performs MC matching. - void processMc(aod::TracksWMc const& tracks, - aod::McParticles const& mcParticles, - aod::McCollisions const&, - BCsInfo const&) + template + void runCreator2ProngMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + CCs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const&) { rowCandidateProng2->bindExternalIndices(&tracks); @@ -689,6 +708,24 @@ struct HfCandidateCreator2ProngExpressions { flag = 0; origin = 0; auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as()}; + + // Check whether the particle is from background events. If so, reject it. + if (rejectBackground) { + bool fromBkg{false}; + for (const auto& daughter : arrayDaughters) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + rowMcMatchRec(flag, origin, -1.f, 0); + continue; + } + } std::vector idxBhadMothers{}; // D0(bar) → π± K∓ @@ -726,54 +763,104 @@ struct HfCandidateCreator2ProngExpressions { } } - // Match generated particles. - for (const auto& particle : mcParticles) { - flag = 0; - origin = 0; - std::vector idxBhadMothers{}; - - auto mcCollision = particle.mcCollision(); + for (const auto& mcCollision : mcCollisions) { - const auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision); + // Slice the particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + if constexpr (centEstimator == CentralityEstimator::FT0C) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::FT0M) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::None) { + const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } hfEvSelMc.fillHistograms(rejectionMask); if (rejectionMask != 0) { - /// at least one event selection not satisfied --> reject the gen particle - rowMcMatchGen(flag, origin, -1); + // at least one event selection not satisfied --> reject all particles from this collision + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + rowMcMatchGen(0, 0, -1); + } continue; } - // D0(bar) → π± K∓ - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { - flag = sign * (1 << DecayType::D0ToPiK); - } + // Match generated particles. + for (const auto& particle : mcParticlesPerMcColl) { + flag = 0; + origin = 0; + std::vector idxBhadMothers{}; + // Reject particles from background events + if (particle.fromBackgroundEvent() && rejectBackground) { + rowMcMatchGen(flag, origin, -1); + continue; + } - // J/ψ → e+ e− - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { - flag = 1 << DecayType::JpsiToEE; + // D0(bar) → π± K∓ + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { + flag = sign * (1 << DecayType::D0ToPiK); } - } - // J/ψ → ÎŒ+ Ό− - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { - flag = 1 << DecayType::JpsiToMuMu; + // J/ψ → e+ e− + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { + flag = 1 << DecayType::JpsiToEE; + } } - } - // Check whether the particle is non-prompt (from a b quark). - if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(flag, origin, idxBhadMothers[0]); - } else { - rowMcMatchGen(flag, origin, -1); + // J/ψ → ÎŒ+ Ό− + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { + flag = 1 << DecayType::JpsiToMuMu; + } + } + + // Check whether the particle is non-prompt (from a b quark). + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMcMatchGen(flag, origin, idxBhadMothers[0]); + } else { + rowMcMatchGen(flag, origin, -1); + } } } } - PROCESS_SWITCH(HfCandidateCreator2ProngExpressions, processMc, "Process MC", false); + void processMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreator2ProngMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreator2ProngExpressions, processMc, "Process MC - no centrality", false); + + void processMcCentFT0C(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Cs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreator2ProngMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreator2ProngExpressions, processMcCentFT0C, "Process MC - FT0c centrality", false); + + void processMcCentFT0M(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Ms const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreator2ProngMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreator2ProngExpressions, processMcCentFT0M, "Process MC - FT0m centrality", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 03650ed7fa4..144f6c45ea6 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -171,7 +171,7 @@ struct HfCandidateCreator3Prong { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng3.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -205,7 +205,7 @@ struct HfCandidateCreator3Prong { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } @@ -403,10 +403,10 @@ struct HfCandidateCreator3Prong { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -420,10 +420,10 @@ struct HfCandidateCreator3Prong { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -437,10 +437,10 @@ struct HfCandidateCreator3Prong { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -453,6 +453,9 @@ struct HfCandidateCreator3ProngExpressions { Produces rowMcMatchRec; Produces rowMcMatchGen; + // Configuration + o2::framework::Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; + bool createDplus{false}; bool createDs{false}; bool createLc{false}; @@ -462,8 +465,20 @@ struct HfCandidateCreator3ProngExpressions { using BCsInfo = soa::Join; HistogramRegistry registry{"registry"}; + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + void init(InitContext& initContext) { + std::array procCollisions = {doprocessMc, doprocessMcCentFT0C, doprocessMcCentFT0M}; + if (std::accumulate(procCollisions.begin(), procCollisions.end(), 0) > 1) { + LOGP(fatal, "At most one process function for collision study can be enabled at a time."); + } // inspect for which particle species the candidates were created and which zPvPosMax cut was set for reconstructed const auto& workflows = initContext.services().get(); @@ -495,10 +510,12 @@ struct HfCandidateCreator3ProngExpressions { } /// Performs MC matching. - void processMc(aod::TracksWMc const& tracks, - aod::McParticles const& mcParticles, - aod::McCollisions const&, - BCsInfo const&) + template + void runCreator3ProngMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + CCs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const&) { rowCandidateProng3->bindExternalIndices(&tracks); @@ -527,6 +544,24 @@ struct HfCandidateCreator3ProngExpressions { std::vector idxBhadMothers{}; auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as(), candidate.prong2_as()}; + // Check whether the particle is from background events. If so, reject it. + if (rejectBackground) { + bool fromBkg{false}; + for (const auto& daughter : arrayDaughters) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + rowMcMatchRec(flag, origin, swapping, channel, -1.f, 0); + continue; + } + } + // D± → π± K∓ π± if (createDplus) { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); @@ -613,103 +648,153 @@ struct HfCandidateCreator3ProngExpressions { } } - // Match generated particles. - for (const auto& particle : mcParticles) { - flag = 0; - origin = 0; - channel = 0; - arrDaughIndex.clear(); - std::vector idxBhadMothers{}; + for (const auto& mcCollision : mcCollisions) { - auto mcCollision = particle.mcCollision(); - - const auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision); + // Slice the particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + if constexpr (centEstimator == CentralityEstimator::FT0C) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::FT0M) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::None) { + const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } hfEvSelMc.fillHistograms(rejectionMask); if (rejectionMask != 0) { - /// at least one event selection not satisfied --> reject the gen particle - rowMcMatchGen(flag, origin, channel, -1); + // at least one event selection not satisfied --> reject all gen particles from this collision + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + rowMcMatchGen(0, 0, 0, -1); + } continue; } - // D± → π± K∓ π± - if (createDplus) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << DecayType::DplusToPiKPi); + // Match generated particles. + for (const auto& particle : mcParticlesPerMcColl) { + flag = 0; + origin = 0; + channel = 0; + arrDaughIndex.clear(); + std::vector idxBhadMothers{}; + // Reject particles from background events + if (particle.fromBackgroundEvent() && rejectBackground) { + rowMcMatchGen(flag, origin, channel, -1); + continue; } - } - // Ds± → K± K∓ π± and D± → K± K∓ π± - if (flag == 0 && createDs) { - bool isDplus = false; - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * (1 << DecayType::DsToKKPi); - } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * (1 << DecayType::DsToKKPi); - isDplus = true; + // D± → π± K∓ π± + if (createDplus) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flag = sign * (1 << DecayType::DplusToPiKPi); + } } - if (flag != 0) { - RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == 2) { - for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); - arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); - } - if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? DecayChannelDToKKPi::DplusToPhiPi : DecayChannelDToKKPi::DsToPhiPi; - } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? DecayChannelDToKKPi::DplusToK0starK : DecayChannelDToKKPi::DsToK0starK; + + // Ds± → K± K∓ π± and D± → K± K∓ π± + if (flag == 0 && createDs) { + bool isDplus = false; + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + // TODO: move to different and explicit flags + flag = sign * (1 << DecayType::DsToKKPi); + } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + // TODO: move to different and explicit flags + flag = sign * (1 << DecayType::DsToKKPi); + isDplus = true; + } + if (flag != 0) { + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { + auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); + arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + } + if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { + channel = isDplus ? DecayChannelDToKKPi::DplusToPhiPi : DecayChannelDToKKPi::DsToPhiPi; + } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { + channel = isDplus ? DecayChannelDToKKPi::DplusToK0starK : DecayChannelDToKKPi::DsToK0starK; + } } } } - } - // Λc± → p± K∓ π± - if (flag == 0 && createLc) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << DecayType::LcToPKPi); - - // Flagging the different Λc± → p± K∓ π± decay channels - RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == 2) { - for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); - arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); - } - if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { - channel = 1; - } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { - channel = 2; - } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { - channel = 3; + // Λc± → p± K∓ π± + if (flag == 0 && createLc) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flag = sign * (1 << DecayType::LcToPKPi); + + // Flagging the different Λc± → p± K∓ π± decay channels + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { + auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); + arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + } + if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { + channel = 1; + } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { + channel = 2; + } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { + channel = 3; + } } } } - } - // Ξc± → p± K∓ π± - if (flag == 0 && createXic) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << DecayType::XicToPKPi); + // Ξc± → p± K∓ π± + if (flag == 0 && createXic) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flag = sign * (1 << DecayType::XicToPKPi); + } } - } - // Check whether the particle is non-prompt (from a b quark). - if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(flag, origin, channel, idxBhadMothers[0]); - } else { - rowMcMatchGen(flag, origin, channel, -1); + // Check whether the particle is non-prompt (from a b quark). + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMcMatchGen(flag, origin, channel, idxBhadMothers[0]); + } else { + rowMcMatchGen(flag, origin, channel, -1); + } } } } - PROCESS_SWITCH(HfCandidateCreator3ProngExpressions, processMc, "Process MC", false); + void processMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreator3ProngMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreator3ProngExpressions, processMc, "Process MC - no centrality", false); + + void processMcCentFT0C(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Cs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreator3ProngMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreator3ProngExpressions, processMcCentFT0C, "Process MC - FT0c centrality", false); + + void processMcCentFT0M(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Ms const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreator3ProngMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreator3ProngExpressions, processMcCentFT0M, "Process MC - FT0m centrality", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateCreatorB0.cxx b/PWGHF/TableProducer/candidateCreatorB0.cxx index ec298631266..559734c7b12 100644 --- a/PWGHF/TableProducer/candidateCreatorB0.cxx +++ b/PWGHF/TableProducer/candidateCreatorB0.cxx @@ -241,7 +241,7 @@ struct HfCandidateCreatorB0 { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for D cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for D cannot work, skipping the candidate."; hCandidatesD->Fill(SVFitting::Fail); continue; } @@ -303,7 +303,7 @@ struct HfCandidateCreatorB0 { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for B cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for B cannot work, skipping the candidate."; hCandidatesB->Fill(SVFitting::Fail); continue; } diff --git a/PWGHF/TableProducer/candidateCreatorBplus.cxx b/PWGHF/TableProducer/candidateCreatorBplus.cxx index 695f42d4710..b8845945df9 100644 --- a/PWGHF/TableProducer/candidateCreatorBplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorBplus.cxx @@ -236,7 +236,7 @@ struct HfCandidateCreatorBplus { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for D cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for D cannot work, skipping the candidate."; hCandidatesD->Fill(SVFitting::Fail); continue; } @@ -303,7 +303,7 @@ struct HfCandidateCreatorBplus { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for B cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for B cannot work, skipping the candidate."; hCandidatesB->Fill(SVFitting::Fail); continue; } diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 7d8ad642fc2..69fb0c3f178 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -221,7 +221,7 @@ struct HfCandidateCreatorBs { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for D cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for D cannot work, skipping the candidate."; hCandidatesD->Fill(SVFitting::Fail); continue; } @@ -284,7 +284,7 @@ struct HfCandidateCreatorBs { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for B cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for B cannot work, skipping the candidate."; hCandidatesB->Fill(SVFitting::Fail); continue; } diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index dcacc81a9a4..3b1a5685ac8 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -143,7 +143,7 @@ struct HfCandidateCreatorCascade { aod::V0Datas const&, aod::V0fCDatas const&, aod::TracksWCov const&, - aod::BCsWithTimestamps const& bcWithTimeStamps) + aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { // loop over pairs of track indices for (const auto& casc : rowsTrackIndexCasc) { @@ -151,7 +151,7 @@ struct HfCandidateCreatorCascade { /// reject candidates in collisions not satisfying the event selections auto collision = casc.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -260,7 +260,7 @@ struct HfCandidateCreatorCascade { // LOG(info) << "Vertexing succeeded for Lc candidate"; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } @@ -374,51 +374,51 @@ struct HfCandidateCreatorCascade { /////////////////////////////////////////////////////////// /// @brief process function to monitor collisions - no centrality - void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreatorCascade, processCollisions, "Collision monitoring - no centrality", true); /// @brief process function to monitor collisions - FT0C centrality - void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreatorCascade, processCollisionsCentFT0C, "Collision monitoring - FT0C centrality", false); /// @brief process function to monitor collisions - FT0M centrality - void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -436,9 +436,25 @@ struct HfCandidateCreatorCascadeMc { using BCsInfo = soa::Join; HistogramRegistry registry{"registry"}; + // Configuration + o2::framework::Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; + + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + // inspect for which zPvPosMax cut was set for reconstructed void init(InitContext& initContext) { + std::array procCollisions = {doprocessMc, doprocessMcCentFT0C, doprocessMcCentFT0M}; + if (std::accumulate(procCollisions.begin(), procCollisions.end(), 0) > 1) { + LOGP(fatal, "At most one process function for collision study can be enabled at a time."); + } + const auto& workflows = initContext.services().get(); for (const DeviceSpec& device : workflows.devices) { if (device.name.compare("hf-candidate-creator-cascade") == 0) { @@ -449,10 +465,12 @@ struct HfCandidateCreatorCascadeMc { hfEvSelMc.addHistograms(registry); // particles monitoring } - void processMc(MyTracksWMc const& tracks, - aod::McParticles const& mcParticles, - aod::McCollisions const&, - BCsInfo const&) + template + void runCreatorCascMc(MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + CCs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const&) { int8_t sign = 0; int8_t origin = 0; @@ -473,6 +491,23 @@ struct HfCandidateCreatorCascadeMc { auto arrayDaughtersV0 = std::array{trackV0DaughPos, trackV0DaughNeg}; auto arrayDaughtersLc = std::array{bach, trackV0DaughPos, trackV0DaughNeg}; + // Check whether the particle is from background events. If so, reject it. + if (rejectBackground) { + bool fromBkg{false}; + for (const auto& daughter : arrayDaughtersLc) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + rowMcMatchRec(sign, origin, -1.f, 0); + continue; + } + } RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, kK0Short, std::array{+kPiPlus, -kPiPlus}, false, &sign, 1); if (sign != 0) { // we have already positively checked the K0s @@ -492,58 +527,106 @@ struct HfCandidateCreatorCascadeMc { rowMcMatchRec(sign, origin, -1.f, 0); } } - //} - // Match generated particles. - for (const auto& particle : mcParticles) { - origin = 0; - std::vector idxBhadMothers{}; - - auto mcCollision = particle.mcCollision(); + for (const auto& mcCollision : mcCollisions) { - const auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision); + // Slice the MC particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + if constexpr (centEstimator == CentralityEstimator::FT0C) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::FT0M) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::None) { + const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } hfEvSelMc.fillHistograms(rejectionMask); if (rejectionMask != 0) { - /// at least one event selection not satisfied --> reject the gen particle - rowMcMatchGen(sign, origin, -1); + // at least one event selection not satisfied --> reject all particles from this collision + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + rowMcMatchGen(0, 0, -1); + } continue; } - // checking if I have a Lc --> K0S + p - RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, +kK0Short}, false, &sign, 2); - if (sign == 0) { // now check for anti-Lc - RecoDecay::isMatchedMCGen(mcParticles, particle, -Pdg::kLambdaCPlus, std::array{-kProton, +kK0Short}, false, &sign, 2); - sign = -sign; - } - if (sign != 0) { - arrDaughLcIndex.clear(); - // checking that the final daughters (decay depth = 3) are p, pi+, pi- - RecoDecay::getDaughters(particle, &arrDaughLcIndex, arrDaughLcPDGRef, 3); // best would be to check the K0S daughters - if (arrDaughLcIndex.size() == 3) { - for (std::size_t iProng = 0; iProng < arrDaughLcIndex.size(); ++iProng) { - auto daughI = mcParticles.rawIteratorAt(arrDaughLcIndex[iProng]); - arrDaughLcPDG[iProng] = daughI.pdgCode(); - } - if (!(arrDaughLcPDG[0] == sign * arrDaughLcPDGRef[0] && arrDaughLcPDG[1] == arrDaughLcPDGRef[1] && arrDaughLcPDG[2] == arrDaughLcPDGRef[2])) { // this should be the condition, first bach, then v0 - sign = 0; - } else { - LOG(debug) << "Lc --> K0S+p found in MC table"; + // Match generated particles. + for (const auto& particle : mcParticlesPerMcColl) { + origin = 0; + std::vector idxBhadMothers{}; + // Reject particles from background events + if (particle.fromBackgroundEvent() && rejectBackground) { + rowMcMatchGen(sign, origin, -1); + continue; + } + // checking if I have a Lc --> K0S + p + RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, +kK0Short}, false, &sign, 2); + if (sign == 0) { // now check for anti-Lc + RecoDecay::isMatchedMCGen(mcParticles, particle, -Pdg::kLambdaCPlus, std::array{-kProton, +kK0Short}, false, &sign, 2); + sign = -sign; + } + if (sign != 0) { + arrDaughLcIndex.clear(); + // checking that the final daughters (decay depth = 3) are p, pi+, pi- + RecoDecay::getDaughters(particle, &arrDaughLcIndex, arrDaughLcPDGRef, 3); // best would be to check the K0S daughters + if (arrDaughLcIndex.size() == 3) { + for (std::size_t iProng = 0; iProng < arrDaughLcIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughLcIndex[iProng]); + arrDaughLcPDG[iProng] = daughI.pdgCode(); + } + if (!(arrDaughLcPDG[0] == sign * arrDaughLcPDGRef[0] && arrDaughLcPDG[1] == arrDaughLcPDGRef[1] && arrDaughLcPDG[2] == arrDaughLcPDGRef[2])) { // this should be the condition, first bach, then v0 + sign = 0; + } else { + LOG(debug) << "Lc --> K0S+p found in MC table"; + } } } - } - // Check whether the particle is non-prompt (from a b quark). - if (sign != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(sign, origin, idxBhadMothers[0]); - } else { - rowMcMatchGen(sign, origin, -1); + // Check whether the particle is non-prompt (from a b quark). + if (sign != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMcMatchGen(sign, origin, idxBhadMothers[0]); + } else { + rowMcMatchGen(sign, origin, -1); + } } } } - PROCESS_SWITCH(HfCandidateCreatorCascadeMc, processMc, "Process MC data", false); + void processMc(MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreatorCascMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreatorCascadeMc, processMc, "Process MC - no centrality", false); + + void processMcCentFT0C(MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Cs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreatorCascMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreatorCascadeMc, processMcCentFT0C, "Process MC - FT0c centrality", false); + + void processMcCentFT0M(MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Ms const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreatorCascMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreatorCascadeMc, processMcCentFT0M, "Process MC - FT0m centrality", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index 285c544c11b..c343d8ce526 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -172,7 +172,7 @@ struct HfCandidateCreatorDstar { CandsDstar const& rowsTrackIndexDstar, aod::Hf2Prongs const&, aod::TracksWCov const&, - aod::BCsWithTimestamps const& bcWithTimeStamps) + aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { // LOG(info) << "runCreatorDstar function called"; // LOG(info) << "candidate loop starts"; @@ -182,7 +182,7 @@ struct HfCandidateCreatorDstar { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexDstar.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -230,7 +230,7 @@ struct HfCandidateCreatorDstar { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } @@ -444,51 +444,51 @@ struct HfCandidateCreatorDstar { /////////////////////////////////////////////////////////// /// @brief process function to monitor collisions - no centrality - void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreatorDstar, processCollisions, "Collision monitoring - no centrality", true); /// @brief process function to monitor collisions - FT0C centrality - void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreatorDstar, processCollisionsCentFT0C, "Collision monitoring - FT0C centrality", false); /// @brief process function to monitor collisions - FT0M centrality - void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -504,6 +504,17 @@ struct HfCandidateCreatorDstarExpressions { Produces rowsMcMatchRecDstar; Produces rowsMcMatchGenDstar; + // Configuration + o2::framework::Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; + + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + HfEventSelectionMc hfEvSelMc; // mc event selection and monitoring using BCsInfo = soa::Join; HistogramRegistry registry{"registry"}; @@ -511,6 +522,11 @@ struct HfCandidateCreatorDstarExpressions { // inspect for which zPvPosMax cut was set for reconstructed void init(InitContext& initContext) { + std::array procCollisions = {doprocessMc, doprocessMcCentFT0C, doprocessMcCentFT0M}; + if (std::accumulate(procCollisions.begin(), procCollisions.end(), 0) > 1) { + LOGP(fatal, "At most one process function for collision study can be enabled at a time."); + } + const auto& workflows = initContext.services().get(); for (const DeviceSpec& device : workflows.devices) { if (device.name.compare("hf-candidate-creator-dstar") == 0) { @@ -522,10 +538,12 @@ struct HfCandidateCreatorDstarExpressions { } /// Perform MC Matching. - void processMc(aod::TracksWMc const& tracks, - aod::McParticles const& mcParticles, - aod::McCollisions const&, - BCsInfo const&) + template + void runCreatorDstarMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + CCs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const&) { rowsCandidateD0->bindExternalIndices(&tracks); rowsCandidateDstar->bindExternalIndices(&tracks); @@ -550,6 +568,24 @@ struct HfCandidateCreatorDstarExpressions { auto arrayDaughtersDstar = std::array{candSoftPi, candD0.prong0_as(), candD0.prong1_as()}; auto arrayDaughtersofD0 = std::array{candD0.prong0_as(), candD0.prong1_as()}; + // Check whether the particle is from background events. If so, reject it. + if (rejectBackground) { + bool fromBkg{false}; + for (const auto& daughter : arrayDaughtersDstar) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + rowsMcMatchRecDstar(flagDstar, originDstar, -1.f, 0); + continue; + } + } + // D*± → D0(bar) π± indexRecDstar = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersDstar, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &signDstar, 2); // D0(bar) → π± K∓ @@ -580,51 +616,102 @@ struct HfCandidateCreatorDstarExpressions { rowsMcMatchRecD0(flagD0, originD0, -1.f, 0); } - // Match generated particles. - for (const auto& particle : mcParticles) { - flagDstar = 0; - flagD0 = 0; - originDstar = 0; - originD0 = 0; - std::vector idxBhadMothers{}; - - auto mcCollision = particle.mcCollision(); - - const auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision); + for (const auto& mcCollision : mcCollisions) { + // Slice the MC particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + if constexpr (centEstimator == CentralityEstimator::FT0C) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::FT0M) { + const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::None) { + const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } hfEvSelMc.fillHistograms(rejectionMask); if (rejectionMask != 0) { - /// at least one event selection not satisfied --> reject the gen particle - rowsMcMatchGenDstar(flagDstar, originDstar, -1); - rowsMcMatchGenD0(flagD0, originD0, -1); + // at least one event selection not satisfied --> reject all particles from this collision + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + rowsMcMatchGenDstar(0, 0, -1); + rowsMcMatchGenD0(0, 0, -1); + } continue; } - // D*± → D0(bar) π± - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &signDstar, 2)) { - flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); - } - // D0(bar) → π± K∓ - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0)) { - flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiK)); - } + // Match generated particles. + for (const auto& particle : mcParticlesPerMcColl) { + flagDstar = 0; + flagD0 = 0; + originDstar = 0; + originD0 = 0; + std::vector idxBhadMothers{}; + // Reject particles from background events + if (particle.fromBackgroundEvent() && rejectBackground) { + rowsMcMatchGenDstar(flagDstar, originDstar, -1); + rowsMcMatchGenD0(flagD0, originD0, -1); + continue; + } - // check wether the particle is non-promt (from a B0 hadron) - if (flagDstar != 0) { - originDstar = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (flagD0 != 0) { - originD0 = RecoDecay::getCharmHadronOrigin(mcParticles, particle); - } + // D*± → D0(bar) π± + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &signDstar, 2)) { + flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); + } + // D0(bar) → π± K∓ + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0)) { + flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiK)); + } - if (originDstar == RecoDecay::OriginType::NonPrompt) { - rowsMcMatchGenDstar(flagDstar, originDstar, idxBhadMothers[0]); - } else { - rowsMcMatchGenDstar(flagDstar, originDstar, -1); + // check wether the particle is non-promt (from a B0 hadron) + if (flagDstar != 0) { + originDstar = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (flagD0 != 0) { + originD0 = RecoDecay::getCharmHadronOrigin(mcParticles, particle); + } + + if (originDstar == RecoDecay::OriginType::NonPrompt) { + rowsMcMatchGenDstar(flagDstar, originDstar, idxBhadMothers[0]); + } else { + rowsMcMatchGenDstar(flagDstar, originDstar, -1); + } + rowsMcMatchGenD0(flagD0, originD0, -1.); } - rowsMcMatchGenD0(flagD0, originD0, -1.); } } - PROCESS_SWITCH(HfCandidateCreatorDstarExpressions, processMc, "Process MC", false); + + void processMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreatorDstarMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreatorDstarExpressions, processMc, "Process MC - no centrality", false); + + void processMcCentFT0C(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Cs const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreatorDstarMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreatorDstarExpressions, processMcCentFT0C, "Process MC - FT0c centrality", false); + + void processMcCentFT0M(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + McCollisionsFT0Ms const& collInfos, + aod::McCollisions const& mcCollisions, + BCsInfo const& BCsInfo) + { + runCreatorDstarMc(tracks, mcParticles, collInfos, mcCollisions, BCsInfo); + } + PROCESS_SWITCH(HfCandidateCreatorDstarExpressions, processMcCentFT0M, "Process MC - FT0m centrality", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateCreatorLb.cxx b/PWGHF/TableProducer/candidateCreatorLb.cxx index f398865793c..a47c0bde898 100644 --- a/PWGHF/TableProducer/candidateCreatorLb.cxx +++ b/PWGHF/TableProducer/candidateCreatorLb.cxx @@ -141,7 +141,7 @@ struct HfCandidateCreatorLb { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidatesLc->Fill(SVFitting::Fail); continue; } @@ -183,7 +183,7 @@ struct HfCandidateCreatorLb { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidatesLb->Fill(SVFitting::Fail); continue; } @@ -255,7 +255,7 @@ struct HfCandidateCreatorLbExpressions { /// @brief dummy process function, to be run on data void process(aod::Tracks const&) {} - void processMc(aod::HfCand3Prong const&, + void processMc(aod::HfCand3Prong const& lcCandidates, aod::TracksWMc const& tracks, aod::McParticles const& mcParticles) { @@ -266,6 +266,7 @@ struct HfCandidateCreatorLbExpressions { int8_t debug = 0; rowCandidateLb->bindExternalIndices(&tracks); + rowCandidateLb->bindExternalIndices(&lcCandidates); // Match reconstructed candidates. for (const auto& candidate : *rowCandidateLb) { diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx new file mode 100644 index 00000000000..3a953ba0ba1 --- /dev/null +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx @@ -0,0 +1,348 @@ +// Copyright 2019-2020 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. + +/// \file candidateCreatorSigmac0plusplusCascade.cxx +/// \brief ÎŁc0,++ → Λc(→ K0sP) + π-,+ candidate builder +/// \note Here the Lc from the cascade channel is obtained using the task taskLcToK0sP.cxx +/// \author Rutuparna Rath , INFN BOLOGNA and GSI Darmstadt +/// In collaboration with Andrea Alici , INFN BOLOGNA + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/TrackSelectionDefaults.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::analysis; +using namespace o2::constants::physics; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct HfCandidateCreatorSigmac0plusplusCascade { + + /// Table with ÎŁc0,++ info + Produces rowScCandidates; + + Configurable trkMinPt{"trkMinPt", 0.15, "track min pT"}; + Configurable trkMaxEta{"trkMaxEta", 0.8, "track max Eta"}; + Configurable maxDCAxyToPVcut{"maxDCAxyToPVcut", 2.0, "Track DCAxy cut to PV Maximum"}; + Configurable maxDCAzToPVcut{"maxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable nTpcNClsFound{"nTpcNClsFound", 120, "nFindable TPC Clusters"}; + Configurable nTPCCrossedRows{"nTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable nTPCChi2{"nTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; + Configurable nITSChi2{"nITSChi2", 36.0, "nITS Chi2 per Cluster"}; + Configurable tpcnSigmaPi{"tpcnSigmaPi", 3.0, "TPC nSigma selection"}; + + /// Selection of candidates Λc+ + Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable yCandLcMax{"yCandLcMax", -1., "max. candLc. Lc rapidity"}; + Configurable selectionFlagLcToK0sP{"selectionFlagLcToK0sP", 1, "Selection Flag for Lc"}; + Configurable selectionFlagLcbarToK0sP{"selectionFlagLcbarToK0sP", 1, "Selection Flag for Lcbar"}; + Configurable cutsMassLcMax{"cutsMassLcMax", 0.08, "Lc candidate mass selection"}; + Configurable> binsPt{"binsPt", std::vector{hf_cuts_sigmac_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + + /// Selections on candidate soft π-,+ + Configurable applyGlobalTrkWoDcaCutsSoftPi{"applyGlobalTrkWoDcaCutsSoftPi", false, "Switch on the application of the global-track w/o dca cuts for soft pion BEFORE ALL OTHER CUSTOM CUTS"}; + Configurable softPiEtaMax{"softPiEtaMax", 0.9f, "Soft pion max value for pseudorapidity (abs vale)"}; + Configurable softPiChi2Max{"softPiChi2Max", 36.f, "Soft pion max value for chi2 ITS"}; + Configurable softPiItsHitMap{"softPiItsHitMap", 127, "Soft pion ITS hitmap"}; + Configurable softPiItsHitsMin{"softPiItsHitsMin", 1, "Minimum number of ITS layers crossed by the soft pion among those in \"softPiItsHitMap\""}; + Configurable softPiDcaXYMax{"softPiDcaXYMax", 0.065, "Soft pion max dcaXY (cm)"}; + Configurable softPiDcaZMax{"softPiDcaZMax", 0.065, "Soft pion max dcaZ (cm)"}; + Configurable addQA{"addQA", true, "Switch for the qa PLOTS"}; + + using TracksWithPID = soa::Join; + + /// Filter the candidate Λc+ used for the ÎŁc0,++ creation + Filter filterSelectCandidateLc = (aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcToK0sP || + aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcbarToK0sP); + + // slice by hand the assoc. track with the Λc+ collisionId + Preslice trackIndicesPerCollision = aod::track::collisionId; + + HistogramRegistry registry; + HfHelper hfHelper; + + void init(InitContext&) + { + // axes + AxisSpec axisBinsPt = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisPt = {300, 0.0f, 30.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta = {500, -2.0f, 2.0f, "#it{#eta}"}; + AxisSpec axisPhi = {100, 0.f, 6.3f, "#it{#phi}"}; + AxisSpec axisMassCand = {600, 1.98f, 2.58f, "inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2})"}; + AxisSpec axisd0 = {500, -0.5f, 0.5f, "DCAxy (cm)"}; + AxisSpec axisd0V0Daughters = {1000, -5.0f, 5.0f, "DCAxy (cm)"}; + AxisSpec axisV0CPA = {500, 0.98f, 1.0001f, "v0 cos pointing angle"}; + AxisSpec axisV0Radius = {1000, 0.f, 40.f, "V0 radius (cm)"}; + AxisSpec axisV0DCADaughters = {200, 0.f, 2.f, "DCA (cm)"}; + AxisSpec axisMassK0Short = {500, 0.4f, 0.6f, "#it{m}(K_{S}^{0}) (GeV/#it{c}^{2})"}; + AxisSpec axisMassLambda = {500, 1.0f, 1.2f, "#it{m}(#Lambda) (GeV/#it{c}^{2})"}; + AxisSpec axisMassGamma = {500, 0.0f, 0.4f, "#it{m}(#gamma) (GeV/#it{c}^{2})"}; + AxisSpec axisCPACand = {110, -1.1f, 1.1f, "candiate cos pointing angle"}; + AxisSpec axisDecLength = {200, 0.f, 2.0f, "decay length (cm)"}; + AxisSpec axisProperLifetime = {100, 0.f, 0.2f, "#it{c#tau} (cm)"}; + AxisSpec axisProperLifetimeV0 = {1000, 0.f, 80.f, "#it{c#tau} (cm)"}; + AxisSpec axisNSigma = {100, -6.f, 6.f, "n#it{#sigma}_{p}"}; + AxisSpec axisPidP = {100, 0.f, 10.0f, "#it{p} (GeV/#it{c})"}; + + auto h = registry.add("candidateStat", "", kTH1D, {{3, 0.5, 3.5}}); + h->GetXaxis()->SetBinLabel(1, "Lc candidates"); + h->GetXaxis()->SetBinLabel(2, "soft #pi (before cuts)"); + h->GetXaxis()->SetBinLabel(3, "soft #pi (after track cuts)"); + // data + if (addQA) { + registry.add("lc/hPtCand", "cascade candidates;candidateLc #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("lc/hEtaCand", "cascade candidates;candidateLc #it{#eta};entries", {HistType::kTH1F, {axisEta}}); + registry.add("lc/hEtaCandVsPtCand", "cascade candidates;candidateLc #it{#eta};p_{T}", {HistType::kTH2F, {axisEta, axisBinsPt}}); + registry.add("lc/hPhiCand", "cascade candidates;candidateLc #it{#phi};entries", {HistType::kTH1F, {axisPhi}}); + registry.add("lc/hPhiCandVsPtCand", "cascade candidates;candidateLc #it{#phi};p_{T}", {HistType::kTH2F, {axisPhi, axisBinsPt}}); + registry.add("lc/hMass", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassCand}}); + registry.add("lc/hMassVsPtCand", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassCand, axisBinsPt}}); + registry.add("lc/hPtBach", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("lc/hPtBachVsPtCand", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); + registry.add("lc/hPtV0", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("lc/hPtV0VsPtCand", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); + registry.add("lc/hd0Bach", "cascade candidates;bachelor DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); + registry.add("lc/hd0BachVsPtCand", "cascade candidates;bachelor DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); + registry.add("lc/hd0V0", "cascade candidates;V0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); + registry.add("lc/hd0V0VsPtCand", "cascade candidates;V0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); + registry.add("lc/hd0V0pos", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); + registry.add("lc/hd0V0posVsPtCand", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); + registry.add("lc/hd0V0neg", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); + registry.add("lc/hd0V0negVsPtCand", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); + registry.add("lc/hPtV0pos", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("lc/hPtV0posVsPtCand", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); + registry.add("lc/hPtV0neg", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("lc/hPtV0negVsPtCand", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); + registry.add("lc/hV0CPA", "cascade candidates;v0 cosine of pointing angle;entries", {HistType::kTH1F, {axisV0CPA}}); + registry.add("lc/hV0CPAVsPtCand", "cascade candidates;v0 cosine of pointing angle;p_{T}", {HistType::kTH2F, {axisV0CPA, axisBinsPt}}); + registry.add("lc/hV0Radius", "cascade candidates;v0 radius (cm);entries", {HistType::kTH1F, {axisV0Radius}}); + registry.add("lc/hV0RadiusVsPtCand", "cascade candidates;v0 radius (cm);p_{T}", {HistType::kTH2F, {axisV0Radius, axisBinsPt}}); + registry.add("lc/hV0DCADaughters", "cascade candidates;v0 dca daughters (cm);entries", {HistType::kTH1F, {axisV0DCADaughters}}); + registry.add("lc/hV0DCADaughtersVsPtCand", "cascade candidates;v0 dca daughters (cm);p_{T}", {HistType::kTH2F, {axisV0DCADaughters, axisBinsPt}}); + registry.add("lc/hV0MK0Short", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassK0Short}}); + registry.add("lc/hV0MK0ShortVsPtCand", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassK0Short, axisBinsPt}}); + registry.add("lc/hV0MLambda", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); + registry.add("lc/hV0MLambdaVsPtCand", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); + registry.add("lc/hV0MAntiLambda", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); + registry.add("lc/hV0MAntiLambdaVsPtCand", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); + registry.add("lc/hV0MGamma", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassGamma}}); + registry.add("lc/hV0MGammaVsPtCand", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassGamma, axisBinsPt}}); + registry.add("lc/hCtV0K0Short", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); + registry.add("lc/hCtV0K0ShortVsPtCand", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); + registry.add("lc/hCtV0Lambda", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); + registry.add("lc/hCtV0LambdaVsPtCand", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); + registry.add("lc/hCPACand", "cascade candidates;cosine pointing angle;entries", {HistType::kTH1F, {axisCPACand}}); + registry.add("lc/hCPACandVsPtCand", "cascade candidates;cosine pointing angle;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); + registry.add("lc/hCPAxyCand", "cascade candidates;cosine pointing angle xy;entries", {HistType::kTH1F, {axisCPACand}}); + registry.add("lc/hCPAxyCandVsPtCand", "cascade candidates;cosine pointing angle xy;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); + registry.add("lc/hDecLengthCand", "cascade candidates;decay length (cm);entries", {HistType::kTH1F, {axisDecLength}}); + registry.add("lc/hDecLengthCandVsPtCand", "cascade candidates;decay length (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); + registry.add("lc/hDecLengthXYCand", "cascade candidates;decay length xy (cm);entries", {HistType::kTH1F, {axisDecLength}}); + registry.add("lc/hDecLengthXYCandVsPtCand", "cascade candidates;decay length xy (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); + registry.add("lc/hCtCand", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetime}}); + registry.add("lc/hCtCandVsPtCand", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetime, axisBinsPt}}); + + // soft pion + registry.add("pion/data/hPtSoftPi", "#pi candidates; #it{p}_{T}(#pi) (GeV/#it{c}); counts;", {HistType::kTH1F, {axisPt}}); + registry.add("pion/data/hEtaSoftPi", "#pi candidates; #eta ; counts;", {HistType::kTH1F, {axisEta}}); + registry.add("pion/data/hPhiSoftPi", "#pi candidates; #Phi ; counts;", {HistType::kTH1F, {axisPhi}}); + } + } + + template + bool isTrackSelected(const TrackType& track) + { + if (track.pt() < trkMinPt) + return false; + if (std::abs(track.eta()) > trkMaxEta) + return false; + if (std::abs(track.dcaXY()) > maxDCAxyToPVcut) + return false; + if (std::abs(track.dcaZ()) > maxDCAzToPVcut) + return false; + if (track.tpcNClsFound() < nTpcNClsFound) + return false; + if (track.tpcNClsCrossedRows() < nTPCCrossedRows) + return false; + if (track.tpcChi2NCl() > nTPCChi2) + return false; + if (track.itsChi2NCl() > nITSChi2) + return false; + if (track.tpcNSigmaPi() > tpcnSigmaPi) + return false; + + return true; + } + + /// @param tracks are the tracks (with dcaXY, dcaZ information) → soft-pion candidate tracks + /// @param candidatesLc are 2-prong candidates satisfying the analysis selections for Λc+ → Ks0P (and charge conj.) + void processData(soa::Filtered> const& candidates, + aod::Collisions const&, + TracksWithPID const& tracks, + aod::V0s const&) + { + for (const auto& candidateLc : candidates) { + /// slice the tracks based on the collisionId + const auto& tracksInThisCollision = tracks.sliceBy(trackIndicesPerCollision, candidateLc.collision().globalIndex()); + const auto& bachProton = candidateLc.prong0_as(); + int chargeLc = bachProton.sign(); // Lc charge depends on its bach charge (here it is proton) + + auto ptCand = candidateLc.pt(); + auto eta = candidateLc.eta(); + auto phi = candidateLc.phi(); + auto invMassLcToK0sP = hfHelper.invMassLcToK0sP(candidateLc); + auto ptProng0 = candidateLc.ptProng0(); + auto ptProng1 = candidateLc.ptProng1(); + auto impactParameter0 = candidateLc.impactParameter0(); + auto impactParameter1 = candidateLc.impactParameter1(); + auto dcaPosToPV = candidateLc.dcapostopv(); + auto dcaNegToPV = candidateLc.dcanegtopv(); + auto ptV0Pos = candidateLc.ptV0Pos(); + auto ptV0Neg = candidateLc.ptV0Neg(); + auto v0CosPA = candidateLc.v0cosPA(); + auto v0Radius = candidateLc.v0radius(); + auto dcaV0Daughters = candidateLc.dcaV0daughters(); + auto mK0Short = candidateLc.mK0Short(); + auto mLambda = candidateLc.mLambda(); + auto mAntiLambda = candidateLc.mAntiLambda(); + auto mGamma = candidateLc.mGamma(); + auto ctV0K0Short = hfHelper.ctV0K0s(candidateLc); + auto ctV0Lambda = hfHelper.ctV0Lambda(candidateLc); + auto cpa = candidateLc.cpa(); + auto cpaXY = candidateLc.cpaXY(); + auto decayLength = candidateLc.decayLength(); + auto decayLengthXY = candidateLc.decayLengthXY(); + auto ctLc = hfHelper.ctLc(candidateLc); + if (addQA) { + registry.fill(HIST("lc/hPtCand"), ptCand); + registry.fill(HIST("lc/hEtaCand"), eta); + registry.fill(HIST("lc/hEtaCandVsPtCand"), eta, ptCand); + registry.fill(HIST("lc/hPhiCand"), phi); + registry.fill(HIST("lc/hPhiCandVsPtCand"), phi, ptCand); + registry.fill(HIST("lc/hMass"), invMassLcToK0sP); + registry.fill(HIST("lc/hMassVsPtCand"), invMassLcToK0sP, ptCand); + registry.fill(HIST("lc/hPtBach"), ptProng0); + registry.fill(HIST("lc/hPtBachVsPtCand"), ptProng0, ptCand); + registry.fill(HIST("lc/hPtV0"), ptProng1); + registry.fill(HIST("lc/hPtV0VsPtCand"), ptProng1, ptCand); + registry.fill(HIST("lc/hd0Bach"), impactParameter0); + registry.fill(HIST("lc/hd0BachVsPtCand"), impactParameter0, ptCand); + registry.fill(HIST("lc/hd0V0"), impactParameter1); + registry.fill(HIST("lc/hd0V0VsPtCand"), impactParameter1, ptCand); + registry.fill(HIST("lc/hd0V0pos"), dcaPosToPV); + registry.fill(HIST("lc/hd0V0posVsPtCand"), dcaPosToPV, ptCand); + registry.fill(HIST("lc/hd0V0neg"), dcaNegToPV); + registry.fill(HIST("lc/hd0V0negVsPtCand"), dcaNegToPV, ptCand); + registry.fill(HIST("lc/hPtV0pos"), ptV0Pos); + registry.fill(HIST("lc/hPtV0posVsPtCand"), ptV0Pos, ptCand); + registry.fill(HIST("lc/hPtV0neg"), ptV0Neg); + registry.fill(HIST("lc/hPtV0negVsPtCand"), ptV0Neg, ptCand); + registry.fill(HIST("lc/hV0CPA"), v0CosPA); + registry.fill(HIST("lc/hV0CPAVsPtCand"), v0CosPA, ptCand); + registry.fill(HIST("lc/hV0Radius"), v0Radius); + registry.fill(HIST("lc/hV0RadiusVsPtCand"), v0Radius, ptCand); + registry.fill(HIST("lc/hV0DCADaughters"), dcaV0Daughters); + registry.fill(HIST("lc/hV0DCADaughtersVsPtCand"), dcaV0Daughters, ptCand); + registry.fill(HIST("lc/hV0MK0Short"), mK0Short); + registry.fill(HIST("lc/hV0MK0ShortVsPtCand"), mK0Short, ptCand); + registry.fill(HIST("lc/hV0MLambda"), mLambda); + registry.fill(HIST("lc/hV0MLambdaVsPtCand"), mLambda, ptCand); + registry.fill(HIST("lc/hV0MAntiLambda"), mAntiLambda); + registry.fill(HIST("lc/hV0MAntiLambdaVsPtCand"), mAntiLambda, ptCand); + registry.fill(HIST("lc/hV0MGamma"), mGamma); + registry.fill(HIST("lc/hV0MGammaVsPtCand"), mGamma, ptCand); + registry.fill(HIST("lc/hCtV0K0Short"), ctV0K0Short); + registry.fill(HIST("lc/hCtV0K0ShortVsPtCand"), ctV0K0Short, ptCand); + registry.fill(HIST("lc/hCtV0Lambda"), ctV0Lambda); + registry.fill(HIST("lc/hCtV0LambdaVsPtCand"), ctV0Lambda, ptCand); + registry.fill(HIST("lc/hCPACand"), cpa); + registry.fill(HIST("lc/hCPACandVsPtCand"), cpa, ptCand); + registry.fill(HIST("lc/hCPAxyCand"), cpaXY); + registry.fill(HIST("lc/hCPAxyCandVsPtCand"), cpaXY, ptCand); + registry.fill(HIST("lc/hDecLengthCand"), decayLength); + registry.fill(HIST("lc/hDecLengthCandVsPtCand"), decayLength, ptCand); + registry.fill(HIST("lc/hDecLengthXYCand"), decayLengthXY); + registry.fill(HIST("lc/hDecLengthXYCandVsPtCand"), decayLengthXY, ptCand); + registry.fill(HIST("lc/hCtCand"), ctLc); + registry.fill(HIST("lc/hCtCandVsPtCand"), ctLc, ptCand); + } + if (std::abs(invMassLcToK0sP - MassLambdaCPlus) > cutsMassLcMax) { + continue; + } + registry.fill(HIST("candidateStat"), 1); + auto K0short = candidateLc.v0_as(); // get the soft pions for the given collId + auto pos = K0short.template posTrack_as(); + auto neg = K0short.template negTrack_as(); + for (const auto& trackSoftPi : tracksInThisCollision) { + int chargeSoftPi = trackSoftPi.sign(); + if (chargeSoftPi == pos.sign() && trackSoftPi.globalIndex() == pos.globalIndex()) { + continue; + } + if (chargeSoftPi == neg.sign() && trackSoftPi.globalIndex() == neg.globalIndex()) { + continue; + } + if (chargeSoftPi == bachProton.sign() && trackSoftPi.globalIndex() == bachProton.globalIndex()) { + continue; + } + registry.fill(HIST("candidateStat"), 2); + if (!isTrackSelected(trackSoftPi)) { + continue; + } + registry.fill(HIST("candidateStat"), 3); + + /// fill histograms for softpion + if (addQA) { + registry.fill(HIST("pion/data/hPtSoftPi"), trackSoftPi.pt()); + registry.fill(HIST("pion/data/hEtaSoftPi"), trackSoftPi.eta()); + registry.fill(HIST("pion/data/hPhiSoftPi"), trackSoftPi.phi()); // π ← ÎŁc0 + } + /// determine the ÎŁc candidate charge + int8_t chargeSigmac = chargeLc + chargeSoftPi; + + /// fill the ÎŁc0,++ candidate table + rowScCandidates(/* general columns */ + candidateLc.collisionId(), + /* 2-prong specific columns */ + candidateLc.px(), candidateLc.py(), candidateLc.pz(), // Lc info + trackSoftPi.px(), trackSoftPi.py(), trackSoftPi.pz(), // soft pion info + candidateLc.collision().globalIndex(), trackSoftPi.globalIndex(), + chargeLc, + chargeSoftPi, + // candLc.hfflag(), + /* ÎŁc0,++ specific columns */ + chargeSigmac); + } + } // SC candidate + } + PROCESS_SWITCH(HfCandidateCreatorSigmac0plusplusCascade, processData, "Process Data", true); +}; +struct HfCandidateCreatorSigmac0plusplusCascadeExpressions { + Spawns candidatesSigmac; + void processMc(aod::Tracks const&) {} + PROCESS_SWITCH(HfCandidateCreatorSigmac0plusplusCascadeExpressions, processMc, "Process MC tracks", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index 6693399dae8..cff26b7e340 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -12,6 +12,18 @@ /// \file candidateCreatorXic0Omegac0.cxx /// \brief Reconstruction of Omegac0 and Xic0 decays candidates /// \author Federica Zanone , Heidelberg University +/// \author Yunfan Liu , China University of Geosciences + +#ifndef HomogeneousField +#define HomogeneousField +#endif + +/// includes KFParticle +#include "KFParticle.h" +#include "KFParticleBase.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFVertex.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" @@ -32,6 +44,7 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" +#include "Tools/KFparticle/KFUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -60,6 +73,7 @@ struct HfCandidateCreatorXic0Omegac0 { Produces rowCandToXiPi; Produces rowCandToOmegaPi; Produces rowCandToOmegaK; + Produces kfCandidateData; Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; @@ -80,6 +94,16 @@ struct HfCandidateCreatorXic0Omegac0 { Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + // KFParticle process setting + // V0 cuts + Configurable lambdaMassWindow{"lambdaMassWindow", 0.0075, "Distance from Lambda mass"}; + // cascade cuts + Configurable massToleranceCascade{"massToleranceCascade", 0.01, "Invariant mass tolerance for cascade"}; + // for KF particle operation + Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct Method"}; + Configurable kfUseV0MassConstraint{"kfUseV0MassConstraint", false, "KF: use Lambda mass constraint"}; + Configurable kfUseCascadeMassConstraint{"kfUseCascadeMassConstraint", false, "KF: use Cascade mass constraint"}; + HfEventSelection hfEvSel; // event selection and monitoring o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter to build the omegac/xic vertex Service ccdb; @@ -91,14 +115,64 @@ struct HfCandidateCreatorXic0Omegac0 { using MyCascTable = soa::Join; // to use strangeness tracking, use aod::TraCascDatas instead of aod::CascDatas using CascadesLinked = soa::Join; using MyV0Table = soa::Join; + using MyLFTracksWCov = soa::Join; + + using MyKfTracks = soa::Join; + using MyKfCascTable = soa::Join; + using KFCascadesLinked = soa::Join; std::shared_ptr hInvMassCharmBaryonToXiPi, hInvMassCharmBaryonToOmegaPi, hInvMassCharmBaryonToOmegaK, hFitterStatusToXiPi, hFitterStatusToOmegaPi, hFitterStatusToOmegaK, hCandidateCounterToXiPi, hCandidateCounterToOmegaPi, hCandidateCounterToOmegaK, hCascadesCounterToXiPi, hCascadesCounterToOmegaPi, hCascadesCounterToOmegaK; HistogramRegistry registry{"registry"}; - + // Helper struct to pass information + struct { + float chi2GeoV0; + float ldlV0; + float chi2TopoV0ToPv; + float chi2GeoCasc; + float ldlCasc; + float chi2TopoCascToPv; + float decayLenXYLambda; + float decayLenXYCasc; + float cosPaV0ToCasc; // PA + float cosPaXYV0ToCasc; + float cosPaV0ToPv; // PA + float cosPaXYV0ToPv; + float cosPaCascToOmegac; // PA + float cosPaXYCascToOmegac; + float cosPaCascToPv; // PA + float cosPaXYCascToPv; // PA + float massV0; + float massCasc; + float ptPiFromOmegac; + float ptOmegac; + float rapOmegac; + float massOmegac; + float cosThetaStarPiFromOmegac; + float chi2TopoPiFromOmegacToPv; + float kfDcaXYPiFromOmegac; + float chi2TopoV0ToCasc; + float chi2TopoCascToOmegac; + float decayLenXYOmegac; + float chi2GeoOmegac; + float kfDcaV0Dau; + float kfDcaCascDau; + float kfDcaOmegacDau; + float kfDcaXYCascToPv; + float chi2TopoOmegacToPv; + float cosPaOmegacToPv; // PA + float cosPaXYOmegacToPv; + float ldlOmegac; + float ctV0; + float ctCasc; + float ctOmegac; + float chi2MassV0; + float chi2MassCasc; + float etaOmegac; + } kfOmegac0Candidate; void init(InitContext const&) { - std::array allProcesses = {doprocessNoCentToXiPi, doprocessCentFT0CToXiPi, doprocessCentFT0MToXiPi, doprocessNoCentToOmegaPi, doprocessCentFT0CToOmegaPi, doprocessCentFT0MToOmegaPi, doprocessNoCentToOmegaK, doprocessCentFT0CToOmegaK, doprocessCentFT0MToOmegaK}; + std::array allProcesses = {doprocessNoCentToXiPi, doprocessCentFT0CToXiPi, doprocessCentFT0MToXiPi, doprocessNoCentToOmegaPi, doprocessOmegacToOmegaPiWithKFParticle, doprocessCentFT0CToOmegaPi, doprocessCentFT0MToOmegaPi, doprocessNoCentToOmegaK, doprocessCentFT0CToOmegaK, doprocessCentFT0MToOmegaK}; if (std::accumulate(allProcesses.begin(), allProcesses.end(), 0) == 0) { LOGP(fatal, "No process function enabled, please select one for at least one channel."); } @@ -107,7 +181,7 @@ struct HfCandidateCreatorXic0Omegac0 { if (std::accumulate(processesToXiPi.begin(), processesToXiPi.end(), 0) > 1) { LOGP(fatal, "One and only one ToXiPi process function must be enabled at a time."); } - std::array processesToOmegaPi = {doprocessNoCentToOmegaPi, doprocessCentFT0CToOmegaPi, doprocessCentFT0MToOmegaPi}; + std::array processesToOmegaPi = {doprocessNoCentToOmegaPi, doprocessCentFT0CToOmegaPi, doprocessCentFT0MToOmegaPi, doprocessOmegacToOmegaPiWithKFParticle}; if (std::accumulate(processesToOmegaPi.begin(), processesToOmegaPi.end(), 0) > 1) { LOGP(fatal, "One and only one process ToOmegaPi function must be enabled at a time."); } @@ -122,7 +196,7 @@ struct HfCandidateCreatorXic0Omegac0 { LOGP(fatal, "At most one process function for collision monitoring can be enabled at a time."); } if (nProcessesCollisions == 1) { - if ((doprocessNoCentToXiPi && !doprocessCollisions) || (doprocessNoCentToOmegaPi && !doprocessCollisions) || (doprocessNoCentToOmegaK && !doprocessCollisions)) { + if ((doprocessNoCentToXiPi && !doprocessCollisions) || (doprocessNoCentToOmegaPi && !doprocessCollisions) || (doprocessNoCentToOmegaK && !doprocessCollisions) || (doprocessOmegacToOmegaPiWithKFParticle && !doprocessCollisions)) { LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisions\"?"); } if ((doprocessCentFT0CToXiPi && !doprocessCollisionsCentFT0C) || (doprocessCentFT0CToOmegaPi && !doprocessCollisionsCentFT0C) || (doprocessCentFT0CToOmegaK && !doprocessCollisionsCentFT0C)) { @@ -146,6 +220,19 @@ struct HfCandidateCreatorXic0Omegac0 { hCascadesCounterToOmegaPi = registry.add("hCascadesCounterToOmegaPi", "Cascades counter wrt derived data - #Omega #pi decay;status;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); // 0 --> cascades in derived data table (and stored in AOD table), 1 --> cascades in derived data table and also accessible in cascData table hCascadesCounterToOmegaK = registry.add("hCascadesCounterToOmegaK", "Cascades counter wrt derived data - #Omega K decay;status;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); // 0 --> cascades in derived data table (and stored in AOD table), 1 --> cascades in derived data table and also accessible in cascData table + // KFparticle variables hist + registry.add("hKFParticleV0Chi2", "hKFParticleV0Chi2", kTH1F, {{1000, -0.10f, 100.0f}}); + registry.add("hKFParticleCascChi2", "hKFParticleCascChi2 from \"track to kf\" daughter", kTH1F, {{1000, -0.1f, 100.0f}}); + registry.add("hKFParticleOmegaC0Chi2", "hKFParticleOmegaC0Chi2", kTH1F, {{1000, -0.1f, 10.0f}}); + registry.add("hKFParticleV0TopoChi2", "hKFParticleV0TopoChi2", kTH1F, {{1000, -0.10f, 100.0f}}); + registry.add("hKFParticleCascTopoChi2", "hKFParticleCascTopoChi2", kTH1F, {{1000, -0.1f, 100.0f}}); + registry.add("hKFParticleCascBachTopoChi2", "hKFParticleCascBachTopoChi2", kTH1F, {{1000, -0.1f, 100.0f}}); + registry.add("hKfLambda_ldl", "hKfLambda_ldl", kTH1F, {{1000, 0.0f, 1000.0f}}); + registry.add("hKfOmega_ldl", "hKfOmega_ldl", kTH1F, {{1000, 0.0f, 1000.0f}}); + registry.add("hKfOmegaC0_ldl", "hKfOmegaC0_ldl", kTH1F, {{1000, 0.0f, 1000.0f}}); + registry.add("hDcaXYCascadeToPVKf", "hDcaXYCascadeToPVKf", kTH1F, {{1000, 0.0f, 2.0f}}); + registry.add("hInvMassOmegaMinus", "hInvMassOmegaMinus", kTH1F, {{1000, 1.6f, 2.0f}}); + hfEvSel.addHistograms(registry); // collision monitoring df.setPropagateToPCA(propagateToPCA); @@ -168,8 +255,9 @@ struct HfCandidateCreatorXic0Omegac0 { template void runXic0Omegac0Creator(Coll const&, - aod::BCsWithTimestamps const& bcWithTimeStamps, - TracksWCovDca const&, + aod::BCsWithTimestamps const& /*bcWithTimeStamps*/, + MyLFTracksWCov const& lfTracks, + TracksWCovDca const& tracks, MyCascTable const&, CascadesLinked const&, aod::HfCascLf2Prongs const& candidates, Hist& hInvMassCharmBaryon, @@ -204,7 +292,7 @@ struct HfCandidateCreatorXic0Omegac0 { auto collision = cand.collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -221,7 +309,8 @@ struct HfCandidateCreatorXic0Omegac0 { } df.setBz(magneticField); - auto trackCharmBachelor = cand.prong0_as(); + auto trackCharmBachelorId = cand.prong0Id(); + auto trackCharmBachelor = tracks.rawIteratorAt(trackCharmBachelorId); auto cascAodElement = cand.cascade_as(); hCascadesCounter->Fill(0); @@ -231,14 +320,17 @@ struct HfCandidateCreatorXic0Omegac0 { } auto casc = cascAodElement.cascData_as(); hCascadesCounter->Fill(1); - auto trackCascDauCharged = casc.bachelor_as(); // pion <- xi track - auto trackV0Dau0 = casc.posTrack_as(); // V0 positive daughter track - auto trackV0Dau1 = casc.negTrack_as(); // V0 negative daughter track + auto trackCascDauChargedId = casc.bachelorId(); // pion <- xi track + auto trackV0Dau0Id = casc.posTrackId(); // V0 positive daughter track + auto trackV0Dau1Id = casc.negTrackId(); // V0 negative daughter track + auto trackCascDauCharged = lfTracks.rawIteratorAt(trackCascDauChargedId); // pion <- xi track + auto trackV0Dau0 = lfTracks.rawIteratorAt(trackV0Dau0Id); // V0 positive daughter track + auto trackV0Dau1 = lfTracks.rawIteratorAt(trackV0Dau1Id); // V0 negative daughter track //-------------------------- V0 info--------------------------- // pseudorapidity - float pseudorapV0Dau0 = trackV0Dau0.eta(); - float pseudorapV0Dau1 = trackV0Dau1.eta(); + float pseudorapV0Dau0 = casc.positiveeta(); + float pseudorapV0Dau1 = casc.negativeeta(); // info from LF table std::array pVecV0 = {casc.pxlambda(), casc.pylambda(), casc.pzlambda()}; @@ -248,7 +340,7 @@ struct HfCandidateCreatorXic0Omegac0 { //-------------------reconstruct cascade track------------------ // pseudorapidity - float pseudorapCascBachelor = trackCascDauCharged.eta(); + float pseudorapCascBachelor = casc.bacheloreta(); // info from LF table std::array vertexCasc = {casc.x(), casc.y(), casc.z()}; @@ -312,20 +404,27 @@ struct HfCandidateCreatorXic0Omegac0 { // pseudorapidity float pseudorapCharmBachelor = trackCharmBachelor.eta(); - // DCAxy (computed with propagateToDCABxByBz method) - float dcaxyV0Dau0 = trackV0Dau0.dcaXY(); - float dcaxyV0Dau1 = trackV0Dau1.dcaXY(); - float dcaxyCascBachelor = trackCascDauCharged.dcaXY(); - - // DCAz (computed with propagateToDCABxByBz method) - float dcazV0Dau0 = trackV0Dau0.dcaZ(); - float dcazV0Dau1 = trackV0Dau1.dcaZ(); - float dcazCascBachelor = trackCascDauCharged.dcaZ(); - // primary vertex of the collision auto primaryVertex = getPrimaryVertex(collision); // get the associated covariance matrix with auto covMatrixPV = primaryVertex.getCov(); std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + // DCAxy and DCAz (computed with propagateToDCABxByBz method) + o2::dataformats::DCA impactParameterV0Dau0; + o2::dataformats::DCA impactParameterV0Dau1; + o2::dataformats::DCA impactParameterCascDauCharged; + auto trackParVarV0Dau0 = getTrackParCov(trackV0Dau0); + auto trackParVarV0Dau1 = getTrackParCov(trackV0Dau1); + auto trackParVarCascDauCharged = getTrackParCov(trackCascDauCharged); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParVarV0Dau0, 2.f, matCorr, &impactParameterV0Dau0); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParVarV0Dau1, 2.f, matCorr, &impactParameterV0Dau1); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParVarCascDauCharged, 2.f, matCorr, &impactParameterCascDauCharged); + float dcaxyV0Dau0 = impactParameterV0Dau0.getY(); + float dcaxyV0Dau1 = impactParameterV0Dau1.getY(); + float dcaxyCascBachelor = impactParameterCascDauCharged.getY(); + float dcazV0Dau0 = impactParameterV0Dau0.getZ(); + float dcazV0Dau1 = impactParameterV0Dau1.getZ(); + float dcazCascBachelor = impactParameterCascDauCharged.getZ(); + // impact parameters o2::dataformats::DCA impactParameterCasc; o2::dataformats::DCA impactParameterCharmBachelor; @@ -404,7 +503,7 @@ struct HfCandidateCreatorXic0Omegac0 { trackCascDauCharged.sign(), covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], - pVecCasc[0], pVecCasc[1], pVecCasc[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], pVecCharmBachelorAsD[0], pVecCharmBachelorAsD[1], pVecCharmBachelorAsD[2], pVecV0[0], pVecV0[1], pVecV0[2], pVecCascBachelor[0], pVecCascBachelor[1], pVecCascBachelor[2], @@ -434,7 +533,7 @@ struct HfCandidateCreatorXic0Omegac0 { trackCascDauCharged.sign(), covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], - pVecCasc[0], pVecCasc[1], pVecCasc[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], pVecCharmBachelorAsD[0], pVecCharmBachelorAsD[1], pVecCharmBachelorAsD[2], pVecV0[0], pVecV0[1], pVecV0[2], pVecCascBachelor[0], pVecCascBachelor[1], pVecCascBachelor[2], @@ -464,7 +563,7 @@ struct HfCandidateCreatorXic0Omegac0 { trackCascDauCharged.sign(), covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], - pVecCasc[0], pVecCasc[1], pVecCasc[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], pVecCharmBachelorAsD[0], pVecCharmBachelorAsD[1], pVecCharmBachelorAsD[2], pVecV0[0], pVecV0[1], pVecV0[2], pVecCascBachelor[0], pVecCascBachelor[1], pVecCascBachelor[2], @@ -489,37 +588,463 @@ struct HfCandidateCreatorXic0Omegac0 { } // loop over LF Cascade-bachelor candidates } // end of run function + template + void runKfOmegac0CreatorWithKFParticle(Coll const&, + aod::BCsWithTimestamps const& /*bcWithTimeStamps*/, + MyKfTracks const&, + MyKfCascTable const&, KFCascadesLinked const&, + aod::HfCascLf2Prongs const& candidates, + Hist& hInvMassCharmBaryon, + Hist& hFitterStatus, + Hist& hCandidateCounter, + Hist& hCascadesCounter) + { + for (const auto& cand : candidates) { + hCandidateCounter->Fill(1); + + auto collision = cand.collision_as(); + + // set the magnetic field from CCDB + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << magneticField; + runNumber = bc.runNumber(); + } + df.setBz(magneticField); + KFParticle::SetField(magneticField); + // bachelor from Omegac0 + auto trackCharmBachelor = cand.prong0_as(); + + auto cascAodElement = cand.cascade_as(); + hCascadesCounter->Fill(0); + int v0index = cascAodElement.v0Id(); + if (!cascAodElement.has_kfCascData()) { + continue; + } + auto casc = cascAodElement.kfCascData_as(); + hCascadesCounter->Fill(1); + auto trackCascDauCharged = casc.bachelor_as(); // pion <- xi track + auto trackV0Dau0 = casc.posTrack_as(); // V0 positive daughter track + auto trackV0Dau1 = casc.negTrack_as(); // V0 negative daughter track + + auto bachCharge = trackCascDauCharged.signed1Pt() > 0 ? +1 : -1; + + //// pion & p TrackParCov + auto trackParCovV0Dau0 = getTrackParCov(trackV0Dau0); + auto trackParCovV0Dau1 = getTrackParCov(trackV0Dau1); + // kaon <- casc TrackParCov + auto omegaDauChargedTrackParCov = getTrackParCov(trackCascDauCharged); + // convert tracks into KFParticle object + KFPTrack kfpTrack0 = createKFPTrackFromTrack(trackV0Dau0); + KFPTrack kfpTrack1 = createKFPTrackFromTrack(trackV0Dau1); + KFPTrack kfpTrackBach = createKFPTrackFromTrack(trackCascDauCharged); + + KFParticle kfpPosPr(kfpTrack0, kProton); + KFParticle kfpNegPi(kfpTrack1, kPiMinus); + KFParticle kfpNegKa(kfpTrackBach, kKMinus); + KFParticle kfpPosPi(kfpTrack0, kPiPlus); + KFParticle kfpNegPr(kfpTrack1, kProton); + KFParticle kfpPosKa(kfpTrackBach, kKPlus); + + KFParticle kfpBachKaon; + KFParticle kfpPos; + KFParticle kfpNeg; + if (bachCharge < 0) { + kfpPos = kfpPosPr; + kfpNeg = kfpNegPi; + kfpBachKaon = kfpNegKa; + } else { + kfpPos = kfpPosPi; + kfpNeg = kfpNegPr; + kfpBachKaon = kfpPosKa; + } + + //__________________________________________ + //*>~<* step 1 : construct V0 with KF + const KFParticle* V0Daughters[2] = {&kfpPos, &kfpNeg}; + // construct V0 + KFParticle KFV0; + KFV0.SetConstructMethod(kfConstructMethod); + try { + KFV0.Construct(V0Daughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct cascade V0 from daughter tracks: " << e.what(); + continue; + } + + // mass window cut on lambda before mass constraint + float massLam, sigLam; + KFV0.GetMass(massLam, sigLam); + if (TMath::Abs(massLam - MassLambda0) > lambdaMassWindow) + continue; + registry.fill(HIST("hKFParticleV0Chi2"), KFV0.GetChi2()); + if (kfUseV0MassConstraint) { + KFV0.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); + } + + KFParticle KFV0_m = KFV0; + KFV0_m.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); + + //-------------------------- V0 info--------------------------- + // pseudorapidity + float pseudorapV0Dau0 = trackV0Dau0.eta(); + float pseudorapV0Dau1 = trackV0Dau1.eta(); + + // info from from KFParticle + std::array pVecV0 = {KFV0.GetPx(), KFV0.GetPy(), KFV0.GetPz()}; // pVec stands for vector containing the 3-momentum components + std::array vertexV0 = {KFV0.GetX(), KFV0.GetY(), KFV0.GetZ()}; + std::array pVecV0Dau0 = {kfpPos.GetPx(), kfpPos.GetPy(), kfpPos.GetPz()}; + std::array pVecV0Dau1 = {kfpNeg.GetPx(), kfpNeg.GetPy(), kfpNeg.GetPz()}; + + //__________________________________________ + //*>~<* step 2 : reconstruc cascade(Omega) with KF + KFParticle kfpV0 = KFV0; + const KFParticle* OmegaDaugthers[2] = {&kfpBachKaon, &kfpV0}; + // construct cascade + KFParticle KFOmega; + KFOmega.SetConstructMethod(kfConstructMethod); + try { + KFOmega.Construct(OmegaDaugthers, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct omega from V0 and bachelor track: " << e.what(); + continue; + } + float massCasc, sigCasc; + KFOmega.GetMass(massCasc, sigCasc); + if (kfUseCascadeMassConstraint) { + // set mass constraint if requested + KFOmega.SetNonlinearMassConstraint(o2::constants::physics::MassOmegaMinus); + } + KFParticle KFOmega_m = KFOmega; + KFOmega_m.SetNonlinearMassConstraint(o2::constants::physics::MassOmegaMinus); + registry.fill(HIST("hInvMassOmegaMinus"), massCasc); + registry.fill(HIST("hKFParticleCascChi2"), KFOmega.GetChi2()); + + //-------------------reconstruct cascade track------------------ + // pseudorapidity + float pseudorapCascBachelor = trackCascDauCharged.eta(); + + // info from KFParticle + std::array vertexCasc = {KFOmega.GetX(), KFOmega.GetY(), KFOmega.GetZ()}; + std::array pVecCasc = {KFOmega.GetPx(), KFOmega.GetPy(), KFOmega.GetPz()}; + std::array covCasc = {0.}; + for (int i = 0; i < 21; i++) { + covCasc[i] = KFOmega.GetCovariance(i); + } + o2::track::TrackParCov trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, bachCharge, true, o2::track::PID::OmegaMinus); + trackCasc.setAbsCharge(1); + trackCasc.setPID(o2::track::PID::OmegaMinus); + std::array pVecCascBachelor = {kfpBachKaon.GetPx(), kfpBachKaon.GetPy(), kfpBachKaon.GetPz()}; + + //------------reconstruct charm baryon decay vtx--------------- + auto trackParVarCharmBachelor = getTrackParCov(trackCharmBachelor); // charm bachelor pion track to be processed with DCAFitter + + //__________________________________________ + //*>~<* step 3 : reconstruc Omegac0 with KF + // Create KF charm bach Pion from track + KFPTrack kfpTrackBachPion = createKFPTrackFromTrack(trackCharmBachelor); + + KFParticle kfpBachPion(kfpTrackBachPion, kPiPlus); + KFParticle kfpCasc = KFOmega; + const KFParticle* OmegaC0Daugthers[2] = {&kfpBachPion, &kfpCasc}; + + // construct OmegaC0 + KFParticle KFOmegaC0; + KFOmegaC0.SetConstructMethod(kfConstructMethod); + try { + KFOmegaC0.Construct(OmegaC0Daugthers, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct OmegaC0 from V0 and bachelor track: " << e.what(); + continue; + } + float massOmegaC0, sigOmegaC0; + KFOmegaC0.GetMass(massOmegaC0, sigOmegaC0); + registry.fill(HIST("hKFParticleOmegaC0Chi2"), KFOmegaC0.GetChi2()); + hFitterStatus->Fill(0); + hCandidateCounter->Fill(2); + + // PV + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + KFParticle KFPV(kfpVertex); + auto primaryVertex = getPrimaryVertex(collision); + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + + std::array vertexCharmBaryonFromFitter = {0.0, 0.0, 0.0}; // This variable get from DCAfitter in default process, in KF process it is set as 0. + std::array pVecCascAsD; + std::array pVecCharmBachelorAsD; + pVecCharmBachelorAsD[0] = kfpBachPion.GetPx(); + pVecCharmBachelorAsD[1] = kfpBachPion.GetPy(); + pVecCharmBachelorAsD[2] = kfpBachPion.GetPz(); + pVecCascAsD[0] = kfpCasc.GetPx(); + pVecCascAsD[1] = kfpCasc.GetPy(); + pVecCascAsD[2] = kfpCasc.GetPz(); + + std::array pVecCharmBaryon = {pVecCascAsD[0] + pVecCharmBachelorAsD[0], pVecCascAsD[1] + pVecCharmBachelorAsD[1], pVecCascAsD[2] + pVecCharmBachelorAsD[2]}; + std::array coordVtxCharmBaryon = {KFOmegaC0.GetX(), KFOmegaC0.GetY(), KFOmegaC0.GetZ()}; + auto covVtxCharmBaryon = KFOmegaC0.CovarianceMatrix(); + float covMatrixPV[6]; + kfpVertex.GetCovarianceMatrix(covMatrixPV); + + // impact parameters + o2::dataformats::DCA impactParameterV0Dau0; + o2::dataformats::DCA impactParameterV0Dau1; + o2::dataformats::DCA impactParameterKaFromCasc; + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovV0Dau0, 2.f, matCorr, &impactParameterV0Dau0); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovV0Dau1, 2.f, matCorr, &impactParameterV0Dau1); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, omegaDauChargedTrackParCov, 2.f, matCorr, &impactParameterKaFromCasc); + float dcaxyV0Dau0 = impactParameterV0Dau0.getY(); + float dcaxyV0Dau1 = impactParameterV0Dau1.getY(); + float dcaxyCascBachelor = impactParameterKaFromCasc.getY(); + float dcazV0Dau0 = impactParameterV0Dau0.getZ(); + float dcazV0Dau1 = impactParameterV0Dau1.getZ(); + float dcazCascBachelor = impactParameterKaFromCasc.getZ(); + + // pseudorapidity + float pseudorapCharmBachelor = trackCharmBachelor.eta(); + + // impact parameters + o2::dataformats::DCA impactParameterCasc; + o2::dataformats::DCA impactParameterCharmBachelor; + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackCasc, 2.f, matCorr, &impactParameterCasc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParVarCharmBachelor, 2.f, matCorr, &impactParameterCharmBachelor); + float impactParBachFromCharmBaryonXY = impactParameterCharmBachelor.getY(); + float impactParBachFromCharmBaryonZ = impactParameterCharmBachelor.getZ(); + + // computing decay length and ctau + float decLenCharmBaryon = RecoDecay::distance(pvCoord, coordVtxCharmBaryon); + float decLenCascade = RecoDecay::distance(coordVtxCharmBaryon, vertexCasc); + float decLenV0 = RecoDecay::distance(vertexCasc, vertexV0); + + double phiCharmBaryon, thetaCharmBaryon; + getPointDirection(std::array{KFV0.GetX(), KFV0.GetY(), KFV0.GetZ()}, coordVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon); + auto errorDecayLengthCharmBaryon = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phiCharmBaryon, thetaCharmBaryon) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon)); + auto errorDecayLengthXYCharmBaryon = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phiCharmBaryon, 0.) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, 0.)); + + // fill test histograms + hInvMassCharmBaryon->Fill(massOmegaC0); + hCandidateCounter->Fill(3); + + //// KFParticle table information + KFParticle kfpNegToV0 = kfpNeg; + KFParticle kfpPosToV0 = kfpPos; + kfpNegToV0.SetProductionVertex(KFV0); + kfpPosToV0.SetProductionVertex(KFV0); + + KFParticle kfpBachKaonToOmega = kfpBachKaon; + KFParticle kfpV0ToCasc = kfpV0; + kfpBachKaonToOmega.SetProductionVertex(KFOmega); + kfpV0ToCasc.SetProductionVertex(KFOmega); + + KFParticle kfpCascToOmegaC = kfpCasc; + KFParticle kfpBachPionToOmegaC = kfpBachPion; + kfpBachPionToOmegaC.SetProductionVertex(KFOmegaC0); + kfpCascToOmegaC.SetProductionVertex(KFOmegaC0); + + // KFParticle to PV + KFParticle kfpV0ToPv = kfpV0; + KFParticle kfpCascToPv = kfpCasc; + KFParticle kfpOmegacToPv = KFOmegaC0; + KFParticle kfpPiFromOmegacToPv = kfpBachPion; + + kfpV0ToPv.SetProductionVertex(KFPV); + kfpCascToPv.SetProductionVertex(KFPV); + kfpOmegacToPv.SetProductionVertex(KFPV); + kfpPiFromOmegacToPv.SetProductionVertex(KFPV); + + // KF geochi2 + kfOmegac0Candidate.chi2GeoV0 = KFV0.GetChi2(); + auto v0NDF = KFV0.GetNDF(); + auto v0Chi2OverNdf = kfOmegac0Candidate.chi2GeoV0 / v0NDF; + + kfOmegac0Candidate.chi2GeoCasc = KFOmega.GetChi2(); + auto cascNDF = KFOmega.GetNDF(); + auto cascChi2OverNdf = kfOmegac0Candidate.chi2GeoCasc / cascNDF; + + kfOmegac0Candidate.chi2GeoOmegac = KFOmegaC0.GetChi2(); + auto charmbaryonNDF = KFOmegaC0.GetNDF(); + auto charmbaryonChi2OverNdf = kfOmegac0Candidate.chi2GeoOmegac / charmbaryonNDF; + + kfOmegac0Candidate.chi2MassV0 = KFV0_m.GetChi2(); + auto v0NDF_m = KFV0_m.GetNDF(); + auto v0Chi2OverNdf_m = kfOmegac0Candidate.chi2MassV0 / v0NDF_m; + + kfOmegac0Candidate.chi2MassCasc = KFOmega_m.GetChi2(); + auto cascNDF_m = KFOmega_m.GetNDF(); + auto cascChi2OverNdf_m = kfOmegac0Candidate.chi2MassCasc / cascNDF_m; + + // KF topo Chi2 + kfOmegac0Candidate.chi2TopoV0ToPv = kfpV0ToPv.GetChi2(); + kfOmegac0Candidate.chi2TopoCascToPv = kfpCascToPv.GetChi2(); + kfOmegac0Candidate.chi2TopoPiFromOmegacToPv = kfpPiFromOmegacToPv.GetChi2(); + kfOmegac0Candidate.chi2TopoOmegacToPv = kfpOmegacToPv.GetChi2(); + + auto cascBachTopoChi2 = kfpBachKaonToOmega.GetChi2(); + kfOmegac0Candidate.chi2TopoV0ToCasc = kfpV0ToCasc.GetChi2(); + kfOmegac0Candidate.chi2TopoCascToOmegac = kfpCascToOmegaC.GetChi2(); + + // KF ldl + kfOmegac0Candidate.ldlV0 = ldlFromKF(KFV0, KFPV); + kfOmegac0Candidate.ldlCasc = ldlFromKF(KFOmega, KFPV); + kfOmegac0Candidate.ldlOmegac = ldlFromKF(KFOmegaC0, KFPV); + + // KF dca + kfOmegac0Candidate.kfDcaXYPiFromOmegac = kfpBachPion.GetDistanceFromVertexXY(KFPV); + kfOmegac0Candidate.kfDcaV0Dau = kfpNegToV0.GetDistanceFromParticle(kfpPosToV0); + kfOmegac0Candidate.kfDcaCascDau = kfpBachKaon.GetDistanceFromParticle(kfpV0); + kfOmegac0Candidate.kfDcaXYCascToPv = kfpCasc.GetDistanceFromVertexXY(KFPV); + kfOmegac0Candidate.kfDcaOmegacDau = kfpBachPion.GetDistanceFromParticle(kfpCasc); + + // KF decay length + float DecayLxy_Lam, err_DecayLxy_Lam; + kfpV0ToCasc.GetDecayLengthXY(DecayLxy_Lam, err_DecayLxy_Lam); + kfOmegac0Candidate.decayLenXYLambda = DecayLxy_Lam; + + float DecayLxy_Casc, err_DecayLxy_Casc; + kfpCascToPv.GetDecayLengthXY(DecayLxy_Casc, err_DecayLxy_Casc); + kfOmegac0Candidate.decayLenXYCasc = DecayLxy_Casc; + + float DecayLxy_Omegac0, err_DecayLxy_Omegac0; + kfpOmegacToPv.GetDecayLengthXY(DecayLxy_Omegac0, err_DecayLxy_Omegac0); + kfOmegac0Candidate.decayLenXYOmegac = DecayLxy_Omegac0; + + // KF cosPA + kfOmegac0Candidate.cosPaV0ToPv = cpaFromKF(kfpV0, KFPV); + kfOmegac0Candidate.cosPaCascToPv = cpaFromKF(kfpCasc, KFPV); + kfOmegac0Candidate.cosPaOmegacToPv = cpaFromKF(KFOmegaC0, KFPV); + kfOmegac0Candidate.cosPaXYV0ToPv = cpaXYFromKF(kfpV0, KFPV); + kfOmegac0Candidate.cosPaXYCascToPv = cpaXYFromKF(kfpCasc, KFPV); + kfOmegac0Candidate.cosPaXYOmegacToPv = cpaXYFromKF(KFOmegaC0, KFPV); + + kfOmegac0Candidate.cosPaV0ToCasc = cpaFromKF(kfpV0, kfpCasc); + kfOmegac0Candidate.cosPaCascToOmegac = cpaFromKF(kfpCasc, KFOmegaC0); + kfOmegac0Candidate.cosPaXYV0ToCasc = cpaXYFromKF(kfpV0, kfpCasc); + kfOmegac0Candidate.cosPaXYCascToOmegac = cpaXYFromKF(kfpCasc, KFOmegaC0); + // KF mass + kfOmegac0Candidate.massV0 = massLam; + kfOmegac0Candidate.massCasc = massCasc; + kfOmegac0Candidate.massOmegac = massOmegaC0; + + // KF pT + kfOmegac0Candidate.ptPiFromOmegac = trackCharmBachelor.pt(); + kfOmegac0Candidate.ptOmegac = kfpOmegacToPv.GetPt(); + + // KF rapidity + kfOmegac0Candidate.rapOmegac = kfpOmegacToPv.GetRapidity(); + + // KF cosThetaStar + kfOmegac0Candidate.cosThetaStarPiFromOmegac = cosThetaStarFromKF(0, 4332, 211, 3312, kfpBachPionToOmegaC, kfpCascToOmegaC); + + // KF ct + kfOmegac0Candidate.ctV0 = kfpV0ToCasc.GetLifeTime(); + kfOmegac0Candidate.ctCasc = kfpCascToOmegaC.GetLifeTime(); + kfOmegac0Candidate.ctOmegac = kfpOmegacToPv.GetLifeTime(); + + // KF eta + kfOmegac0Candidate.etaOmegac = kfpOmegacToPv.GetEta(); + + // fill KF hist + registry.fill(HIST("hKFParticleCascBachTopoChi2"), cascBachTopoChi2); + registry.fill(HIST("hKFParticleV0TopoChi2"), kfOmegac0Candidate.chi2TopoV0ToCasc); + registry.fill(HIST("hKFParticleCascTopoChi2"), kfOmegac0Candidate.chi2TopoCascToOmegac); + + registry.fill(HIST("hKfLambda_ldl"), kfOmegac0Candidate.ldlV0); + registry.fill(HIST("hKfOmega_ldl"), kfOmegac0Candidate.ldlCasc); + registry.fill(HIST("hKfOmegaC0_ldl"), kfOmegac0Candidate.ldlOmegac); + registry.fill(HIST("hDcaXYCascadeToPVKf"), kfOmegac0Candidate.kfDcaXYCascToPv); + + // fill the table + rowCandToOmegaPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + vertexCharmBaryonFromFitter[0], vertexCharmBaryonFromFitter[1], vertexCharmBaryonFromFitter[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + trackCascDauCharged.sign(), + covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCasc[0], pVecCasc[1], pVecCasc[2], + pVecCharmBachelorAsD[0], pVecCharmBachelorAsD[1], pVecCharmBachelorAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecCascBachelor[0], pVecCascBachelor[1], pVecCascBachelor[2], + pVecV0Dau0[0], pVecV0Dau0[1], pVecV0Dau0[2], + pVecV0Dau1[0], pVecV0Dau1[1], pVecV0Dau1[2], + impactParameterCasc.getY(), impactParBachFromCharmBaryonXY, + impactParameterCasc.getZ(), impactParBachFromCharmBaryonZ, + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBachelor.getSigmaY2()), + v0index, casc.posTrackId(), casc.negTrackId(), + casc.cascadeId(), trackCharmBachelor.globalIndex(), casc.bachelorId(), + kfOmegac0Candidate.massV0, kfOmegac0Candidate.massCasc, kfOmegac0Candidate.massOmegac, + kfOmegac0Candidate.cosPaV0ToPv, kfOmegac0Candidate.cosPaOmegacToPv, kfOmegac0Candidate.cosPaCascToPv, kfOmegac0Candidate.cosPaXYV0ToPv, kfOmegac0Candidate.cosPaXYOmegacToPv, kfOmegac0Candidate.cosPaXYCascToPv, + kfOmegac0Candidate.ctOmegac, kfOmegac0Candidate.ctCasc, kfOmegac0Candidate.ctV0, + pseudorapV0Dau0, pseudorapV0Dau1, pseudorapCascBachelor, pseudorapCharmBachelor, + kfOmegac0Candidate.etaOmegac, KFOmega.GetEta(), KFV0.GetEta(), + dcaxyV0Dau0, dcaxyV0Dau1, dcaxyCascBachelor, + dcazV0Dau0, dcazV0Dau1, dcazCascBachelor, + kfOmegac0Candidate.kfDcaCascDau, kfOmegac0Candidate.kfDcaV0Dau, kfOmegac0Candidate.kfDcaOmegacDau, + decLenCharmBaryon, decLenCascade, decLenV0, errorDecayLengthCharmBaryon, errorDecayLengthXYCharmBaryon); + // fill kf table + kfCandidateData(kfOmegac0Candidate.kfDcaXYPiFromOmegac, kfOmegac0Candidate.kfDcaXYCascToPv, + kfOmegac0Candidate.chi2GeoV0, kfOmegac0Candidate.chi2GeoCasc, kfOmegac0Candidate.chi2GeoOmegac, kfOmegac0Candidate.chi2MassV0, kfOmegac0Candidate.chi2MassCasc, + kfOmegac0Candidate.ldlV0, kfOmegac0Candidate.ldlCasc, kfOmegac0Candidate.ldlOmegac, + kfOmegac0Candidate.chi2TopoV0ToPv, kfOmegac0Candidate.chi2TopoCascToPv, kfOmegac0Candidate.chi2TopoPiFromOmegacToPv, kfOmegac0Candidate.chi2TopoOmegacToPv, + kfOmegac0Candidate.chi2TopoV0ToCasc, kfOmegac0Candidate.chi2TopoCascToOmegac, + kfOmegac0Candidate.decayLenXYLambda, kfOmegac0Candidate.decayLenXYCasc, kfOmegac0Candidate.decayLenXYOmegac, + kfOmegac0Candidate.cosPaV0ToCasc, kfOmegac0Candidate.cosPaCascToOmegac, kfOmegac0Candidate.cosPaXYV0ToCasc, kfOmegac0Candidate.cosPaXYCascToOmegac, + kfOmegac0Candidate.rapOmegac, kfOmegac0Candidate.ptPiFromOmegac, kfOmegac0Candidate.ptOmegac, + kfOmegac0Candidate.cosThetaStarPiFromOmegac, + v0NDF, cascNDF, charmbaryonNDF, v0NDF_m, cascNDF_m, + v0Chi2OverNdf, cascChi2OverNdf, charmbaryonChi2OverNdf, v0Chi2OverNdf_m, cascChi2OverNdf_m); + + } // loop over LF Cascade-bachelor candidates + } // end of run function + /// @brief process function w/o centrality selections void processNoCentToXiPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processNoCentToXiPi, "Run candidate creator w/o centrality selections for xi pi decay channel", true); void processNoCentToOmegaPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processNoCentToOmegaPi, "Run candidate creator w/o centrality selections for omega pi decay channel", false); + void processOmegacToOmegaPiWithKFParticle(aod::Collisions const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracks const& tracks, + MyKfCascTable const& cascades, + KFCascadesLinked const& cascadeLinks, + aod::HfCascLf2Prongs const& candidates) + { + runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processOmegacToOmegaPiWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega pi decay channel using KFParticle", false); + void processNoCentToOmegaK(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processNoCentToOmegaK, "Run candidate creator w/o centrality selections for omega K decay channel", false); @@ -527,33 +1052,36 @@ struct HfCandidateCreatorXic0Omegac0 { void processCentFT0CToXiPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0CToXiPi, "Run candidate creator w/ centrality selection on FT0C for xi pi channel", false); void processCentFT0CToOmegaPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0CToOmegaPi, "Run candidate creator w/ centrality selection on FT0C for omega pi channel", false); void processCentFT0CToOmegaK(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0CToOmegaK, "Run candidate creator w/ centrality selection on FT0C for omega K channel", false); @@ -561,33 +1089,36 @@ struct HfCandidateCreatorXic0Omegac0 { void processCentFT0MToXiPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0MToXiPi, "Run candidate creator w/ centrality selection on FT0M for xi pi channel", false); void processCentFT0MToOmegaPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0MToOmegaPi, "Run candidate creator w/ centrality selection on FT0M for omega pi channel", false); void processCentFT0MToOmegaK(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, TracksWCovDca const& tracks, + MyLFTracksWCov const& lfTracks, MyCascTable const& cascades, CascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runXic0Omegac0Creator(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); + runXic0Omegac0Creator(collisions, bcWithTimeStamps, lfTracks, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0MToOmegaK, "Run candidate creator w/ centrality selection on FT0M for omega K channel", false); @@ -598,51 +1129,51 @@ struct HfCandidateCreatorXic0Omegac0 { /////////////////////////////////////////////////////////// /// @brief process function to monitor collisions - no centrality - void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisions(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCollisions, "Collision monitoring - no centrality", true); /// @brief process function to monitor collisions - FT0C centrality - void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0C(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCollisionsCentFT0C, "Collision monitoring - FT0C centrality", false); /// @brief process function to monitor collisions - FT0M centrality - void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps) + void processCollisionsCentFT0M(soa::Join const& collisions, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { /// loop over collisions for (const auto& collision : collisions) { /// bitmask with event. selection info float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); } /// end loop over collisions } @@ -661,13 +1192,45 @@ struct HfCandidateCreatorXic0Omegac0Mc { Produces rowMCMatchRecToOmegaK; Produces rowMCMatchGenToOmegaK; + // Configuration + o2::framework::Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; + + using MyTracksWMc = soa::Join; + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + HfEventSelectionMc hfEvSelMc; // mc event selection and monitoring using BCsInfo = soa::Join; + + std::shared_ptr hGenCharmBaryonPtRapidityTightXicToXiPi, hGenCharmBaryonPtRapidityLooseXicToXiPi, hGenCharmBaryonPtRapidityTightOmegacToXiPi, hGenCharmBaryonPtRapidityLooseOmegacToXiPi, hGenCharmBaryonPtRapidityTightOmegacToOmegaPi, hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi, hGenCharmBaryonPtRapidityTightOmegacToOmegaK, hGenCharmBaryonPtRapidityLooseOmegacToOmegaK; + HistogramRegistry registry{"registry"}; // inspect for which zPvPosMax cut was set for reconstructed void init(InitContext& initContext) { + std::array procCollisionsXicToXiPi{doprocessMcXicToXiPi, doprocessMcXicToXiPiFT0m, doprocessMcXicToXiPiFT0c}; + if (std::accumulate(procCollisionsXicToXiPi.begin(), procCollisionsXicToXiPi.end(), 0) > 1) { + LOGP(fatal, "At most one process function for XicToXiPi collision study can be enabled at a time."); + } + std::array procCollisionsOmegacToXiPi{doprocessMcOmegacToXiPi, doprocessMcOmegacToXiPiFT0m, doprocessMcOmegacToXiPiFT0c}; + if (std::accumulate(procCollisionsOmegacToXiPi.begin(), procCollisionsOmegacToXiPi.end(), 0) > 1) { + LOGP(fatal, "At most one process function for OmegacToXiPi collision study can be enabled at a time."); + } + std::array procCollisionsOmegacToOmegaPi{doprocessMcOmegacToOmegaPi, doprocessMcOmegacToOmegaPiFT0m, doprocessMcOmegacToOmegaPiFT0c}; + if (std::accumulate(procCollisionsOmegacToOmegaPi.begin(), procCollisionsOmegacToOmegaPi.end(), 0) > 1) { + LOGP(fatal, "At most one process function for OmegacToOmegaPi collision study can be enabled at a time."); + } + std::array procCollisionsOmegacToOmegaK{doprocessMcOmegacToOmegaK, doprocessMcOmegacToOmegaKFT0m, doprocessMcOmegacToOmegaKFT0c}; + if (std::accumulate(procCollisionsOmegacToOmegaK.begin(), procCollisionsOmegacToOmegaK.end(), 0) > 1) { + LOGP(fatal, "At most one process function for OmegacToOmegaK collision study can be enabled at a time."); + } + const auto& workflows = initContext.services().get(); for (const DeviceSpec& device : workflows.devices) { if (device.name.compare("hf-candidate-creator-xic0-omegac0") == 0) { @@ -676,14 +1239,26 @@ struct HfCandidateCreatorXic0Omegac0Mc { } } hfEvSelMc.addHistograms(registry); // particles monitoring + + hGenCharmBaryonPtRapidityTightXicToXiPi = registry.add("hGenCharmBaryonPtRapidityTightXicToXiPi", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); // keep track of generated candidates pt when |y|<0.5 + hGenCharmBaryonPtRapidityLooseXicToXiPi = registry.add("hGenCharmBaryonPtRapidityLooseXicToXiPi", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); // keep track of generated candidates pt when |y|<0.8 + + hGenCharmBaryonPtRapidityTightOmegacToXiPi = registry.add("hGenCharmBaryonPtRapidityTightOmegacToXiPi", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + hGenCharmBaryonPtRapidityLooseOmegacToXiPi = registry.add("hGenCharmBaryonPtRapidityLooseOmegacToXiPi", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + + hGenCharmBaryonPtRapidityTightOmegacToOmegaPi = registry.add("hGenCharmBaryonPtRapidityTightOmegacToOmegaPi", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi = registry.add("hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + + hGenCharmBaryonPtRapidityTightOmegacToOmegaK = registry.add("hGenCharmBaryonPtRapidityTightOmegacToOmegaK", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + hGenCharmBaryonPtRapidityLooseOmegacToOmegaK = registry.add("hGenCharmBaryonPtRapidityLooseOmegacToOmegaK", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); } - template + template void runXic0Omegac0Mc(TMyRecoCand const& candidates, - aod::TracksWMc const&, + MyTracksWMc const&, aod::McParticles const& mcParticles, - aod::McCollisions const&, - aod::McCollisionLabels const&, + Colls const& collsWithMcLabels, + aod::McCollisions const& mcCollisions, BCsInfo const&) { float ptCharmBaryonGen = -999.; @@ -720,15 +1295,37 @@ struct HfCandidateCreatorXic0Omegac0Mc { collisionMatched = false; std::vector idxBhadMothers{}; - auto arrayDaughters = std::array{candidate.template bachelorFromCharmBaryon_as(), // bachelor <- charm baryon - candidate.template bachelor_as(), // bachelor <- cascade - candidate.template posTrack_as(), // p <- lambda - candidate.template negTrack_as()}; // pi <- lambda - auto arrayDaughtersCasc = std::array{candidate.template bachelor_as(), - candidate.template posTrack_as(), - candidate.template negTrack_as()}; - auto arrayDaughtersV0 = std::array{candidate.template posTrack_as(), - candidate.template negTrack_as()}; + auto arrayDaughters = std::array{candidate.template bachelorFromCharmBaryon_as(), // bachelor <- charm baryon + candidate.template bachelor_as(), // bachelor <- cascade + candidate.template posTrack_as(), // p <- lambda + candidate.template negTrack_as()}; // pi <- lambda + auto arrayDaughtersCasc = std::array{candidate.template bachelor_as(), + candidate.template posTrack_as(), + candidate.template negTrack_as()}; + auto arrayDaughtersV0 = std::array{candidate.template posTrack_as(), + candidate.template negTrack_as()}; + + // Check whether the particle is from background events. If so, reject it. + if (rejectBackground) { + bool fromBkg{false}; + for (const auto& daughter : arrayDaughters) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + rowMCMatchRecXicToXiPi(flag, debug, origin, collisionMatched, -1.f, 0); + rowMCMatchRecOmegacToXiPi(flag, debug, origin, collisionMatched, -1.f, 0); + rowMCMatchRecToOmegaPi(flag, debug, origin, collisionMatched, -1.f, 0); + rowMCMatchRecToOmegaK(flag, debug, origin, collisionMatched, -1.f, 0); + continue; + } + } + // Xic0 -> xi pi matching if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { // Xic → pi pi pi p @@ -751,7 +1348,7 @@ struct HfCandidateCreatorXic0Omegac0Mc { } if (indexRec > -1) { flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi); - collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); } } } @@ -790,7 +1387,7 @@ struct HfCandidateCreatorXic0Omegac0Mc { } if (indexRec > -1) { flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi); - collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); } } } @@ -829,7 +1426,7 @@ struct HfCandidateCreatorXic0Omegac0Mc { } if (indexRec > -1) { flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi); - collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); } } } @@ -868,7 +1465,7 @@ struct HfCandidateCreatorXic0Omegac0Mc { } if (indexRec > -1) { flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK); - collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); } } } @@ -889,181 +1486,237 @@ struct HfCandidateCreatorXic0Omegac0Mc { } } // close loop over candidates - // Match generated particles. - for (const auto& particle : mcParticles) { - ptCharmBaryonGen = -999.; - rapidityCharmBaryonGen = -999.; - flag = 0; - sign = -9; - debugGenCharmBar = 0; - debugGenCasc = 0; - debugGenLambda = 0; - origin = RecoDecay::OriginType::None; - std::vector idxBhadMothers{}; + for (const auto& mcCollision : mcCollisions) { - auto mcCollision = particle.mcCollision(); - const auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision); + // Slice the particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + if constexpr (centEstimator == CentralityEstimator::FT0C) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::FT0M) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } else if constexpr (centEstimator == CentralityEstimator::None) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + } hfEvSelMc.fillHistograms(rejectionMask); if (rejectionMask != 0) { - /// at least one event selection not satisfied --> reject the gen particle - if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { - rowMCMatchGenXicToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { - rowMCMatchGenOmegacToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { - rowMCMatchGenToOmegaPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK) { - rowMCMatchGenToOmegaK(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + /// at least one event selection not satisfied --> reject all particles from this collision + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + rowMCMatchGenXicToXiPi(0, 0, 0, 0, -999., -999., RecoDecay::OriginType::None, -1); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + rowMCMatchGenOmegacToXiPi(0, 0, 0, 0, -999., -999., RecoDecay::OriginType::None, -1); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + rowMCMatchGenToOmegaPi(0, 0, 0, 0, -999., -999., RecoDecay::OriginType::None, -1); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK) { + rowMCMatchGenToOmegaK(0, 0, 0, 0, -999., -999., RecoDecay::OriginType::None, -1); + } } continue; } - if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { - // Xic → Xi pi - if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeXic0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { - debugGenCharmBar = 1; - ptCharmBaryonGen = particle.pt(); - rapidityCharmBaryonGen = particle.y(); - for (const auto& daughterCharm : particle.daughters_as()) { - if (std::abs(daughterCharm.pdgCode()) != pdgCodeXiMinus) { - continue; - } - // Xi -> Lambda pi - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { - debugGenCasc = 1; - for (const auto& daughterCascade : daughterCharm.daughters_as()) { - if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { - continue; - } - // Lambda -> p pi - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { - debugGenLambda = 1; - flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi); + // Match generated particles. + for (const auto& particle : mcParticlesPerMcColl) { + ptCharmBaryonGen = -999.; + rapidityCharmBaryonGen = -999.; + flag = 0; + sign = -9; + debugGenCharmBar = 0; + debugGenCasc = 0; + debugGenLambda = 0; + origin = RecoDecay::OriginType::None; + std::vector idxBhadMothers{}; + + // Reject particles from background events + if (particle.fromBackgroundEvent() && rejectBackground) { + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + rowMCMatchGenXicToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + rowMCMatchGenOmegacToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + rowMCMatchGenToOmegaPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK) { + rowMCMatchGenToOmegaK(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } + continue; + } + + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + // Xic → Xi pi + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeXic0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { + debugGenCharmBar = 1; + ptCharmBaryonGen = particle.pt(); + rapidityCharmBaryonGen = particle.y(); + for (const auto& daughterCharm : particle.daughters_as()) { + if (std::abs(daughterCharm.pdgCode()) != pdgCodeXiMinus) { + continue; + } + // Xi -> Lambda pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { + debugGenCasc = 1; + for (const auto& daughterCascade : daughterCharm.daughters_as()) { + if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { + continue; + } + // Lambda -> p pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { + debugGenLambda = 1; + flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi); + } } } } } - } - // Check whether the charm baryon is non-prompt (from a b quark) - if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMCMatchGenXicToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); - } else { - rowMCMatchGenXicToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } - - } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { - // Omegac → Xi pi - if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { - debugGenCharmBar = 1; - ptCharmBaryonGen = particle.pt(); - rapidityCharmBaryonGen = particle.y(); - for (const auto& daughterCharm : particle.daughters_as()) { - if (std::abs(daughterCharm.pdgCode()) != pdgCodeXiMinus) { - continue; + // Check whether the charm baryon is non-prompt (from a b quark) + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + if (std::abs(rapidityCharmBaryonGen) < 0.5) { + hGenCharmBaryonPtRapidityTightXicToXiPi->SetBinContent(hGenCharmBaryonPtRapidityTightXicToXiPi->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityTightXicToXiPi->GetBinContent(hGenCharmBaryonPtRapidityTightXicToXiPi->FindBin(ptCharmBaryonGen)) + 1); } - // Xi -> Lambda pi - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { - debugGenCasc = 1; - for (const auto& daughterCascade : daughterCharm.daughters_as()) { - if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { - continue; - } - // Lambda -> p pi - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { - debugGenLambda = 1; - flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi); + if (std::abs(rapidityCharmBaryonGen) < 0.8) { + hGenCharmBaryonPtRapidityLooseXicToXiPi->SetBinContent(hGenCharmBaryonPtRapidityLooseXicToXiPi->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityLooseXicToXiPi->GetBinContent(hGenCharmBaryonPtRapidityLooseXicToXiPi->FindBin(ptCharmBaryonGen)) + 1); + } + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMCMatchGenXicToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); + } else { + rowMCMatchGenXicToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } + + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + // Omegac → Xi pi + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { + debugGenCharmBar = 1; + ptCharmBaryonGen = particle.pt(); + rapidityCharmBaryonGen = particle.y(); + for (const auto& daughterCharm : particle.daughters_as()) { + if (std::abs(daughterCharm.pdgCode()) != pdgCodeXiMinus) { + continue; + } + // Xi -> Lambda pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { + debugGenCasc = 1; + for (const auto& daughterCascade : daughterCharm.daughters_as()) { + if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { + continue; + } + // Lambda -> p pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { + debugGenLambda = 1; + flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi); + } } } } } - } - // Check whether the charm baryon is non-prompt (from a b quark) - if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMCMatchGenOmegacToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); - } else { - rowMCMatchGenOmegacToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } - - } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { - // Omegac → Omega pi - if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeOmegaMinus, pdgCodePiPlus}, true, &sign)) { - debugGenCharmBar = 1; - ptCharmBaryonGen = particle.pt(); - rapidityCharmBaryonGen = particle.y(); - for (const auto& daughterCharm : particle.daughters_as()) { - if (std::abs(daughterCharm.pdgCode()) != pdgCodeOmegaMinus) { - continue; + // Check whether the charm baryon is non-prompt (from a b quark) + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + if (std::abs(rapidityCharmBaryonGen) < 0.5) { + hGenCharmBaryonPtRapidityTightOmegacToXiPi->SetBinContent(hGenCharmBaryonPtRapidityTightOmegacToXiPi->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityTightOmegacToXiPi->GetBinContent(hGenCharmBaryonPtRapidityTightOmegacToXiPi->FindBin(ptCharmBaryonGen)) + 1); } - // Omega -> Lambda K - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeOmegaMinus, std::array{pdgCodeLambda, pdgCodeKaonMinus}, true)) { - debugGenCasc = 1; - for (const auto& daughterCascade : daughterCharm.daughters_as()) { - if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { - continue; - } - // Lambda -> p pi - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { - debugGenLambda = 1; - flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi); + if (std::abs(rapidityCharmBaryonGen) < 0.8) { + hGenCharmBaryonPtRapidityLooseOmegacToXiPi->SetBinContent(hGenCharmBaryonPtRapidityLooseOmegacToXiPi->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityLooseOmegacToXiPi->GetBinContent(hGenCharmBaryonPtRapidityLooseOmegacToXiPi->FindBin(ptCharmBaryonGen)) + 1); + } + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMCMatchGenOmegacToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); + } else { + rowMCMatchGenOmegacToXiPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } + + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + // Omegac → Omega pi + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeOmegaMinus, pdgCodePiPlus}, true, &sign)) { + debugGenCharmBar = 1; + ptCharmBaryonGen = particle.pt(); + rapidityCharmBaryonGen = particle.y(); + for (const auto& daughterCharm : particle.daughters_as()) { + if (std::abs(daughterCharm.pdgCode()) != pdgCodeOmegaMinus) { + continue; + } + // Omega -> Lambda K + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeOmegaMinus, std::array{pdgCodeLambda, pdgCodeKaonMinus}, true)) { + debugGenCasc = 1; + for (const auto& daughterCascade : daughterCharm.daughters_as()) { + if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { + continue; + } + // Lambda -> p pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { + debugGenLambda = 1; + flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi); + } } } } } - } - // Check whether the charm baryon is non-prompt (from a b quark) - if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMCMatchGenToOmegaPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); - } else { - rowMCMatchGenToOmegaPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } - - } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK) { - // Omegac → Omega K - if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeOmegaMinus, pdgCodeKaonPlus}, true, &sign)) { - debugGenCharmBar = 1; - ptCharmBaryonGen = particle.pt(); - rapidityCharmBaryonGen = particle.y(); - for (const auto& daughterCharm : particle.daughters_as()) { - if (std::abs(daughterCharm.pdgCode()) != pdgCodeOmegaMinus) { - continue; + // Check whether the charm baryon is non-prompt (from a b quark) + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + if (std::abs(rapidityCharmBaryonGen) < 0.5) { + hGenCharmBaryonPtRapidityTightOmegacToOmegaPi->SetBinContent(hGenCharmBaryonPtRapidityTightOmegacToOmegaPi->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityTightOmegacToOmegaPi->GetBinContent(hGenCharmBaryonPtRapidityTightOmegacToOmegaPi->FindBin(ptCharmBaryonGen)) + 1); } - // Omega -> Lambda K - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeOmegaMinus, std::array{pdgCodeLambda, pdgCodeKaonMinus}, true)) { - debugGenCasc = 1; - for (const auto& daughterCascade : daughterCharm.daughters_as()) { - if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { - continue; - } - // Lambda -> p pi - if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { - debugGenLambda = 1; - flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK); + if (std::abs(rapidityCharmBaryonGen) < 0.8) { + hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi->SetBinContent(hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi->GetBinContent(hGenCharmBaryonPtRapidityLooseOmegacToOmegaPi->FindBin(ptCharmBaryonGen)) + 1); + } + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMCMatchGenToOmegaPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); + } else { + rowMCMatchGenToOmegaPi(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } + + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK) { + // Omegac → Omega K + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeOmegaMinus, pdgCodeKaonPlus}, true, &sign)) { + debugGenCharmBar = 1; + ptCharmBaryonGen = particle.pt(); + rapidityCharmBaryonGen = particle.y(); + for (const auto& daughterCharm : particle.daughters_as()) { + if (std::abs(daughterCharm.pdgCode()) != pdgCodeOmegaMinus) { + continue; + } + // Omega -> Lambda K + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgCodeOmegaMinus, std::array{pdgCodeLambda, pdgCodeKaonMinus}, true)) { + debugGenCasc = 1; + for (const auto& daughterCascade : daughterCharm.daughters_as()) { + if (std::abs(daughterCascade.pdgCode()) != pdgCodeLambda) { + continue; + } + // Lambda -> p pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { + debugGenLambda = 1; + flag = sign * (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaK); + } } } } } + // Check whether the charm baryon is non-prompt (from a b quark) + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + if (std::abs(rapidityCharmBaryonGen) < 0.5) { + hGenCharmBaryonPtRapidityTightOmegacToOmegaK->SetBinContent(hGenCharmBaryonPtRapidityTightOmegacToOmegaK->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityTightOmegacToOmegaK->GetBinContent(hGenCharmBaryonPtRapidityTightOmegacToOmegaK->FindBin(ptCharmBaryonGen)) + 1); + } + if (std::abs(rapidityCharmBaryonGen) < 0.8) { + hGenCharmBaryonPtRapidityLooseOmegacToOmegaK->SetBinContent(hGenCharmBaryonPtRapidityLooseOmegacToOmegaK->FindBin(ptCharmBaryonGen), hGenCharmBaryonPtRapidityLooseOmegacToOmegaK->GetBinContent(hGenCharmBaryonPtRapidityLooseOmegacToOmegaK->FindBin(ptCharmBaryonGen)) + 1); + } + } + if (origin == RecoDecay::OriginType::NonPrompt) { + rowMCMatchGenToOmegaK(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); + } else { + rowMCMatchGenToOmegaK(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); + } } - // Check whether the charm baryon is non-prompt (from a b quark) - if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); - } - if (origin == RecoDecay::OriginType::NonPrompt) { - rowMCMatchGenToOmegaK(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, idxBhadMothers[0]); - } else { - rowMCMatchGenToOmegaK(flag, debugGenCharmBar, debugGenCasc, debugGenLambda, ptCharmBaryonGen, rapidityCharmBaryonGen, origin, -1); - } - } - } // close loop on MCParticles - } // close process + } // close loop on MCParticles + } // close loop on MCCollisions + } // close process void processDoNoMc(aod::Collisions::iterator const&) { @@ -1072,48 +1725,136 @@ struct HfCandidateCreatorXic0Omegac0Mc { PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processDoNoMc, "Do not run any MC process function", true); void processMcXicToXiPi(aod::HfCandToXiPi const& candidates, - aod::TracksWMc const& tracks, + MyTracksWMc const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcColls, - aod::McCollisionLabels const& mcLabels, + McCollisionsNoCents const& collsWithMcLabels, BCsInfo const& bcs) { - runXic0Omegac0Mc(candidates, tracks, mcParticles, mcColls, mcLabels, bcs); + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcXicToXiPi, "Run Xic0 to xi pi MC process function - no centrality", false); + + void processMcXicToXiPiFT0m(aod::HfCandToXiPi const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); } - PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcXicToXiPi, "Run Xic0 to xi pi MC process function", false); + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcXicToXiPiFT0m, "Run Xic0 to xi pi MC process function - FT0M", false); + + void processMcXicToXiPiFT0c(aod::HfCandToXiPi const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcXicToXiPiFT0c, "Run Xic0 to xi pi MC process function - FT0C", false); void processMcOmegacToXiPi(aod::HfCandToXiPi const& candidates, - aod::TracksWMc const& tracks, + MyTracksWMc const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcColls, - aod::McCollisionLabels const& mcLabels, + McCollisionsNoCents const& collsWithMcLabels, BCsInfo const& bcs) { - runXic0Omegac0Mc(candidates, tracks, mcParticles, mcColls, mcLabels, bcs); + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToXiPi, "Run Omegac0 to xi pi MC process function - no centrality", false); + + void processMcOmegacToXiPiFT0m(aod::HfCandToXiPi const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); } - PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToXiPi, "Run Omegac0 to xi pi MC process function", false); + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToXiPiFT0m, "Run Omegac0 to xi pi MC process function - FT0M", false); + + void processMcOmegacToXiPiFT0c(aod::HfCandToXiPi const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToXiPiFT0c, "Run Omegac0 to xi pi MC process function - FT0C", false); void processMcOmegacToOmegaPi(aod::HfCandToOmegaPi const& candidates, - aod::TracksWMc const& tracks, + MyTracksWMc const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcColls, - aod::McCollisionLabels const& mcLabels, + McCollisionsNoCents const& collsWithMcLabels, BCsInfo const& bcs) { - runXic0Omegac0Mc(candidates, tracks, mcParticles, mcColls, mcLabels, bcs); + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaPi, "Run Omegac0 to omega pi MC process function - no centrality", false); + + void processMcOmegacToOmegaPiFT0m(aod::HfCandToOmegaPi const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaPiFT0m, "Run Omegac0 to omega pi MC process function - FT0M", false); + + void processMcOmegacToOmegaPiFT0c(aod::HfCandToOmegaPi const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); } - PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaPi, "Run Omegac0 to omega pi MC process function", false); + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaPiFT0c, "Run Omegac0 to omega pi MC process function - FT0C", false); void processMcOmegacToOmegaK(aod::HfCandToOmegaK const& candidates, - aod::TracksWMc const& tracks, + MyTracksWMc const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcColls, - aod::McCollisionLabels const& mcLabels, + McCollisionsNoCents const& collsWithMcLabels, BCsInfo const& bcs) { - runXic0Omegac0Mc(candidates, tracks, mcParticles, mcColls, mcLabels, bcs); + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaK, "Run Omegac0 to omega K MC process function - no centrality", false); + + void processMcOmegacToOmegaKFT0m(aod::HfCandToOmegaK const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaKFT0m, "Run Omegac0 to omega K MC process function - FT0M", false); + + void processMcOmegacToOmegaKFT0c(aod::HfCandToOmegaK const& candidates, + MyTracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcColls, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcColls, bcs); } - PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaK, "Run Omegac0 to omega K MC process function", false); + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Mc, processMcOmegacToOmegaKFT0c, "Run Omegac0 to omega K MC process function - FT0C", false); }; // close struct diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx new file mode 100644 index 00000000000..207159a6f25 --- /dev/null +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -0,0 +1,705 @@ +// Copyright 2019-2020 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. + +/// \file candidateCreatorXicToXiPiPi.cxx +/// \brief Reconstruction of Ξc± → (Ξ∓ → (Λ → p π∓) π∓) π± π± candidates +/// +/// \author Phil Lennart Stahlhut , Heidelberg University +/// \author Carolina Reetz , Heidelberg University +/// \author Jinjoo Seo , Heidelberg University + +#ifndef HomogeneousField +#define HomogeneousField +#endif + +#include +#include +#include +#include +#include + +#include + +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Tools/KFparticle/KFUtilities.h" + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" + +using namespace o2; +using namespace o2::analysis; +using namespace o2::aod::hf_cand_xic_to_xi_pi_pi; +using namespace o2::constants::physics; +using namespace o2::framework; + +/// Reconstruction of heavy-flavour 3-prong decay candidates +struct HfCandidateCreatorXicToXiPiPi { + Produces rowCandidateBase; + Produces rowCandidateKF; + + Configurable fillHistograms{"fillHistograms", true, "do validation plots"}; + // magnetic field setting from CCDB + Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + // cascade preselections + Configurable doCascadePreselection{"doCascadePreselection", true, "Use invariant mass and dcaXY cuts to preselect cascade candidates"}; + Configurable massToleranceCascade{"massToleranceCascade", 0.01, "Invariant mass tolerance for cascade"}; + Configurable dcaXYToPVCascadeMax{"dcaXYToPVCascadeMax", 3, "Max cascade DCA to PV in xy plane"}; + // DCA fitter + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + // KFParticle + Configurable constrainXicPlusToPv{"constrainXicPlusToPv", false, "Constrain XicPlus to PV"}; + Configurable constrainXiToXicPlus{"constrainXiToXicPlus", false, "Constrain Xi to XicPlus"}; + Configurable kfConstructMethod{"kfConstructMethod", 2, "Construct method of XicPlus: 0 fast mathematics without constraint of fixed daughter particle masses, 2 daughter particle masses stay fixed in construction process"}; + Configurable rejDiffCollTrack{"rejDiffCollTrack", true, "Reject tracks coming from different collisions (effective only for KFParticle w/o derived data)"}; + + Service ccdb; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + o2::vertexing::DCAFitterN<3> df; + + int runNumber{0}; + float massXiPiPi{0.}; + float massXiPi0{0.}; + float massXiPi1{0.}; + double bz{0.}; + + using CascadesLinked = soa::Join; + using CascFull = soa::Join; + using KFCascadesLinked = soa::Join; + using KFCascFull = soa::Join; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + if ((doprocessXicplusWithDcaFitter + doprocessXicplusWithKFParticle) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } + + // add histograms to registry + if (fillHistograms) { + registry.add("hMass3", "3-prong candidates;inv. mass (#Xi #pi #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 2.3, 2.7}}}); + registry.add("hCovPVXX", "3-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 1.e-4}}}); + registry.add("hCovSVXX", "3-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 0.2}}}); + registry.add("hCovPVYY", "3-prong candidates;YY element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 1.e-4}}}); + registry.add("hCovSVYY", "3-prong candidates;YY element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 0.2}}}); + registry.add("hCovPVXZ", "3-prong candidates;XZ element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, -1.e-4, 1.e-4}}}); + registry.add("hCovSVXZ", "3-prong candidates;XZ element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, -1.e-4, 0.2}}}); + registry.add("hCovPVZZ", "3-prong candidates;ZZ element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 1.e-4}}}); + registry.add("hCovSVZZ", "3-prong candidates;ZZ element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 0.2}}}); + registry.add("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); // See o2::aod::hf_cand::VertexerType + registry.add("hDcaXYProngs", "DCAxy of 3-prong candidates;#it{p}_{T} (GeV/#it{c};#it{d}_{xy}) (#mum);entries", {HistType::kTH2D, {{100, 0., 20.}, {200, -500., 500.}}}); + registry.add("hDcaZProngs", "DCAz of 3-prong candidates;#it{p}_{T} (GeV/#it{c};#it{d}_{z}) (#mum);entries", {HistType::kTH2D, {{100, 0., 20.}, {200, -500., 500.}}}); + } + + // fill hVertexerType histogram + if (doprocessXicplusWithDcaFitter && fillHistograms) { + registry.fill(HIST("hVertexerType"), aod::hf_cand::VertexerType::DCAFitter); + } + if (doprocessXicplusWithKFParticle && fillHistograms) { + registry.fill(HIST("hVertexerType"), aod::hf_cand::VertexerType::KfParticle); + } + + // initialize CCDB + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); + runNumber = 0; + + // initialize 3-prong vertex fitter + df.setPropagateToPCA(propagateToPCA); + df.setMaxR(maxR); + df.setMaxDZIni(maxDZIni); + df.setMinParamChange(minParamChange); + df.setMinRelChi2Change(minRelChi2Change); + df.setUseAbsDCA(useAbsDCA); + df.setWeightedFinalPCA(useWeightedFinalPCA); + } + + void processXicplusWithDcaFitter(aod::Collisions const&, + aod::HfCascLf3Prongs const& rowsTrackIndexXicPlus, + CascadesLinked const&, + CascFull const&, + aod::TracksWCovDca const&, + aod::BCsWithTimestamps const&) + { + // loop over triplets of track indices + for (const auto& rowTrackIndexXicPlus : rowsTrackIndexXicPlus) { + auto cascAodElement = rowTrackIndexXicPlus.cascade_as(); + if (!cascAodElement.has_cascData()) { + continue; + } + auto casc = cascAodElement.cascData_as(); + auto trackCharmBachelor0 = rowTrackIndexXicPlus.prong0_as(); + auto trackCharmBachelor1 = rowTrackIndexXicPlus.prong1_as(); + auto collision = rowTrackIndexXicPlus.collision(); + + // preselect cascade candidates + if (doCascadePreselection) { + if (std::abs(casc.dcaXYCascToPV()) > dcaXYToPVCascadeMax) { + continue; + } + if (std::abs(casc.mXi() - MassXiMinus) > massToleranceCascade) { + continue; + } + } + + //----------------------Set the magnetic field from ccdb--------------------------------------- + /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + /// but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + } + df.setBz(bz); + + //----------------accessing particles in the decay chain------------- + auto trackPionFromXi = casc.bachelor_as(); // pion <- xi track from TracksWCovDca table + + //--------------------------info of V0 and cascades track from LF-tables--------------------------- + std::array vertexV0 = {casc.xlambda(), casc.ylambda(), casc.zlambda()}; + std::array pVecV0 = {casc.pxlambda(), casc.pylambda(), casc.pzlambda()}; + std::array vertexCasc = {casc.x(), casc.y(), casc.z()}; + std::array pVecCasc = {casc.px(), casc.py(), casc.pz()}; + std::array covCasc = {0.}; + + //----------------create cascade track------------------------------------------------------------ + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covCasc[MomInd[i]] = casc.momentumCovMat()[i]; + covCasc[i] = casc.positionCovMat()[i]; + } + // create cascade track + o2::track::TrackParCov trackCasc; + if (trackPionFromXi.sign() > 0) { + trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, 1, true); + } else if (trackPionFromXi.sign() < 0) { + trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, -1, true); + } else { + continue; + } + trackCasc.setAbsCharge(1); + trackCasc.setPID(o2::track::PID::XiMinus); + + //----------------------------fit SV and create XicPlus track------------------ + auto trackParCovCharmBachelor0 = getTrackParCov(trackCharmBachelor0); + auto trackParCovCharmBachelor1 = getTrackParCov(trackCharmBachelor1); + + // reconstruct the 3-prong secondary vertex + try { + if (df.process(trackCasc, trackParCovCharmBachelor0, trackParCovCharmBachelor1) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + continue; + } + + //----------------------------calculate physical properties----------------------- + // Charge of charm baryon + int signXic = casc.sign() < 0 ? +1 : -1; + + // get SV properties + const auto& secondaryVertex = df.getPCACandidate(); + auto chi2SV = df.getChi2AtPCACandidate(); + auto covMatrixSV = df.calcPCACovMatrixFlat(); + + // get track momenta + trackCasc = df.getTrack(0); + trackParCovCharmBachelor0 = df.getTrack(1); + trackParCovCharmBachelor1 = df.getTrack(2); + std::array pVecXi; + std::array pVecPi0; + std::array pVecPi1; + trackCasc.getPxPyPzGlo(pVecXi); + trackParCovCharmBachelor0.getPxPyPzGlo(pVecPi0); + trackParCovCharmBachelor1.getPxPyPzGlo(pVecPi1); + + // get invariant mass of Xic candidate + auto arrayMomenta = std::array{pVecXi, pVecPi0, pVecPi1}; + massXiPiPi = RecoDecay::m(std::move(arrayMomenta), std::array{MassXiMinus, MassPiPlus, MassPiPlus}); + + // get track impact parameters + // This modifies track momenta! + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + // calculate impact parameter + o2::dataformats::DCA impactParameterCasc; + o2::dataformats::DCA impactParameter0; + o2::dataformats::DCA impactParameter1; + trackCasc.propagateToDCA(primaryVertex, bz, &impactParameterCasc); + trackParCovCharmBachelor0.propagateToDCA(primaryVertex, bz, &impactParameter0); + trackParCovCharmBachelor1.propagateToDCA(primaryVertex, bz, &impactParameter1); + + // calculate cosine of pointing angle + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + double cpaLambda = casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + double cpaXYLambda = RecoDecay::cpaXY(pvCoord, vertexV0, pVecV0); + double cpaXi = casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()); + double cpaXYXi = RecoDecay::cpaXY(pvCoord, vertexCasc, pVecCasc); + + // get invariant mass of Xi-pi pairs + auto arrayMomentaXiPi0 = std::array{pVecXi, pVecPi0}; + massXiPi0 = RecoDecay::m(std::move(arrayMomentaXiPi0), std::array{MassXiMinus, MassPiPlus}); + auto arrayMomentaXiPi1 = std::array{pVecXi, pVecPi1}; + massXiPi1 = RecoDecay::m(std::move(arrayMomentaXiPi1), std::array{MassXiMinus, MassPiPlus}); + + // get uncertainty of the decay length + double phi, theta; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixSV, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixSV, phi, 0.)); + + //--------------------------------------------fill histograms---------------------------------------------------------------- + if (fillHistograms) { + // invariant mass + registry.fill(HIST("hMass3"), massXiPiPi); + // covariance matrix elements of PV + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + registry.fill(HIST("hCovPVYY"), covMatrixPV[2]); + registry.fill(HIST("hCovPVXZ"), covMatrixPV[3]); + registry.fill(HIST("hCovPVZZ"), covMatrixPV[5]); + // covariance matrix elements of SV + registry.fill(HIST("hCovSVXX"), covMatrixSV[0]); + registry.fill(HIST("hCovSVYY"), covMatrixSV[2]); + registry.fill(HIST("hCovSVXZ"), covMatrixSV[3]); + registry.fill(HIST("hCovSVZZ"), covMatrixSV[5]); + // DCAs of prongs + registry.fill(HIST("hDcaXYProngs"), trackCasc.getPt(), impactParameterCasc.getY()); + registry.fill(HIST("hDcaXYProngs"), trackCharmBachelor0.pt(), impactParameter0.getY()); + registry.fill(HIST("hDcaXYProngs"), trackCharmBachelor1.pt(), impactParameter1.getY()); + registry.fill(HIST("hDcaZProngs"), trackCasc.getPt(), impactParameterCasc.getZ()); + registry.fill(HIST("hDcaZProngs"), trackCharmBachelor0.pt(), impactParameter0.getZ()); + registry.fill(HIST("hDcaZProngs"), trackCharmBachelor1.pt(), impactParameter1.getZ()); + } + + //---------------------------------fill candidate table rows------------------------------------------------------------------------------------------- + rowCandidateBase(collision.globalIndex(), + primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), + covMatrixPV[0], covMatrixPV[2], covMatrixPV[5], + /*3-prong specific columns*/ + rowTrackIndexXicPlus.cascadeId(), rowTrackIndexXicPlus.prong0Id(), rowTrackIndexXicPlus.prong1Id(), + casc.bachelorId(), casc.posTrackId(), casc.negTrackId(), + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + covMatrixSV[0], covMatrixSV[2], covMatrixSV[5], + errorDecayLength, errorDecayLengthXY, + chi2SV, massXiPiPi, signXic, + pVecXi[0], pVecXi[1], pVecXi[2], + pVecPi0[0], pVecPi0[1], pVecPi0[2], + pVecPi1[0], pVecPi1[1], pVecPi1[2], + impactParameterCasc.getY(), impactParameter0.getY(), impactParameter1.getY(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), + /*cascade specific columns*/ + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + cpaXi, cpaXYXi, cpaLambda, cpaXYLambda, + massXiPi0, massXiPi1); + } // loop over track triplets + } + PROCESS_SWITCH(HfCandidateCreatorXicToXiPiPi, processXicplusWithDcaFitter, "Run candidate creator with DCAFitter.", true); + + void processXicplusWithKFParticle(aod::Collisions const&, + aod::HfCascLf3Prongs const& rowsTrackIndexXicPlus, + KFCascadesLinked const&, + KFCascFull const&, + aod::TracksWCovExtra const&, + aod::BCsWithTimestamps const&) + { + // loop over triplets of track indices + for (const auto& rowTrackIndexXicPlus : rowsTrackIndexXicPlus) { + auto cascAodElement = rowTrackIndexXicPlus.cascade_as(); + if (!cascAodElement.has_kfCascData()) { + continue; + } + auto casc = cascAodElement.kfCascData_as(); + auto trackCharmBachelor0 = rowTrackIndexXicPlus.prong0_as(); + auto trackCharmBachelor1 = rowTrackIndexXicPlus.prong1_as(); + auto collision = rowTrackIndexXicPlus.collision(); + + //-------------------preselect cascade candidates-------------------------------------- + if (doCascadePreselection) { + if (std::abs(casc.dcaXYCascToPV()) > dcaXYToPVCascadeMax) { + continue; + } + if (std::abs(casc.mXi() - MassXiMinus) > massToleranceCascade) { + continue; + } + } + + //----------------------Set the magnetic field from ccdb----------------------------- + /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + /// but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + } + KFParticle::SetField(bz); + + //----------------------info of V0 and cascade tracks from LF-table------------------ + std::array vertexV0 = {casc.xlambda(), casc.ylambda(), casc.zlambda()}; + std::array pVecV0 = {casc.pxlambda(), casc.pylambda(), casc.pzlambda()}; + std::array vertexCasc = {casc.x(), casc.y(), casc.z()}; + std::array pVecCasc = {casc.px(), casc.py(), casc.pz()}; + + //----------------------Create XicPlus as KFParticle object------------------------------------------- + // initialize primary vertex + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + float covMatrixPV[6]; + kfpVertex.GetCovarianceMatrix(covMatrixPV); + KFParticle KFPV(kfpVertex); // for calculation of DCAs to PV + + // convert pion tracks into KFParticle object + KFPTrack kfpTrackCharmBachelor0 = createKFPTrackFromTrack(trackCharmBachelor0); + KFPTrack kfpTrackCharmBachelor1 = createKFPTrackFromTrack(trackCharmBachelor1); + KFParticle kfCharmBachelor0(kfpTrackCharmBachelor0, kPiPlus); + KFParticle kfCharmBachelor1(kfpTrackCharmBachelor1, kPiPlus); + + // create Xi as KFParticle object + // read {X,Y,Z,Px,Py,Pz} and corresponding covariance matrix from KF cascade Tables + std::array xyzpxpypz = {casc.x(), casc.y(), casc.z(), casc.px(), casc.py(), casc.pz()}; + float parPosMom[6]; + for (int i{0}; i < 6; ++i) { + parPosMom[i] = xyzpxpypz[i]; + } + // create KFParticle + KFParticle kfXi; + kfXi.Create(parPosMom, casc.kfTrackCovMat(), casc.sign(), casc.mXi()); + + // create XicPlus as KFParticle object + KFParticle kfXicPlus; + const KFParticle* kfDaughtersXicPlus[3] = {&kfCharmBachelor0, &kfCharmBachelor1, &kfXi}; + kfXicPlus.SetConstructMethod(kfConstructMethod); + try { + kfXicPlus.Construct(kfDaughtersXicPlus, 3); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct XicPlus : " << e.what(); + continue; + } + + // get geometrical chi2 of XicPlus + float chi2GeoXicPlus = kfXicPlus.GetChi2() / kfXicPlus.GetNDF(); + + // topological constraint of Xic to PV + KFParticle kfXicPlusToPV = kfXicPlus; + kfXicPlusToPV.SetProductionVertex(KFPV); + float chi2topoXicPlusPV = kfXicPlusToPV.GetChi2() / kfXicPlusToPV.GetNDF(); + if (constrainXicPlusToPv) { + kfXicPlus = kfXicPlusToPV; + kfXicPlus.TransportToDecayVertex(); + } + + // topological constraint of Xi to XicPlus + KFParticle kfXiToXicPlus = kfXi; + kfXiToXicPlus.SetProductionVertex(kfXicPlus); + float chi2topoXiToXicPlus = kfXiToXicPlus.GetChi2() / kfXiToXicPlus.GetNDF(); + kfXiToXicPlus.TransportToDecayVertex(); + if (constrainXiToXicPlus) { + KFParticle kfXicPlusWithXiToXicPlus; + const KFParticle* kfDaughtersXicPlusWithXiToXicPlus[3] = {&kfCharmBachelor0, &kfCharmBachelor1, &kfXiToXicPlus}; + kfXicPlusWithXiToXicPlus.SetConstructMethod(kfConstructMethod); + try { + kfXicPlusWithXiToXicPlus.Construct(kfDaughtersXicPlusWithXiToXicPlus, 3); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct XicPlus with Xi connstrained to XicPlus: " << e.what(); + continue; + } + kfXicPlus = kfXicPlusWithXiToXicPlus; + } + + // get covariance matrix of XicPlus + auto covMatrixXicPlus = kfXicPlus.CovarianceMatrix(); + + //---------------------calculate physical parameters of XicPlus candidate---------------------- + // sign of charm baryon + int signXic = casc.sign() < 0 ? +1 : -1; + + // get updated daughter tracks after vertex fit + // after production vertex constraint the parameters of the particle are stored at the position of the production vertex + KFParticle kfCharmBachelor0Upd = kfCharmBachelor0; + KFParticle kfCharmBachelor1Upd = kfCharmBachelor1; + KFParticle kfXiUpd = kfXi; + kfCharmBachelor0Upd.SetProductionVertex(kfXicPlus); + kfCharmBachelor1Upd.SetProductionVertex(kfXicPlus); + kfXiUpd.SetProductionVertex(kfXicPlus); + + // get impact parameters of updated XicPlus daughters + float impactParameterPi0XY = 0., errImpactParameterPi0XY = 0.; + float impactParameterPi1XY = 0., errImpactParameterPi1XY = 0.; + float impactParameterXiXY = 0., errImpactParameterXiXY = 0.; + kfCharmBachelor0Upd.GetDistanceFromVertexXY(KFPV, impactParameterPi0XY, errImpactParameterPi0XY); + kfCharmBachelor1Upd.GetDistanceFromVertexXY(KFPV, impactParameterPi1XY, errImpactParameterPi1XY); + kfXiUpd.GetDistanceFromVertexXY(KFPV, impactParameterXiXY, errImpactParameterXiXY); + + // calculate cosine of pointing angle + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + double cpaLambda = casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + double cpaXYLambda = RecoDecay::cpaXY(pvCoord, vertexV0, pVecV0); + double cpaXi = casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()); + double cpaXYXi = RecoDecay::cpaXY(pvCoord, vertexCasc, pVecCasc); + + // get DCAs of Pi0-Pi1, Pi0-Xi, Pi1-Xi + float dcaXYPi0Pi1 = kfCharmBachelor0Upd.GetDistanceFromParticleXY(kfCharmBachelor1Upd); + float dcaXYPi0Xi = kfCharmBachelor0Upd.GetDistanceFromParticleXY(kfXiUpd); + float dcaXYPi1Xi = kfCharmBachelor1Upd.GetDistanceFromParticleXY(kfXiUpd); + float dcaPi0Pi1 = kfCharmBachelor0Upd.GetDistanceFromParticle(kfCharmBachelor1Upd); + float dcaPi0Xi = kfCharmBachelor0Upd.GetDistanceFromParticle(kfXiUpd); + float dcaPi1Xi = kfCharmBachelor1Upd.GetDistanceFromParticle(kfXiUpd); + + // mass of Xi-Pi0 pair + KFParticle kfXiPi0; + float errMassXiPi0; + const KFParticle* kfXiResonanceDaughtersPi0[2] = {&kfXi, &kfCharmBachelor0}; + kfXiPi0.SetConstructMethod(kfConstructMethod); + try { + kfXiPi0.Construct(kfXiResonanceDaughtersPi0, 2); + } catch (...) { + LOG(info) << "Failed to construct Xi(1530) with Pi 0"; + } + kfXiPi0.GetMass(massXiPi0, errMassXiPi0); + + // mass of Xi-Pi1 pair + KFParticle kfXiPi1; + float errMassXiPi1; + const KFParticle* kfXiResonanceDaughtersPi1[2] = {&kfXi, &kfCharmBachelor1}; + kfXiPi1.SetConstructMethod(kfConstructMethod); + try { + kfXiPi1.Construct(kfXiResonanceDaughtersPi1, 2); + } catch (...) { + LOG(info) << "Failed to construct Xi(1530) with Pi 1"; + } + kfXiPi1.GetMass(massXiPi1, errMassXiPi1); + + // get invariant mass of Xic candidate + float errMassXiPiPi; + kfXicPlus.GetMass(massXiPiPi, errMassXiPiPi); + + //-------------------------------fill histograms-------------------------------------------- + if (fillHistograms) { + // invariant mass + registry.fill(HIST("hMass3"), massXiPiPi); + // covariance matrix elements of PV + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + registry.fill(HIST("hCovPVYY"), covMatrixPV[2]); + registry.fill(HIST("hCovPVXZ"), covMatrixPV[3]); + registry.fill(HIST("hCovPVZZ"), covMatrixPV[5]); + // covariance matrix elements of SV + registry.fill(HIST("hCovSVXX"), covMatrixXicPlus[0]); + registry.fill(HIST("hCovSVYY"), covMatrixXicPlus[2]); + registry.fill(HIST("hCovSVXZ"), covMatrixXicPlus[3]); + registry.fill(HIST("hCovSVZZ"), covMatrixXicPlus[5]); + // DCAs of prongs + registry.fill(HIST("hDcaXYProngs"), kfXi.GetPt(), impactParameterXiXY); + registry.fill(HIST("hDcaXYProngs"), kfCharmBachelor0.GetPt(), impactParameterPi0XY); + registry.fill(HIST("hDcaXYProngs"), kfCharmBachelor1.GetPt(), impactParameterPi1XY); + } + + //------------------------------fill candidate table rows-------------------------------------- + rowCandidateBase(collision.globalIndex(), + KFPV.GetX(), KFPV.GetY(), KFPV.GetZ(), + covMatrixPV[0], covMatrixPV[2], covMatrixPV[5], + /*3-prong specific columns*/ + rowTrackIndexXicPlus.cascadeId(), rowTrackIndexXicPlus.prong0Id(), rowTrackIndexXicPlus.prong1Id(), + casc.bachelorId(), casc.posTrackId(), casc.negTrackId(), + kfXicPlus.GetX(), kfXicPlus.GetY(), kfXicPlus.GetZ(), + kfXicPlus.GetErrX(), kfXicPlus.GetErrY(), kfXicPlus.GetErrZ(), + kfXicPlus.GetErrDecayLength(), kfXicPlus.GetErrDecayLengthXY(), + chi2GeoXicPlus, massXiPiPi, signXic, + kfXi.GetPx(), kfXi.GetPy(), kfXi.GetPz(), + kfCharmBachelor0.GetPx(), kfCharmBachelor0.GetPy(), kfCharmBachelor0.GetPz(), + kfCharmBachelor1.GetPx(), kfCharmBachelor1.GetPy(), kfCharmBachelor1.GetPz(), + impactParameterXiXY, impactParameterPi0XY, impactParameterPi1XY, + errImpactParameterXiXY, errImpactParameterPi0XY, errImpactParameterPi1XY, + /*cascade specific columns*/ + casc.x(), casc.y(), casc.z(), + casc.xlambda(), casc.ylambda(), casc.zlambda(), + cpaXi, cpaXYXi, cpaLambda, cpaXYLambda, + massXiPi0, massXiPi1); + rowCandidateKF(casc.kfCascadeChi2(), casc.kfV0Chi2(), chi2topoXicPlusPV, chi2topoXiToXicPlus, + dcaXYPi0Pi1, dcaXYPi0Xi, dcaXYPi1Xi, + dcaPi0Pi1, dcaPi0Xi, dcaPi1Xi, + casc.dcacascdaughters()); + } // loop over track triplets + } + PROCESS_SWITCH(HfCandidateCreatorXicToXiPiPi, processXicplusWithKFParticle, "Run candidate creator with KFParticle using derived data from HfTrackIndexSkimCreatorLfCascades.", false); +}; // struct + +/// Performs MC matching. +struct HfCandidateCreatorXicToXiPiPiExpressions { + Spawns rowCandidateXic; + Produces rowMcMatchRec; + Produces rowMcMatchGen; + + void init(InitContext const&) {} + + void processMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) + { + rowCandidateXic->bindExternalIndices(&tracks); + + int indexRec = -1; + int indexRecXicPlus = -1; + int8_t sign = 0; + int8_t flag = 0; + int8_t origin = 0; + int8_t debug = 0; + // for resonance matching: + std::vector arrDaughIndex; + std::array arrPDGDaugh; + std::array arrXiResonance = {3324, kPiPlus}; // 3324: Ξ(1530) + + // Match reconstructed candidates. + for (const auto& candidate : *rowCandidateXic) { + flag = 0; + sign = 0; + origin = RecoDecay::OriginType::None; + debug = 0; + arrDaughIndex.clear(); + + auto arrayDaughters = std::array{candidate.pi0_as(), // pi <- Xic + candidate.pi1_as(), // pi <- Xic + candidate.bachelor_as(), // pi <- cascade + candidate.posTrack_as(), // p <- lambda + candidate.negTrack_as()}; // pi <- lambda + auto arrayDaughtersCasc = std::array{candidate.bachelor_as(), + candidate.posTrack_as(), + candidate.negTrack_as()}; + auto arrayDaughtersV0 = std::array{candidate.posTrack_as(), + candidate.negTrack_as()}; + + // Xic → pi pi pi pi p + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, &sign, 4); + indexRecXicPlus = indexRec; + if (indexRec == -1) { + debug = 1; + } + if (indexRec > -1) { + // Xi- → pi pi p + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersCasc, +kXiMinus, std::array{+kPiMinus, +kProton, +kPiMinus}, true, &sign, 2); + if (indexRec == -1) { + debug = 2; + } + if (indexRec > -1) { + // Lambda → p pi + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &sign, 1); + if (indexRec == -1) { + debug = 3; + } + if (indexRec > -1) { + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRecXicPlus), &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPDGDaugh[0] == arrXiResonance[0] && arrPDGDaugh[1] == arrXiResonance[1]) || (arrPDGDaugh[0] == arrXiResonance[1] && arrPDGDaugh[1] == arrXiResonance[0])) { + flag = sign * (1 << aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi); + } else { + debug = 4; + } + } else { + flag = sign * (1 << aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi); + } + } + } + } + + // Check whether the charm baryon is non-prompt (from a b quark). + if (flag != 0) { + auto particle = mcParticles.rawIteratorAt(indexRecXicPlus); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, true); + } + + rowMcMatchRec(flag, debug, origin); + } // close loop over candidates + + // Match generated particles. + for (const auto& particle : mcParticles) { + flag = 0; + sign = 0; + debug = 0; + origin = RecoDecay::OriginType::None; + arrDaughIndex.clear(); + + // Xic → Xi pi pi + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, true, &sign, 2)) { + debug = 1; + // Xi- -> Lambda pi + auto cascMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, cascMC, +kXiMinus, std::array{+kLambda0, +kPiMinus}, true)) { + debug = 2; + // Lambda -> p pi + auto v0MC = mcParticles.rawIteratorAt(cascMC.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, v0MC, +kLambda0, std::array{+kProton, +kPiMinus}, true)) { + debug = 3; + + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPDGDaugh[0] == arrXiResonance[0] && arrPDGDaugh[1] == arrXiResonance[1]) || (arrPDGDaugh[0] == arrXiResonance[1] && arrPDGDaugh[1] == arrXiResonance[0])) { + flag = sign * (1 << aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi); + } else { + debug = 4; + } + } else { + flag = sign * (1 << aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi); + } + } + } + } + + // Check whether the charm baryon is non-prompt (from a b quark). + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, true); + } + + rowMcMatchGen(flag, debug, origin); + } // close loop over generated particles + } // close process + PROCESS_SWITCH(HfCandidateCreatorXicToXiPiPiExpressions, processMc, "Process MC", false); +}; // close struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/candidateSelectorD0.cxx b/PWGHF/TableProducer/candidateSelectorD0.cxx index 3254d513237..9164cf42d41 100644 --- a/PWGHF/TableProducer/candidateSelectorD0.cxx +++ b/PWGHF/TableProducer/candidateSelectorD0.cxx @@ -26,6 +26,7 @@ #include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" using namespace o2; using namespace o2::analysis; @@ -72,6 +73,8 @@ struct HfCandidateSelectorD0 { Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_D0ToKPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + // Mass Cut for trigger analysis + Configurable useTriggerMassCut{"useTriggerMassCut", false, "Flag to enable parametrize pT differential mass cut for triggered data"}; o2::analysis::HfMlResponseD0ToKPi hfMlResponse; std::vector outputMlD0 = {}; @@ -80,6 +83,7 @@ struct HfCandidateSelectorD0 { TrackSelectorPi selectorPion; TrackSelectorKa selectorKaon; HfHelper hfHelper; + HfTrigger2ProngCuts hfTriggerCuts; using TracksSel = soa::Join; @@ -158,7 +162,9 @@ struct HfCandidateSelectorD0 { return false; } // candidate DCA - // if (candidate.chi2PCA() > cuts[pTBin][1]) return false; + if (std::abs(candidate.impactParameterXY()) > cuts->get(pTBin, "DCA")) { + return false; + } // candidate topological chi2 over ndf when using KFParticle, need to add this selection to the SelectorCuts.h // if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -209,10 +215,16 @@ struct HfCandidateSelectorD0 { if (std::abs(massD0 - o2::constants::physics::MassD0) > cuts->get(pTBin, "m")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(massD0, o2::constants::physics::MassD0, candidate.pt(), hfTriggerCuts)) { + return false; + } } else { if (std::abs(massD0bar - o2::constants::physics::MassD0) > cuts->get(pTBin, "m")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(massD0bar, o2::constants::physics::MassD0, candidate.pt(), hfTriggerCuts)) { + return false; + } } // cut on daughter pT diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index 326833bfa08..b911656d114 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -25,6 +25,7 @@ #include "PWGHF/Core/HfMlResponseDplusToPiKPi.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" using namespace o2; using namespace o2::analysis; @@ -72,14 +73,17 @@ struct HfCandidateSelectorDplusToPiKPi { Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_DPlusToKPiPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + // Mass Cut for trigger analysis + Configurable useTriggerMassCut{"useTriggerMassCut", false, "Flag to enable parametrize pT differential mass cut for triggered data"}; - o2::analysis::HfMlResponseDplusToPiKPi hfMlResponse; + HfMlResponseDplusToPiKPi hfMlResponse; std::vector outputMlNotPreselected = {}; std::vector outputMl = {}; o2::ccdb::CcdbApi ccdbApi; TrackSelectorPi selectorPion; TrackSelectorKa selectorKaon; HfHelper hfHelper; + HfTrigger3ProngCuts hfTriggerCuts; using TracksSel = soa::Join; @@ -132,13 +136,13 @@ struct HfCandidateSelectorDplusToPiKPi { template bool selection(const T1& candidate, const T2& trackPion1, const T2& trackKaon, const T2& trackPion2) { - auto candpT = candidate.pt(); - int pTBin = findBin(binsPt, candpT); + auto ptCand = candidate.pt(); + int pTBin = findBin(binsPt, ptCand); if (pTBin == -1) { return false; } // check that the candidate pT is within the analysis range - if (candpT < ptCandMin || candpT > ptCandMax) { + if (ptCand < ptCandMin || ptCand > ptCandMax) { return false; } // cut on daughter pT @@ -149,6 +153,9 @@ struct HfCandidateSelectorDplusToPiKPi { if (std::abs(hfHelper.invMassDplusToPiKPi(candidate) - o2::constants::physics::MassDPlus) > cuts->get(pTBin, "deltaM")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(hfHelper.invMassDplusToPiKPi(candidate), o2::constants::physics::MassDPlus, ptCand, hfTriggerCuts)) { + return false; + } if (candidate.decayLength() < cuts->get(pTBin, "decay length")) { return false; } diff --git a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx index c32ffdfd711..9720f270469 100644 --- a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx @@ -52,6 +52,8 @@ struct HfCandidateSelectorDsToKKPi { // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_ds_to_k_k_pi::cuts[0], hf_cuts_ds_to_k_k_pi::nBinsPt, hf_cuts_ds_to_k_k_pi::nCutVars, hf_cuts_ds_to_k_k_pi::labelsPt, hf_cuts_ds_to_k_k_pi::labelsCutVar}, "Ds candidate selection per pT bin"}; + Configurable rejectCandsInDplusToPiKPiRegion{"rejectCandsInDplusToPiKPiRegion", false, "Flag to reject candidates in the D+ to PiKPi signal region"}; + Configurable deltaMRegionDplusToPiKPi{"deltaMRegionDplusToPiKPi", 0.03, "Width of the D+ to PiKPi signal region (GeV/c^2)"}; // DCAxy and DCAz selections Configurable> cutsSingleTrack{"cutsSingleTrack", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections"}; // pT bins for single-track cuts @@ -172,6 +174,9 @@ struct HfCandidateSelectorDsToKKPi { if (!isSelectedCandidateProngDca(candidate)) { return false; } + if (rejectCandsInDplusToPiKPiRegion && std::abs(hfHelper.invMassDplusToPiKPi(candidate) - o2::constants::physics::MassDPlus) < deltaMRegionDplusToPiKPi) { + return false; + } return true; } diff --git a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx index 7f7f8501863..777b095fcbb 100644 --- a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx @@ -45,6 +45,8 @@ struct HfCandidateSelectorDstarToD0Pi { Configurable ptD0CandMax{"ptD0CandMax", 50., "Maximum D0 candidate pT"}; Configurable> binsPtD0{"binsPtD0", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for D0"}; Configurable> cutsD0{"cutsD0", {hf_cuts_d0_to_pi_k::cuts[0], hf_cuts_d0_to_pi_k::nBinsPt, hf_cuts_d0_to_pi_k::nCutVars, hf_cuts_d0_to_pi_k::labelsPt, hf_cuts_d0_to_pi_k::labelsCutVar}, "D0 candidate selection per pT bin"}; + // Mass Cut for trigger analysis + Configurable useTriggerMassCut{"useTriggerMassCut", false, "Flag to enable parametrize pT differential mass cut for triggered data"}; // Configurable specific to Dstar Configurable ptDstarCandMin{"ptDstarCandMin", 0., "Minimum Dstar candidate pT"}; @@ -108,6 +110,8 @@ struct HfCandidateSelectorDstarToD0Pi { AxisSpec axisSelStatus{2, -0.5f, 1.5f}; HistogramRegistry registry{"registry"}; + HfTrigger2ProngCuts hfTriggerCuts; + void init(InitContext&) { massPi = MassPiPlus; @@ -282,6 +286,9 @@ struct HfCandidateSelectorDstarToD0Pi { if (std::abs(mInvD0 - massD0) > cutsD0->get(binPt, "m")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(mInvD0, massD0, candidate.ptD0(), hfTriggerCuts)) { + return false; + } // cut on daughter pT auto d0prong0 = candidate.template prong0_as(); auto d0prong1 = candidate.template prong1_as(); @@ -307,6 +314,9 @@ struct HfCandidateSelectorDstarToD0Pi { if (std::abs(mInvD0Bar - massD0) > cutsD0->get(binPt, "m")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(mInvD0Bar, massD0, candidate.ptD0(), hfTriggerCuts)) { + return false; + } // cut on daughter pT auto d0prong0 = candidate.template prong0_as(); auto d0prong1 = candidate.template prong1_as(); diff --git a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx index 10f2873dd1e..d9b1872e83e 100644 --- a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx @@ -18,6 +18,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -48,11 +50,14 @@ struct HfCandidateSelectorLbToLcPi { Configurable impactParameterMaximum{"impactParameterMaximum", 0.2, "Maximum impact parameter for single tracks"}; Configurable maxDecayLengthError{"maxDecayLengthError", 0.015, "decay length error quality selection"}; Configurable maxDecayLengthXYError{"maxDecayLengthXYError", 0.01, "decay length xy error quality selection"}; + Configurable maxVertexDistanceLbLc{"maxVertexDistanceLbLc", 0.05, "maximum distance between Lb and Lc vertex"}; Configurable> cuts{"cuts", {hf_cuts_lb_to_lc_pi::cuts[0], hf_cuts_lb_to_lc_pi::nBinsPt, hf_cuts_lb_to_lc_pi::nCutVars, hf_cuts_lb_to_lc_pi::labelsPt, hf_cuts_lb_to_lc_pi::labelsCutVar}, "Lb0 candidate selection per pT bin"}; Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc+"}; HfHelper hfHelper; + using TracksWExt = soa::Join; + bool passesImpactParameterResolution(float pT, float d0Resolution) { float expectedResolution(0.001 + 0.0052 * exp(-0.655 * pT)); @@ -138,12 +143,21 @@ struct HfCandidateSelectorLbToLcPi { return false; } + // distance between Lb and Lc decay + float diffXVert = hfCandLb.xSecondaryVertex() - hfCandLc.xSecondaryVertex(); + float diffYVert = hfCandLb.ySecondaryVertex() - hfCandLc.ySecondaryVertex(); + float diffZVert = hfCandLb.zSecondaryVertex() - hfCandLc.zSecondaryVertex(); + float vertexDistance = sqrt(diffXVert * diffXVert + diffYVert * diffYVert + diffZVert * diffZVert); + if (vertexDistance > maxVertexDistanceLbLc) { + return false; + } + return true; } void process(aod::HfCandLb const& hfCandLbs, soa::Join const&, - aod::Tracks const&) + TracksWExt const&) { for (const auto& hfCandLb : hfCandLbs) { // looping over Lb candidates @@ -159,12 +173,12 @@ struct HfCandidateSelectorLbToLcPi { // Lc is always index0 and pi is index1 by default // auto candLc = hfCandLb.prong0(); auto candLc = hfCandLb.prong0_as>(); - auto trackPi = hfCandLb.prong1(); + auto trackPi = hfCandLb.prong1_as(); // Check that the impact parameter resolution is not too far from the typical - auto track0 = candLc.prong0_as(); - auto track1 = candLc.prong1_as(); - auto track2 = candLc.prong2_as(); + auto track0 = candLc.prong0_as(); + auto track1 = candLc.prong1_as(); + auto track2 = candLc.prong2_as(); float reso0 = candLc.errorImpactParameter0(); float reso1 = candLc.errorImpactParameter1(); float reso2 = candLc.errorImpactParameter2(); @@ -186,6 +200,20 @@ struct HfCandidateSelectorLbToLcPi { continue; } + // PID selection for pion + if (trackPi.pt() > ptPidTpcMin && trackPi.pt() < ptPidTpcMax) { + if (std::abs(trackPi.tpcNSigmaPi()) > nSigmaTpcMax) { + hfSelLbToLcPiCandidate(statusLb); + continue; + } + } + if (trackPi.pt() > ptPidTofMin && trackPi.pt() < ptPidTofMax) { + if (std::abs(trackPi.tofNSigmaPi()) > nSigmaTofMax) { + hfSelLbToLcPiCandidate(statusLb); + continue; + } + } + hfSelLbToLcPiCandidate(1); // LOGF(debug, "Lb candidate selection successful, candidate should be selected"); } diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx index 12f2dddc6f6..b523f8bd7a4 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx @@ -129,6 +129,7 @@ struct HfCandidateSelectorToOmegaKa { TrackSelectorKa selectorKaon; using TracksSel = soa::Join; + using TracksSelLf = soa::Join; HistogramRegistry registry{"registry"}; // for QA of selections @@ -194,7 +195,8 @@ struct HfCandidateSelectorToOmegaKa { } void process(aod::HfCandToOmegaK const& candidates, - TracksSel const&) + TracksSel const& tracks, + TracksSelLf const& lfTracks) { // looping over charm baryon candidates @@ -202,10 +204,14 @@ struct HfCandidateSelectorToOmegaKa { bool resultSelections = true; // True if the candidate passes all the selections, False otherwise - auto trackV0PosDau = candidate.posTrack_as(); // positive V0 daughter - auto trackV0NegDau = candidate.negTrack_as(); // negative V0 daughter - auto trackKaFromCasc = candidate.bachelor_as(); // kaon <- cascade - auto trackKaFromCharm = candidate.bachelorFromCharmBaryon_as(); // kaon <- charm baryon + auto trackV0PosDauId = candidate.posTrackId(); // positive V0 daughter + auto trackV0NegDauId = candidate.negTrackId(); // negative V0 daughter + auto trackKaFromCascId = candidate.bachelorId(); // kaon <- cascade + auto trackKaFromCharmId = candidate.bachelorFromCharmBaryonId(); // pion <- charm baryon + auto trackV0PosDau = lfTracks.rawIteratorAt(trackV0PosDauId); + auto trackV0NegDau = lfTracks.rawIteratorAt(trackV0NegDauId); + auto trackKaFromCasc = lfTracks.rawIteratorAt(trackKaFromCascId); + auto trackKaFromCharm = tracks.rawIteratorAt(trackKaFromCharmId); auto trackPiFromLam = trackV0NegDau; auto trackPrFromLam = trackV0PosDau; @@ -302,7 +308,7 @@ struct HfCandidateSelectorToOmegaKa { } // dcaXY v0 daughters to PV cut - if (candidate.dcaXYToPvV0Dau0() < dcaPosToPvMin || candidate.dcaXYToPvV0Dau1() < dcaNegToPvMin) { + if (std::abs(candidate.dcaXYToPvV0Dau0()) < dcaPosToPvMin || std::abs(candidate.dcaXYToPvV0Dau1()) < dcaNegToPvMin) { resultSelections = false; registry.fill(HIST("hSelDcaXYToPvV0Daughters"), 0); } else { @@ -310,7 +316,7 @@ struct HfCandidateSelectorToOmegaKa { } // dcaXY ka <-- cascade to PV cut - if (candidate.dcaXYToPvCascDau() < dcaBachToPvMin) { + if (std::abs(candidate.dcaXYToPvCascDau()) < dcaBachToPvMin) { resultSelections = false; registry.fill(HIST("hSelDcaXYToPvKaFromCasc"), 0); } else { diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx index 2ecc7afc038..129887ed876 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx @@ -129,6 +129,7 @@ struct HfCandidateSelectorToOmegaPi { TrackSelectorKa selectorKaon; using TracksSel = soa::Join; + using TracksSelLf = soa::Join; HistogramRegistry registry{"registry"}; // for QA of selections @@ -194,17 +195,22 @@ struct HfCandidateSelectorToOmegaPi { } void process(aod::HfCandToOmegaPi const& candidates, - TracksSel const&) + TracksSel const& tracks, + TracksSelLf const& lfTracks) { // looping over charm baryon candidates for (const auto& candidate : candidates) { bool resultSelections = true; // True if the candidate passes all the selections, False otherwise - auto trackV0PosDau = candidate.posTrack_as(); // positive V0 daughter - auto trackV0NegDau = candidate.negTrack_as(); // negative V0 daughter - auto trackKaFromCasc = candidate.bachelor_as(); // kaon <- cascade - auto trackPiFromCharm = candidate.bachelorFromCharmBaryon_as(); // pion <- charm baryon + auto trackV0PosDauId = candidate.posTrackId(); // positive V0 daughter + auto trackV0NegDauId = candidate.negTrackId(); // negative V0 daughter + auto trackKaFromCascId = candidate.bachelorId(); // kaon <- cascade + auto trackPiFromCharmId = candidate.bachelorFromCharmBaryonId(); // pion <- charm baryon + auto trackV0PosDau = lfTracks.rawIteratorAt(trackV0PosDauId); + auto trackV0NegDau = lfTracks.rawIteratorAt(trackV0NegDauId); + auto trackKaFromCasc = lfTracks.rawIteratorAt(trackKaFromCascId); + auto trackPiFromCharm = tracks.rawIteratorAt(trackPiFromCharmId); auto trackPiFromLam = trackV0NegDau; auto trackPrFromLam = trackV0PosDau; @@ -301,7 +307,7 @@ struct HfCandidateSelectorToOmegaPi { } // dcaXY v0 daughters to PV cut - if (candidate.dcaXYToPvV0Dau0() < dcaPosToPvMin || candidate.dcaXYToPvV0Dau1() < dcaNegToPvMin) { + if (std::abs(candidate.dcaXYToPvV0Dau0()) < dcaPosToPvMin || std::abs(candidate.dcaXYToPvV0Dau1()) < dcaNegToPvMin) { resultSelections = false; registry.fill(HIST("hSelDcaXYToPvV0Daughters"), 0); } else { @@ -309,7 +315,7 @@ struct HfCandidateSelectorToOmegaPi { } // dcaXY ka <-- cascade to PV cut - if (candidate.dcaXYToPvCascDau() < dcaBachToPvMin) { + if (std::abs(candidate.dcaXYToPvCascDau()) < dcaBachToPvMin) { resultSelections = false; registry.fill(HIST("hSelDcaXYToPvKaFromCasc"), 0); } else { diff --git a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx index eff8377e44a..20fb96ece0b 100644 --- a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx @@ -118,6 +118,7 @@ struct HfCandidateSelectorToXiPi { TrackSelectorPr selectorProton; using TracksSel = soa::Join; + using TracksSelLf = soa::Join; HistogramRegistry registry{"registry"}; // for QA of selections @@ -176,7 +177,8 @@ struct HfCandidateSelectorToXiPi { } void process(aod::HfCandToXiPi const& candidates, - TracksSel const&) + TracksSel const& tracks, + TracksSelLf const& lfTracks) { double massLambdaFromPDG = o2::constants::physics::MassLambda0; @@ -187,10 +189,14 @@ struct HfCandidateSelectorToXiPi { bool resultSelections = true; // True if the candidate passes all the selections, False otherwise - auto trackV0PosDau = candidate.posTrack_as(); // positive V0 daughter - auto trackV0NegDau = candidate.negTrack_as(); // negative V0 daughter - auto trackPiFromCasc = candidate.bachelor_as(); // pion <- cascade - auto trackPiFromCharm = candidate.bachelorFromCharmBaryon_as(); // pion <- charm baryon + auto trackV0PosDauId = candidate.posTrackId(); // positive V0 daughter + auto trackV0NegDauId = candidate.negTrackId(); // negative V0 daughter + auto trackPiFromCascId = candidate.bachelorId(); // pion <- cascade + auto trackPiFromCharmId = candidate.bachelorFromCharmBaryonId(); // pion <- charm baryon + auto trackV0PosDau = lfTracks.rawIteratorAt(trackV0PosDauId); + auto trackV0NegDau = lfTracks.rawIteratorAt(trackV0NegDauId); + auto trackPiFromCasc = lfTracks.rawIteratorAt(trackPiFromCascId); + auto trackPiFromCharm = tracks.rawIteratorAt(trackPiFromCharmId); auto trackPiFromLam = trackV0NegDau; auto trackPrFromLam = trackV0PosDau; @@ -287,7 +293,7 @@ struct HfCandidateSelectorToXiPi { } // dcaXY v0 daughters to PV cut - if (candidate.dcaXYToPvV0Dau0() < dcaPosToPvMin || candidate.dcaXYToPvV0Dau1() < dcaNegToPvMin) { + if (std::abs(candidate.dcaXYToPvV0Dau0()) < dcaPosToPvMin || std::abs(candidate.dcaXYToPvV0Dau1()) < dcaNegToPvMin) { resultSelections = false; registry.fill(HIST("hSelDcaXYToPvV0Daughters"), 0); } else { @@ -295,7 +301,7 @@ struct HfCandidateSelectorToXiPi { } // dcaXY pi <-- cascade to PV cut - if (candidate.dcaXYToPvCascDau() < dcaBachToPvMin) { + if (std::abs(candidate.dcaXYToPvCascDau()) < dcaBachToPvMin) { resultSelections = false; registry.fill(HIST("hSelDcaXYToPvPiFromCasc"), 0); } else { diff --git a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx new file mode 100644 index 00000000000..a1a76ac86ea --- /dev/null +++ b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx @@ -0,0 +1,252 @@ +// Copyright 2019-2020 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. + +/// \file candidateSelectorXicToXiPiPi.cxx +/// \brief Ξc± → Ξ∓ π± π± candidate selector +/// +/// \author Phil Lennart Stahlhut , Heidelberg University + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" // findBin function + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +struct HfCandidateSelectorXicToXiPiPi { + Produces hfSelXicToXiPiPiCandidate; + + Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; + Configurable ptCandMax{"ptCandMax", 36., "Upper bound of candidate pT"}; + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_xi_pi_pi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_xic_to_xi_pi_pi::cuts[0], hf_cuts_xic_to_xi_pi_pi::nBinsPt, hf_cuts_xic_to_xi_pi_pi::nCutVars, hf_cuts_xic_to_xi_pi_pi::labelsPt, hf_cuts_xic_to_xi_pi_pi::labelsCutVar}, "Xicplus candidate selection per pT bin"}; + // QA switch + Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // Enable PID + Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + + TrackSelectorPi selectorPion; + TrackSelectorPr selectorProton; + + using TracksPidWithSel = soa::Join; + + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + if (usePid) { + // pion + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + // proton + selectorProton.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorProton.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorProton.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorProton.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorProton.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorProton.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + if (activateQA) { + constexpr int kNBinsSelections = 1 + SelectionStep::NSelectionSteps; + std::string labels[kNBinsSelections]; + labels[0] = "No selection"; + labels[1 + SelectionStep::RecoSkims] = "Skims selection"; + labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; + labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + labels[1 + SelectionStep::RecoMl] = "Skims & Topological & PID & ML selections"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } + } + + /// Conjugate-independent topological cuts + /// \param candidate is candidate + /// \return true if candidate passes all cuts + template + bool selectionTopol(const T1& hfCandXic) + { + auto candpT = hfCandXic.pt(); + int pTBin = findBin(binsPt, candpT); + if (pTBin == -1) { + return false; + } + + // check that the candidate pT is within the analysis range + if (candpT < ptCandMin || candpT >= ptCandMax) { + return false; + } + + // check candidate mass is within a defined mass window + if (std::abs(hfCandXic.invMassXic() - o2::constants::physics::MassXiCPlus) > cuts->get(pTBin, "m")) { + return false; + } + + // cosine of pointing angle + if (hfCandXic.cpa() <= cuts->get(pTBin, "cos pointing angle")) { + return false; + } + + // cosine of pointing angle XY + if (hfCandXic.cpaXY() <= cuts->get(pTBin, "cos pointing angle XY")) { + return false; + } + + // candidate maximum decay length + if (hfCandXic.decayLength() > cuts->get(pTBin, "max decay length")) { + return false; + } + + // candidate maximum decay length XY + if (hfCandXic.decayLengthXY() > cuts->get(pTBin, "max decay length XY")) { + return false; + } + + // candidate chi2PC + if (hfCandXic.chi2PCA() > cuts->get(pTBin, "chi2PCA")) { + return false; + } + + // maximum DCA of daughters + if ((std::abs(hfCandXic.impactParameter0()) > cuts->get(pTBin, "max impParXY Xi")) || + (std::abs(hfCandXic.impactParameter1()) > cuts->get(pTBin, "max impParXY Pi0")) || + (std::abs(hfCandXic.impactParameter2()) > cuts->get(pTBin, "max impParXY Pi1"))) { + return false; + } + + // cut on daughter pT + if (hfCandXic.ptProng0() < cuts->get(pTBin, "pT Xi") || + hfCandXic.ptProng1() < cuts->get(pTBin, "pT Pi0") || + hfCandXic.ptProng2() < cuts->get(pTBin, "pT Pi1")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackPi0 PID status of trackPi0 (prong1 of Xic candidate) + /// \param pidTrackPi1 PID status of trackPi1 (prong2 of Xic candidate) + /// \param pidTrackPr PID status of trackPr (positive daughter of V0 candidate) + /// \param pidTrackPiLam PID status of trackPiLam (negative daughter of V0 candidate) + /// \param pidTrackPiXi PID status of trackPiXi (Bachelor of cascade candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prongs of Xic candidate pass all selections + bool selectionPid(TrackSelectorPID::Status const pidTrackPi0, + TrackSelectorPID::Status const pidTrackPi1, + TrackSelectorPID::Status const pidTrackPr, + TrackSelectorPID::Status const pidTrackPiLam, + TrackSelectorPID::Status const pidTrackPiXi, + bool const acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && (pidTrackPi0 != TrackSelectorPID::Accepted || pidTrackPi1 != TrackSelectorPID::Accepted || pidTrackPr != TrackSelectorPID::Accepted || pidTrackPiLam != TrackSelectorPID::Accepted || pidTrackPiXi != TrackSelectorPID::Accepted)) { + return false; + } + if (acceptPIDNotApplicable && (pidTrackPi0 == TrackSelectorPID::Rejected || pidTrackPi1 == TrackSelectorPID::Rejected || pidTrackPr == TrackSelectorPID::Rejected || pidTrackPiLam == TrackSelectorPID::Rejected || pidTrackPiXi == TrackSelectorPID::Rejected)) { + return false; + } + return true; + } + + void process(aod::HfCandXic const& hfCandsXic, + TracksPidWithSel const&) + { + for (const auto& hfCandXic : hfCandsXic) { + int statusXicToXiPiPi = 0; + auto ptCandXic = hfCandXic.pt(); + + if (activateQA) { + registry.fill(HIST("hSelections"), 1, ptCandXic); + } + + // No hfFlag -> by default skim selected + SETBIT(statusXicToXiPiPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusXicToXiPiPi = 1 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandXic); + } + + // topological cuts + if (!selectionTopol(hfCandXic)) { + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + continue; + } + SETBIT(statusXicToXiPiPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusXicToXiPiPi = 3 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandXic); + } + + // track-level PID selection + if (usePid) { + auto trackPi0 = hfCandXic.pi0_as(); + auto trackPi1 = hfCandXic.pi1_as(); + auto trackV0PosDau = hfCandXic.posTrack_as(); + auto trackV0NegDau = hfCandXic.negTrack_as(); + auto trackPiFromXi = hfCandXic.bachelor_as(); + // assign proton and pion hypothesis to V0 daughters + auto trackPr = trackV0PosDau; + auto trackPiFromLam = trackV0NegDau; + if (hfCandXic.sign() < 0) { + trackPr = trackV0NegDau; + trackPiFromLam = trackV0PosDau; + } + // PID info + TrackSelectorPID::Status pidTrackPi0 = selectorPion.statusTpcAndTof(trackPi0); + TrackSelectorPID::Status pidTrackPi1 = selectorPion.statusTpcAndTof(trackPi1); + TrackSelectorPID::Status pidTrackPr = selectorProton.statusTpcAndTof(trackPr); + TrackSelectorPID::Status pidTrackPiLam = selectorPion.statusTpcAndTof(trackPiFromLam); + TrackSelectorPID::Status pidTrackPiXi = selectorPion.statusTpcAndTof(trackPiFromXi); + + if (!selectionPid(pidTrackPi0, pidTrackPi1, pidTrackPr, pidTrackPiLam, pidTrackPiXi, acceptPIDNotApplicable.value)) { + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + continue; + } + SETBIT(statusXicToXiPiPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusXicToXiPiPi = 7 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandXic); + } + } + + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx index 694d773cf4f..d6dfcd06fcc 100644 --- a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx @@ -204,7 +204,34 @@ struct HfDerivedDataCreatorD0ToKPi { invMass, y); } + if (fillCandidatePar) { + float tpcNSigmaPiExpPi = prong0.tpcNSigmaPi(); + float tofNSigmaPiExpPi = prong0.tofNSigmaPi(); + float tpcTofNSigmaPiExpPi = prong0.tpcTofNSigmaPi(); + float tpcNSigmaKaExpPi = prong0.tpcNSigmaKa(); + float tofNSigmaKaExpPi = prong0.tofNSigmaKa(); + float tpcTofNSigmaKaExpPi = prong0.tpcTofNSigmaKa(); + float tpcNSigmaPiExpKa = prong1.tpcNSigmaPi(); + float tofNSigmaPiExpKa = prong1.tofNSigmaPi(); + float tpcTofNSigmaPiExpKa = prong1.tpcTofNSigmaPi(); + float tpcNSigmaKaExpKa = prong1.tpcNSigmaKa(); + float tofNSigmaKaExpKa = prong1.tofNSigmaKa(); + float tpcTofNSigmaKaExpKa = prong1.tpcTofNSigmaKa(); + if (candFlag == 1) { + tpcNSigmaPiExpPi = prong1.tpcNSigmaPi(); + tofNSigmaPiExpPi = prong1.tofNSigmaPi(); + tpcTofNSigmaPiExpPi = prong1.tpcTofNSigmaPi(); + tpcNSigmaKaExpPi = prong1.tpcNSigmaKa(); + tofNSigmaKaExpPi = prong1.tofNSigmaKa(); + tpcTofNSigmaKaExpPi = prong1.tpcTofNSigmaKa(); + tpcNSigmaPiExpKa = prong0.tpcNSigmaPi(); + tofNSigmaPiExpKa = prong0.tofNSigmaPi(); + tpcTofNSigmaPiExpKa = prong0.tpcTofNSigmaPi(); + tpcNSigmaKaExpKa = prong0.tpcNSigmaKa(); + tofNSigmaKaExpKa = prong0.tofNSigmaKa(); + tpcTofNSigmaKaExpKa = prong0.tpcTofNSigmaKa(); + } rowCandidatePar( candidate.chi2PCA(), candidate.cpa(), @@ -219,18 +246,18 @@ struct HfDerivedDataCreatorD0ToKPi { candidate.impactParameter1(), candidate.impactParameterNormalised0(), candidate.impactParameterNormalised1(), - prong0.tpcNSigmaPi(), - prong0.tpcNSigmaKa(), - prong0.tofNSigmaPi(), - prong0.tofNSigmaKa(), - prong0.tpcTofNSigmaPi(), - prong0.tpcTofNSigmaKa(), - prong1.tpcNSigmaPi(), - prong1.tpcNSigmaKa(), - prong1.tofNSigmaPi(), - prong1.tofNSigmaKa(), - prong1.tpcTofNSigmaPi(), - prong1.tpcTofNSigmaKa(), + tpcNSigmaPiExpPi, + tofNSigmaPiExpPi, + tpcTofNSigmaPiExpPi, + tpcNSigmaKaExpPi, + tofNSigmaKaExpPi, + tpcTofNSigmaKaExpPi, + tpcNSigmaPiExpKa, + tofNSigmaPiExpKa, + tpcTofNSigmaPiExpKa, + tpcNSigmaKaExpKa, + tofNSigmaKaExpKa, + tpcTofNSigmaKaExpKa, candidate.maxNormalisedDeltaIP(), candidate.impactParameterProduct()); } diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index 09b543755ce..fe77bb275d9 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -134,10 +134,10 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { void selectCollision(const Col& collision, const BCs&) { float centrality = -1.; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); if (fillHistograms) { - hfEvSel.fillHistograms(collision, rejectionMask); + hfEvSel.fillHistograms(collision, rejectionMask, centrality); // additional centrality histos if constexpr (centEstimator != o2::hf_centrality::None) { if (rejectionMask == 0) { @@ -2959,13 +2959,11 @@ struct HfTrackIndexSkimCreator { struct HfTrackIndexSkimCreatorCascades { Produces rowTrackIndexCasc; - struct ConfigurableGroup { + struct : ConfigurableGroup { Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; Configurable fillHistograms{"fillHistograms", true, "fill histograms"}; - // event selection - // Configurable triggerindex{"triggerindex", -1, "trigger index"}; // vertexing - // Configurable bz{"bz", 5., "magnetic field"}; + Configurable useDCAFitter{"useDCAFitter", true, "flag to optionally turn on/off the vertex reconstruction with the DCAFitter"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; @@ -2973,24 +2971,12 @@ struct HfTrackIndexSkimCreatorCascades { Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations if chi2/chi2old > this"}; Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", true, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; - // quality cut - Configurable doCutQuality{"doCutQuality", true, "apply quality cuts"}; - // track cuts for bachelor - Configurable tpcRefitBach{"tpcRefitBach", true, "request TPC refit bachelor"}; - Configurable nCrossedRowsMinBach{"nCrossedRowsMinBach", 50, "min crossed rows bachelor"}; // track cuts for V0 daughters - Configurable tpcRefitV0Daugh{"tpcRefitV0Daugh", true, "request TPC refit V0 daughters"}; - Configurable nCrossedRowsMinV0Daugh{"nCrossedRowsMinV0Daugh", 50, "min crossed rows V0 daughters"}; Configurable etaMinV0Daugh{"etaMinV0Daugh", -99999., "min. pseudorapidity V0 daughters"}; Configurable etaMaxV0Daugh{"etaMaxV0Daugh", 1.1, "max. pseudorapidity V0 daughters"}; Configurable ptMinV0Daugh{"ptMinV0Daugh", 0.05, "min. pT V0 daughters"}; - // bachelor cuts - // Configurable dcabachtopv{"dcabachtopv", .1, "DCA Bach To PV"}; - // Configurable ptminbach{"ptminbach", -1., "min. track pT bachelor"}; // v0 cuts - Configurable cpaV0Min{"cpaV0Min", .995, "min. cos PA V0"}; // as in the task that create the V0s - Configurable dcaXYNegToPvMin{"dcaXYNegToPvMin", .1, "min. DCA_XY Neg To PV"}; // check: in HF Run 2, it was 0 at filtering - Configurable dcaXYPosToPvMin{"dcaXYPosToPvMin", .1, "min. DCA_XY Pos To PV"}; // check: in HF Run 2, it was 0 at filtering + Configurable cpaV0Min{"cpaV0Min", 0.95, "min. cos PA V0"}; // as in the task that create the V0s Configurable cutInvMassV0{"cutInvMassV0", 0.05, "V0 candidate invariant mass difference wrt PDG"}; // cascade cuts Configurable ptCascCandMin{"ptCascCandMin", -1., "min. pT of the cascade candidate"}; // PbPb 2018: use 1 @@ -3011,11 +2997,11 @@ struct HfTrackIndexSkimCreatorCascades { Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - int runNumber; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + int runNumber{0}; double massP{0.}; double massK0s{0.}; - double massPi{0.}; double massLc{0.}; using SelectedCollisions = soa::Filtered>; @@ -3042,23 +3028,22 @@ struct HfTrackIndexSkimCreatorCascades { massP = o2::constants::physics::MassProton; massK0s = o2::constants::physics::MassK0Short; - massPi = o2::constants::physics::MassPiPlus; massLc = o2::constants::physics::MassLambdaCPlus; - df2.setPropagateToPCA(config.propagateToPCA); - df2.setMaxR(config.maxR); - df2.setMinParamChange(config.minParamChange); - df2.setMinRelChi2Change(config.minRelChi2Change); - // df2.setMaxDZIni(1e9); // used in cascadeproducer.cxx, but not for the 2 prongs - // df2.setMaxChi2(1e9); // used in cascadeproducer.cxx, but not for the 2 prongs - df2.setUseAbsDCA(config.useAbsDCA); - df2.setWeightedFinalPCA(config.useWeightedFinalPCA); + if (config.useDCAFitter) { + df2.setPropagateToPCA(config.propagateToPCA); + df2.setMaxR(config.maxR); + df2.setMinParamChange(config.minParamChange); + df2.setMinRelChi2Change(config.minRelChi2Change); + df2.setMaxDZIni(config.maxDZIni); + df2.setUseAbsDCA(config.useAbsDCA); + df2.setWeightedFinalPCA(config.useWeightedFinalPCA); + } ccdb->setURL(config.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(config.ccdbPathLut)); - runNumber = 0; if (config.fillHistograms) { registry.add("hVtx2ProngX", "2-prong candidates;#it{x}_{sec. vtx.} (cm);entries", {HistType::kTH1D, {{1000, -2., 2.}}}); @@ -3075,7 +3060,7 @@ struct HfTrackIndexSkimCreatorCascades { PROCESS_SWITCH(HfTrackIndexSkimCreatorCascades, processNoCascades, "Do not skim HF -> V0 cascades", true); void processCascades(SelectedCollisions const& collisions, - aod::V0Datas const& v0s, + soa::Join const& v0s, FilteredTrackAssocSel const& trackIndices, aod::TracksWCovDcaExtra const&, aod::BCsWithTimestamps const&) @@ -3084,67 +3069,52 @@ struct HfTrackIndexSkimCreatorCascades { for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc, runNumber, ccdb, config.isRun2 ? config.ccdbPathGrp : config.ccdbPathGrpMag, lut, config.isRun2); - df2.setBz(o2::base::Propagator::Instance()->getNominalBz()); - - // fist we loop over the bachelor candidate + if (config.useDCAFitter) { + df2.setBz(o2::base::Propagator::Instance()->getNominalBz()); + df2.setMatCorrType(matCorr); + } const auto thisCollId = collision.globalIndex(); auto groupedBachTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto groupedV0s = v0s.sliceBy(v0sPerCollision, thisCollId); - // for (const auto& bach : selectedTracks) { + // fist we loop over the bachelor candidate for (const auto& bachIdx : groupedBachTrackIndices) { auto bach = bachIdx.track_as(); - - // selections on the bachelor - - // pT cut - // FIXME: this should go in the tag-sel-tracks - if (config.tpcRefitBach) { - if (!(bach.trackType() & o2::aod::track::TPCrefit)) { - continue; - } - } - if (bach.tpcNClsCrossedRows() < config.nCrossedRowsMinBach) { - continue; - } - + std::array pVecBach{bach.pVector()}; auto trackBach = getTrackParCov(bach); + if (thisCollId != bach.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it + o2::gpu::gpustd::array dcaInfoBach{bach.dcaXY(), bach.dcaZ()}; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackBach, 2.f, noMatCorr, &dcaInfoBach); + getPxPyPz(trackBach, pVecBach); + } - auto groupedV0s = v0s.sliceBy(v0sPerCollision, thisCollId); // now we loop over the V0s for (const auto& v0 : groupedV0s) { // selections on the V0 daughters - const auto& trackV0DaughPos = v0.posTrack_as(); - const auto& trackV0DaughNeg = v0.negTrack_as(); + const auto& trackV0DaughPos = v0.posTrack_as(); // only used for indices and track cuts (TPC clusters, TPC refit) + const auto& trackV0DaughNeg = v0.negTrack_as(); // only used for indices and track cuts (TPC clusters, TPC refit) // check not to take the same track twice (as bachelor and V0 daughter) if (trackV0DaughPos.globalIndex() == bach.globalIndex() || trackV0DaughNeg.globalIndex() == bach.globalIndex()) { continue; } - if (config.tpcRefitV0Daugh) { - if (!(trackV0DaughPos.trackType() & o2::aod::track::TPCrefit) || - !(trackV0DaughNeg.trackType() & o2::aod::track::TPCrefit)) { - continue; - } - } - if (trackV0DaughPos.tpcNClsCrossedRows() < config.nCrossedRowsMinV0Daugh || - trackV0DaughNeg.tpcNClsCrossedRows() < config.nCrossedRowsMinV0Daugh) { - continue; - } - // - // if (trackV0DaughPos.dcaXY() < dcaXYPosToPvMin || // to the filters? - // trackV0DaughNeg.dcaXY() < dcaXYNegToPvMin) { - // continue; - // } - // - if (trackV0DaughPos.pt() < config.ptMinV0Daugh || // to the filters? I can't for now, it is not in the tables - trackV0DaughNeg.pt() < config.ptMinV0Daugh) { + std::array pVecPos = {v0.pxpos(), v0.pypos(), v0.pzpos()}; + std::array pVecNeg = {v0.pxneg(), v0.pyneg(), v0.pzneg()}; + + float ptPos = RecoDecay::pt(pVecPos); + float ptNeg = RecoDecay::pt(pVecNeg); + if (ptPos < config.ptMinV0Daugh || // to the filters? I can't for now, it is not in the tables + ptNeg < config.ptMinV0Daugh) { continue; } - if ((trackV0DaughPos.eta() > config.etaMaxV0Daugh || trackV0DaughPos.eta() < config.etaMinV0Daugh) || // to the filters? I can't for now, it is not in the tables - (trackV0DaughNeg.eta() > config.etaMaxV0Daugh || trackV0DaughNeg.eta() < config.etaMinV0Daugh)) { + + float etaPos = RecoDecay::eta(pVecPos); + float etaNeg = RecoDecay::eta(pVecNeg); + if ((etaPos > config.etaMaxV0Daugh || etaPos < config.etaMinV0Daugh) || // to the filters? I can't for now, it is not in the tables + (etaNeg > config.etaMaxV0Daugh || etaNeg < config.etaMinV0Daugh)) { continue; } @@ -3158,40 +3128,44 @@ struct HfTrackIndexSkimCreatorCascades { continue; } - const std::array momentumV0 = {v0.px(), v0.py(), v0.pz()}; + std::array pVecV0 = {v0.px(), v0.py(), v0.pz()}; // invariant-mass cut: we do it here, before updating the momenta of bach and V0 during the fitting to save CPU // TODO: but one should better check that the value here and after the fitter do not change significantly!!! - double mass2K0sP = RecoDecay::m(std::array{bach.pVector(), momentumV0}, std::array{massP, massK0s}); + double mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); if ((config.cutInvMassCascLc >= 0.) && (std::abs(mass2K0sP - massLc) > config.cutInvMassCascLc)) { continue; } - auto trackParCovV0DaughPos = getTrackParCov(trackV0DaughPos); - trackParCovV0DaughPos.propagateTo(v0.posX(), o2::base::Propagator::Instance()->getNominalBz()); // propagate the track to the X closest to the V0 vertex - auto trackParCovV0DaughNeg = getTrackParCov(trackV0DaughNeg); - trackParCovV0DaughNeg.propagateTo(v0.negX(), o2::base::Propagator::Instance()->getNominalBz()); // propagate the track to the X closest to the V0 vertex - std::array pVecV0 = {0., 0., 0.}; - std::array pVecBach = {0., 0., 0.}; - - const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; - // we build the neutral track to then build the cascade - auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, {0, 0, 0, 0, 0, 0}, trackParCovV0DaughPos, trackParCovV0DaughNeg); // build the V0 track - // now we find the DCA between the V0 and the bachelor, for the cascade - int nCand2 = 0; - try { - nCand2 = df2.process(trackV0, trackBach); - } catch (...) { - continue; - } + if (config.useDCAFitter) { + + const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; + // we build the neutral track to then build the cascade + std::array covV = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV[MomInd[i]] = v0.momentumCovMat()[i]; + covV[i] = v0.positionCovMat()[i]; + } + auto trackV0 = o2::track::TrackParCov(vertexV0, pVecV0, covV, 0, true); + trackV0.setAbsCharge(0); + trackV0.setPID(o2::track::PID::K0); - if (nCand2 == 0) { - continue; + int nCand2 = 0; + try { + nCand2 = df2.process(trackV0, trackBach); + } catch (...) { + continue; + } + + if (nCand2 == 0) { + continue; + } + df2.propagateTracksToVertex(); // propagate the bach and V0 to the Lc vertex + df2.getTrack(0).getPxPyPzGlo(pVecV0); // take the momentum at the Lc vertex + df2.getTrack(1).getPxPyPzGlo(pVecBach); } - df2.propagateTracksToVertex(); // propagate the bach and V0 to the Lc vertex - df2.getTrack(0).getPxPyPzGlo(pVecV0); // take the momentum at the Lc vertex - df2.getTrack(1).getPxPyPzGlo(pVecBach); // cascade candidate pT cut auto ptCascCand = RecoDecay::pt(pVecBach, pVecV0); @@ -3202,11 +3176,12 @@ struct HfTrackIndexSkimCreatorCascades { // invariant mass // re-calculate invariant masses with updated momenta, to fill the histogram mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); - std::array posCasc = {0., 0., 0.}; - const auto& cascVtx = df2.getPCACandidate(); - for (int i = 0; i < 3; i++) { - posCasc[i] = cascVtx[i]; + if (config.useDCAFitter) { + const auto& cascVtx = df2.getPCACandidate(); + for (int iCoord{0}; iCoord < 3; ++iCoord) { + posCasc[iCoord] = cascVtx[iCoord]; + } } // fill table row diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index d9efc0202a7..f0c1c1503c2 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -244,15 +244,12 @@ DECLARE_SOA_TABLE(HfCandLcFullEvs, "AOD", "HFCANDLCFULLEV", full::MultZeqNTracksPV); DECLARE_SOA_TABLE(HfCandLcFullPs, "AOD", "HFCANDLCFULLP", - full::McCollisionId, full::Pt, full::Eta, full::Phi, full::Y, full::FlagMc, - full::OriginMcGen, - full::McParticleId); - + full::OriginMcGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -502,14 +499,12 @@ struct HfTreeCreatorLcToPKPi { for (const auto& particle : particles) { if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { rowCandidateFullParticles( - particle.mcCollisionId(), particle.pt(), particle.eta(), particle.phi(), RecoDecay::y(particle.pVector(), o2::constants::physics::MassLambdaCPlus), particle.flagMcMatchGen(), - particle.originMcGen(), - particle.globalIndex()); + particle.originMcGen()); } } } diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index d8985b6314a..b91f65cb654 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -48,10 +48,40 @@ using namespace o2::hf_trkcandsel; namespace o2::aod { +namespace hf_st_charmed_baryon_gen +{ +DECLARE_SOA_COLUMN(PxCharmedBaryon, pxCharmedBaryon, float); +DECLARE_SOA_COLUMN(PyCharmedBaryon, pyCharmedBaryon, float); +DECLARE_SOA_COLUMN(PzCharmedBaryon, pzCharmedBaryon, float); +DECLARE_SOA_COLUMN(PdgCodeCharmedBaryon, pdgCodeCharmedBaryon, int); +DECLARE_SOA_COLUMN(PxCasc, pxCasc, float); +DECLARE_SOA_COLUMN(PyCasc, pyCasc, float); +DECLARE_SOA_COLUMN(PzCasc, pzCasc, float); +DECLARE_SOA_COLUMN(PdgCodeCasc, pdgCodeCasc, int); +DECLARE_SOA_COLUMN(DecayLengthCharmedBaryon, decayLengthCharmedBaryon, float); +DECLARE_SOA_COLUMN(DecayLengthXYCharmedBaryon, decayLengthXYCharmedBaryon, float); +DECLARE_SOA_COLUMN(DecayLengthCasc, decayLengthCasc, float); +DECLARE_SOA_COLUMN(DecayLengthXYCasc, decayLengthXYCasc, float); +} // namespace hf_st_charmed_baryon_gen + +DECLARE_SOA_TABLE(HfStChBarGens, "AOD", "HFSTCHBARGEN", + hf_st_charmed_baryon_gen::PxCharmedBaryon, + hf_st_charmed_baryon_gen::PyCharmedBaryon, + hf_st_charmed_baryon_gen::PzCharmedBaryon, + hf_st_charmed_baryon_gen::PdgCodeCharmedBaryon, + hf_st_charmed_baryon_gen::PxCasc, + hf_st_charmed_baryon_gen::PyCasc, + hf_st_charmed_baryon_gen::PzCasc, + hf_st_charmed_baryon_gen::PdgCodeCasc, + hf_st_charmed_baryon_gen::DecayLengthCharmedBaryon, + hf_st_charmed_baryon_gen::DecayLengthXYCharmedBaryon, + hf_st_charmed_baryon_gen::DecayLengthCasc, + hf_st_charmed_baryon_gen::DecayLengthXYCasc); + // CharmedBaryon -> Casc + Pion // -> Lambda + BachPi/BachKa // -> Pr + Pi -namespace st_omegac +namespace hf_st_charmed_baryon { DECLARE_SOA_COLUMN(MassOmega, massOmega, float); DECLARE_SOA_COLUMN(MassXi, massXi, float); @@ -99,90 +129,64 @@ DECLARE_SOA_COLUMN(DecayLengthCharmedBaryon, decayLengthCharmedBaryon, float); DECLARE_SOA_COLUMN(DecayLengthXYCharmedBaryon, decayLengthXYCharmedBaryon, float); DECLARE_SOA_COLUMN(DecayLengthCasc, decayLengthCasc, float); DECLARE_SOA_COLUMN(DecayLengthXYCasc, decayLengthXYCasc, float); -} // namespace st_omegac - -namespace st_omegac_gen -{ -DECLARE_SOA_COLUMN(PxOmegac, pxOmegac, float); -DECLARE_SOA_COLUMN(PyOmegac, pyOmegac, float); -DECLARE_SOA_COLUMN(PzOmegac, pzOmegac, float); -DECLARE_SOA_COLUMN(IsPositiveOmegac, isPositiveOmegac, bool); -DECLARE_SOA_COLUMN(PxOmega, pxOmega, float); -DECLARE_SOA_COLUMN(PyOmega, pyOmega, float); -DECLARE_SOA_COLUMN(PzOmega, pzOmega, float); -DECLARE_SOA_COLUMN(IsPositiveOmega, isPositiveOmega, bool); -DECLARE_SOA_COLUMN(DecayLengthOmegac, decayLengthOmegac, float); -DECLARE_SOA_COLUMN(DecayLengthXYOmegac, decayLengthXYOmegac, float); -DECLARE_SOA_COLUMN(DecayLengthOmega, decayLengthOmega, float); -DECLARE_SOA_COLUMN(DecayLengthXYOmega, decayLengthXYOmega, float); -} // namespace st_omegac_gen - -DECLARE_SOA_TABLE(HfOmegacSt, "AOD", "HFOMEGACST", - st_omegac::MassOmega, - st_omegac::MassXi, - st_omegac::MassLambda, - st_omegac::NSigmaTpcPion, - st_omegac::NSigmaTofPion, - st_omegac::NSigmaTpcV0Pr, - st_omegac::NSigmaTofV0Pr, - st_omegac::NSigmaTpcV0Pi, - st_omegac::NSigmaTofV0Pi, - st_omegac::NSigmaTpcBachPi, - st_omegac::NSigmaTofBachPi, - st_omegac::NSigmaTpcBachKa, - st_omegac::NSigmaTofBachKa, - st_omegac::PxCasc, - st_omegac::PyCasc, - st_omegac::PzCasc, - st_omegac::IsPositiveCasc, - st_omegac::PxPion, - st_omegac::PyPion, - st_omegac::PzPion, - st_omegac::IsPositivePion, - st_omegac::ITSClusterMapPion, - st_omegac::CpaCharmedBaryon, - st_omegac::CpaXYCharmedBaryon, - st_omegac::CpaCasc, - st_omegac::CpaXYCasc, - st_omegac::DcaXYCasc, - st_omegac::DcaXYUncCasc, - st_omegac::DcaZCasc, - st_omegac::DcaZUncCasc, - st_omegac::DcaXYPion, - st_omegac::DcaXYUncPion, - st_omegac::DcaZPion, - st_omegac::DcaZUncPion, - st_omegac::DcaXYPr, - st_omegac::DcaZPr, - st_omegac::DcaXYKa, - st_omegac::DcaZKa, - st_omegac::DcaXYPi, - st_omegac::DcaZPi, - st_omegac::Chi2TopologicalCharmedBaryon, - st_omegac::Chi2TopologicalCasc, - st_omegac::DecayLengthCharmedBaryon, - st_omegac::DecayLengthXYCharmedBaryon, - st_omegac::DecayLengthCasc, - st_omegac::DecayLengthXYCasc); - -DECLARE_SOA_TABLE(HfOmegaStGen, "AOD", "HFOMEGACSTGEN", - st_omegac_gen::PxOmegac, - st_omegac_gen::PyOmegac, - st_omegac_gen::PzOmegac, - st_omegac_gen::IsPositiveOmegac, - st_omegac_gen::PxOmega, - st_omegac_gen::PyOmega, - st_omegac_gen::PzOmega, - st_omegac_gen::IsPositiveOmega, - st_omegac_gen::DecayLengthOmegac, - st_omegac_gen::DecayLengthXYOmegac, - st_omegac_gen::DecayLengthOmega, - st_omegac_gen::DecayLengthXYOmega); +DECLARE_SOA_INDEX_COLUMN_FULL(MotherCasc, motherCasc, int, HfStChBarGens, "_Casc"); +DECLARE_SOA_INDEX_COLUMN_FULL(MotherPion, motherPion, int, HfStChBarGens, "_Pion"); +} // namespace hf_st_charmed_baryon + +DECLARE_SOA_TABLE(HfStChBars, "AOD", "HFSTCHBAR", + hf_st_charmed_baryon::MassOmega, + hf_st_charmed_baryon::MassXi, + hf_st_charmed_baryon::MassLambda, + hf_st_charmed_baryon::NSigmaTpcPion, + hf_st_charmed_baryon::NSigmaTofPion, + hf_st_charmed_baryon::NSigmaTpcV0Pr, + hf_st_charmed_baryon::NSigmaTofV0Pr, + hf_st_charmed_baryon::NSigmaTpcV0Pi, + hf_st_charmed_baryon::NSigmaTofV0Pi, + hf_st_charmed_baryon::NSigmaTpcBachPi, + hf_st_charmed_baryon::NSigmaTofBachPi, + hf_st_charmed_baryon::NSigmaTpcBachKa, + hf_st_charmed_baryon::NSigmaTofBachKa, + hf_st_charmed_baryon::PxCasc, + hf_st_charmed_baryon::PyCasc, + hf_st_charmed_baryon::PzCasc, + hf_st_charmed_baryon::IsPositiveCasc, + hf_st_charmed_baryon::PxPion, + hf_st_charmed_baryon::PyPion, + hf_st_charmed_baryon::PzPion, + hf_st_charmed_baryon::IsPositivePion, + hf_st_charmed_baryon::ITSClusterMapPion, + hf_st_charmed_baryon::CpaCharmedBaryon, + hf_st_charmed_baryon::CpaXYCharmedBaryon, + hf_st_charmed_baryon::CpaCasc, + hf_st_charmed_baryon::CpaXYCasc, + hf_st_charmed_baryon::DcaXYCasc, + hf_st_charmed_baryon::DcaXYUncCasc, + hf_st_charmed_baryon::DcaZCasc, + hf_st_charmed_baryon::DcaZUncCasc, + hf_st_charmed_baryon::DcaXYPion, + hf_st_charmed_baryon::DcaXYUncPion, + hf_st_charmed_baryon::DcaZPion, + hf_st_charmed_baryon::DcaZUncPion, + hf_st_charmed_baryon::DcaXYPr, + hf_st_charmed_baryon::DcaZPr, + hf_st_charmed_baryon::DcaXYKa, + hf_st_charmed_baryon::DcaZKa, + hf_st_charmed_baryon::DcaXYPi, + hf_st_charmed_baryon::DcaZPi, + hf_st_charmed_baryon::Chi2TopologicalCharmedBaryon, + hf_st_charmed_baryon::Chi2TopologicalCasc, + hf_st_charmed_baryon::DecayLengthCharmedBaryon, + hf_st_charmed_baryon::DecayLengthXYCharmedBaryon, + hf_st_charmed_baryon::DecayLengthCasc, + hf_st_charmed_baryon::DecayLengthXYCasc, + hf_st_charmed_baryon::MotherCascId, + hf_st_charmed_baryon::MotherPionId); } // namespace o2::aod struct HfTreeCreatorOmegacSt { - Produces outputTable; - Produces outputTableGen; + Produces outputTable; + Produces outputTableGen; Configurable materialCorrectionType{"materialCorrectionType", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -218,6 +222,7 @@ struct HfTreeCreatorOmegacSt { float bz = 0.; int runNumber{0}; + std::map mapMcPartToGenTable; using Collisions = soa::Filtered>; using TracksExt = soa::Join; @@ -227,8 +232,8 @@ struct HfTreeCreatorOmegacSt { (filterCollisions.node() == 8 && o2::aod::evsel::sel8 == true); // Preslice perCol = aod::track::collisionId; - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Preslice assignedTrackedCascadesPerCollision = aod::track::collisionId; + PresliceUnsorted trackIndicesPerCollision = aod::track_association::collisionId; + PresliceUnsorted assignedTrackedCascadesPerCollision = aod::track::collisionId; std::shared_ptr hCandidatesPrPi, hCandidatesV0Pi, hCandidatesCascPi; HistogramRegistry registry{ @@ -289,30 +294,68 @@ struct HfTreeCreatorOmegacSt { // processData: loop over reconstructed objects, no MC information // processGen: loop over reconstructed objects, use MC information (mutually exclusive? combine?) - void processMc(aod::McCollision const&, + void processMc(aod::McCollisions const&, aod::McParticles const& mcParticles) { + mapMcPartToGenTable.clear(); for (const auto& mcParticle : mcParticles) { - if ((mcParticle.pdgCode() == kOmegaMinus) && - mcParticle.has_mothers() && - (mcParticle.mothers_first_as().pdgCode() == constants::physics::Pdg::kOmegaC0)) { - const auto& mcColl = mcParticle.mcCollision(); - std::array primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; - std::array secondaryVertexGen = {mcParticle.vx(), mcParticle.vy(), mcParticle.vz()}; - const auto decayLengthGen = RecoDecay::distance(secondaryVertexGen, primaryVertexPosGen); - registry.fill(HIST("hDecayLengthScaledMc"), decayLengthGen * o2::constants::physics::MassOmegaC0 / mcParticle.mothers_first_as().p() * 1e4); + const bool isOmegaC = std::abs(mcParticle.pdgCode()) == constants::physics::Pdg::kOmegaC0; + const bool isXiC = std::abs(mcParticle.pdgCode()) == constants::physics::Pdg::kXiC0; + if (isOmegaC || isXiC) { + const auto daughters = mcParticle.daughters_as(); + if (daughters.size() == 2) { + int idxPionDaughter = -1; + int idxCascDaughter = -1; + const auto daughters = mcParticle.daughters_as(); + for (const auto& daughter : daughters) { + if (idxCascDaughter < 0 && (std::abs(daughter.pdgCode()) == (isOmegaC ? kOmegaMinus : kXiMinus))) { + idxCascDaughter = daughter.globalIndex(); + } + if (idxPionDaughter < 0 && (std::abs(daughter.pdgCode()) == kPiPlus)) { + idxPionDaughter = daughter.globalIndex(); + } + } + if ((idxPionDaughter >= 0) && (idxCascDaughter >= 0)) { + const auto& cascDaughter = mcParticles.iteratorAt(idxCascDaughter); + const auto& mcColl = mcParticle.mcCollision(); + std::array primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; + std::array secondaryVertexGen = {cascDaughter.vx(), cascDaughter.vy(), cascDaughter.vz()}; + float decayLengthCascGen = -1.; + float decayLengthXYCascGen = -1.; + if (cascDaughter.has_daughters()) { + const auto& cascDecayDaughter = cascDaughter.daughters_as().iteratorAt(0); + std::array tertiaryVertexGen = {cascDecayDaughter.vx(), cascDecayDaughter.vy(), cascDecayDaughter.vz()}; + decayLengthCascGen = RecoDecay::distance(tertiaryVertexGen, primaryVertexPosGen); + decayLengthXYCascGen = RecoDecay::distanceXY(tertiaryVertexGen, primaryVertexPosGen); + } + const auto decayLengthGen = RecoDecay::distance(secondaryVertexGen, primaryVertexPosGen); + const auto decayLengthXYGen = RecoDecay::distanceXY(secondaryVertexGen, primaryVertexPosGen); + registry.fill(HIST("hDecayLengthScaledMc"), decayLengthGen * o2::constants::physics::MassOmegaC0 / mcParticle.mothers_first_as().p() * 1e4); + outputTableGen( + mcParticle.px(), + mcParticle.py(), + mcParticle.pz(), + mcParticle.pdgCode(), + cascDaughter.px(), + cascDaughter.py(), + cascDaughter.pz(), + cascDaughter.pdgCode(), + decayLengthGen, + decayLengthXYGen, + decayLengthCascGen, + decayLengthXYCascGen); + mapMcPartToGenTable[mcParticle.globalIndex()] = outputTableGen.lastIndex(); + } + } } } } PROCESS_SWITCH(HfTreeCreatorOmegacSt, processMc, "Process MC", true); - void processData(Collisions const& collisions, - aod::AssignedTrackedCascades const& trackedCascades, - aod::TrackAssoc const& trackIndices, - aod::Cascades const&, - aod::V0s const&, - TracksExt const&, - aod::BCsWithTimestamps const&) + template + void fillTable(Collisions const& collisions, + aod::AssignedTrackedCascades const& trackedCascades, + aod::TrackAssoc const& trackIndices) { const auto matCorr = static_cast(materialCorrectionType.value); @@ -343,7 +386,15 @@ struct HfTreeCreatorOmegacSt { o2::dataformats::DCA impactParameterCasc; for (const auto& trackedCascade : groupedTrackedCascades) { - const auto trackCasc = trackedCascade.track_as(); + const auto trackCasc = trackedCascade.track_as(); + int trackCascMotherId = -1; + if constexpr (std::is_same::value) { + if (trackCasc.has_mcParticle() && trackCasc.mcParticle().has_mothers()) { + if (auto res = mapMcPartToGenTable.find(trackCasc.mcParticle().mothersIds()[0]); res != mapMcPartToGenTable.end()) { + trackCascMotherId = res->second; + } + } + } auto trackParCovCasc = getTrackParCov(trackCasc); if (bzOnly) { o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, trackParCovCasc, bz, 2.f, matCorr, &impactParameterCasc); @@ -352,10 +403,10 @@ struct HfTreeCreatorOmegacSt { } const auto& casc = trackedCascade.cascade(); - const auto& bachelor = casc.bachelor_as(); + const auto& bachelor = casc.bachelor_as(); const auto& v0 = casc.v0(); - const auto& v0TrackPos = v0.posTrack_as(); - const auto& v0TrackNeg = v0.negTrack_as(); + const auto& v0TrackPos = v0.posTrack_as(); + const auto& v0TrackNeg = v0.negTrack_as(); if (!v0TrackPos.hasTPC() || !v0TrackNeg.hasTPC() || !bachelor.hasTPC() || v0TrackPos.tpcNClsFindable() < minNoClsTrackedCascade || @@ -374,7 +425,7 @@ struct HfTreeCreatorOmegacSt { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for Pr-Pi cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for Pr-Pi cannot work, skipping the candidate."; hCandidatesPrPi->Fill(SVFitting::Fail); continue; } @@ -395,7 +446,7 @@ struct HfTreeCreatorOmegacSt { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for V0-bachelor cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for V0-bachelor cannot work, skipping the candidate."; hCandidatesV0Pi->Fill(SVFitting::Fail); continue; } @@ -454,7 +505,7 @@ struct HfTreeCreatorOmegacSt { } for (auto trackId : groupedTrackIds) { - const auto track = trackId.template track_as(); + const auto track = trackId.template track_as(); if (track.globalIndex() == v0TrackPr.globalIndex() || track.globalIndex() == v0TrackPi.globalIndex() || track.globalIndex() == bachelor.globalIndex()) { @@ -468,6 +519,14 @@ struct HfTreeCreatorOmegacSt { (track.itsChi2NCl() <= 36.f) && (std::abs(track.tpcNSigmaPi()) < maxNSigmaPion)) { LOGF(debug, " .. combining with pion candidate %d", track.globalIndex()); + int trackMotherId = -1; + if constexpr (std::is_same::value) { + if (track.has_mcParticle() && track.mcParticle().has_mothers()) { + if (auto res = mapMcPartToGenTable.find(track.mcParticle().mothersIds()[0]); res != mapMcPartToGenTable.end()) { + trackMotherId = res->second; + } + } + } auto trackParCovCasc = getTrackParCov(trackCasc); auto trackParCovPion = getTrackParCov(track); o2::dataformats::DCA impactParameterPion; @@ -545,13 +604,15 @@ struct HfTreeCreatorOmegacSt { decayLength, decayLengthXY, decayLengthCasc, - decayLengthCascXY); + decayLengthCascXY, + trackCascMotherId, + trackMotherId); } } else { continue; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for Casc-Pi cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for Casc-Pi cannot work, skipping the candidate."; hCandidatesCascPi->Fill(SVFitting::Fail); continue; } @@ -563,11 +624,37 @@ struct HfTreeCreatorOmegacSt { } } } + + void processData(Collisions const& collisions, + soa::SmallGroups const& trackedCascades, + aod::TrackAssoc const& trackIndices, + aod::Cascades const&, + aod::V0s const&, + TracksExt const&, + aod::BCsWithTimestamps const&) + { + fillTable(collisions, trackedCascades, trackIndices); + } PROCESS_SWITCH(HfTreeCreatorOmegacSt, processData, "Process data", true); + void processMcRec(Collisions const& collisions, + aod::McCollisions const&, + soa::SmallGroups const& trackedCascades, + aod::TrackAssoc const& trackIndices, + aod::Cascades const&, + aod::V0s const&, + // TracksExt const& tracks, // TODO: should be TracksExtMc + TracksExtMc const&, + aod::McParticles const&, + aod::BCsWithTimestamps const&) + { + fillTable(collisions, trackedCascades, trackIndices); + } + PROCESS_SWITCH(HfTreeCreatorOmegacSt, processMcRec, "Process MC reco", true); + void processMcGen(aod::Collision const& collision, aod::McCollisions const&, - aod::AssignedTrackedCascades const& trackedCascades, + soa::SmallGroups const& trackedCascades, aod::Cascades const&, aod::V0s const&, TracksExtMc const& tracks, @@ -677,7 +764,7 @@ struct HfTreeCreatorOmegacSt { hCandidatesCascPi->Fill(SVFitting::FitOk); } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCFitterN for Casc-Pi cannot work, skipping the candidate."; + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN for Casc-Pi cannot work, skipping the candidate."; hCandidatesCascPi->Fill(SVFitting::Fail); continue; } diff --git a/PWGHF/TableProducer/treeCreatorOmegacToOmegaPi.cxx b/PWGHF/TableProducer/treeCreatorOmegacToOmegaPi.cxx index 7014e64d0ef..99128171973 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacToOmegaPi.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacToOmegaPi.cxx @@ -14,6 +14,7 @@ /// In this file are defined and filled the output tables /// /// \author Federica Zanone , Heidelberg University +/// \author Yunfan Liu , China University of Geosciences #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" @@ -99,6 +100,53 @@ DECLARE_SOA_COLUMN(TofNSigmaPiFromCharmBaryon, tofNSigmaPiFromCharmBaryon, float DECLARE_SOA_COLUMN(TofNSigmaKaFromCasc, tofNSigmaKaFromCasc, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); +// from creator KF +DECLARE_SOA_COLUMN(NSigmaTPCPiFromOmegac, nSigmaTPCPiFromOmegac, float); +DECLARE_SOA_COLUMN(NSigmaTOFPiFromOmegac, nSigmaTOFPiFromOmegac, float); +DECLARE_SOA_COLUMN(NSigmaTPCKaFromCasc, nSigmaTPCKaFromCasc, float); +DECLARE_SOA_COLUMN(NSigmaTOFKaFromCasc, nSigmaTOFKaFromCasc, float); +DECLARE_SOA_COLUMN(NSigmaTPCPiFromV0, nSigmaTPCPiFromV0, float); +DECLARE_SOA_COLUMN(NSigmaTPCPrFromV0, nSigmaTPCPrFromV0, float); +DECLARE_SOA_COLUMN(KfDcaXYPiFromOmegac, kfDcaXYPiFromOmegac, float); +DECLARE_SOA_COLUMN(KfDcaXYCascToPv, kfDcaXYCascToPv, float); +DECLARE_SOA_COLUMN(Chi2GeoV0, chi2GeoV0, float); +DECLARE_SOA_COLUMN(Chi2GeoCasc, chi2GeoCasc, float); +DECLARE_SOA_COLUMN(Chi2GeoOmegac, chi2GeoOmegac, float); +DECLARE_SOA_COLUMN(Chi2MassV0, chi2MassV0, float); +DECLARE_SOA_COLUMN(Chi2MassCasc, chi2MassCasc, float); +DECLARE_SOA_COLUMN(V0ldl, v0ldl, float); +DECLARE_SOA_COLUMN(Cascldl, cascldl, float); +DECLARE_SOA_COLUMN(Omegacldl, omegacldl, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToPv, chi2TopoV0ToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToPv, chi2TopoCascToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoPiFromOmegacToPv, chi2TopoPiFromOmegacToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoOmegacToPv, chi2TopoOmegacToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToCasc, chi2TopoV0ToCasc, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToOmegac, chi2TopoCascToOmegac, float); +DECLARE_SOA_COLUMN(DecayLenXYLambda, decayLenXYLambda, float); +DECLARE_SOA_COLUMN(DecayLenXYCasc, decayLenXYCasc, float); +DECLARE_SOA_COLUMN(DecayLenXYOmegac, decayLenXYOmegac, float); +DECLARE_SOA_COLUMN(CosPaV0ToCasc, cosPaV0ToCasc, float); +DECLARE_SOA_COLUMN(CosPaV0ToPv, cosPaV0ToPv, float); +DECLARE_SOA_COLUMN(CosPaCascToOmegac, cosPaCascToOmegac, float); +DECLARE_SOA_COLUMN(CosPaCascToPv, cosPaCascToPv, float); +DECLARE_SOA_COLUMN(CosPaOmegacToPv, cosPaOmegacToPv, float); +DECLARE_SOA_COLUMN(KfRapOmegac, kfRapOmegac, float); +DECLARE_SOA_COLUMN(KfptPiFromOmegac, kfptPiFromOmegac, float); +DECLARE_SOA_COLUMN(KfptOmegac, kfptOmegac, float); +DECLARE_SOA_COLUMN(CosThetaStarPiFromOmegac, cosThetaStarPiFromOmegac, float); +DECLARE_SOA_COLUMN(CtOmegac, ctOmegac, float); +DECLARE_SOA_COLUMN(EtaOmegac, etaOmegac, float); +DECLARE_SOA_COLUMN(V0Ndf, v0Ndf, float); +DECLARE_SOA_COLUMN(CascNdf, cascNdf, float); +DECLARE_SOA_COLUMN(OmegacNdf, omegacNdf, float); +DECLARE_SOA_COLUMN(MassV0Ndf, massV0Ndf, float); +DECLARE_SOA_COLUMN(MassCascNdf, massCascNdf, float); +DECLARE_SOA_COLUMN(V0Chi2OverNdf, v0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(CascChi2OverNdf, cascChi2OverNdf, float); +DECLARE_SOA_COLUMN(OmegacChi2OverNdf, omegacChi2OverNdf, float); +DECLARE_SOA_COLUMN(MassV0Chi2OverNdf, massV0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(MassCascChi2OverNdf, massCascChi2OverNdf, float); } // namespace full @@ -129,12 +177,32 @@ DECLARE_SOA_TABLE(HfOmegac0ToOmegaPiLites, "AOD", "HFTOOMEPILITE", full::TofNSigmaPiFromCharmBaryon, full::TofNSigmaKaFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched); +DECLARE_SOA_TABLE(HfKfOmegacFulls, "AOD", "HFKFOMEGACFULL", + full::NSigmaTPCPiFromOmegac, full::NSigmaTOFPiFromOmegac, full::NSigmaTPCKaFromCasc, full::NSigmaTOFKaFromCasc, + full::NSigmaTPCPiFromV0, full::NSigmaTPCPrFromV0, + full::KfDcaXYPiFromOmegac, full::DcaCascDau, full::DcaCharmBaryonDau, full::KfDcaXYCascToPv, + full::Chi2GeoV0, full::Chi2GeoCasc, full::Chi2GeoOmegac, + full::Chi2MassV0, full::Chi2MassCasc, + full::V0ldl, full::Cascldl, full::Omegacldl, + full::Chi2TopoV0ToPv, full::Chi2TopoCascToPv, full::Chi2TopoPiFromOmegacToPv, full::Chi2TopoOmegacToPv, + full::Chi2TopoV0ToCasc, full::Chi2TopoCascToOmegac, + full::DecayLenXYLambda, full::DecayLenXYCasc, full::DecayLenXYOmegac, + full::CosPaV0ToCasc, full::CosPaV0ToPv, full::CosPaCascToOmegac, full::CosPaCascToPv, full::CosPaOmegacToPv, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::KfRapOmegac, full::KfptPiFromOmegac, full::KfptOmegac, + full::CosThetaStarPiFromOmegac, full::CtOmegac, full::EtaOmegac, + full::V0Ndf, full::CascNdf, full::OmegacNdf, + full::MassV0Ndf, full::MassCascNdf, + full::V0Chi2OverNdf, full::CascChi2OverNdf, full::OmegacChi2OverNdf, + full::MassV0Chi2OverNdf, full::MassCascChi2OverNdf, + full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched); } // namespace o2::aod /// Writes the full information in an output TTree struct HfTreeCreatorOmegac0ToOmegaPi { Produces rowCandidateLite; + Produces rowKfCandidateFull; Produces rowEv; Configurable zPvCut{"zPvCut", 10., "Cut on absolute value of primary vertex z coordinate"}; @@ -226,6 +294,69 @@ struct HfTreeCreatorOmegac0ToOmegaPi { } } + template + void fillKfCandidate(const T& candidate, int8_t flagMc, int8_t originMc, bool collisionMatched) + { + if (candidate.resultSelections() && candidate.statusPidCharmBaryon() && candidate.statusInvMassLambda() && candidate.statusInvMassCascade() && candidate.statusInvMassCharmBaryon()) { + + rowKfCandidateFull( + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaKaFromCasc(), + candidate.tofNSigmaKaFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.kfDcaXYPiFromOmegac(), + candidate.dcaCascDau(), + candidate.dcaCharmBaryonDau(), + candidate.kfDcaXYCascToPv(), + candidate.chi2GeoV0(), + candidate.chi2GeoCasc(), + candidate.chi2GeoOmegac(), + candidate.chi2MassV0(), + candidate.chi2MassCasc(), + candidate.v0ldl(), + candidate.cascldl(), + candidate.omegacldl(), + candidate.chi2TopoV0ToPv(), + candidate.chi2TopoCascToPv(), + candidate.chi2TopoPiFromOmegacToPv(), + candidate.chi2TopoOmegacToPv(), + candidate.chi2TopoV0ToCasc(), + candidate.chi2TopoCascToOmegac(), + candidate.decayLenXYLambda(), + candidate.decayLenXYCasc(), + candidate.decayLenXYOmegac(), + candidate.cosPaV0ToCasc(), + candidate.cosPAV0(), + candidate.cosPaCascToOmegac(), + candidate.cosPACasc(), + candidate.cosPACharmBaryon(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.kfRapOmegac(), + candidate.kfptPiFromOmegac(), + candidate.kfptOmegac(), + candidate.cosThetaStarPiFromOmegac(), + candidate.ctauOmegac(), + candidate.etaCharmBaryon(), + candidate.v0Ndf(), + candidate.cascNdf(), + candidate.omegacNdf(), + candidate.massV0Ndf(), + candidate.massCascNdf(), + candidate.v0Chi2OverNdf(), + candidate.cascChi2OverNdf(), + candidate.omegacChi2OverNdf(), + candidate.massV0Chi2OverNdf(), + candidate.massCascChi2OverNdf(), + flagMc, + originMc, + collisionMatched); + } + } + void processDataLite(MyEventTable const& collisions, MyTrackTable const&, soa::Join const& candidates) { @@ -243,6 +374,23 @@ struct HfTreeCreatorOmegac0ToOmegaPi { } PROCESS_SWITCH(HfTreeCreatorOmegac0ToOmegaPi, processDataLite, "Process data", true); + void processKfDataFull(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillKfCandidate(candidate, -7, RecoDecay::OriginType::None, false); + } + } + PROCESS_SWITCH(HfTreeCreatorOmegac0ToOmegaPi, processKfDataFull, "Process KF data", false); + void processMcLite(MyEventTable const& collisions, MyTrackTable const&, soa::Join const& candidates) { @@ -260,6 +408,23 @@ struct HfTreeCreatorOmegac0ToOmegaPi { } PROCESS_SWITCH(HfTreeCreatorOmegac0ToOmegaPi, processMcLite, "Process MC", false); + void processKFMcFull(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + } + } + PROCESS_SWITCH(HfTreeCreatorOmegac0ToOmegaPi, processKFMcFull, "Process KF MC", false); + }; // end of struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx new file mode 100644 index 00000000000..1514e5670ab --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx @@ -0,0 +1,890 @@ +// Copyright 2019-2020 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. + +/// \file treeCreatorXicToXiPiPi.cxx +/// \brief Writer of Ξc± → Ξ∓ π± π± candidates in the form of flat tables to be stored in TTrees. +/// +/// \author Phil Lennart Stahlhut , Heidelberg University +/// \author Carolina Reetz , Heidelberg University + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) +// vertices +DECLARE_SOA_COLUMN(XPv, xPv, float); +DECLARE_SOA_COLUMN(YPv, yPv, float); +DECLARE_SOA_COLUMN(ZPv, zPv, float); +DECLARE_SOA_COLUMN(XPvErr, xPvErr, float); +DECLARE_SOA_COLUMN(YPvErr, yPvErr, float); +DECLARE_SOA_COLUMN(ZPvErr, zPvErr, float); +DECLARE_SOA_COLUMN(XPvGen, xPvGen, float); +DECLARE_SOA_COLUMN(YPvGen, yPvGen, float); +DECLARE_SOA_COLUMN(ZPvGen, zPvGen, float); +DECLARE_SOA_COLUMN(XSv, xSv, float); +DECLARE_SOA_COLUMN(YSv, ySv, float); +DECLARE_SOA_COLUMN(ZSv, zSv, float); +DECLARE_SOA_COLUMN(XSvErr, xSvErr, float); +DECLARE_SOA_COLUMN(YSvErr, ySvErr, float); +DECLARE_SOA_COLUMN(ZSvErr, zSvErr, float); +DECLARE_SOA_COLUMN(Chi2Sv, chi2Sv, float); +DECLARE_SOA_COLUMN(XSvGen, xSvGen, float); +DECLARE_SOA_COLUMN(YSvGen, ySvGen, float); +DECLARE_SOA_COLUMN(ZSvGen, zSvGen, float); +DECLARE_SOA_COLUMN(XDecVtxXi, xDecVtxXi, float); +DECLARE_SOA_COLUMN(YDecVtxXi, yDecVtxXi, float); +DECLARE_SOA_COLUMN(ZDecVtxXi, zDecVtxXi, float); +DECLARE_SOA_COLUMN(Chi2XiVtx, chi2XiVtx, float); +DECLARE_SOA_COLUMN(XDecVtxLam, xDecVtxLam, float); +DECLARE_SOA_COLUMN(YDecVtxLam, yDecVtxLam, float); +DECLARE_SOA_COLUMN(ZDecVtxLam, zDecVtxLam, float); +DECLARE_SOA_COLUMN(Chi2LamVtx, chi2LamVtx, float); +// properties of XicPlus +DECLARE_SOA_COLUMN(Sign, sign, float); +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime time ctau of candidate (cm) +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(Chi2XicPlusTopoToPV, chi2XicPlusTopoToPV, float); +DECLARE_SOA_COLUMN(Chi2XicPlusTopoXiToXicPlus, chi2XicPlusTopoXiToXicPlus, float); +// properties of daughter tracks +DECLARE_SOA_COLUMN(PtXi, ptXi, float); //! Transverse momentum of Xi (prong0) (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterXi, impactParameterXi, float); //! Impact parameter of Xi (prong0) +DECLARE_SOA_COLUMN(ImpactParameterNormalisedXi, impactParameterNormalisedXi, float); //! Normalised impact parameter of Xi (prong0) +DECLARE_SOA_COLUMN(PtPi0, ptPi0, float); //! Transverse momentum of Pi0 (prong1) (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterPi0, impactParameterPi0, float); //! Impact parameter of Pi0 (prong1) +DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi0, impactParameterNormalisedPi0, float); //! Normalised impact parameter of Pi0 (prong1) +DECLARE_SOA_COLUMN(PtPi1, ptPi1, float); //! Transverse momentum of Pi1 (prong2) (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterPi1, impactParameterPi1, float); //! Normalised impact parameter of Pi1 (prong2) +DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi1, impactParameterNormalisedPi1, float); //! Normalised impact parameter of Pi1 (prong2) +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(CpaXi, cpaXi, float); +DECLARE_SOA_COLUMN(CpaXYXi, cpaXYXi, float); +DECLARE_SOA_COLUMN(CpaLam, cpaLam, float); +DECLARE_SOA_COLUMN(CpaXYLam, cpaXYLam, float); +DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); +DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); +DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); +DECLARE_SOA_COLUMN(DcaPi0Pi1, dcaPi0Pi1, float); +DECLARE_SOA_COLUMN(DcaPi0Xi, dcaPi0Xi, float); +DECLARE_SOA_COLUMN(DcaPi1Xi, dcaPi1Xi, float); +DECLARE_SOA_COLUMN(DcaXiDaughters, dcaXiDaughters, float); +DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); +DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); +// residuals and pulls +DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); +DECLARE_SOA_COLUMN(PResidual, pResidual, float); +DECLARE_SOA_COLUMN(XPvResidual, xPvResidual, float); +DECLARE_SOA_COLUMN(YPvResidual, yPvResidual, float); +DECLARE_SOA_COLUMN(ZPvResidual, zPvResidual, float); +DECLARE_SOA_COLUMN(XPvPull, xPvPull, float); +DECLARE_SOA_COLUMN(YPvPull, yPvPull, float); +DECLARE_SOA_COLUMN(ZPvPull, zPvPull, float); +DECLARE_SOA_COLUMN(XSvResidual, xSvResidual, float); +DECLARE_SOA_COLUMN(YSvResidual, ySvResidual, float); +DECLARE_SOA_COLUMN(ZSvResidual, zSvResidual, float); +DECLARE_SOA_COLUMN(XSvPull, xSvPull, float); +DECLARE_SOA_COLUMN(YSvPull, ySvPull, float); +DECLARE_SOA_COLUMN(ZSvPull, zSvPull, float); +} // namespace full + +DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", + full::CandidateSelFlag, + full::XPv, + full::YPv, + full::ZPv, + full::XSv, + full::YSv, + full::ZSv, + full::Chi2Sv, + full::Sign, + full::E, + full::M, + full::P, + full::Pt, + full::Y, + full::Eta, + full::Phi, + full::Ct, + full::DecayLength, + full::DecayLengthXY, + full::Cpa, + full::CpaXY, + full::PtXi, + full::PtPi0, + full::PtPi1, + full::ImpactParameterXi, + full::ImpactParameterPi0, + full::ImpactParameterPi1, + full::CpaXi, + full::CpaXYXi, + full::CpaLam, + full::CpaXYLam, + hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec); + +DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", + full::CandidateSelFlag, + full::XPv, + full::YPv, + full::ZPv, + full::XSv, + full::YSv, + full::ZSv, + full::Chi2Sv, + full::Sign, + full::E, + full::M, + full::P, + full::Pt, + full::Y, + full::Eta, + full::Phi, + full::Ct, + full::DecayLength, + full::DecayLengthXY, + full::Cpa, + full::CpaXY, + full::PtXi, + full::PtPi0, + full::PtPi1, + full::ImpactParameterXi, + full::ImpactParameterPi0, + full::ImpactParameterPi1, + full::CpaXi, + full::CpaXYXi, + full::CpaLam, + full::CpaXYLam, + full::Chi2XiVtx, + full::Chi2LamVtx, + full::Chi2XicPlusTopoToPV, + full::Chi2XicPlusTopoXiToXicPlus, + full::DcaXYPi0Pi1, + full::DcaXYPi0Xi, + full::DcaXYPi1Xi, + full::DcaPi0Pi1, + full::DcaPi0Xi, + full::DcaPi1Xi, + full::DcaXiDaughters, + hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec); + +DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", + full::CandidateSelFlag, + full::XPv, + full::YPv, + full::ZPv, + full::XPvErr, + full::YPvErr, + full::ZPvErr, + full::XSv, + full::YSv, + full::ZSv, + full::Chi2Sv, + full::XSvErr, + full::YSvErr, + full::ZSvErr, + full::XDecVtxXi, + full::YDecVtxXi, + full::ZDecVtxXi, + full::XDecVtxLam, + full::YDecVtxLam, + full::ZDecVtxLam, + full::Sign, + full::E, + full::M, + full::P, + full::Pt, + full::Y, + full::Eta, + full::Phi, + full::Ct, + full::DecayLength, + full::DecayLengthNormalised, + full::DecayLengthXY, + full::DecayLengthXYNormalised, + full::Cpa, + full::CpaXY, + full::PtXi, + full::PtPi0, + full::PtPi1, + full::ImpactParameterXi, + full::ImpactParameterNormalisedXi, + full::ImpactParameterPi0, + full::ImpactParameterNormalisedPi0, + full::ImpactParameterPi1, + full::ImpactParameterNormalisedPi1, + full::MaxNormalisedDeltaIP, + full::CpaXi, + full::CpaXYXi, + full::CpaLam, + full::CpaXYLam, + full::InvMassXiPi0, + full::InvMassXiPi1, + hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec); + +DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", + full::CandidateSelFlag, + full::XPv, + full::YPv, + full::ZPv, + full::XPvErr, + full::YPvErr, + full::ZPvErr, + full::XSv, + full::YSv, + full::ZSv, + full::Chi2Sv, + full::XSvErr, + full::YSvErr, + full::ZSvErr, + full::XDecVtxXi, + full::YDecVtxXi, + full::ZDecVtxXi, + full::XDecVtxLam, + full::YDecVtxLam, + full::ZDecVtxLam, + full::Sign, + full::E, + full::M, + full::P, + full::Pt, + full::Y, + full::Eta, + full::Phi, + full::Ct, + full::DecayLength, + full::DecayLengthNormalised, + full::DecayLengthXY, + full::DecayLengthXYNormalised, + full::Cpa, + full::CpaXY, + full::PtXi, + full::PtPi0, + full::PtPi1, + full::ImpactParameterXi, + full::ImpactParameterNormalisedXi, + full::ImpactParameterPi0, + full::ImpactParameterNormalisedPi0, + full::ImpactParameterPi1, + full::ImpactParameterNormalisedPi1, + full::MaxNormalisedDeltaIP, + full::CpaXi, + full::CpaXYXi, + full::CpaLam, + full::CpaXYLam, + full::InvMassXiPi0, + full::InvMassXiPi1, + full::Chi2XiVtx, + full::Chi2LamVtx, + full::Chi2XicPlusTopoToPV, + full::Chi2XicPlusTopoXiToXicPlus, + full::DcaXYPi0Pi1, + full::DcaXYPi0Xi, + full::DcaXYPi1Xi, + full::DcaPi0Pi1, + full::DcaPi0Xi, + full::DcaPi1Xi, + full::DcaXiDaughters, + hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec); + +DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullPs, "AOD", "HFXICXI2PIFULLP", + full::Pt, + full::Eta, + full::Phi, + full::Y, + full::XPvGen, + full::YPvGen, + full::ZPvGen, + full::XSvGen, + full::YSvGen, + full::ZSvGen, + hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen); + +DECLARE_SOA_TABLE(HfCandXicToXiPiPiResiduals, "AOD", "HFXICXI2PIRESID", + full::PResidual, + full::PtResidual, + full::XPvResidual, + full::YPvResidual, + full::ZPvResidual, + full::XPvPull, + full::YPvPull, + full::ZPvPull, + full::XSvResidual, + full::YSvResidual, + full::ZSvResidual, + full::XSvPull, + full::YSvPull, + full::ZSvPull); +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorXicToXiPiPi { + Produces rowCandidateLite; + Produces rowCandidateLiteKf; + Produces rowCandidateFull; + Produces rowCandidateFullKf; + Produces rowCandidateFullParticles; + Produces rowCandidateResiduals; + + Configurable selectionFlagXic{"selectionXic", 1, "Selection Flag for Xic"}; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + Configurable fillResidualTable{"fillResidualTable", false, "Switch to fill table with residuals for MC candidates"}; + // parameters for production of training samples + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + using SelectedCandidates = soa::Filtered>; + using SelectedCandidatesKf = soa::Filtered>; + using SelectedCandidatesMc = soa::Filtered>; + using SelectedCandidatesKfMc = soa::Filtered>; + using TracksWPid = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic; + + Preslice genParticlesPerCollision = aod::mcparticle::mcCollisionId; + + Partition recSig = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) != int8_t(0); + Partition recBg = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) == int8_t(0); + Partition recSigKf = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) != int8_t(0); + Partition recBgKf = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) == int8_t(0); + + void init(InitContext const&) + { + } + + template + void fillCandidateTable(const T& candidate) + { + int8_t flagMc = 0; + if constexpr (doMc) { + flagMc = candidate.flagMcMatchRec(); + } + if constexpr (!doKf) { + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.isSelXicToXiPiPi(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.chi2PCA(), + candidate.sign(), + candidate.e(o2::constants::physics::MassXiCPlus), + candidate.invMassXic(), + candidate.p(), + candidate.pt(), + candidate.y(o2::constants::physics::MassXiCPlus), + candidate.eta(), + candidate.phi(), + candidate.ct(o2::constants::physics::MassXiCPlus), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.cpa(), + candidate.cpaXY(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.cosPaXi(), + candidate.cosPaXYXi(), + candidate.cosPaLambda(), + candidate.cosPaXYLambda(), + flagMc); + } else { + rowCandidateFull( + candidate.isSelXicToXiPiPi(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xPvErr(), + candidate.yPvErr(), + candidate.zPvErr(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.chi2PCA(), + candidate.xSvErr(), + candidate.ySvErr(), + candidate.zSvErr(), + candidate.xDecayVtxXi(), + candidate.yDecayVtxXi(), + candidate.zDecayVtxXi(), + candidate.xDecayVtxLambda(), + candidate.yDecayVtxLambda(), + candidate.zDecayVtxLambda(), + candidate.sign(), + candidate.e(o2::constants::physics::MassXiCPlus), + candidate.invMassXic(), + candidate.p(), + candidate.pt(), + candidate.y(o2::constants::physics::MassXiCPlus), + candidate.eta(), + candidate.phi(), + candidate.ct(o2::constants::physics::MassXiCPlus), + candidate.decayLength(), + candidate.decayLengthNormalised(), + candidate.decayLengthXY(), + candidate.decayLengthXYNormalised(), + candidate.cpa(), + candidate.cpaXY(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameterNormalised0(), + candidate.impactParameter1(), + candidate.impactParameterNormalised1(), + candidate.impactParameter2(), + candidate.impactParameterNormalised2(), + candidate.maxNormalisedDeltaIP(), + candidate.cosPaXi(), + candidate.cosPaXYXi(), + candidate.cosPaLambda(), + candidate.cosPaXYLambda(), + candidate.invMassXiPi0(), + candidate.invMassXiPi1(), + flagMc); + } + } else { + if (fillCandidateLiteTable) { + rowCandidateLiteKf( + candidate.isSelXicToXiPiPi(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.chi2PCA(), + candidate.sign(), + candidate.e(o2::constants::physics::MassXiCPlus), + candidate.invMassXic(), + candidate.p(), + candidate.pt(), + candidate.y(o2::constants::physics::MassXiCPlus), + candidate.eta(), + candidate.phi(), + candidate.ct(o2::constants::physics::MassXiCPlus), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.cpa(), + candidate.cpaXY(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.cosPaXi(), + candidate.cosPaXYXi(), + candidate.cosPaLambda(), + candidate.cosPaXYLambda(), + candidate.kfCascadeChi2(), + candidate.kfV0Chi2(), + candidate.chi2TopoXicPlusToPV(), + candidate.chi2TopoXiToXicPlus(), + candidate.dcaXYPi0Pi1(), + candidate.dcaXYPi0Xi(), + candidate.dcaXYPi1Xi(), + candidate.dcaPi0Pi1(), + candidate.dcaPi0Xi(), + candidate.dcaPi1Xi(), + candidate.dcacascdaughters(), + flagMc); + } else { + rowCandidateFullKf( + candidate.isSelXicToXiPiPi(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xPvErr(), + candidate.yPvErr(), + candidate.zPvErr(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.chi2PCA(), + candidate.xSvErr(), + candidate.ySvErr(), + candidate.zSvErr(), + candidate.xDecayVtxXi(), + candidate.yDecayVtxXi(), + candidate.zDecayVtxXi(), + candidate.xDecayVtxLambda(), + candidate.yDecayVtxLambda(), + candidate.zDecayVtxLambda(), + candidate.sign(), + candidate.e(o2::constants::physics::MassXiCPlus), + candidate.invMassXic(), + candidate.p(), + candidate.pt(), + candidate.y(o2::constants::physics::MassXiCPlus), + candidate.eta(), + candidate.phi(), + candidate.ct(o2::constants::physics::MassXiCPlus), + candidate.decayLength(), + candidate.decayLengthNormalised(), + candidate.decayLengthXY(), + candidate.decayLengthXYNormalised(), + candidate.cpa(), + candidate.cpaXY(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameterNormalised0(), + candidate.impactParameter1(), + candidate.impactParameterNormalised1(), + candidate.impactParameter2(), + candidate.impactParameterNormalised2(), + candidate.maxNormalisedDeltaIP(), + candidate.cosPaXi(), + candidate.cosPaXYXi(), + candidate.cosPaLambda(), + candidate.cosPaXYLambda(), + candidate.invMassXiPi0(), + candidate.invMassXiPi1(), + candidate.kfCascadeChi2(), + candidate.kfV0Chi2(), + candidate.chi2TopoXicPlusToPV(), + candidate.chi2TopoXiToXicPlus(), + candidate.dcaXYPi0Pi1(), + candidate.dcaXYPi0Xi(), + candidate.dcaXYPi1Xi(), + candidate.dcaPi0Pi1(), + candidate.dcaPi0Xi(), + candidate.dcaPi1Xi(), + candidate.dcacascdaughters(), + flagMc); + } + } + } + + void processData(SelectedCandidates const& candidates) + { + // Filling candidate properties + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + if (fillOnlyBackground && downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (pseudoRndm >= downSampleBkgFactor && candidate.pt() < ptMaxForDownSample) { + continue; + } + } + fillCandidateTable(candidate); + } + } + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processData, "Process data", true); + + void processDataKf(SelectedCandidatesKf const& candidates) + { + // Filling candidate properties + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + if (fillOnlyBackground && downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (pseudoRndm >= downSampleBkgFactor && candidate.pt() < ptMaxForDownSample) { + continue; + } + } + fillCandidateTable(candidate); + } + } + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processDataKf, "Process data with KF Particle reconstruction", false); + + void processMc(SelectedCandidatesMc const& candidates, + soa::Join const& particles) + { + std::vector arrDaughIndex; + + // Filling candidate properties + if (fillOnlySignal) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recSig.size()); + } else { + rowCandidateFull.reserve(recSig.size()); + } + for (const auto& candidate : recSig) { + fillCandidateTable(candidate); + } + } else if (fillOnlyBackground) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recBg.size()); + } else { + rowCandidateFull.reserve(recBg.size()); + } + for (const auto& candidate : recBg) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + fillCandidateTable(candidate); + } + } else { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + fillCandidateTable(candidate); + } + } + + // Filling particle properties + rowCandidateFullParticles.reserve(particles.size()); + for (const auto& particle : particles) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi) || TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi)) { + arrDaughIndex.clear(); + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); + auto xicDaugh0 = particles.rawIteratorAt(arrDaughIndex[0]); + + rowCandidateFullParticles( + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(particle.pVector(), o2::constants::physics::MassXiCPlus), + particle.vx(), + particle.vy(), + particle.vz(), + xicDaugh0.vx(), + xicDaugh0.vx(), + xicDaugh0.vz(), + particle.flagMcMatchGen()); + } + } + + if (fillResidualTable) { + rowCandidateResiduals.reserve(recSig.size()); + for (const auto& candidate : recSig) { + auto thisCollId = candidate.collisionId(); + auto groupedParticles = particles.sliceBy(genParticlesPerCollision, thisCollId); + + for (const auto& particle : groupedParticles) { + std::array pvResiduals; + std::array svResiduals; + std::array pvPulls = {-999.9}; + std::array svPulls = {-999.9}; + + arrDaughIndex.clear(); + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); + + if ((candidate.cascadeId() == arrDaughIndex[0] || candidate.cascadeId() == arrDaughIndex[1] || candidate.cascadeId() == arrDaughIndex[2]) && (candidate.pi0Id() == arrDaughIndex[0] || candidate.pi0Id() == arrDaughIndex[1] || candidate.pi0Id() == arrDaughIndex[2]) && (candidate.pi1Id() == arrDaughIndex[0] || candidate.pi1Id() == arrDaughIndex[1] || candidate.pi1Id() == arrDaughIndex[2])) { + auto xicDaugh0 = particles.rawIteratorAt(arrDaughIndex[0]); + + // residuals + float pResidual = candidate.p() - particle.p(); + float ptResidual = candidate.pt() - particle.pt(); + pvResiduals[0] = candidate.posX() - particle.vx(); + pvResiduals[1] = candidate.posY() - particle.vy(); + pvResiduals[2] = candidate.posZ() - particle.vz(); + svResiduals[0] = candidate.xSecondaryVertex() - xicDaugh0.vx(); + svResiduals[1] = candidate.ySecondaryVertex() - xicDaugh0.vy(); + svResiduals[2] = candidate.zSecondaryVertex() - xicDaugh0.vz(); + // pulls + try { + pvPulls[0] = pvResiduals[0] / candidate.xPvErr(); + pvPulls[1] = pvResiduals[1] / candidate.yPvErr(); + pvPulls[2] = pvResiduals[2] / candidate.zPvErr(); + svPulls[0] = svResiduals[0] / candidate.xSvErr(); + svPulls[1] = svResiduals[1] / candidate.ySvErr(); + svPulls[2] = svResiduals[2] / candidate.zSvErr(); + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". Set values of vertex pulls to -999.9."; + } + + // fill table + rowCandidateResiduals( + pResidual, + ptResidual, + pvResiduals[0], + pvResiduals[1], + pvResiduals[2], + pvPulls[0], + pvPulls[1], + pvPulls[2], + svResiduals[0], + svResiduals[1], + svResiduals[2], + svPulls[0], + svPulls[1], + svPulls[2]); + } + } // loop over generated particles + } // loop over reconstructed candidates + } + } + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processMc, "Process MC", false); + + void processMcKf(SelectedCandidatesKfMc const& candidates, + soa::Join const& particles) + { + std::vector arrDaughIndex; + + // Filling candidate properties + if (fillOnlySignal) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recSigKf.size()); + } else { + rowCandidateFull.reserve(recSigKf.size()); + } + for (const auto& candidate : recSigKf) { + fillCandidateTable(candidate); + } + } else if (fillOnlyBackground) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recBgKf.size()); + } else { + rowCandidateFull.reserve(recBgKf.size()); + } + for (const auto& candidate : recBgKf) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + fillCandidateTable(candidate); + } + } else { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + fillCandidateTable(candidate); + } + } + + // Filling particle properties + rowCandidateFullParticles.reserve(particles.size()); + for (const auto& particle : particles) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi) || TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi)) { + arrDaughIndex.clear(); + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); + auto xicDaugh0 = particles.rawIteratorAt(arrDaughIndex[0]); + + rowCandidateFullParticles( + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(particle.pVector(), o2::constants::physics::MassXiCPlus), + particle.vx(), + particle.vy(), + particle.vz(), + xicDaugh0.vx(), + xicDaugh0.vx(), + xicDaugh0.vz(), + particle.flagMcMatchGen()); + } + } + + if (fillResidualTable) { + rowCandidateResiduals.reserve(recSigKf.size()); + for (const auto& candidate : recSigKf) { + auto thisCollId = candidate.collisionId(); + auto groupedParticles = particles.sliceBy(genParticlesPerCollision, thisCollId); + + for (const auto& particle : groupedParticles) { + std::array pvResiduals; + std::array svResiduals; + std::array pvPulls = {-999.9}; + std::array svPulls = {-999.9}; + + arrDaughIndex.clear(); + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); + + if ((candidate.cascadeId() == arrDaughIndex[0] || candidate.cascadeId() == arrDaughIndex[1] || candidate.cascadeId() == arrDaughIndex[2]) && (candidate.pi0Id() == arrDaughIndex[0] || candidate.pi0Id() == arrDaughIndex[1] || candidate.pi0Id() == arrDaughIndex[2]) && (candidate.pi1Id() == arrDaughIndex[0] || candidate.pi1Id() == arrDaughIndex[1] || candidate.pi1Id() == arrDaughIndex[2])) { + auto xicDaugh0 = particles.rawIteratorAt(arrDaughIndex[0]); + + // residuals + float pResidual = candidate.p() - particle.p(); + float ptResidual = candidate.pt() - particle.pt(); + pvResiduals[0] = candidate.posX() - particle.vx(); + pvResiduals[1] = candidate.posY() - particle.vy(); + pvResiduals[2] = candidate.posZ() - particle.vz(); + svResiduals[0] = candidate.xSecondaryVertex() - xicDaugh0.vx(); + svResiduals[1] = candidate.ySecondaryVertex() - xicDaugh0.vy(); + svResiduals[2] = candidate.zSecondaryVertex() - xicDaugh0.vz(); + // pulls + try { + pvPulls[0] = pvResiduals[0] / candidate.xPvErr(); + pvPulls[1] = pvResiduals[1] / candidate.yPvErr(); + pvPulls[2] = pvResiduals[2] / candidate.zPvErr(); + svPulls[0] = svResiduals[0] / candidate.xSvErr(); + svPulls[1] = svResiduals[1] / candidate.ySvErr(); + svPulls[2] = svResiduals[2] / candidate.zSvErr(); + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". Set values of vertex pulls to -999.9."; + } + + // fill table + rowCandidateResiduals( + pResidual, + ptResidual, + pvResiduals[0], + pvResiduals[1], + pvResiduals[2], + pvPulls[0], + pvPulls[1], + pvPulls[2], + svResiduals[0], + svResiduals[1], + svResiduals[2], + svPulls[0], + svPulls[1], + svPulls[2]); + } + } // loop over generated particles + } // loop over reconstructed candidates + } + } + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processMcKf, "Process MC with KF Particle reconstruction", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/Tasks/CMakeLists.txt b/PWGHF/Tasks/CMakeLists.txt index 60edb086f1e..00878e48a2c 100644 --- a/PWGHF/Tasks/CMakeLists.txt +++ b/PWGHF/Tasks/CMakeLists.txt @@ -36,7 +36,7 @@ o2physics_add_dpl_workflow(task-mc-gen-pt-rap-shapes o2physics_add_dpl_workflow(task-mc-validation SOURCES taskMcValidation.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) # o2physics_add_dpl_workflow(task-sel-optimisation diff --git a/PWGHF/Tasks/taskMcEfficiency.cxx b/PWGHF/Tasks/taskMcEfficiency.cxx index 024632dd7a1..abdbfcd2d59 100644 --- a/PWGHF/Tasks/taskMcEfficiency.cxx +++ b/PWGHF/Tasks/taskMcEfficiency.cxx @@ -39,7 +39,7 @@ struct HfTaskMcEfficiency { ConfigurableAxis axisPt{"axisPt", {10, 0, 10}, "pT axis"}; ConfigurableAxis axisMass{"axisMass", {120, 1.5848, 2.1848}, "m_inv axis"}; - ConfigurableAxis axisPdg{"axisPdg", {VARIABLE_WIDTH, -4122.5, -431.5, -421.5, -411.5, 0, 411.5, 421.5, 431.5, 4122.5}, "PDG code axis"}; + ConfigurableAxis axisPdg{"axisPdg", {VARIABLE_WIDTH, -4232.5, -4122.5, -431.5, -421.5, -411.5, 0, 411.5, 421.5, 431.5, 4122.5, 4232.5}, "PDG code axis"}; ConfigurableAxis axisCPA{"axisCPA", {102, -1.02, 1.02}, "Cosine of pointing angle axis"}; Configurable mcAcceptancePt{"mcAcceptancePt", 0.1, "MC Acceptance: lower pt limit"}; @@ -101,7 +101,7 @@ struct HfTaskMcEfficiency { return track.isGlobalTrackWoDCA(); } - template + template void candidate3ProngLoop(T1& candidates, T2& tracks, T3& mcParticles, std::vector pdgCodes) { using TracksType = std::decay_t; @@ -130,6 +130,11 @@ struct HfTaskMcEfficiency { pdgDaughters[0] = +kProton; pdgDaughters[1] = -kKPlus; pdgDaughters[2] = +kPiPlus; + } else if (pdgCode == Pdg::kXiCPlus) { + decayType = 1 << aod::hf_cand_3prong::DecayType::XicToPKPi; + pdgDaughters[0] = +kProton; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; } else { LOGP(fatal, "Not implemented for PDG {}", pdgCode); } @@ -164,6 +169,12 @@ struct HfTaskMcEfficiency { isHypoMass2SelStep = candidate.isSelLcToPiKP(); } } + if constexpr (hasXicPlus) { + if (pdgCode == Pdg::kXiCPlus) { + isHypoMass1SelStep = candidate.isSelXicToPKPi(); + isHypoMass2SelStep = candidate.isSelXicToPiKP(); + } + } bool collisionMatched = false; int origin = RecoDecay::OriginType::None; @@ -194,6 +205,23 @@ struct HfTaskMcEfficiency { } } + if (pdgCode == Pdg::kXiCPlus) { + auto daughter = trackPos.mcParticle(); + if (std::abs(daughter.pdgCode()) == kProton) { + isHypoMass1TrackStep = true; + isHypoMass1SelStep = true; + isHypoMass2TrackStep = false; + isHypoMass2SelStep = false; + } else if (std::abs(daughter.pdgCode()) == kPiPlus) { + isHypoMass1TrackStep = false; + isHypoMass1SelStep = false; + isHypoMass2TrackStep = true; + isHypoMass2SelStep = true; + } else { + continue; + } + } + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRec).mcCollisionId(); } /// end info MC used @@ -207,6 +235,8 @@ struct HfTaskMcEfficiency { if (isHypoMass1TrackStep) { if (pdgCode == Pdg::kLambdaCPlus) { massHypo1 = hfHelper.invMassLcToPKPi(candidate); + } else if (pdgCode == Pdg::kXiCPlus) { + massHypo1 = hfHelper.invMassXicToPKPi(candidate); } else if (pdgCode == Pdg::kDPlus) { massHypo1 = hfHelper.invMassDplusToPiKPi(candidate); } else if (pdgCode == Pdg::kDS) { @@ -217,6 +247,8 @@ struct HfTaskMcEfficiency { if (isHypoMass2TrackStep) { if (pdgCode == Pdg::kLambdaCPlus) { massHypo2 = hfHelper.invMassLcToPiKP(candidate); + } else if (pdgCode == Pdg::kXiCPlus) { + massHypo2 = hfHelper.invMassXicToPiKP(candidate); } else if (pdgCode == Pdg::kDS) { massHypo2 = hfHelper.invMassDsToPiKK(candidate); } @@ -481,10 +513,10 @@ struct HfTaskMcEfficiency { /// 3-prong analyses - template + template void candidate3ProngMcLoop(C const& candidates, TracksWithSelectionMC const& tracks, aod::McParticles const& mcParticles, aod::McCollisionLabels const&, std::vector pdgCodes) { - candidate3ProngLoop(candidates, tracks, mcParticles, pdgCodes); + candidate3ProngLoop(candidates, tracks, mcParticles, pdgCodes); auto hCandidates = registry.get(HIST("hCandidates")); auto hTrackablePtEta = registry.get(HIST("hTrackablePtEta")); @@ -535,6 +567,10 @@ struct HfTaskMcEfficiency { pdgDaughters[0] = +kProton; pdgDaughters[1] = -kKPlus; pdgDaughters[2] = +kPiPlus; + } else if (pdgCode == Pdg::kXiCPlus) { + pdgDaughters[0] = +kProton; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; } else { LOGP(fatal, "Not implemented for PDG {}", pdgCode); } @@ -661,7 +697,7 @@ struct HfTaskMcEfficiency { TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kDPlus}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplus, "Process D+ data (no MC information needed)", false); @@ -669,7 +705,7 @@ struct HfTaskMcEfficiency { TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kDS}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataDs, "Process Ds+ data (no MC information needed)", false); @@ -677,15 +713,23 @@ struct HfTaskMcEfficiency { TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kLambdaCPlus}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataLc, "Process Lc data (no MC information needed)", false); + void processDataXic(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{Pdg::kXiCPlus}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataXic, "Process Xic data (no MC information needed)", false); + void processDataDplusDs(soa::Join const& candidates, TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kDS}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplusDs, "Process D+ and Ds+ data (no MC information needed)", false); @@ -693,7 +737,7 @@ struct HfTaskMcEfficiency { TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kDS, Pdg::kLambdaCPlus}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplusDsLc, "Process D+, Ds+, and Lc data (no MC information needed)", false); @@ -701,7 +745,7 @@ struct HfTaskMcEfficiency { TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kLambdaCPlus}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplusLc, "Process D+ and Lc data (no MC information needed)", false); @@ -709,7 +753,7 @@ struct HfTaskMcEfficiency { TracksWithSelection const& tracks) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kDS, Pdg::kLambdaCPlus}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataDsLc, "Process Ds+ and Lc data (no MC information needed)", false); @@ -730,7 +774,7 @@ struct HfTaskMcEfficiency { aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kDPlus}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplus, "Process MC for D+ signal", false); @@ -740,7 +784,7 @@ struct HfTaskMcEfficiency { aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kDS}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcDs, "Process MC for Ds+ signal", false); @@ -750,17 +794,27 @@ struct HfTaskMcEfficiency { aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kLambdaCPlus}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcLc, "Process MC for Lc signal", false); + void processMcXic(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{Pdg::kXiCPlus}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcXic, "Process MC for Xic signal", false); + void processMcDplusDs(soa::Join const& candidates, TracksWithSelectionMC const& tracks, aod::McParticles const& mcParticles, aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kDS}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplusDs, "Process MC for D+ and Ds+ signals", false); @@ -770,7 +824,7 @@ struct HfTaskMcEfficiency { aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kDS, Pdg::kLambdaCPlus}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplusDsLc, "Process MC for D+, Ds+, and Lc signals", false); @@ -780,7 +834,7 @@ struct HfTaskMcEfficiency { aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kDPlus, Pdg::kLambdaCPlus}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplusLc, "Process MC for D+ and Lc signals", false); @@ -790,7 +844,7 @@ struct HfTaskMcEfficiency { aod::McCollisionLabels const& colls) { std::vector pdgCodes{Pdg::kDS, Pdg::kLambdaCPlus}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcDsLc, "Process MC for Ds+ and Lc signals", false); }; diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index f8e18855dff..cc18c2d6924 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -22,18 +22,24 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" #include "Framework/StaticFor.h" +#include "CCDB/BasicCCDBManager.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" using namespace o2; using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_evsel; +using namespace o2::hf_centrality; namespace { @@ -43,6 +49,10 @@ enum DecayChannels { DzeroToKPi = 0, DplusToPhiPiToKKPi, // resonant channel with Phi, Dplus -> PhiPi -> KKPi DsToPhiPiToKKPi, // resonant channel with Phi, Ds -> PhiPi -> KKPi DsToK0starKToKKPi, // resonant channel with K0*, Ds -> K0*K -> KKPi + Ds1ToDStarK0s, + Ds2StarToDPlusK0s, + D10ToDStarPi, + D2Star0ToDPlusPi, LcToPKPi, LcToPiK0s, XiCplusToPKPi, @@ -52,23 +62,25 @@ enum DecayChannels { DzeroToKPi = 0, OmegaCToXiPi, nChannels }; // always keep nChannels at the end -static constexpr int nMesonChannels = 6; // number of meson channels +static constexpr int nMesonChannels = 10; // number of meson channels static constexpr int nOriginTypes = 2; // number of origin types (prompt, non-prompt) static constexpr std::array PDGArrayParticle = {o2::constants::physics::Pdg::kD0, o2::constants::physics::Pdg::kDStar, o2::constants::physics::Pdg::kDPlus, o2::constants::physics::Pdg::kDPlus, - o2::constants::physics::Pdg::kDS, o2::constants::physics::Pdg::kDS, o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kLambdaCPlus, + o2::constants::physics::Pdg::kDS, o2::constants::physics::Pdg::kDS, o2::constants::physics::Pdg::kDS1, o2::constants::physics::Pdg::kDS2Star, + o2::constants::physics::Pdg::kD10, o2::constants::physics::Pdg::kD2Star0, o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kXiCPlus, o2::constants::physics::Pdg::kXiCPlus, o2::constants::physics::Pdg::kXiC0, o2::constants::physics::Pdg::kOmegaC0, o2::constants::physics::Pdg::kOmegaC0}; -static constexpr std::array nDaughters = {2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 4}; -static constexpr std::array maxDepthForSearch = {1, 2, 2, 2, 2, 2, 2, 3, 2, 4, 3, 3, 3}; +static constexpr std::array nDaughters = {2, 3, 3, 3, 3, 3, 5, 5, 4, 4, 3, 3, 3, 5, 4, 4, 4}; +static constexpr std::array maxDepthForSearch = {1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 3, 2, 4, 3, 3, 3}; // keep coherent indexing with PDGArrayParticle // FIXME: look for a better solution -static constexpr std::array, nChannels> arrPDGFinal2Prong = {{{+kPiPlus, -kKPlus}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}}; -static constexpr std::array, nChannels> arrPDGFinal3Prong = {{{}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kProton, -kKPlus, +kPiPlus}, {+kProton, -kPiPlus, +kPiPlus}, {+kProton, -kKPlus, +kPiPlus}, {}, {}, {}, {}}}; -static constexpr std::array, nChannels> arrPDGFinal4Prong = {{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {+kPiPlus, -kPiPlus, -kPiPlus, +kProton}, {+kPiPlus, -kKPlus, -kPiPlus, +kProton}, {+kPiPlus, -kPiPlus, -kPiPlus, +kProton}}}; -static constexpr std::array, nChannels> arrPDGFinal5Prong = {{{}, {}, {}, {}, {}, {}, {}, {}, {}, {+kPiPlus, +kPiPlus, -kPiPlus, -kPiPlus, +kProton}, {}, {}, {}}}; +static constexpr std::array, nChannels> arrPDGFinal2Prong = {{{+kPiPlus, -kKPlus}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}}; +static constexpr std::array, nChannels> arrPDGFinal3Prong = {{{}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {}, {}, {}, {}, {+kProton, -kKPlus, +kPiPlus}, {+kProton, -kPiPlus, +kPiPlus}, {+kProton, -kKPlus, +kPiPlus}, {}, {}, {}, {}}}; +static constexpr std::array, nChannels> arrPDGFinal4Prong = {{{}, {}, {}, {}, {}, {}, {}, {}, {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}, {}, {}, {}, {}, {+kPiPlus, -kPiPlus, -kPiPlus, +kProton}, {+kPiPlus, -kKPlus, -kPiPlus, +kProton}, {+kPiPlus, -kPiPlus, -kPiPlus, +kProton}}}; +static constexpr std::array, nChannels> arrPDGFinal5Prong = {{{}, {}, {}, {}, {}, {}, {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, {}, {}, {}, {}, {}, {+kPiPlus, +kPiPlus, -kPiPlus, -kPiPlus, +kProton}, {}, {}, {}}}; static constexpr std::string_view labels[nChannels] = {"D^{0} #rightarrow K#pi", "D*^{+} #rightarrow D^{0}#pi", "D^{+} #rightarrow K#pi#pi", "D^{+} #rightarrow KK#pi", "D_{s}^{+} #rightarrow #Phi#pi #rightarrow KK#pi", - "D_{s}^{+} #rightarrow #bar{K}^{*0}K #rightarrow KK#pi", "#Lambda_{c}^{+} #rightarrow pK#pi", "#Lambda_{c}^{+} #rightarrow pK^{0}_{s}", "#Xi_{c}^{+} #rightarrow pK#pi", + "D_{s}^{+} #rightarrow #bar{K}^{*0}K #rightarrow KK#pi", "D_{s}1 #rightarrow D*^{+}K^{0}_{s}", "D_{s}2* #rightarrow D^{+}K^{0}_{s}", "D1^{0} #rightarrow D*^{+}#pi", + "D2^{*} #rightarrow D^{+}#pi", "#Lambda_{c}^{+} #rightarrow pK#pi", "#Lambda_{c}^{+} #rightarrow pK^{0}_{s}", "#Xi_{c}^{+} #rightarrow pK#pi", "#Xi_{c}^{+} #rightarrow #Xi#pi#pi", "#Xi_{c}^{0} #rightarrow #Xi#pi", "#Omega_{c}^{0} #rightarrow #Omega#pi", "#Omega_{c}^{0} #rightarrow #Xi#pi"}; -static constexpr std::string_view particleNames[nChannels] = {"DzeroToKPi", "DstarToDzeroPi", "DplusToPiKPi", "DplusToPhiPiToKKPi", "DsToPhiPiToKKPi", "DsToK0starKToKKPi", +static constexpr std::string_view particleNames[nChannels] = {"DzeroToKPi", "DstarToDzeroPi", "DplusToPiKPi", "DplusToPhiPiToKKPi", "DsToPhiPiToKKPi", "DsToK0starKToKKPi", "Ds1ToDStarK0s", "Ds2StarToDPlusK0s", "D10ToDStarPi", "D2Star0ToDPlusPi", "LcToPKPi", "LcToPiK0s", "XiCplusToPKPi", "XiCplusToXiPiPi", "XiCzeroToXiPi", "OmegaCToOmegaPi", "OmegaCToXiPi"}; static constexpr std::string_view originNames[nOriginTypes] = {"Prompt", "NonPrompt"}; } // namespace @@ -79,15 +91,22 @@ static constexpr std::string_view originNames[nOriginTypes] = {"Prompt", "NonPro /// - Number of candidates per collision /// - Momentum Conservation for these particles struct HfTaskMcValidationGen { - Configurable xVertexMin{"xVertexMin", -100., "min. x of generated primary vertex [cm]"}; - Configurable xVertexMax{"xVertexMax", 100., "max. x of generated primary vertex [cm]"}; - Configurable yVertexMin{"yVertexMin", -100., "min. y of generated primary vertex [cm]"}; - Configurable yVertexMax{"yVertexMax", 100., "max. y of generated primary vertex [cm]"}; - Configurable zVertexMin{"zVertexMin", -100., "min. z of generated primary vertex [cm]"}; - Configurable zVertexMax{"zVertexMax", 100., "max. z of generated primary vertex [cm]"}; + + using BCsInfo = soa::Join; + using CollisionsNoCents = soa::Join; + using CollisionsFT0Cs = soa::Join; + using CollisionsFT0Ms = soa::Join; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + Configurable eventGeneratorType{"eventGeneratorType", -1, "If positive, enable event selection using subGeneratorId information. The value indicates which events to keep (0 = MB, 4 = charm triggered, 5 = beauty triggered)"}; + Configurable rejectParticlesFromBkgEvent{"rejectParticlesFromBkgEvent", true, "Reject particles"}; + + HfEventSelectionMc hfEvSelMc; // mc event selection and monitoring - AxisSpec axisNhadrons{10, -0.5, 9.5}; + AxisSpec axisNhadrons{nChannels, -0.5, static_cast(nChannels) - 0.5}; AxisSpec axisNquarks{20, -0.5, 19.5}; AxisSpec axisResiduals{100, -0.01, 0.01}; AxisSpec axisPt{100, 0., 50.}; @@ -123,8 +142,14 @@ struct HfTaskMcValidationGen { {"NonPromptCharmBaryons/hNonPromptBaryonsYDistr", "Y distribution vs non-prompt charm baryon; ; #it{y}^{gen}", {HistType::kTH2F, {axisBaryonSpecies, axisY}}}, {"NonPromptCharmBaryons/hNonPromptBaryonsDecLenDistr", "Decay length distribution vs non-prompt charm baryon; ; decay length (#mum)", {HistType::kTH2F, {axisBaryonSpecies, axisDecLen}}}}}; - void init(InitContext&) + void init(InitContext& initContext) { + + std::array processes = {doprocessNoCentSel, doprocessCentFT0C, doprocessCentFT0M}; + if (std::accumulate(processes.begin(), processes.end(), 0) > 1) { + LOGP(fatal, "At most one process function for generated particles can be enabled at a time."); + } + // add per species histograms for (size_t iOrigin = 0; iOrigin < nOriginTypes; iOrigin++) { for (int iChannel = 0; iChannel < nMesonChannels; iChannel++) { @@ -153,35 +178,38 @@ struct HfTaskMcValidationGen { registry.get(HIST("NonPromptCharmBaryons/hNonPromptBaryonsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); registry.get(HIST("NonPromptCharmBaryons/hNonPromptBaryonsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); } - } - /// Primary-vertex selection - /// \param collision mcCollision table row - template - bool selectVertex(const Col& collision) - { - // x position - if (collision.posX() < xVertexMin || collision.posX() > xVertexMax) { - return false; - } - // y position - if (collision.posY() < yVertexMin || collision.posY() > yVertexMax) { - return false; - } - // z position - if (collision.posZ() < zVertexMin || collision.posZ() > zVertexMax) { - return false; + // inspect for which particle species the candidates were created and which zPvPosMax cut was set for reconstructed + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-task-mc-validation-rec") == 0) { + hfEvSelMc.configureFromDevice(device); + break; + } } - return true; + + hfEvSelMc.addHistograms(registry); // particles monitoring } - void process(aod::McCollision const& mcCollision, - aod::McParticles const& mcParticles) + template + void runCheckGenParticles(GenColl const& mcCollision, Particles const& mcParticles, RecoColls const& recoCollisions, BCsInfo const&, std::array& counterPrompt, std::array& counterNonPrompt) { if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { return; } - if (!selectVertex(mcCollision)) { + + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + if constexpr (centEstimator == CentralityEstimator::FT0C) { + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, recoCollisions, centrality); + } else if constexpr (centEstimator == CentralityEstimator::FT0M) { + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, recoCollisions, centrality); + } else if constexpr (centEstimator == CentralityEstimator::None) { + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, recoCollisions, centrality); + } + hfEvSelMc.fillHistograms(rejectionMask); + if (rejectionMask != 0) { return; } @@ -189,16 +217,20 @@ struct HfTaskMcValidationGen { int cBarPerCollision = 0; int bPerCollision = 0; int bBarPerCollision = 0; - std::array counterPrompt{0}, counterNonPrompt{0}; for (const auto& particle : mcParticles) { + + if (rejectParticlesFromBkgEvent && particle.fromBackgroundEvent()) { + continue; + } + if (!particle.has_mothers()) { continue; } int particlePdgCode = particle.pdgCode(); bool isDiffFromMothers = true; - for (const auto& mother : particle.mothers_as()) { + for (const auto& mother : particle.template mothers_as()) { if (particlePdgCode == mother.pdgCode()) { isDiffFromMothers = false; break; @@ -268,6 +300,14 @@ struct HfTaskMcValidationGen { if (!RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], arrPDGFinal4Prong[iD], true, nullptr, maxDepthForSearch[iD], &listDaughters)) { continue; } + if (iD == D10ToDStarPi && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+o2::constants::physics::Pdg::kDStar, -kPiPlus}, true)) { + continue; + } + if (iD == D2Star0ToDPlusPi && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+o2::constants::physics::Pdg::kDPlus, -kPiPlus}, true)) { + continue; + } if ((iD == XiCzeroToXiPi || iD == OmegaCToXiPi) && !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+kXiMinus, +kPiPlus}, true)) { continue; @@ -282,6 +322,16 @@ struct HfTaskMcValidationGen { if (!RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], arrPDGFinal5Prong[iD], true, nullptr, maxDepthForSearch[iD], &listDaughters)) { continue; } + if (iD == Ds1ToDStarK0s && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+kK0Short, +o2::constants::physics::Pdg::kDStar}, false, nullptr, 2) && + !RecoDecay::isMatchedMCGen(mcParticles, particle, -PDGArrayParticle[iD], std::array{+kK0Short, -o2::constants::physics::Pdg::kDStar}, false, nullptr, 2)) { + continue; + } + if (iD == Ds2StarToDPlusK0s && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+kK0Short, +o2::constants::physics::Pdg::kDPlus}, false, nullptr, 2) && + !RecoDecay::isMatchedMCGen(mcParticles, particle, -PDGArrayParticle[iD], std::array{+kK0Short, -o2::constants::physics::Pdg::kDPlus}, false, nullptr, 2)) { + continue; + } if (iD == XiCplusToXiPiPi && !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+kXiMinus, +kPiPlus, +kPiPlus}, true, nullptr, 2)) { continue; @@ -321,7 +371,7 @@ struct HfTaskMcValidationGen { counterNonPrompt[iD]++; } - auto daughter0 = particle.daughters_as().begin(); + auto daughter0 = particle.template daughters_as().begin(); double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; double vertexPrimary[3] = {mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()}; auto decayLength = RecoDecay::distance(vertexPrimary, vertexDau); @@ -361,17 +411,79 @@ struct HfTaskMcValidationGen { registry.fill(HIST("Quarks/hCountB"), bPerCollision); registry.fill(HIST("Quarks/hCountCbar"), cBarPerCollision); registry.fill(HIST("Quarks/hCountBbar"), bBarPerCollision); - static_for<0, nMesonChannels - 1>([&](auto i) { - constexpr int index = i.value; - registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); - registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); - }); - static_for([&](auto i) { - constexpr int index = i.value; - registry.fill(HIST("PromptCharmBaryons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); - registry.fill(HIST("NonPromptCharmBaryons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); - }); - }; + } + + void processNoCentSel(aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles, + CollisionsNoCents const& recoCollisions, + BCsInfo const& bcInfo) + { + for (const auto& mcCollision : mcCollisions) { + const auto recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + std::array counterPrompt{0}, counterNonPrompt{0}; + runCheckGenParticles(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt); + static_for<0, nMesonChannels - 1>([&](auto i) { + constexpr int index = i.value; + registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); + registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); + }); + static_for([&](auto i) { + constexpr int index = i.value; + registry.fill(HIST("PromptCharmBaryons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); + registry.fill(HIST("NonPromptCharmBaryons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); + }); + } + } // end processNoCentSel + PROCESS_SWITCH(HfTaskMcValidationGen, processNoCentSel, "Process generated collisions information without centrality selection", true); + + void processCentFT0C(aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles, + CollisionsFT0Cs const& recoCollisions, + BCsInfo const& bcInfo) + { + for (const auto& mcCollision : mcCollisions) { + const auto recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + std::array counterPrompt{0}, counterNonPrompt{0}; + runCheckGenParticles(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt); + static_for<0, nMesonChannels - 1>([&](auto i) { + constexpr int index = i.value; + registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); + registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); + }); + static_for([&](auto i) { + constexpr int index = i.value; + registry.fill(HIST("PromptCharmBaryons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); + registry.fill(HIST("NonPromptCharmBaryons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); + }); + } + } // end processCentFT0C + PROCESS_SWITCH(HfTaskMcValidationGen, processCentFT0C, "Process generated collisions information with centrality selection using FT0C", false); + + void processCentFT0M(aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles, + CollisionsFT0Ms const& recoCollisions, + BCsInfo const& bcInfo) + { + for (const auto& mcCollision : mcCollisions) { + const auto recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + std::array counterPrompt{0}, counterNonPrompt{0}; + runCheckGenParticles(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt); + static_for<0, nMesonChannels - 1>([&](auto i) { + constexpr int index = i.value; + registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); + registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); + }); + static_for([&](auto i) { + constexpr int index = i.value; + registry.fill(HIST("PromptCharmBaryons/hCountPrompt") + HIST(particleNames[index]), counterPrompt[index]); + registry.fill(HIST("NonPromptCharmBaryons/hCountNonPrompt") + HIST(particleNames[index]), counterNonPrompt[index]); + }); + } + } // end processCentFT0M + PROCESS_SWITCH(HfTaskMcValidationGen, processCentFT0M, "Process generated collisions information with centrality selection using FT0M", false); }; /// Reconstruction Level Validation @@ -393,12 +505,17 @@ struct HfTaskMcValidationRec { using HfCand2ProngWithMCRec = soa::Join; using HfCand3ProngWithMCRec = soa::Join; - using CollisionsWithMCLabels = soa::Join; + using CollisionsWithMCLabels = soa::Join; + using CollisionsWithMCLabelsAndCentFT0C = soa::Join; + using CollisionsWithMCLabelsAndCentFT0M = soa::Join; using TracksWithSel = soa::Join; Partition tracksFilteredGlobalTrackWoDCA = requireGlobalTrackWoDCAInFilter(); Partition tracksInAcc = requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks); + Service ccdb; + HfEventSelection hfEvSel; // event selection and monitoring + AxisSpec axisDeltaMom{2000, -1., 1.}; AxisSpec axisOrigin{4, -1.5, 2.5}; AxisSpec axisEta{40, -1., 1.}; @@ -422,6 +539,8 @@ struct HfTaskMcValidationRec { {"TrackToCollChecks/histAmbiguousTrackZvtxRMS", "RMS of #it{Z}^{reco} of collisions associated to a track;RMS(#it{Z}^{reco}) (cm);entries", {HistType::kTH1F, {{100, 0., 0.5}}}}, {"TrackToCollChecks/histFracGoodContributors", "Fraction of PV contributors originating from the correct collision;fraction;entries", {HistType::kTH1F, {{101, 0., 1.01}}}}, {"TrackToCollChecks/histCollisionsSameBC", "Collisions in same BC;number of contributors collision 1;number of contributors collision 2;#it{R}_{xy} collision 1 (cm);#it{R}_{xy} collision 2 (cm);number of contributors from beauty collision 1;number of contributors from beauty collision 2;", {HistType::kTHnSparseF, {axisMult, axisMult, axisR, axisR, axisSmallNum, axisSmallNum}}}}}; + HistogramRegistry registryMesons{"registryMesons"}; + HistogramRegistry registryBaryons{"registryBaryons"}; /// RMS calculation /// \param vec vector of values to compute RMS @@ -478,6 +597,16 @@ struct HfTaskMcValidationRec { void init(InitContext&) { + std::array procCollisions = {doprocessColl, doprocessCollWithCentFTOC, doprocessCollWithCentFTOM}; + if (std::accumulate(procCollisions.begin(), procCollisions.end(), 0) > 1) { + LOGP(fatal, "At most one process function for collision study can be enabled at a time."); + } + + std::array procCollAccoc = {doprocessCollAssoc, doprocessCollAssocWithCentFTOC, doprocessCollAssocWithCentFTOM}; + if (std::accumulate(procCollAccoc.begin(), procCollAccoc.end(), 0) > 1) { + LOGP(fatal, "At most one process for collision association study function can be enabled at a time."); + } + histOriginTracks[0] = registry.add("TrackToCollChecks/histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks not associated to any collision histOriginTracks[1] = registry.add("TrackToCollChecks/histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associasted to a collision histOriginTracks[2] = registry.add("TrackToCollChecks/histOriginGoodAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) @@ -499,39 +628,70 @@ struct HfTaskMcValidationRec { histAmbiguousTracks->GetXaxis()->SetBinLabel(3, "charm"); histAmbiguousTracks->GetXaxis()->SetBinLabel(4, "beauty"); for (auto iHad = 0; iHad < nChannels; ++iHad) { - histDeltaPt[iHad] = registry.add(Form("%s/histDeltaPt", particleNames[iHad].data()), Form("Pt difference reco - MC %s; #it{p}_{T}^{reco} - #it{p}_{T}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaPx[iHad] = registry.add(Form("%s/histDeltaPx", particleNames[iHad].data()), Form("Px difference reco - MC %s; #it{p}_{x}^{reco} - #it{p}_{x}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaPy[iHad] = registry.add(Form("%s/histDeltaPy", particleNames[iHad].data()), Form("Py difference reco - MC %s; #it{p}_{y}^{reco} - #it{p}_{y}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaPz[iHad] = registry.add(Form("%s/histDeltaPz", particleNames[iHad].data()), Form("Pz difference reco - MC %s; #it{p}_{z}^{reco} - #it{p}_{z}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaSecondaryVertexX[iHad] = registry.add(Form("%s/histDeltaSecondaryVertexX", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta x (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - histDeltaSecondaryVertexY[iHad] = registry.add(Form("%s/histDeltaSecondaryVertexY", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta y (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - histDeltaSecondaryVertexZ[iHad] = registry.add(Form("%s/histDeltaSecondaryVertexZ", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - histDeltaDecayLength[iHad] = registry.add(Form("%s/histDeltaDecayLength", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - for (auto iOrigin = 0; iOrigin < 2; ++iOrigin) { - histPtReco[iHad][iOrigin] = registry.add(Form("%s/histPtReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); - for (unsigned int iDau = 0; iDau < nDaughters[iHad]; ++iDau) { - histPtDau[iHad][iOrigin][iDau] = registry.add(Form("%s/histPtDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); - histEtaDau[iHad][iOrigin][iDau] = registry.add(Form("%s/histEtaDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); - histImpactParameterDau[iHad][iOrigin][iDau] = registry.add(Form("%s/histImpactParameterDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d DCAxy reco - %s %s; DCAxy (cm); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + if (iHad < nMesonChannels) { + histDeltaPt[iHad] = registryMesons.add(Form("%s/histDeltaPt", particleNames[iHad].data()), Form("Pt difference reco - MC %s; #it{p}_{T}^{reco} - #it{p}_{T}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPx[iHad] = registryMesons.add(Form("%s/histDeltaPx", particleNames[iHad].data()), Form("Px difference reco - MC %s; #it{p}_{x}^{reco} - #it{p}_{x}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPy[iHad] = registryMesons.add(Form("%s/histDeltaPy", particleNames[iHad].data()), Form("Py difference reco - MC %s; #it{p}_{y}^{reco} - #it{p}_{y}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPz[iHad] = registryMesons.add(Form("%s/histDeltaPz", particleNames[iHad].data()), Form("Pz difference reco - MC %s; #it{p}_{z}^{reco} - #it{p}_{z}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaSecondaryVertexX[iHad] = registryMesons.add(Form("%s/histDeltaSecondaryVertexX", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta x (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaSecondaryVertexY[iHad] = registryMesons.add(Form("%s/histDeltaSecondaryVertexY", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta y (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaSecondaryVertexZ[iHad] = registryMesons.add(Form("%s/histDeltaSecondaryVertexZ", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaDecayLength[iHad] = registryMesons.add(Form("%s/histDeltaDecayLength", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + for (auto iOrigin = 0; iOrigin < 2; ++iOrigin) { + histPtReco[iHad][iOrigin] = registryMesons.add(Form("%s/histPtReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); + for (unsigned int iDau = 0; iDau < nDaughters[iHad]; ++iDau) { + histPtDau[iHad][iOrigin][iDau] = registryMesons.add(Form("%s/histPtDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); + histEtaDau[iHad][iOrigin][iDau] = registryMesons.add(Form("%s/histEtaDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); + histImpactParameterDau[iHad][iOrigin][iDau] = registryMesons.add(Form("%s/histImpactParameterDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d DCAxy reco - %s %s; DCAxy (cm); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + } + } + } else { + histDeltaPt[iHad] = registryBaryons.add(Form("%s/histDeltaPt", particleNames[iHad].data()), Form("Pt difference reco - MC %s; #it{p}_{T}^{reco} - #it{p}_{T}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPx[iHad] = registryBaryons.add(Form("%s/histDeltaPx", particleNames[iHad].data()), Form("Px difference reco - MC %s; #it{p}_{x}^{reco} - #it{p}_{x}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPy[iHad] = registryBaryons.add(Form("%s/histDeltaPy", particleNames[iHad].data()), Form("Py difference reco - MC %s; #it{p}_{y}^{reco} - #it{p}_{y}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPz[iHad] = registryBaryons.add(Form("%s/histDeltaPz", particleNames[iHad].data()), Form("Pz difference reco - MC %s; #it{p}_{z}^{reco} - #it{p}_{z}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaSecondaryVertexX[iHad] = registryBaryons.add(Form("%s/histDeltaSecondaryVertexX", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta x (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaSecondaryVertexY[iHad] = registryBaryons.add(Form("%s/histDeltaSecondaryVertexY", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta y (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaSecondaryVertexZ[iHad] = registryBaryons.add(Form("%s/histDeltaSecondaryVertexZ", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaDecayLength[iHad] = registryBaryons.add(Form("%s/histDeltaDecayLength", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + for (auto iOrigin = 0; iOrigin < 2; ++iOrigin) { + histPtReco[iHad][iOrigin] = registryBaryons.add(Form("%s/histPtReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); + for (unsigned int iDau = 0; iDau < nDaughters[iHad]; ++iDau) { + histPtDau[iHad][iOrigin][iDau] = registryBaryons.add(Form("%s/histPtDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); + histEtaDau[iHad][iOrigin][iDau] = registryBaryons.add(Form("%s/histEtaDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); + histImpactParameterDau[iHad][iOrigin][iDau] = registryBaryons.add(Form("%s/histImpactParameterDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d DCAxy reco - %s %s; DCAxy (cm); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + } } } } histContributors = registry.add("TrackToCollChecks/histContributors", "PV contributors from correct/wrong MC collision;;entries", HistType::kTH1F, {axisDecision}); histContributors->GetXaxis()->SetBinLabel(1, "correct MC collision"); histContributors->GetXaxis()->SetBinLabel(2, "wrong MC collision"); + hfEvSel.addHistograms(registry); // collision monitoring + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); } - void process(CollisionsWithMCLabels::iterator const& collision, - aod::McCollisions const&) + template + void checkCollisions(Coll const& collision, + aod::McCollisions const&, + aod::BCsWithTimestamps const&) { - // check that collision is selected by hf-track-index-skim-creator-tag-sel-collisions - if (collision.whyRejectColl() != 0) { + // apply event selection + if (!collision.has_mcCollision()) { return; } - if (!collision.has_mcCollision()) { + + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { + /// at least one event selection not satisfied --> reject the candidate return; } - auto mcCollision = collision.mcCollision_as(); + + auto mcCollision = collision.template mcCollision_as(); if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { return; } @@ -540,24 +700,30 @@ struct HfTaskMcValidationRec { registry.fill(HIST("histYvtxReco"), collision.posY()); registry.fill(HIST("histZvtxReco"), collision.posZ()); registry.fill(HIST("histDeltaZvtx"), collision.numContrib(), collision.posZ() - mcCollision.posZ()); - } // end process + } - void processCollAssoc(CollisionsWithMCLabels const& collisions, - TracksWithSel const&, - aod::McParticles const& mcParticles, - aod::McCollisions const&, - aod::BCs const&) + template + void checkCollisionAssociation(Colls const& collisions, + TracksWithSel const&, + aod::McParticles const& mcParticles, + aod::McCollisions const&, + aod::BCsWithTimestamps const&) { // loop over collisions - for (auto collision = collisions.begin(); collision != collisions.end(); ++collision) { + for (const auto& collision : collisions) { // check that collision is selected by hf-track-index-skim-creator-tag-sel-collisions - if (collision.whyRejectColl() != 0) { + + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { + /// at least one event selection not satisfied --> reject the candidate continue; } + if (!collision.has_mcCollision()) { continue; } - auto mcCollision = collision.mcCollision_as(); + auto mcCollision = collision.template mcCollision_as(); if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { continue; } @@ -678,8 +844,61 @@ struct HfTaskMcValidationRec { } } } + + void processColl(CollisionsWithMCLabels::iterator const& collision, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs) + { + checkCollisions(collision, mcCollisions, bcs); + } // end process + PROCESS_SWITCH(HfTaskMcValidationRec, processColl, "Process collision information without centrality selection", true); + + void processCollWithCentFTOC(CollisionsWithMCLabelsAndCentFT0C::iterator const& collision, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs) + { + checkCollisions(collision, mcCollisions, bcs); + } // end process + PROCESS_SWITCH(HfTaskMcValidationRec, processCollWithCentFTOC, "Process collision information with centrality selection with FT0C", false); + + void processCollWithCentFTOM(CollisionsWithMCLabelsAndCentFT0M::iterator const& collision, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs) + { + checkCollisions(collision, mcCollisions, bcs); + } // end process + PROCESS_SWITCH(HfTaskMcValidationRec, processCollWithCentFTOM, "Process collision information with centrality selection with FT0M", false); + + void processCollAssoc(CollisionsWithMCLabels const& collisions, + TracksWithSel const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs) + { + checkCollisionAssociation(collisions, tracks, mcParticles, mcCollisions, bcs); + } PROCESS_SWITCH(HfTaskMcValidationRec, processCollAssoc, "Process collision-association information, requires extra table from TrackToCollisionAssociation task (fillTableOfCollIdsPerTrack=true)", false); + void processCollAssocWithCentFTOC(CollisionsWithMCLabelsAndCentFT0C const& collisions, + TracksWithSel const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs) + { + checkCollisionAssociation(collisions, tracks, mcParticles, mcCollisions, bcs); + } + PROCESS_SWITCH(HfTaskMcValidationRec, processCollAssocWithCentFTOC, "Process collision-association information with centrality selection with FT0C, requires extra table from TrackToCollisionAssociation task (fillTableOfCollIdsPerTrack=true)", false); + + void processCollAssocWithCentFTOM(CollisionsWithMCLabelsAndCentFT0M const& collisions, + TracksWithSel const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs) + { + checkCollisionAssociation(collisions, tracks, mcParticles, mcCollisions, bcs); + } + PROCESS_SWITCH(HfTaskMcValidationRec, processCollAssocWithCentFTOM, "Process collision-association information with centrality selection with FT0M, requires extra table from TrackToCollisionAssociation task (fillTableOfCollIdsPerTrack=true)", false); + void processEff(HfCand2ProngWithMCRec const& cand2Prongs, HfCand3ProngWithMCRec const& cand3Prongs, aod::TracksWMc const&, diff --git a/PWGHF/Utils/utilsAnalysis.h b/PWGHF/Utils/utilsAnalysis.h index 0b4233bff15..b10a851072d 100644 --- a/PWGHF/Utils/utilsAnalysis.h +++ b/PWGHF/Utils/utilsAnalysis.h @@ -17,6 +17,7 @@ #include // std::upper_bound #include // std::distance +#include //std::string namespace o2::analysis { @@ -24,7 +25,7 @@ namespace o2::analysis /// \param bins array of pT bins /// \param value pT /// \return index of the pT bin -/// \note Accounts for the offset so that pt bin array can be used to also configure a histogram axis. +/// \note Accounts for the offset so that pT bin array can be used to also configure a histogram axis. template int findBin(T1 const& binsPt, T2 value) { @@ -108,6 +109,48 @@ bool isSelectedTrackTpcQuality(T const& track, const int tpcNClustersFoundMin, c return true; } +/// Mass selection of 2 or 3 prong canidates in triggered data analysis +/// \tparam nProngs switch between 2-prong and 3-prong selection +/// \param invMass is the invariant mass of the candidate +/// \param pdgMass is the pdg Mass of the candidate particle +/// \param pt is the pT of the candidate +/// \param cutConfig is the struct with the pt-dependent mass configurations +/// \return true if candidate passes selection +template +bool isCandidateInMassRange(const float& invMass, const double& pdgMass, const float& pt, Config const& cutConfig) +{ + float peakMean = (pt < cutConfig.ptDeltaMassMax.value) ? ((pdgMass + cutConfig.deltaMassPars->get("constant")) + cutConfig.deltaMassPars->get("linear") * pt) : pdgMass; + float peakWidth = cutConfig.sigmaPars->get("constant") + cutConfig.sigmaPars->get("linear") * pt; + + return (!(std::abs(invMass - peakMean) > cutConfig.nSigmaMax.value * peakWidth && pt < cutConfig.ptMassCutMax.value)); +} + +/// Configurable group to apply trigger specific cuts for 2-prong HF analysis +struct HfTrigger2ProngCuts : o2::framework::ConfigurableGroup { + std::string prefix = "hfTrigger2ProngCuts"; // JSON group name + + static constexpr float defaultDeltaMassPars[1][2] = {{-0.0025f, 0.0001f}}; + static constexpr float defaultSigmaPars[1][2] = {{0.01424f, 0.00178f}}; + o2::framework::Configurable nSigmaMax{"nSigmaMax", 2, "Maximum number of sigmas for pT-differential mass cut for 2-prong candidates"}; + o2::framework::Configurable ptDeltaMassMax{"ptDeltaMassMax", 10., "Max pT to apply delta mass shift to PDG mass value for 2-prong candidates"}; + o2::framework::Configurable ptMassCutMax{"ptMassCutMax", 9999., "Max pT to apply pT-differential cut for 2-prong candidates"}; + o2::framework::Configurable> deltaMassPars{"deltaMassPars", {defaultDeltaMassPars[0], 2, {"constant", "linear"}}, "delta mass parameters for HF 2-prong trigger mass cut"}; + o2::framework::Configurable> sigmaPars{"sigmaPars", {defaultSigmaPars[0], 2, {"constant", "linear"}}, "sigma parameters for HF 2-prong trigger mass cut"}; +}; + +/// Configurable group to apply trigger specific cuts for 3-prong HF analysis +struct HfTrigger3ProngCuts : o2::framework::ConfigurableGroup { + std::string prefix = "hfTrigger3ProngCuts"; // JSON group name + + static constexpr float defaultDeltaMassPars[1][2] = {{-0.0025f, 0.0001f}}; + static constexpr float defaultSigmaPars[1][2] = {{0.00796f, 0.00176f}}; + o2::framework::Configurable nSigmaMax{"nSigmaMax", 2, "Maximum number of sigmas for pT-differential mass cut for 3-prong candidates"}; + o2::framework::Configurable ptDeltaMassMax{"ptDeltaMassMax", 10., "Max pT to apply delta mass shift to PDG mass value for 3-prong candidates"}; + o2::framework::Configurable ptMassCutMax{"ptMassCutMax", 9999., "Max pT to apply pT-differential cut for 3-prong candidates"}; + o2::framework::Configurable> deltaMassPars{"deltaMassPars", {defaultDeltaMassPars[0], 2, {"constant", "linear"}}, "delta mass parameters for HF 3-prong trigger mass cut"}; + o2::framework::Configurable> sigmaPars{"sigmaPars", {defaultSigmaPars[0], 2, {"constant", "linear"}}, "sigma parameters for HF 3-prong trigger mass cut"}; +}; + } // namespace o2::analysis #endif // PWGHF_UTILS_UTILSANALYSIS_H_ diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index 1b5b0531a25..5c1c93505d4 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -33,6 +33,7 @@ namespace o2::hf_evsel // event rejection types enum EventRejection { None = 0, + SoftwareTrigger, Centrality, Trigger, TvxTrigger, @@ -44,7 +45,6 @@ enum EventRejection { NContrib, Chi2, PositionZ, - SoftwareTrigger, NEventRejection }; @@ -52,11 +52,13 @@ o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +E /// \brief Function to put labels on monitoring histogram /// \param hRejection monitoring histogram +/// \param softwareTriggerLabel bin label for software trigger rejection template void setEventRejectionLabels(Histo& hRejection, std::string softwareTriggerLabel = "") { // Puts labels on the collision monitoring histogram. hRejection->GetXaxis()->SetBinLabel(EventRejection::None + 1, "All"); + hRejection->GetXaxis()->SetBinLabel(EventRejection::SoftwareTrigger + 1, softwareTriggerLabel.data()); hRejection->GetXaxis()->SetBinLabel(EventRejection::Centrality + 1, "Centrality"); hRejection->GetXaxis()->SetBinLabel(EventRejection::Trigger + 1, "Trigger"); hRejection->GetXaxis()->SetBinLabel(EventRejection::TvxTrigger + 1, "TVX Trigger"); @@ -68,7 +70,6 @@ void setEventRejectionLabels(Histo& hRejection, std::string softwareTriggerLabel hRejection->GetXaxis()->SetBinLabel(EventRejection::NContrib + 1, "# of PV contributors"); hRejection->GetXaxis()->SetBinLabel(EventRejection::Chi2 + 1, "PV #it{#chi}^{2}"); hRejection->GetXaxis()->SetBinLabel(EventRejection::PositionZ + 1, "PV #it{z}"); - hRejection->GetXaxis()->SetBinLabel(EventRejection::SoftwareTrigger + 1, softwareTriggerLabel.data()); } struct HfEventSelection : o2::framework::ConfigurableGroup { @@ -90,17 +91,19 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { o2::framework::Configurable chi2PvMax{"chi2PvMax", -1.f, "Maximum PV chi2"}; o2::framework::Configurable zPvPosMin{"zPvPosMin", -10.f, "Minimum PV posZ (cm)"}; o2::framework::Configurable zPvPosMax{"zPvPosMax", 10.f, "Maximum PV posZ (cm)"}; - o2::framework::Configurable softwareTrigger{"softwareTrigger", "", "Label of software trigger. Multiple triggers can be selected dividing them by a comma"}; + o2::framework::Configurable softwareTrigger{"softwareTrigger", "", "Label of software trigger. Multiple triggers can be selected dividing them by a comma. Set None if you want bcs that are not selected by any trigger"}; + o2::framework::Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; // histogram names static constexpr char nameHistCollisions[] = "hCollisions"; + static constexpr char nameHistSelCollisionsCent[] = "hSelCollisionsCent"; static constexpr char nameHistPosZBeforeEvSel[] = "hPosZBeforeEvSel"; static constexpr char nameHistPosZAfterEvSel[] = "hPosZAfterEvSel"; static constexpr char nameHistPosXAfterEvSel[] = "hPosXAfterEvSel"; static constexpr char nameHistPosYAfterEvSel[] = "hPosYAfterEvSel"; static constexpr char nameHistNumPvContributorsAfterSel[] = "hNumPvContributorsAfterSel"; - std::shared_ptr hCollisions, hPosZBeforeEvSel, hPosZAfterEvSel, hPosXAfterEvSel, hPosYAfterEvSel, hNumPvContributorsAfterSel; + std::shared_ptr hCollisions, hSelCollisionsCent, hPosZBeforeEvSel, hPosZAfterEvSel, hPosXAfterEvSel, hPosYAfterEvSel, hNumPvContributorsAfterSel; // util to retrieve trigger mask in case of software triggers Zorro zorro; @@ -111,12 +114,13 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { void addHistograms(o2::framework::HistogramRegistry& registry) { hCollisions = registry.add(nameHistCollisions, "HF event counter;;# of accepted collisions", {o2::framework::HistType::kTH1D, {axisEvents}}); + hSelCollisionsCent = registry.add(nameHistSelCollisionsCent, "HF event counter;T0M;# of accepted collisions", {o2::framework::HistType::kTH1D, {{100, 0., 100.}}}); hPosZBeforeEvSel = registry.add(nameHistPosZBeforeEvSel, "all events;#it{z}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{400, -20., 20.}}}); hPosZAfterEvSel = registry.add(nameHistPosZAfterEvSel, "selected events;#it{z}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{400, -20., 20.}}}); hPosXAfterEvSel = registry.add(nameHistPosXAfterEvSel, "selected events;#it{x}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); hPosYAfterEvSel = registry.add(nameHistPosYAfterEvSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); hNumPvContributorsAfterSel = registry.add(nameHistNumPvContributorsAfterSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{500, -0.5, 499.5}}}); - setEventRejectionLabels(hCollisions); + setEventRejectionLabels(hCollisions, softwareTrigger); } /// \brief Applies event selection. @@ -125,9 +129,10 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { /// \param collision collision to test against the selection criteria /// \param centrality collision centrality variable to be set in this function /// \param ccdb ccdb service needed to retrieve the needed info for zorro + /// \param registry reference to the histogram registry needed for zorro /// \return bitmask with the event selection criteria not satisfied by the collision template - uint16_t getHfCollisionRejectionMask(const Coll& collision, float& centrality, o2::framework::Service const& ccdb) + uint16_t getHfCollisionRejectionMask(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry) { uint16_t rejectionMask{0}; // 16 bits, in case new ev. selections will be added @@ -205,11 +210,19 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { int runNumber = bc.runNumber(); if (runNumber != currentRun) { // We might need to update Zorro from CCDB if the run number changes zorro.initCCDB(ccdb.service, runNumber, bc.timestamp(), softwareTrigger.value); + zorro.setBCtolerance(bcMarginForSoftwareTrigger); currentRun = runNumber; } + zorro.populateHistRegistry(registry, runNumber); - if (!zorro.isSelected(bc.globalBC())) { /// Just let Zorro do the accounting - SETBIT(rejectionMask, EventRejection::SoftwareTrigger); + if (softwareTrigger.value != "None") { + if (!zorro.isSelected(bc.globalBC(), bcMarginForSoftwareTrigger)) { /// Just let Zorro do the accounting + SETBIT(rejectionMask, EventRejection::SoftwareTrigger); + } + } else { + if (!zorro.isNotSelectedByAny(bc.globalBC(), bcMarginForSoftwareTrigger)) { /// Just let Zorro do the accounting of not selected BCs + SETBIT(rejectionMask, EventRejection::SoftwareTrigger); + } } } @@ -220,7 +233,7 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { /// \param collision analysed collision /// \param rejectionMask bitmask storing the info about which ev. selections are not satisfied by the collision template - void fillHistograms(Coll const& collision, const uint16_t rejectionMask) + void fillHistograms(Coll const& collision, const uint16_t rejectionMask, float& centrality) { hCollisions->Fill(EventRejection::None); const float posZ = collision.posZ(); @@ -237,6 +250,7 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { hPosYAfterEvSel->Fill(collision.posY()); hPosZAfterEvSel->Fill(posZ); hNumPvContributorsAfterSel->Fill(collision.numContrib()); + hSelCollisionsCent->Fill(centrality); } }; @@ -248,6 +262,8 @@ struct HfEventSelectionMc { bool useItsRofBorderCut{false}; // Apply the ITS RO frame border cut float zPvPosMin{-1000.f}; // Minimum PV posZ (cm) float zPvPosMax{1000.f}; // Maximum PV posZ (cm) + float centralityMin{0.f}; // Minimum centrality + float centralityMax{100.f}; // Maximum centrality // histogram names static constexpr char nameHistParticles[] = "hParticles"; @@ -277,20 +293,53 @@ struct HfEventSelectionMc { zPvPosMin = option.defaultValue.get(); } else if (option.name.compare("hfEvSel.zPvPosMax") == 0) { zPvPosMax = option.defaultValue.get(); + } else if (option.name.compare("hfEvSel.centralityMin") == 0) { + centralityMin = option.defaultValue.get(); + } else if (option.name.compare("hfEvSel.centralityMax") == 0) { + centralityMax = option.defaultValue.get(); } } } /// \brief Function to apply event selections to generated MC collisions /// \param mcCollision MC collision to test against the selection criteria + /// \param collSlice collection of reconstructed collisions + /// \param centrality centrality variable to be set in this function /// \return a bitmask with the event selections not satisfied by the analysed collision - template - uint16_t getHfMcCollisionRejectionMask(TMcColl const& mcCollision) + template + uint16_t getHfMcCollisionRejectionMask(TMcColl const& mcCollision, CCs const& collSlice, float& centrality) { uint16_t rejectionMask{0}; float zPv = mcCollision.posZ(); auto bc = mcCollision.template bc_as(); + if constexpr (centEstimator != o2::hf_centrality::CentralityEstimator::None) { + float multiplicity{0.f}; + for (const auto& collision : collSlice) { + float collCent{0.f}; + float collMult{0.f}; + if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0A) { + collCent = collision.centFT0A(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0C) { + collCent = collision.centFT0C(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0M) { + collCent = collision.centFT0M(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FV0A) { + collCent = collision.centFV0A(); + } else { + LOGP(fatal, "Unsupported centrality estimator!"); + } + collMult = collision.numContrib(); + if (collMult > multiplicity) { + centrality = collCent; + multiplicity = collMult; + } + } + /// centrality selection + if (centrality < centralityMin || centrality > centralityMax) { + SETBIT(rejectionMask, EventRejection::Centrality); + } + } /// Sel8 trigger selection if (useSel8Trigger && (!bc.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { SETBIT(rejectionMask, EventRejection::Trigger); diff --git a/PWGJE/Core/FastJetUtilities.cxx b/PWGJE/Core/FastJetUtilities.cxx index ae2a91345c6..ba7acabbdf3 100644 --- a/PWGJE/Core/FastJetUtilities.cxx +++ b/PWGJE/Core/FastJetUtilities.cxx @@ -23,7 +23,7 @@ void fastjetutilities::setFastJetUserInfo(std::vector& const if (status == static_cast(JetConstituentStatus::cluster)) { i = -1 * (i + 1); } - if (status == static_cast(JetConstituentStatus::candidateHF)) { + if (status == static_cast(JetConstituentStatus::candidate)) { i = 0; } constituents.back().set_user_index(i); // FIXME: needed for constituent subtraction, but need to be quite careful to make sure indices dont overlap between tracks, clusters and HF candidates. Current solution might not be optimal diff --git a/PWGJE/Core/FastJetUtilities.h b/PWGJE/Core/FastJetUtilities.h index bce39428c10..01da286521b 100644 --- a/PWGJE/Core/FastJetUtilities.h +++ b/PWGJE/Core/FastJetUtilities.h @@ -30,7 +30,7 @@ enum class JetConstituentStatus { track = 0, cluster = 1, - candidateHF = 2 + candidate = 2 }; namespace fastjetutilities @@ -85,7 +85,7 @@ void setFastJetUserInfo(std::vector& constituents, int index template void fillTracks(const T& constituent, std::vector& constituents, int index = -99999999, int status = static_cast(JetConstituentStatus::track), float mass = mPion) { - if (status == static_cast(JetConstituentStatus::track) || status == static_cast(JetConstituentStatus::candidateHF)) { + if (status == static_cast(JetConstituentStatus::track) || status == static_cast(JetConstituentStatus::candidate)) { // auto p = std::sqrt((constituent.px() * constituent.px()) + (constituent.py() * constituent.py()) + (constituent.pz() * constituent.pz())); auto energy = std::sqrt((constituent.p() * constituent.p()) + (mass * mass)); constituents.emplace_back(constituent.px(), constituent.py(), constituent.pz(), energy); diff --git a/PWGJE/Core/JetCandidateUtilities.h b/PWGJE/Core/JetCandidateUtilities.h new file mode 100644 index 00000000000..43e66f82d66 --- /dev/null +++ b/PWGJE/Core/JetCandidateUtilities.h @@ -0,0 +1,418 @@ +// Copyright 2019-2020 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. + +/// \file JetCandidateUtilities.h +/// \brief Jet candidate related utilities +/// +/// \author Nima Zardoshti + +#ifndef PWGJE_CORE_JETCANDIDATEUTILITIES_H_ +#define PWGJE_CORE_JETCANDIDATEUTILITIES_H_ + +#include +#include +#include +#include +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/O2DatabasePDGPlugin.h" + +#include "Framework/Logger.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGJE/DataModel/EMCALClusters.h" + +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/DataModel/DerivedTablesStored.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetV0Utilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" + +namespace jetcandidateutilities +{ + +/** + * returns true if the candidate is from a candidate table + * * @param candidate candidate that is being checked + */ +template +constexpr bool isCandidate() +{ + if constexpr (jethfutilities::isHFCandidate()) { + return true; + } else if constexpr (jetv0utilities::isV0Candidate()) { + return true; + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return true; + } else { + return false; + } +} + +/** + * returns true if the candidate is from a MC candidate table + * * @param candidate candidate that is being checked + */ +template +constexpr bool isMcCandidate() +{ + if constexpr (jethfutilities::isHFMcCandidate()) { + return true; + } else if constexpr (jetv0utilities::isV0McCandidate()) { + return true; + } else if constexpr (jetdqutilities::isDielectronMcCandidate()) { + return true; + } else { + return false; + } +} + +/** + * returns true if the table type is a candidate table + */ +template +constexpr bool isCandidateTable() +{ + if constexpr (jethfutilities::isHFTable()) { + return true; + } else if constexpr (jetv0utilities::isV0Table()) { + return true; + } else if constexpr (jetdqutilities::isDielectronTable()) { + return true; + } else { + return false; + } +} + +/** + * returns true if the table type is a candidate table + */ +template +constexpr bool isCandidateMcTable() +{ + if constexpr (jethfutilities::isHFMcTable()) { + return true; + } else if constexpr (jetv0utilities::isV0McTable()) { + return true; + } else if constexpr (jetdqutilities::isDielectronMcTable()) { + return true; + } else { + return false; + } +} + +/** + * returns true if the candidate is matched to a reconstructed level candidate with the correct decay + * * @param candidate candidate that is being checked + */ +template +constexpr bool isMatchedCandidate(T const& candidate) +{ + if constexpr (jethfutilities::isHFCandidate() || jethfutilities::isHFMcCandidate()) { + return jethfutilities::isMatchedHFCandidate(candidate); + } else if constexpr (jetdqutilities::isDielectronCandidate() || jetdqutilities::isDielectronMcCandidate()) { + return jetdqutilities::isMatchedDielectronCandidate(candidate); + } else { + return false; + } +} + +/** + * returns true if the track is a daughter of the candidate + * + * @param track track that is being checked + * @param candidate candidate that is being checked + * @param tracks the track table + */ +template +bool isDaughterTrack(T& track, U& candidate, V const& tracks) +{ + if constexpr (jethfutilities::isHFCandidate()) { + return jethfutilities::isHFDaughterTrack(track, candidate, tracks); + } else if constexpr (jetv0utilities::isV0Candidate()) { + return jetv0utilities::isV0DaughterTrack(track, candidate, tracks); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return jetdqutilities::isDielectronDaughterTrack(track, candidate, tracks); + } else { + return false; + } +} + +/** + * returns true if the particle has any daughters with the given global index + * + * @param candidate mother hf particle that is being checked + * @param globalIndex global index of potnetial daughter particle + */ +template +bool isDaughterParticle(const T& particle, int globalIndex) +{ + for (auto daughter : particle.template daughters_as::parent_t>()) { + if (daughter.globalIndex() == globalIndex) { + return true; + } + if (isDaughterParticle(daughter, globalIndex)) { + return true; + } + } + return false; +} + +/** + * returns the index of the JMcParticle matched to the candidate + * + * @param candidate hf candidate that is being checked + * @param tracks track table + * @param particles particle table + */ +template +auto matchedParticleId(const T& candidate, const U& tracks, const V& particles) +{ + if constexpr (jethfutilities::isHFCandidate()) { + return jethfutilities::matchedHFParticleId(candidate, tracks, particles); + } else if constexpr (jetv0utilities::isV0Candidate()) { + return jetv0utilities::matchedV0ParticleId(candidate, tracks, particles); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return jetdqutilities::matchedDielectronParticleId(candidate, tracks, particles); + } else { + return -1; + } +} + +/** + * returns the JMcParticle matched to the candidate + * + * @param candidate hf candidate that is being checked + * @param tracks track table + * @param particles particle table + */ +template +auto matchedParticle(const T& candidate, const U& tracks, const V& particles) +{ + if constexpr (jethfutilities::isHFCandidate()) { + return jethfutilities::matchedHFParticle(candidate, tracks, particles); + } else if constexpr (jetv0utilities::isV0Candidate()) { + return jetv0utilities::matchedV0Particle(candidate, tracks, particles); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return jetdqutilities::matchedDielectronParticle(candidate, tracks, particles); + } else { + return jethfutilities::matchedHFParticle(candidate, tracks, particles); // this is a dummy output which should never be triggered + } +} + +/** + * returns a slice of the table depending on the index of the candidate + * + * @param candidate candidate that is being checked + * @param table the table to be sliced + */ +template +auto slicedPerCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perLcCandidate, N const& perBplusCandidate, O const& perDielectronCandidate) +{ + if constexpr (jethfutilities::isHFCandidate()) { + return jethfutilities::slicedPerHFCandidate(table, candidate, perD0Candidate, perLcCandidate, perBplusCandidate); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return jetdqutilities::slicedPerDielectronCandidate(table, candidate, perDielectronCandidate); + } else { + return table; + } +} + +/** + * returns a slice of the table depending on the type of the candidate and index of the collision + * + * @param candidate candidate that is being checked + * @param table the table to be sliced + */ +template +auto slicedPerCandidateCollision(T const& table, U const& candidates, V const& collision, M const& D0CollisionPerCollision, N const& LcCollisionPerCollision, O const& BplusCollisionPerCollision, P const& DielectronCollisionPerCollision) +{ + if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { + return jethfutilities::slicedPerHFCollision(table, candidates, collision, D0CollisionPerCollision, LcCollisionPerCollision, BplusCollisionPerCollision); + } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { + return jetdqutilities::slicedPerDielectronCollision(table, candidates, collision, DielectronCollisionPerCollision); + } else { + return table; + } +} + +/** + * returns the candidate collision Id of candidate based on type of candidate + * + * @param candidate candidate that is being checked + */ +template +int getCandidateCollisionId(T const& candidate) +{ + if constexpr (jethfutilities::isHFCandidate()) { + return jethfutilities::getHFCandidateCollisionId(candidate); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return jetdqutilities::getDielectronCandidateCollisionId(candidate); + } else { + return -1; + } +} + +/** + * returns the candidate Mc collision Id of candidate based on type of candidate + * + * @param candidate candidate that is being checked + */ +template +int getMcCandidateCollisionId(T const& candidate) +{ + if constexpr (jethfutilities::isHFMcCandidate()) { + return jethfutilities::getHFMcCandidateCollisionId(candidate); + } else if constexpr (jetdqutilities::isDielectronMcCandidate()) { + return jetdqutilities::getDielectronMcCandidateCollisionId(candidate); + } else { + return -1; + } +} + +/** + * returns the PDG of the candidate based on Table + * + * @param candidate candidate that is being checked + */ + +template +int getCandidatePDG(T const& candidate) +{ + if constexpr (jethfutilities::isHFCandidate() || jethfutilities::isHFMcCandidate()) { + return jethfutilities::getHFCandidatePDG(candidate); + } else if constexpr (jetdqutilities::isDielectronCandidate() || jetdqutilities::isDielectronMcCandidate()) { + return jetdqutilities::getDielectronCandidatePDG(candidate); + } else { + return 0; + } +} + +/** + * returns the PDG of the candidates in the table type + */ +template +int getTablePDG() +{ + if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { + return jethfutilities::getHFTablePDG(); + } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { + return jetdqutilities::getDielectronTablePDG(); + } else { + return 0; + } +} + +/** + * returns the pdg mass of the candidate based on Table + * + * @param candidate candidate that is being checked + */ +template +float getCandidatePDGMass(T const& candidate) +{ + if constexpr (jethfutilities::isHFCandidate() || jethfutilities::isHFMcCandidate()) { + return jethfutilities::getHFCandidatePDGMass(candidate); + } else if constexpr (jetdqutilities::isDielectronCandidate() || jetdqutilities::isDielectronMcCandidate()) { + return jetdqutilities::getDielectronCandidatePDGMass(candidate); + } else { + return -1.0; + } +} + +/** + * returns the pdg mass of the candidates in the table type + * + */ +template +float getTablePDGMass() +{ + if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { + return jethfutilities::getHFTablePDGMass(); + } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { + return jetdqutilities::getDielectronTablePDGMass(); + } else { + return -1.0; + } +} + +/** + * returns the invariant mass of the candidate based on Table + * + * @param candidate candidate that is being checked + */ +template +float getCandidateInvariantMass(T const& candidate) +{ + if constexpr (jethfutilities::isHFCandidate()) { + return jethfutilities::getHFCandidateInvariantMass(candidate); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + return jetdqutilities::getDielectronCandidateInvariantMass(candidate); + } else { + return -1.0; + } +} + +template +void fillCandidateCollisionTable(T const& collision, U const& candidates, V& CandiateCollisionTable, int32_t& CandidateCollisionTableIndex) +{ + if constexpr (jethfutilities::isHFTable()) { + jethfutilities::fillHFCollisionTable(collision, candidates, CandiateCollisionTable, CandidateCollisionTableIndex); + } else if constexpr (jetdqutilities::isDielectronTable()) { + jetdqutilities::fillDielectronCollisionTable(collision, CandiateCollisionTable, CandidateCollisionTableIndex); // if more dilepton tables are added we would need a fillDQCollisionTable + } +} + +template +void fillCandidateMcCollisionTable(T const& mcCollision, U const& candidates, V& CandiateMcCollisionTable, int32_t& CandidateMcCollisionTableIndex) +{ + if constexpr (jethfutilities::isHFMcTable()) { + jethfutilities::fillHFMcCollisionTable(mcCollision, candidates, CandiateMcCollisionTable, CandidateMcCollisionTableIndex); + } else if constexpr (jetdqutilities::isDielectronMcTable()) { + jetdqutilities::fillDielectronMcCollisionTable(mcCollision, CandiateMcCollisionTable, CandidateMcCollisionTableIndex); + } +} + +template +void fillCandidateTable(T const& candidate, int32_t collisionIndex, U& BaseTable, V& HFParTable, M& HFParETable, N& HFSelectionFlagTable, O& HFMlTable, P& HFMCDTable, int32_t& candidateTableIndex) +{ + if constexpr (jethfutilities::isHFCandidate()) { + jethfutilities::fillHFCandidateTable(candidate, collisionIndex, BaseTable, HFParTable, HFParETable, HFSelectionFlagTable, HFMlTable, HFMCDTable, candidateTableIndex); + } else if constexpr (jetdqutilities::isDielectronCandidate()) { + jetdqutilities::fillDielectronCandidateTable(candidate, collisionIndex, BaseTable, candidateTableIndex); + } +} + +template +void fillCandidateMcTable(T const& candidate, int32_t mcCollisionIndex, U& BaseMcTable, int32_t& candidateTableIndex) +{ + if constexpr (jethfutilities::isHFMcCandidate()) { + jethfutilities::fillHFCandidateMcTable(candidate, mcCollisionIndex, BaseMcTable, candidateTableIndex); + } else if constexpr (jetdqutilities::isDielectronMcCandidate()) { + jetdqutilities::fillDielectronCandidateMcTable(candidate, mcCollisionIndex, BaseMcTable, candidateTableIndex); + } +} + +}; // namespace jetcandidateutilities + +#endif // PWGJE_CORE_JETCANDIDATEUTILITIES_H_ diff --git a/PWGJE/Core/JetDQUtilities.h b/PWGJE/Core/JetDQUtilities.h new file mode 100644 index 00000000000..fdd5ca9cbcd --- /dev/null +++ b/PWGJE/Core/JetDQUtilities.h @@ -0,0 +1,352 @@ +// Copyright 2019-2020 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. + +/// \file JetDQUtilities.h +/// \brief Jet DQ related utilities +/// +/// \author Nima Zardoshti + +#ifndef PWGJE_CORE_JETDQUTILITIES_H_ +#define PWGJE_CORE_JETDQUTILITIES_H_ + +#include +#include +#include +#include + +#include + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/O2DatabasePDGPlugin.h" + +#include "Framework/Logger.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" + +namespace jetdqutilities +{ + +/** + * returns true if the candidate is from a Dielectron table + */ +template +constexpr bool isDielectronCandidate() +{ + return std::is_same_v, CandidatesDielectronData::iterator> || std::is_same_v, CandidatesDielectronData::filtered_iterator> || std::is_same_v, CandidatesDielectronMCD::iterator> || std::is_same_v, CandidatesDielectronMCD::filtered_iterator>; +} + +/** + * returns true if the candidate is from a MC Dielectron table + */ +template +constexpr bool isDielectronMcCandidate() +{ + return std::is_same_v, CandidatesDielectronMCP::iterator> || std::is_same_v, CandidatesDielectronMCP::filtered_iterator>; +} + +/** + * returns true if the table is a Dielectron table + */ +template +constexpr bool isDielectronTable() +{ + return isDielectronCandidate() || isDielectronCandidate(); +} + +/** + * returns true if the table is a Dielectron MC table + */ +template +constexpr bool isDielectronMcTable() +{ + return isDielectronMcCandidate() || isDielectronMcCandidate(); +} + +/** + * returns true if the candidate is matched to a reconstructed level candidate with the correct decay + * * @param candidate candidate that is being checked + */ +template +constexpr bool isMatchedDielectronCandidate(T const& /*candidate*/) +{ + if constexpr (isDielectronCandidate()) { + // For now the decision to select signals is done in the DQ framework + return true; + } else if constexpr (isDielectronMcCandidate()) { + return true; // this is true because we always only select Jpsi in our decay channel. If more channels are added this needs to be expanded + } else { + return false; + } +} + +/** + * returns true if the track is a daughter of the dielectron candidate + * + * @param track track that is being checked + * @param candidate Dielectron candidate that is being checked + * @param tracks the track table + */ +template +bool isDielectronDaughterTrack(T& track, U& candidate, V const& /*tracks*/) +{ + if constexpr (isDielectronCandidate()) { + if (candidate.prong0Id() == track.globalIndex() || candidate.prong1Id() == track.globalIndex()) { + return true; + } else { + return false; + } + } else { + return false; + } +} + +/** + * returns the index of the JMcParticle matched to the Dielectron candidate + * + * @param candidate dielectron candidate that is being checked + * @param tracks track table + * @param particles particle table + */ +template +auto matchedDielectronParticleId(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +{ + const auto candidateDaughterParticle = candidate.template prong1_as().template mcParticle_as(); + return candidateDaughterParticle.template mothers_first_as().globalIndex(); // can we get the Id directly? +} + +/** + * returns the JMcParticle matched to the Dielectron candidate + * + * @param candidate dielectron candidate that is being checked + * @param tracks track table + * @param particles particle table + */ +template +auto matchedDielectronParticle(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +{ + const auto candidateDaughterParticle = candidate.template prong1_as().template mcParticle_as(); + return candidateDaughterParticle.template mothers_first_as(); +} + +/** + * returns a slice of the table depending on the index of the Dielectron candidate + * + * @param candidate dielectron candidate that is being checked + * @param table the table to be sliced + */ +template +auto slicedPerDielectronCandidate(T const& table, U const& candidate, V const& perDielectronCandidate) +{ + if constexpr (isDielectronCandidate()) { + return table.sliceBy(perDielectronCandidate, candidate.globalIndex()); + } else { + return table; + } +} + +/** + * returns a slice of the table depending on the type of the Dielectron candidate and index of the collision + * + * @param candidate dielectron candidate that is being checked + * @param table the table to be sliced + */ +template +auto slicedPerDielectronCollision(T const& table, U const& /*candidates*/, V const& collision, M const& DielectronCollisionPerCollision) +{ + if constexpr (isDielectronTable() || isDielectronMcTable()) { + return table.sliceBy(DielectronCollisionPerCollision, collision.globalIndex()); + } else { + return table; + } +} + +/** + * returns the Dielectron collision Id of candidate based on type of Dielectron candidate + * + * @param candidate dielectron candidate that is being checked + */ +template +int getDielectronCandidateCollisionId(T const& candidate) +{ + if constexpr (isDielectronCandidate()) { + return candidate.reducedeventId(); + } else { + return -1; + } +} + +/** + * returns the Dielectron Mc collision Id of candidate based on type of Dielectron candidate + * + * @param candidate dielectron candidate that is being checked + */ +template +int getDielectronMcCandidateCollisionId(T const& candidate) +{ + if constexpr (isDielectronMcCandidate()) { + return candidate.dielectronmccollisionId(); + } else { + return -1; + } +} + +/** + * returns the PDG of the candidate based on Dielectron Table + * + * @param candidate dielectron candidate that is being checked + */ +template +int getDielectronCandidatePDG(T const& /*candidate*/) +{ + if constexpr (isDielectronCandidate() || isDielectronMcCandidate()) { + return static_cast(o2::constants::physics::Pdg::kJPsi); + } else { + return 0; + } +} + +/** + * returns the PDG of the candidates in the table type + */ +template +int getDielectronTablePDG() +{ + if constexpr (isDielectronTable() || isDielectronMcTable()) { + return static_cast(o2::constants::physics::Pdg::kJPsi); + } else { + return 0; + } +} + +/** + * returns the mass of the candidate based on Dielectron Table + * + * @param candidate dielectron candidate that is being checked + */ +template +float getDielectronCandidatePDGMass(T const& /*candidate*/) +{ + if constexpr (isDielectronCandidate() || isDielectronMcCandidate()) { + return static_cast(o2::constants::physics::MassJPsi); + } else { + return -1.0; + } +} + +/** + * returns the mass of the candidates in the table type + * + */ +template +float getDielectronTablePDGMass() +{ + if constexpr (isDielectronTable() || isDielectronMcTable()) { + return static_cast(o2::constants::physics::MassJPsi); + } else { + return -1.0; + } +} + +/** + * returns the mass of the candidate based on Dielectron Table + * + * @param candidate dielectron candidate that is being checked + */ +template +float getDielectronCandidateInvariantMass(T const& candidate) +{ + if constexpr (isDielectronCandidate()) { + return candidate.mass(); + } else { + return -1.0; + } +} + +template +bool isDielectronParticle(T const& particles, U const& particle) +{ + return RecoDecay::isMatchedMCGen(particles, particle, o2::constants::physics::Pdg::kJPsi, std::array{+kElectron, -kElectron}, true); +} + +enum JDielectronParticleDecays { + JPsiToEE = 0, +}; + +template +bool selectDielectronParticleDecay(T const& dielectronParticle, int dielectronParticleDecaySelection = -1) +{ + if (dielectronParticleDecaySelection == -1) { + return true; + } + return (dielectronParticle.decayFlag() & (1 << dielectronParticleDecaySelection)); +} + +int initialiseDielectronParticleDecaySelection(std::string dielectronParticleDecaySelection) +{ + if (dielectronParticleDecaySelection == "JPsiToEE") { + return JDielectronParticleDecays::JPsiToEE; + } + return -1; +} + +template +uint8_t setDielectronParticleDecayBit(T const& particles, U const& particle) +{ + uint8_t bit = 0; + if (RecoDecay::isMatchedMCGen(particles, particle, o2::constants::physics::Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { + SETBIT(bit, JDielectronParticleDecays::JPsiToEE); + } + return bit; +} + +template +void fillDielectronCollisionTable(T const& collision, U& DielectronCollisionTable, int32_t& DielectronCollisionTableIndex) +{ + DielectronCollisionTable(collision.tag_raw(), collision.runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes()); + DielectronCollisionTableIndex = DielectronCollisionTable.lastIndex(); +} + +template +void fillDielectronMcCollisionTable(T const& mcCollision, U& DielectronMcCollisionTable, int32_t& DielectronMcCollisionTableIndex) +{ + DielectronMcCollisionTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + DielectronMcCollisionTableIndex = DielectronMcCollisionTable.lastIndex(); +} + +template +void fillDielectronCandidateTable(T const& candidate, int32_t collisionIndex, U& DielectronTable, int32_t& DielectronCandidateTableIndex) +{ + DielectronTable(collisionIndex, candidate.mass(), candidate.pt(), candidate.eta(), candidate.phi(), candidate.sign(), candidate.filterMap_raw(), candidate.mcDecision()); + DielectronCandidateTableIndex = DielectronTable.lastIndex(); +} + +template +void fillDielectronCandidateMcTable(T const& candidate, int32_t mcCollisionIndex, U& DielectronMcTable, int32_t& DielectronCandidateTableIndex) +{ + DielectronMcTable(mcCollisionIndex, candidate.pt(), candidate.eta(), candidate.phi(), candidate.y(), candidate.e(), candidate.m(), candidate.pdgCode(), candidate.getGenStatusCode(), candidate.getHepMCStatusCode(), candidate.isPhysicalPrimary(), candidate.decayFlag(), candidate.origin()); + DielectronCandidateTableIndex = DielectronMcTable.lastIndex(); +} + +}; // namespace jetdqutilities + +#endif // PWGJE_CORE_JETDQUTILITIES_H_ diff --git a/PWGJE/Core/JetDerivedDataUtilities.h b/PWGJE/Core/JetDerivedDataUtilities.h index abf335d6e19..435a362e0db 100644 --- a/PWGJE/Core/JetDerivedDataUtilities.h +++ b/PWGJE/Core/JetDerivedDataUtilities.h @@ -17,6 +17,7 @@ #ifndef PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ #define PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ +#include #include #include "Common/CCDB/TriggerAliases.h" #include "Common/CCDB/EventSelectionParams.h" @@ -29,9 +30,14 @@ static constexpr float mPion = 0.139; // TDatabasePDG::Instance()->GetParticle(2 enum JCollisionSel { sel8 = 0, sel8Full = 1, - sel7 = 2, + sel8FullPbPb = 2, selMC = 3, - selUnanchoredMC = 4 + selMCFull = 4, + selMCFullPbPb = 5, + selUnanchoredMC = 6, + selTVX = 7, + sel7 = 8, + sel7KINT7 = 9 }; template @@ -51,35 +57,63 @@ int initialiseEventSelection(std::string eventSelection) if (eventSelection == "sel8Full") { return JCollisionSel::sel8Full; } - if (eventSelection == "sel7") { - return JCollisionSel::sel7; + if (eventSelection == "sel8FullPbPb") { + return JCollisionSel::sel8FullPbPb; } if (eventSelection == "selMC") { return JCollisionSel::selMC; } + if (eventSelection == "selMCFull") { + return JCollisionSel::selMCFull; + } + if (eventSelection == "selMCFullPbPb") { + return JCollisionSel::selMCFullPbPb; + } if (eventSelection == "selUnanchoredMC") { return JCollisionSel::selUnanchoredMC; } + if (eventSelection == "selTVX") { + return JCollisionSel::selTVX; + } + if (eventSelection == "sel7") { + return JCollisionSel::sel7; + } + if (eventSelection == "sel7KINT7") { + return JCollisionSel::sel7KINT7; + } return -1; } template -uint8_t setEventSelectionBit(T const& collision) +uint16_t setEventSelectionBit(T const& collision) { - uint8_t bit = 0; + uint16_t bit = 0; if (collision.sel8()) { SETBIT(bit, JCollisionSel::sel8); if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup) && collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { SETBIT(bit, JCollisionSel::sel8Full); + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + SETBIT(bit, JCollisionSel::sel8FullPbPb); + } } } if (collision.sel7()) { SETBIT(bit, JCollisionSel::sel7); + if (collision.alias_bit(kINT7)) { + SETBIT(bit, JCollisionSel::sel7KINT7); + } } if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + SETBIT(bit, JCollisionSel::selTVX); SETBIT(bit, JCollisionSel::selUnanchoredMC); if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { SETBIT(bit, JCollisionSel::selMC); + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup) && collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + SETBIT(bit, JCollisionSel::selMCFull); + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + SETBIT(bit, JCollisionSel::selMCFullPbPb); + } + } } } return bit; @@ -100,10 +134,154 @@ bool eventEMCAL(T const& collision) return found; } +inline const std::string JTriggerMasks = "fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"; + +enum JTrigSel { + noTrigSel = 0, + JetChLowPt = 1, + JetChHighPt = 2, + TrackLowPt = 3, + TrackHighPt = 4, + JetD0ChLowPt = 5, + JetD0ChHighPt = 6, + JetLcChLowPt = 7, + JetLcChHighPt = 8, + EMCALReadout = 9, + JetFullHighPt = 10, + JetFullLowPt = 11, + JetNeutralHighPt = 12, + JetNeutralLowPt = 13, + GammaVeryHighPtEMCAL = 14, + GammaVeryHighPtDCAL = 15, + GammaHighPtEMCAL = 16, + GammaHighPtDCAL = 17, + GammaLowPtEMCAL = 18, + GammaLowPtDCAL = 19, + GammaVeryLowPtEMCAL = 20, + GammaVeryLowPtDCAL = 21 +}; + +template +bool selectTrigger(T const& collision, std::vector triggerMaskBits) +{ + if (triggerMaskBits.size() == 0) { + return true; + } + for (auto triggerMaskBit : triggerMaskBits) { + if (collision.triggerSel() & (1 << triggerMaskBit)) { + return true; + } + } + return false; +} + +template +bool selectTrigger(T const& collision, int triggerMaskBit) +{ + if (triggerMaskBit == -1) { + return false; + } + return collision.triggerSel() & (1 << triggerMaskBit); +} + +bool triggerMasksContainTrigger(std::string triggerMasks, std::string trigger) +{ + size_t position = 0; + while ((position = triggerMasks.find(trigger, position)) != std::string::npos) { + bool validStart = (position == 0 || triggerMasks[position - 1] == ','); + bool validEnd = (position + trigger.length() == triggerMasks.length() || triggerMasks[position + trigger.length()] == ','); + if (validStart && validEnd) { + return true; + } + position += trigger.length(); + } + return false; +} + +std::vector initialiseTriggerMaskBits(std::string triggerMasks) +{ + std::vector triggerMaskBits; + if (triggerMasksContainTrigger(triggerMasks, "fJetChLowPt")) { + triggerMaskBits.push_back(JetChLowPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetChHighPt")) { + triggerMaskBits.push_back(JetChHighPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fTrackLowPt")) { + triggerMaskBits.push_back(TrackLowPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fTrackHighPt")) { + triggerMaskBits.push_back(TrackHighPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetD0ChLowPt")) { + triggerMaskBits.push_back(JetD0ChLowPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetD0ChHighPt")) { + triggerMaskBits.push_back(JetD0ChHighPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetLcChLowPt")) { + triggerMaskBits.push_back(JetLcChLowPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetLcChHighPt")) { + triggerMaskBits.push_back(JetLcChHighPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fEMCALReadout")) { + triggerMaskBits.push_back(EMCALReadout); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetFullHighPt")) { + triggerMaskBits.push_back(JetFullHighPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetFullLowPt")) { + triggerMaskBits.push_back(JetFullLowPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetNeutralHighPt")) { + triggerMaskBits.push_back(JetNeutralHighPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fJetNeutralLowPt")) { + triggerMaskBits.push_back(JetNeutralLowPt); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaVeryHighPtEMCAL")) { + triggerMaskBits.push_back(GammaVeryHighPtEMCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaVeryHighPtDCAL")) { + triggerMaskBits.push_back(GammaVeryHighPtDCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaHighPtEMCAL")) { + triggerMaskBits.push_back(GammaHighPtEMCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaHighPtDCAL")) { + triggerMaskBits.push_back(GammaHighPtDCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaLowPtEMCAL")) { + triggerMaskBits.push_back(GammaLowPtEMCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaLowPtDCAL")) { + triggerMaskBits.push_back(GammaLowPtDCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaVeryLowPtEMCAL")) { + triggerMaskBits.push_back(GammaVeryLowPtEMCAL); + } + if (triggerMasksContainTrigger(triggerMasks, "fGammaVeryLowPtDCAL")) { + triggerMaskBits.push_back(GammaVeryLowPtDCAL); + } + return triggerMaskBits; +} + +uint64_t setTriggerSelectionBit(std::vector triggerDecisions) +{ + uint64_t bit = 0; + for (std::vector::size_type i = 0; i < triggerDecisions.size(); i++) { + if (triggerDecisions[i]) { + SETBIT(bit, i + 1); + } + } + return bit; +} + enum JTrigSelCh { noChargedTigger = 0, - chargedLow = 1, - chargedHigh = 2, + jetChLowPt = 1, + jetChHighPt = 2, trackLowPt = 3, trackHighPt = 4 }; @@ -119,11 +297,11 @@ bool selectChargedTrigger(T const& collision, int triggerSelection) int initialiseChargedTriggerSelection(std::string triggerSelection) { - if (triggerSelection == "chargedLow") { - return JTrigSelCh::chargedLow; + if (triggerSelection == "jetChLowPt") { + return JTrigSelCh::jetChLowPt; } - if (triggerSelection == "chargedHigh") { - return JTrigSelCh::chargedHigh; + if (triggerSelection == "jetChHighPt") { + return JTrigSelCh::jetChHighPt; } if (triggerSelection == "trackLowPt") { return JTrigSelCh::trackLowPt; @@ -141,10 +319,10 @@ uint8_t setChargedTriggerSelectionBit(T const& collision) uint8_t bit = 0; if (collision.hasJetChLowPt()) { - SETBIT(bit, JTrigSelCh::chargedLow); + SETBIT(bit, JTrigSelCh::jetChLowPt); } if (collision.hasJetChHighPt()) { - SETBIT(bit, JTrigSelCh::chargedHigh); + SETBIT(bit, JTrigSelCh::jetChHighPt); } if (collision.hasTrackLowPt()) { SETBIT(bit, JTrigSelCh::trackLowPt); @@ -158,18 +336,19 @@ uint8_t setChargedTriggerSelectionBit(T const& collision) enum JTrigSelFull { noFullTrigger = 0, - fullHigh = 1, - fullLow = 2, - neutralHigh = 3, - neutralLow = 4, - gammaVeryHighEMCAL = 5, - gammaHighEMCAL = 6, - gammaLowEMCAL = 7, - gammaVeryLowEMCAL = 8, - gammaVeryHighDCAL = 9, - gammaHighDCAL = 10, - gammaLowDCAL = 11, - gammaVeryLowDCAL = 12 + emcalReadout = 1, + jetFullHighPt = 2, + jetFullLowPt = 3, + jetNeutralHighPt = 4, + jetNeutralLowPt = 5, + gammaVeryHighPtEMCAL = 6, + gammaVeryHighPtDCAL = 7, + gammaHighPtEMCAL = 8, + gammaHighPtDCAL = 9, + gammaLowPtEMCAL = 10, + gammaLowPtDCAL = 11, + gammaVeryLowPtEMCAL = 12, + gammaVeryLowPtDCAL = 13 }; template @@ -183,30 +362,32 @@ bool selectFullTrigger(T const& collision, int triggerSelection) int initialiseFullTriggerSelection(std::string triggerSelection) { - if (triggerSelection == "fullHigh") { - return JTrigSelFull::fullHigh; - } else if (triggerSelection == "fullLow") { - return JTrigSelFull::fullLow; - } else if (triggerSelection == "neutralHigh") { - return JTrigSelFull::neutralHigh; - } else if (triggerSelection == "neutralLow") { - return JTrigSelFull::neutralLow; - } else if (triggerSelection == "gammaVeryHighEMCAL") { - return JTrigSelFull::gammaVeryHighEMCAL; - } else if (triggerSelection == "gammaHighEMCAL") { - return JTrigSelFull::gammaHighEMCAL; - } else if (triggerSelection == "gammaLowEMCAL") { - return JTrigSelFull::gammaLowEMCAL; - } else if (triggerSelection == "gammaVeryLowEMCAL") { - return JTrigSelFull::gammaVeryLowEMCAL; - } else if (triggerSelection == "gammaVeryHighDCAL") { - return JTrigSelFull::gammaVeryHighDCAL; - } else if (triggerSelection == "gammaHighDCAL") { - return JTrigSelFull::gammaHighDCAL; - } else if (triggerSelection == "gammaLowDCAL") { - return JTrigSelFull::gammaLowDCAL; - } else if (triggerSelection == "gammaVeryLowDCAL") { - return JTrigSelFull::gammaVeryLowDCAL; + if (triggerSelection == "emcalReadout") { + return JTrigSelFull::emcalReadout; + } else if (triggerSelection == "jetFullHighPt") { + return JTrigSelFull::jetFullHighPt; + } else if (triggerSelection == "jetFullLowPt") { + return JTrigSelFull::jetFullLowPt; + } else if (triggerSelection == "jetNeutralHighPt") { + return JTrigSelFull::jetNeutralHighPt; + } else if (triggerSelection == "jetNeutralLowPt") { + return JTrigSelFull::jetNeutralLowPt; + } else if (triggerSelection == "gammaVeryHighPtEMCAL") { + return JTrigSelFull::gammaVeryHighPtEMCAL; + } else if (triggerSelection == "gammaVeryHighPtDCAL") { + return JTrigSelFull::gammaVeryHighPtDCAL; + } else if (triggerSelection == "gammaHighPtEMCAL") { + return JTrigSelFull::gammaHighPtEMCAL; + } else if (triggerSelection == "gammaHighPtDCAL") { + return JTrigSelFull::gammaHighPtDCAL; + } else if (triggerSelection == "gammaLowPtEMCAL") { + return JTrigSelFull::gammaLowPtEMCAL; + } else if (triggerSelection == "gammaLowPtDCAL") { + return JTrigSelFull::gammaLowPtDCAL; + } else if (triggerSelection == "gammaVeryLowPtEMCAL") { + return JTrigSelFull::gammaVeryLowPtEMCAL; + } else if (triggerSelection == "gammaVeryLowPtDCAL") { + return JTrigSelFull::gammaVeryLowPtDCAL; } return -1; } @@ -215,51 +396,54 @@ template uint32_t setFullTriggerSelectionBit(T const& collision) { uint32_t bit = 0; + if (collision.hasEMCALinReadout()) { + SETBIT(bit, JTrigSelFull::emcalReadout); + } if (collision.hasJetFullHighPt()) { - SETBIT(bit, JTrigSelFull::fullHigh); + SETBIT(bit, JTrigSelFull::jetFullHighPt); } if (collision.hasJetFullLowPt()) { - SETBIT(bit, JTrigSelFull::fullLow); + SETBIT(bit, JTrigSelFull::jetFullLowPt); } if (collision.hasJetNeutralHighPt()) { - SETBIT(bit, JTrigSelFull::neutralHigh); + SETBIT(bit, JTrigSelFull::jetNeutralHighPt); } if (collision.hasJetNeutralLowPt()) { - SETBIT(bit, JTrigSelFull::neutralLow); + SETBIT(bit, JTrigSelFull::jetNeutralLowPt); } if (collision.hasGammaVeryHighPtEMCAL()) { - SETBIT(bit, JTrigSelFull::gammaVeryHighEMCAL); - } - if (collision.hasGammaHighPtEMCAL()) { - SETBIT(bit, JTrigSelFull::gammaHighEMCAL); - } - if (collision.hasGammaLowPtEMCAL()) { - SETBIT(bit, JTrigSelFull::gammaLowEMCAL); - } - if (collision.hasGammaVeryLowPtEMCAL()) { - SETBIT(bit, JTrigSelFull::gammaVeryLowEMCAL); + SETBIT(bit, JTrigSelFull::gammaVeryHighPtEMCAL); } if (collision.hasGammaVeryHighPtDCAL()) { - SETBIT(bit, JTrigSelFull::gammaVeryHighDCAL); + SETBIT(bit, JTrigSelFull::gammaVeryHighPtDCAL); + } + if (collision.hasGammaHighPtEMCAL()) { + SETBIT(bit, JTrigSelFull::gammaHighPtEMCAL); } if (collision.hasGammaHighPtDCAL()) { - SETBIT(bit, JTrigSelFull::gammaHighDCAL); + SETBIT(bit, JTrigSelFull::gammaHighPtDCAL); + } + if (collision.hasGammaLowPtEMCAL()) { + SETBIT(bit, JTrigSelFull::gammaLowPtEMCAL); } if (collision.hasGammaLowPtDCAL()) { - SETBIT(bit, JTrigSelFull::gammaLowDCAL); + SETBIT(bit, JTrigSelFull::gammaLowPtDCAL); + } + if (collision.hasGammaVeryLowPtEMCAL()) { + SETBIT(bit, JTrigSelFull::gammaVeryLowPtEMCAL); } if (collision.hasGammaVeryLowPtDCAL()) { - SETBIT(bit, JTrigSelFull::gammaVeryLowDCAL); + SETBIT(bit, JTrigSelFull::gammaVeryLowPtDCAL); } return bit; } enum JTrigSelChHF { noChargedHFTigger = 0, - chargedD0Low = 1, - chargedD0High = 2, - chargedLcLow = 3, - chargedLcHigh = 4 + jetD0ChLowPt = 1, + jetD0ChHighPt = 2, + jetLcChLowPt = 3, + jetLcChHighPt = 4 }; template @@ -273,17 +457,17 @@ bool selectChargedHFTrigger(T const& collision, int triggerSelection) int initialiseChargedHFTriggerSelection(std::string triggerSelection) { - if (triggerSelection == "chargedD0Low") { - return JTrigSelChHF::chargedD0Low; + if (triggerSelection == "jetD0ChLowPt") { + return JTrigSelChHF::jetD0ChLowPt; } - if (triggerSelection == "chargedD0High") { - return JTrigSelChHF::chargedD0High; + if (triggerSelection == "jetD0ChHighPt") { + return JTrigSelChHF::jetD0ChHighPt; } - if (triggerSelection == "chargedLcLow") { - return JTrigSelChHF::chargedLcLow; + if (triggerSelection == "jetLcChLowPt") { + return JTrigSelChHF::jetLcChLowPt; } - if (triggerSelection == "chargedLcHigh") { - return JTrigSelChHF::chargedLcHigh; + if (triggerSelection == "jetLcChHighPt") { + return JTrigSelChHF::jetLcChHighPt; } return -1; } @@ -294,16 +478,16 @@ uint8_t setChargedHFTriggerSelectionBit(T const& collision) uint8_t bit = 0; if (collision.hasJetD0ChLowPt()) { - SETBIT(bit, JTrigSelChHF::chargedD0Low); + SETBIT(bit, JTrigSelChHF::jetD0ChLowPt); } if (collision.hasJetD0ChHighPt()) { - SETBIT(bit, JTrigSelChHF::chargedD0High); + SETBIT(bit, JTrigSelChHF::jetD0ChHighPt); } if (collision.hasJetLcChLowPt()) { - SETBIT(bit, JTrigSelChHF::chargedLcLow); + SETBIT(bit, JTrigSelChHF::jetLcChLowPt); } if (collision.hasJetLcChHighPt()) { - SETBIT(bit, JTrigSelChHF::chargedLcHigh); + SETBIT(bit, JTrigSelChHF::jetLcChHighPt); } return bit; } @@ -312,8 +496,8 @@ enum JTrackSel { trackSign = 0, // warning : this number is hardcoded in the sign coloumn in the JTracks table so should not be changed without changing it there too globalTrack = 1, qualityTrack = 2, - hybridTrack = 3, - uniformTrack = 4 + qualityTrackWDCA = 3, + hybridTrack = 4 }; template @@ -340,16 +524,16 @@ int initialiseTrackSelection(std::string trackSelection) return JTrackSel::globalTrack; } else if (trackSelection == "QualityTracks") { return JTrackSel::qualityTrack; + } else if (trackSelection == "QualityTracksWDCA") { + return JTrackSel::qualityTrackWDCA; } else if (trackSelection == "hybridTracks") { return JTrackSel::hybridTrack; - } else if (trackSelection == "uniformTracks") { - return JTrackSel::uniformTrack; } return -1; } template -uint8_t setTrackSelectionBit(T const& track) +uint8_t setTrackSelectionBit(T const& track, float trackDCAZ, float maxDCAZ) { uint8_t bit = 0; @@ -362,16 +546,13 @@ uint8_t setTrackSelectionBit(T const& track) } if (track.isQualityTrack()) { SETBIT(bit, JTrackSel::qualityTrack); + if (std::abs(trackDCAZ) < maxDCAZ) { + SETBIT(bit, JTrackSel::qualityTrackWDCA); + } } if (track.trackCutFlagFb5()) { SETBIT(bit, JTrackSel::hybridTrack); } - if ((track.passedGoldenChi2() && track.passedDCAxy()) && - (track.passedITSNCls() && track.passedITSChi2NDF() && track.passedITSHits()) && - (!track.hasTPC() || (track.passedTPCNCls() && track.passedTPCChi2NDF() && track.passedTPCCrossedRowsOverNCls()))) { // removing track.passedDCAz() so aimeric can test. Needs to be added into the bracket with passedGoldenChi2 - SETBIT(bit, JTrackSel::uniformTrack); - } - return bit; } diff --git a/PWGJE/Core/JetFinder.cxx b/PWGJE/Core/JetFinder.cxx index 940a201bb92..03583a9e622 100644 --- a/PWGJE/Core/JetFinder.cxx +++ b/PWGJE/Core/JetFinder.cxx @@ -37,7 +37,11 @@ void JetFinder::setParams() // selGhosts =fastjet::SelectorRapRange(ghostEtaMin,ghostEtaMax) && fastjet::SelectorPhiRange(phiMin,phiMax); // ghostAreaSpec=fastjet::GhostedAreaSpec(selGhosts,ghostRepeatN,ghostArea,gridScatter,ktScatter,ghostktMean); ghostAreaSpec = fastjet::GhostedAreaSpec(ghostEtaMax, ghostRepeatN, ghostArea, gridScatter, ktScatter, ghostktMean); // the first argument is rapidity not pseudorapidity, to be checked - jetDef = fastjet::JetDefinition(algorithm, jetR, recombScheme, strategy); + jetDef = fastjet::JetDefinition(fastjet::antikt_algorithm, jetR, recombScheme, strategy); + if (fastjetExtraParam > -98.0) { + jetDef.set_extra_param(fastjetExtraParam); + } + jetDef.set_jet_algorithm(algorithm); areaDef = fastjet::AreaDefinition(areaType, ghostAreaSpec); selJets = fastjet::SelectorPtRange(jetPtMin, jetPtMax) && fastjet::SelectorEtaRange(jetEtaMin, jetEtaMax) && fastjet::SelectorPhiRange(jetPhiMin, jetPhiMax); } diff --git a/PWGJE/Core/JetFinder.h b/PWGJE/Core/JetFinder.h index bdb03434b2a..26b4a3c5f0f 100644 --- a/PWGJE/Core/JetFinder.h +++ b/PWGJE/Core/JetFinder.h @@ -82,6 +82,7 @@ class JetFinder fastjet::AreaDefinition areaDef; fastjet::Selector selJets; fastjet::Selector selGhosts; + double fastjetExtraParam = -99.0; /// Sets the jet finding parameters void setParams(); diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index d515735fbce..997a27fc265 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -44,9 +45,11 @@ #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/Core/JetCandidateUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" + namespace jetfindingutilities { @@ -63,7 +66,7 @@ constexpr bool isEMCALCluster() * returns true if the table is an EMCAL table */ template -constexpr bool isEMCALTable() +constexpr bool isEMCALClusterTable() { return isEMCALCluster() || isEMCALCluster(); } @@ -78,7 +81,7 @@ constexpr bool isEMCALTable() */ template -void analyseTracks(std::vector& inputParticles, T const& tracks, int trackSelection, std::optional const& candidate = std::nullopt) +void analyseTracks(std::vector& inputParticles, T const& tracks, int trackSelection, double trackingEfficinecy, std::optional const& candidate = std::nullopt) { for (auto& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -86,7 +89,13 @@ void analyseTracks(std::vector& inputParticles, T const& tra } if (candidate != std::nullopt) { auto cand = candidate.value(); - if (jethfutilities::isDaughterTrack(track, cand, tracks)) { + if (jetcandidateutilities::isDaughterTrack(track, cand, tracks)) { + continue; + } + } + if (trackingEfficinecy < 0.999) { // this code is a bit ugly but it stops us needing to do the random generation unless asked for + TRandom3 randomNumber(0); + if (randomNumber.Rndm() > trackingEfficinecy) { // Is Rndm ok to use? continue; } } @@ -104,14 +113,20 @@ void analyseTracks(std::vector& inputParticles, T const& tra */ template -void analyseTracksMultipleCandidates(std::vector& inputParticles, T const& tracks, int trackSelection, U const& candidates) +void analyseTracksMultipleCandidates(std::vector& inputParticles, T const& tracks, int trackSelection, double trackingEfficinecy, U const& candidates) { for (auto& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } for (auto& candidate : candidates) { - if (jethfutilities::isDaughterTrack(track, candidate, tracks)) { + if (jetcandidateutilities::isDaughterTrack(track, candidate, tracks)) { + continue; + } + } + if (trackingEfficinecy < 0.999) { // this code is a bit ugly but it stops us needing to do the random generation unless asked for + TRandom3 randomNumber(0); + if (randomNumber.Rndm() > trackingEfficinecy) { // Is Rndm ok to use? continue; } } @@ -147,8 +162,8 @@ void analyseClusters(std::vector& inputParticles, T const& c template bool analyseCandidate(std::vector& inputParticles, T const& candidate, float candPtMin, float candPtMax, float candYMin, float candYMax) { - auto candMass = jethfutilities::getCandidatePDGMass(candidate); - if (isnan(candidate.y())) { + auto candMass = jetcandidateutilities::getCandidatePDGMass(candidate); + if (std::isnan(candidate.y())) { return false; } if (candidate.y() < candYMin || candidate.y() > candYMax) { @@ -157,7 +172,7 @@ bool analyseCandidate(std::vector& inputParticles, T const& if (candidate.pt() < candPtMin || candidate.pt() >= candPtMax) { return false; } - fastjetutilities::fillTracks(candidate, inputParticles, candidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), candMass); + fastjetutilities::fillTracks(candidate, inputParticles, candidate.globalIndex(), static_cast(JetConstituentStatus::candidate), candMass); return true; } @@ -175,7 +190,7 @@ bool analyseCandidate(std::vector& inputParticles, T const& template bool analyseCandidateMC(std::vector& inputParticles, T const& candidate, float candPtMin, float candPtMax, float candYMin, float candYMax, bool rejectBackgroundMCCandidates) { - if (rejectBackgroundMCCandidates && !jethfutilities::isMatchedHFCandidate(candidate)) { + if (rejectBackgroundMCCandidates && !jetcandidateutilities::isMatchedCandidate(candidate)) { return false; } return analyseCandidate(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax); @@ -212,7 +227,7 @@ bool analyseV0s(std::vector& inputParticles, T const& v0s, f } v0Y = v0.rapidity(v0Index); } - if (isnan(v0Y)) { + if (std::isnan(v0Y)) { continue; } if (v0Y < v0YMin || v0Y > v0YMax) { @@ -221,7 +236,7 @@ bool analyseV0s(std::vector& inputParticles, T const& v0s, f if (v0.pt() < v0PtMin || v0.pt() >= v0PtMax) { continue; } - fastjetutilities::fillTracks(v0, inputParticles, v0.globalIndex(), static_cast(JetConstituentStatus::candidateHF), v0Mass); + fastjetutilities::fillTracks(v0, inputParticles, v0.globalIndex(), static_cast(JetConstituentStatus::candidate), v0Mass); nSelectedV0s++; } if (nSelectedV0s > 0) { @@ -263,7 +278,7 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic if (doCandidateJetFinding) { for (const auto& constituent : jet.constituents()) { auto constituentStatus = constituent.template user_info().getStatus(); - if (constituentStatus == static_cast(JetConstituentStatus::candidateHF)) { // note currently we cannot run V0 and HF in the same jet. If we ever need to we can seperate the loops + if (constituentStatus == static_cast(JetConstituentStatus::candidate)) { // note currently we cannot run V0 and HF in the same jet. If we ever need to we can seperate the loops isCandidateJet = true; break; } @@ -284,7 +299,7 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::cluster)) { clusters.push_back(constituent.template user_info().getIndex()); } - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidateHF)) { + if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidate)) { cands.push_back(constituent.template user_info().getIndex()); } } @@ -316,7 +331,7 @@ void analyseParticles(std::vector& inputParticles, std::stri } else if (particleSelection == "PhysicalPrimaryAndHepMCStatus" && (!particle.isPhysicalPrimary() || particle.getHepMCStatusCode() != 1)) { continue; } - if (isinf(particle.eta())) { + if (std::isinf(particle.eta())) { continue; } auto pdgParticle = pdgDatabase->GetParticle(particle.pdgCode()); @@ -327,14 +342,14 @@ void analyseParticles(std::vector& inputParticles, std::stri if (jetTypeParticleLevel == static_cast(JetType::neutral) && pdgCharge != 0.0) { continue; } - if constexpr (jethfutilities::isHFMcCandidate()) { + if constexpr (jetcandidateutilities::isMcCandidate() && !jetv0utilities::isV0McCandidate()) { if (candidate != std::nullopt) { auto cand = candidate.value(); if (cand.mcParticleId() == particle.globalIndex()) { continue; } auto hfParticle = cand.template mcParticle_as(); - if (jethfutilities::isDaughterParticle(hfParticle, particle.globalIndex())) { + if (jetcandidateutilities::isDaughterParticle(hfParticle, particle.globalIndex())) { continue; } } @@ -347,7 +362,7 @@ void analyseParticles(std::vector& inputParticles, std::stri continue; } auto v0Particle = cand.template mcParticle_as(); - if (jethfutilities::isDaughterParticle(v0Particle, particle.globalIndex())) { + if (jetcandidateutilities::isDaughterParticle(v0Particle, particle.globalIndex())) { continue; } } diff --git a/PWGJE/Core/JetHFUtilities.h b/PWGJE/Core/JetHFUtilities.h index 6737eaef1bc..913231d1999 100644 --- a/PWGJE/Core/JetHFUtilities.h +++ b/PWGJE/Core/JetHFUtilities.h @@ -42,7 +42,6 @@ #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetV0Utilities.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" @@ -73,7 +72,6 @@ constexpr bool isD0McCandidate() template constexpr bool isD0Table() { - return isD0Candidate() || isD0Candidate(); } @@ -83,7 +81,6 @@ constexpr bool isD0Table() template constexpr bool isD0McTable() { - return isD0McCandidate() || isD0McCandidate(); } @@ -178,13 +175,12 @@ constexpr bool isHFCandidate() } /** - * returns true if the candidate is from a MC HF table + * returns true if the candidate is from a HF MC candidate table * * @param candidate candidate that is being checked */ template constexpr bool isHFMcCandidate() { - if constexpr (isD0McCandidate()) { return true; } else if constexpr (isLcMcCandidate()) { @@ -202,7 +198,6 @@ constexpr bool isHFMcCandidate() template constexpr bool isHFTable() { - if constexpr (isD0Candidate() || isD0Candidate()) { return true; } else if constexpr (isLcCandidate() || isLcCandidate()) { @@ -215,12 +210,11 @@ constexpr bool isHFTable() } /** - * returns true if the table type is a HF table + * returns true if the table type is a HF MC table */ template constexpr bool isHFMcTable() { - if constexpr (isD0McCandidate() || isD0McCandidate()) { return true; } else if constexpr (isLcMcCandidate() || isLcMcCandidate()) { @@ -239,7 +233,6 @@ constexpr bool isHFMcTable() template constexpr bool isMatchedHFCandidate(T const& candidate) { - if constexpr (isD0Candidate()) { if (std::abs(candidate.flagMcMatchRec()) == 1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK) { return true; @@ -289,9 +282,8 @@ constexpr bool isMatchedHFCandidate(T const& candidate) * @param tracks the track table */ template -bool isDaughterTrack(T& track, U& candidate, V const& /*tracks*/) +bool isHFDaughterTrack(T& track, U& candidate, V const& /*tracks*/) { - if constexpr (isD0Candidate()) { if (candidate.prong0Id() == track.globalIndex() || candidate.prong1Id() == track.globalIndex()) { return true; @@ -310,73 +302,47 @@ bool isDaughterTrack(T& track, U& candidate, V const& /*tracks*/) } else { return false; } - } else if constexpr (jetv0utilities::isV0Candidate()) { - if (candidate.posTrackId() == track.globalIndex() || candidate.negTrackId() == track.globalIndex()) { - return true; - } else { - return false; - } } else { return false; } } /** - * returns true if the particle has any daughters with the given global index - * - * @param candidate mother hf particle that is being checked - * @param globalIndex global index of potnetial daughter particle - */ -template -bool isDaughterParticle(const T& particle, int globalIndex) -{ - for (auto daughter : particle.template daughters_as::parent_t>()) { - if (daughter.globalIndex() == globalIndex) { - return true; - } - if (isDaughterParticle(daughter, globalIndex)) { - return true; - } - } - return false; -} - -/** - * returns the index of the JMcParticle matched to the candidate + * returns the index of the JMcParticle matched to the HF candidate * * @param candidate hf candidate that is being checked * @param tracks track table * @param particles particle table */ template -auto matchedParticleId(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +auto matchedHFParticleId(const T& candidate, const U& /*tracks*/, const V& /*particles*/) { const auto candidateDaughterParticle = candidate.template prong1_as().template mcParticle_as(); return candidateDaughterParticle.template mothers_first_as().globalIndex(); // can we get the Id directly? } /** - * returns the JMcParticle matched to the candidate + * returns the JMcParticle matched to the HF candidate * * @param candidate hf candidate that is being checked * @param tracks track table * @param particles particle table */ template -auto matchedParticle(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +auto matchedHFParticle(const T& candidate, const U& /*tracks*/, const V& /*particles*/) { const auto candidateDaughterParticle = candidate.template prong1_as().template mcParticle_as(); return candidateDaughterParticle.template mothers_first_as(); } /** - * returns a slice of the table depending on the index of the candidate + * returns a slice of the table depending on the index of the HF candidate * * @param candidate HF candidate that is being checked * @param table the table to be sliced */ template -auto slicedPerCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perLcCandidate, N const& perBplusCandidate) +auto slicedPerHFCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perLcCandidate, N const& perBplusCandidate) { if constexpr (isD0Candidate()) { return table.sliceBy(perD0Candidate, candidate.globalIndex()); @@ -390,13 +356,13 @@ auto slicedPerCandidate(T const& table, U const& candidate, V const& perD0Candid } /** - * returns a slice of the table depending on the type of the candidate and index of the collision + * returns a slice of the table depending on the type of the HF candidate and index of the collision * * @param candidate HF candidate that is being checked * @param table the table to be sliced */ template -auto slicedPerCollision(T const& table, U const& /*candidates*/, V const& collision, M const& D0CollisionPerCollision, N const& LcCollisionPerCollision, O const& BplusCollisionPerCollision) +auto slicedPerHFCollision(T const& table, U const& /*candidates*/, V const& collision, M const& D0CollisionPerCollision, N const& LcCollisionPerCollision, O const& BplusCollisionPerCollision) { if constexpr (isD0Table() || isD0McTable()) { return table.sliceBy(D0CollisionPerCollision, collision.globalIndex()); @@ -409,8 +375,51 @@ auto slicedPerCollision(T const& table, U const& /*candidates*/, V const& collis } } +/** + * returns the HF collision Id of candidate based on type of HF candidate + * + * @param candidate HF candidate that is being checked + */ +template +int getHFCandidateCollisionId(T const& candidate) +{ + if constexpr (isD0Candidate()) { + return candidate.hfCollBaseId(); + } else if constexpr (isLcCandidate()) { + return candidate.hfCollBaseId(); + } else if constexpr (isBplusCandidate()) { + return candidate.hfCollBaseId(); + } else { + return -1; + } +} + +/** + * returns the HF Mc collision Id of candidate based on type of HF candidate + * + * @param candidate HF candidate that is being checked + */ +template +int getHFMcCandidateCollisionId(T const& candidate) +{ + if constexpr (isD0McCandidate()) { + return candidate.hfMcCollBaseId(); + } else if constexpr (isLcMcCandidate()) { + return candidate.hfMcCollBaseId(); + } else if constexpr (isBplusMcCandidate()) { + return candidate.hfMcCollBaseId(); + } else { + return -1; + } +} + +/** + * returns the PDG of the candidate based on HF Table + * + * @param candidate HF candidate that is being checked + */ template -int getCandidatePDG(T const& /*candidate*/) +int getHFCandidatePDG(T const& /*candidate*/) { if constexpr (isD0Candidate() || isD0McCandidate()) { return static_cast(o2::constants::physics::Pdg::kD0); @@ -425,8 +434,11 @@ int getCandidatePDG(T const& /*candidate*/) } } +/** + * returns the PDG of the candidates in the table type + */ template -int getTablePDG() +int getHFTablePDG() { if constexpr (isD0Table() || isD0McTable()) { return static_cast(o2::constants::physics::Pdg::kD0); @@ -441,10 +453,14 @@ int getTablePDG() } } +/** + * returns the mass of the candidate based on HF Table + * + * @param candidate HF candidate that is being checked + */ template -float getCandidatePDGMass(T const& /*candidate*/) +float getHFCandidatePDGMass(T const& /*candidate*/) { - if constexpr (isD0Candidate() || isD0McCandidate()) { return static_cast(o2::constants::physics::MassD0); } @@ -454,14 +470,17 @@ float getCandidatePDGMass(T const& /*candidate*/) if constexpr (isBplusCandidate() || isBplusMcCandidate()) { return static_cast(o2::constants::physics::MassBPlus); } else { - return 0.; + return -1.0; } } +/** + * returns the mass of the candidates in the table type + * + */ template -float getTablePDGMass() +float getHFTablePDGMass() { - if constexpr (isD0Table() || isD0McTable()) { return static_cast(o2::constants::physics::MassD0); } @@ -471,7 +490,28 @@ float getTablePDGMass() if constexpr (isBplusTable() || isBplusMcTable()) { return static_cast(o2::constants::physics::MassBPlus); } else { - return 0.; + return -1.0; + } +} + +/** + * returns the mass of the candidate based on HF Table + * + * @param candidate HF candidate that is being checked + */ +template +float getHFCandidateInvariantMass(T const& candidate) +{ + if constexpr (isD0Candidate()) { + return candidate.m(); + } + if constexpr (isLcCandidate()) { + return candidate.m(); + } + if constexpr (isBplusCandidate()) { + return candidate.m(); + } else { + return -1.0; } } @@ -485,7 +525,6 @@ void fillD0CollisionTable(T const& collision, U& D0CollisionTable, int32_t& D0Co template void fillLcCollisionTable(T const& collision, U& LcCollisionTable, int32_t& LcCollisionTableIndex) { - LcCollisionTable(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.centFV0A(), collision.multZeqNTracksPV()); LcCollisionTableIndex = LcCollisionTable.lastIndex(); } @@ -545,18 +584,18 @@ void fillD0CandidateTable(T const& candidate, int32_t collisionIndex, U& D0BaseT candidate.impactParameter1(), candidate.impactParameterNormalised0(), candidate.impactParameterNormalised1(), - candidate.nSigTpcPi0(), - candidate.nSigTpcKa0(), - candidate.nSigTofPi0(), - candidate.nSigTofKa0(), - candidate.nSigTpcTofPi0(), - candidate.nSigTpcTofKa0(), - candidate.nSigTpcPi1(), - candidate.nSigTpcKa1(), - candidate.nSigTofPi1(), - candidate.nSigTofKa1(), - candidate.nSigTpcTofPi1(), - candidate.nSigTpcTofKa1(), + candidate.nSigTpcPiExpPi(), + candidate.nSigTofPiExpPi(), + candidate.nSigTpcTofPiExpPi(), + candidate.nSigTpcKaExpPi(), + candidate.nSigTofKaExpPi(), + candidate.nSigTpcTofKaExpPi(), + candidate.nSigTpcPiExpKa(), + candidate.nSigTofPiExpKa(), + candidate.nSigTpcTofPiExpKa(), + candidate.nSigTpcKaExpKa(), + candidate.nSigTofKaExpKa(), + candidate.nSigTpcTofKaExpKa(), candidate.maxNormalisedDeltaIP(), candidate.impactParameterProduct()); @@ -671,7 +710,7 @@ void fillLcCandidateTable(T const& candidate, int32_t collisionIndex, U& LcBaseT } template -void fillCandidateTable(T const& candidate, int32_t collisionIndex, U& HFBaseTable, V& HFParTable, M& HFParETable, N& HFSelectionFlagTable, O& HFMlTable, P& HFMCDTable, int32_t& HFCandidateTableIndex) +void fillHFCandidateTable(T const& candidate, int32_t collisionIndex, U& HFBaseTable, V& HFParTable, M& HFParETable, N& HFSelectionFlagTable, O& HFMlTable, P& HFMCDTable, int32_t& HFCandidateTableIndex) { if constexpr (isD0Candidate()) { fillD0CandidateTable(candidate, collisionIndex, HFBaseTable, HFParTable, HFParETable, HFSelectionFlagTable, HFMlTable, HFMCDTable, HFCandidateTableIndex); @@ -695,7 +734,7 @@ void fillLcCandidateMcTable(T const& candidate, int32_t mcCollisionIndex, U& LcP } template -void fillCandidateMcTable(T const& candidate, int32_t mcCollisionIndex, U& BaseMcTable, int32_t& candidateTableIndex) +void fillHFCandidateMcTable(T const& candidate, int32_t mcCollisionIndex, U& BaseMcTable, int32_t& candidateTableIndex) { if constexpr (isD0McCandidate()) { fillD0CandidateMcTable(candidate, mcCollisionIndex, BaseMcTable, candidateTableIndex); diff --git a/PWGJE/Core/JetMatchingUtilities.h b/PWGJE/Core/JetMatchingUtilities.h index 9e815e773dc..babf8da52cb 100644 --- a/PWGJE/Core/JetMatchingUtilities.h +++ b/PWGJE/Core/JetMatchingUtilities.h @@ -38,11 +38,8 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/Core/JetCandidateUtilities.h" namespace jetmatchingutilities { @@ -367,15 +364,15 @@ template >& baseToTagMatchingHF, std::vector>& tagToBaseMatchingHF, V const& /*candidatesBase*/, M const& /*candidatesTag*/, N const& tracksBase, O const& tracksTag) { for (const auto& jetBase : jetsBasePerCollision) { - const auto candidateBase = jetBase.template hfcandidates_first_as(); + const auto candidateBase = jetBase.template candidates_first_as(); for (const auto& jetTag : jetsTagPerCollision) { if (std::round(jetBase.r()) != std::round(jetTag.r())) { continue; } if constexpr (jetsBaseIsMc || jetsTagIsMc) { - if (jethfutilities::isMatchedHFCandidate(candidateBase)) { - const auto candidateBaseMcId = jethfutilities::matchedParticleId(candidateBase, tracksBase, tracksTag); - const auto candidateTag = jetTag.template hfcandidates_first_as(); + if (jetcandidateutilities::isMatchedCandidate(candidateBase)) { + const auto candidateBaseMcId = jetcandidateutilities::matchedParticleId(candidateBase, tracksBase, tracksTag); + const auto candidateTag = jetTag.template candidates_first_as(); const auto candidateTagId = candidateTag.mcParticleId(); if (candidateBaseMcId == candidateTagId) { baseToTagMatchingHF[jetBase.globalIndex()].push_back(jetTag.globalIndex()); @@ -383,7 +380,7 @@ void MatchHF(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::v } } } else { - const auto candidateTag = jetTag.template hfcandidates_first_as(); + const auto candidateTag = jetTag.template candidates_first_as(); if (candidateBase.globalIndex() == candidateTag.globalIndex()) { baseToTagMatchingHF[jetBase.globalIndex()].push_back(jetTag.globalIndex()); tagToBaseMatchingHF[jetTag.globalIndex()].push_back(jetBase.globalIndex()); @@ -473,7 +470,7 @@ float getPtSum(T const& tracksBase, U const& clustersBase, V const& tracksTag, O template auto getConstituents(T const& jet, U const& /*constituents*/) { - if constexpr (jetfindingutilities::isEMCALTable()) { + if constexpr (jetfindingutilities::isEMCALClusterTable()) { return jet.template clusters_as(); } else { return jet.template tracks_as(); @@ -495,8 +492,8 @@ void MatchPt(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::v auto jetTagTracks = getConstituents(jetTag, tracksTag); auto jetTagClusters = getConstituents(jetTag, clustersTag); - ptSumBase = getPtSum < jetfindingutilities::isEMCALTable() || jetfindingutilities::isEMCALTable(), jetsBaseIsMc, jetsTagIsMc > (jetBaseTracks, jetBaseClusters, jetTagTracks, jetTagClusters); - ptSumTag = getPtSum < jetfindingutilities::isEMCALTable() || jetfindingutilities::isEMCALTable(), jetsTagIsMc, jetsBaseIsMc > (jetTagTracks, jetTagClusters, jetBaseTracks, jetBaseClusters); + ptSumBase = getPtSum < jetfindingutilities::isEMCALClusterTable() || jetfindingutilities::isEMCALClusterTable(), jetsBaseIsMc, jetsTagIsMc > (jetBaseTracks, jetBaseClusters, jetTagTracks, jetTagClusters); + ptSumTag = getPtSum < jetfindingutilities::isEMCALClusterTable() || jetfindingutilities::isEMCALClusterTable(), jetsTagIsMc, jetsBaseIsMc > (jetTagTracks, jetTagClusters, jetBaseTracks, jetBaseClusters); if (ptSumBase > jetBase.pt() * minPtFraction) { baseToTagMatchingPt[jetBase.globalIndex()].push_back(jetTag.globalIndex()); } @@ -520,7 +517,7 @@ void doAllMatching(T const& jetsBasePerCollision, U const& jetsTagPerCollision, MatchPt(jetsBasePerCollision, jetsTagPerCollision, baseToTagMatchingPt, tagToBaseMatchingPt, tracksBase, clustersBase, tracksTag, clustersTag, minPtFraction); } // HF matching - if constexpr (jethfutilities::isHFTable()) { + if constexpr (jetcandidateutilities::isCandidateTable()) { if (doMatchingHf) { MatchHF(jetsBasePerCollision, jetsTagPerCollision, baseToTagMatchingHF, tagToBaseMatchingHF, candidatesBase, candidatesTag, tracksBase, tracksTag); } diff --git a/PWGJE/Core/JetSubstructureUtilities.h b/PWGJE/Core/JetSubstructureUtilities.h index 27946659967..cf67d789ead 100644 --- a/PWGJE/Core/JetSubstructureUtilities.h +++ b/PWGJE/Core/JetSubstructureUtilities.h @@ -33,7 +33,7 @@ #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/Core/JetCandidateUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "fastjet/contrib/Nsubjettiness.hh" #include "fastjet/contrib/AxesDefinition.hh" @@ -64,9 +64,9 @@ fastjet::ClusterSequenceArea jetToPseudoJet(T const& jet, U const& /*tracks*/, V fastjetutilities::fillClusters(jetClusterConstituent, jetConstituents, jetClusterConstituent.globalIndex()); } } - if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { - for (auto& jetHFConstituent : jet.template hfcandidates_as()) { - fastjetutilities::fillTracks(jetHFConstituent, jetConstituents, jetHFConstituent.globalIndex(), static_cast(JetConstituentStatus::candidateHF), jethfutilities::getTablePDGMass()); + if constexpr (jetcandidateutilities::isCandidateTable() || jetcandidateutilities::isCandidateMcTable()) { + for (auto& jetHFConstituent : jet.template candidates_as()) { + fastjetutilities::fillTracks(jetHFConstituent, jetConstituents, jetHFConstituent.globalIndex(), static_cast(JetConstituentStatus::candidate), jetcandidateutilities::getTablePDGMass()); } } std::vector jetReclustered; @@ -96,7 +96,7 @@ fastjet::ClusterSequenceArea jetToPseudoJet(T const& jet, U const& /*tracks*/, V // function that returns the N-subjettiness ratio and the distance betewwen the two axes considered for tau2, in the form of a vector template -std::vector getNSubjettiness(T const& jet, U const& tracks, V const& clusters, O const& candidates, int nMax, M const& reclusteringAlgorithm, bool doSoftDrop = false, float zCut = 0.1, float beta = 0.0) +std::vector getNSubjettiness(T const& jet, U const& tracks, V const& clusters, O const& candidates, std::vector::size_type nMax, M const& reclusteringAlgorithm, bool doSoftDrop = false, float zCut = 0.1, float beta = 0.0) { std::vector result; fastjet::PseudoJet pseudoJet; @@ -106,11 +106,11 @@ std::vector getNSubjettiness(T const& jet, U const& tracks, V const& clus pseudoJet = softDrop(pseudoJet); } - for (auto n = 0; n < nMax + 1; n++) { + for (std::vector::size_type n = 0; n < nMax + 1; n++) { result.push_back(-1.0 * (n + 1)); } - for (auto n = 1; n <= nMax; n++) { + for (std::vector::size_type n = 1; n <= nMax; n++) { if (pseudoJet.constituents().size() < n) { // Tau_N needs at least N tracks return result; } diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index 66bb4d598c8..d79d160401f 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -46,6 +46,28 @@ namespace jettaggingutilities { const int cmTomum = 10000; // using cm -> #mum for impact parameter (dca) +//________________________________________________________________________ +bool isBHadron(int pc) +{ + std::vector bPdG = {511, 521, 10511, 10521, 513, 523, 10513, 10523, 20513, 20523, 20513, 20523, 515, 525, 531, 10531, 533, 10533, + 20533, 535, 541, 10541, 543, 10543, 20543, 545, 551, 10551, 100551, 110551, 200551, 210551, 553, 10553, 20553, + 30553, 100553, 110553, 120553, 130553, 200553, 210553, 220553, 300553, 9000533, 9010553, 555, 10555, 20555, + 100555, 110555, 120555, 200555, 557, 100557, 5122, 5112, 5212, 5222, 5114, 5214, 5224, 5132, 5232, 5312, 5322, + 5314, 5324, 5332, 5334, 5142, 5242, 5412, 5422, 5414, 5424, 5342, 5432, 5434, 5442, 5444, 5512, 5522, 5514, 5524, + 5532, 5534, 5542, 5544, 5554}; + + return (std::find(bPdG.begin(), bPdG.end(), std::abs(pc)) != bPdG.end()); +} +//________________________________________________________________________ +bool isCHadron(int pc) +{ + std::vector bPdG = {411, 421, 10411, 10421, 413, 423, 10413, 10423, 20431, 20423, 415, 425, 431, 10431, 433, 10433, 20433, 435, 441, + 10441, 100441, 443, 10443, 20443, 100443, 30443, 9000443, 9010443, 9020443, 445, 100445, 4122, 4222, 4212, 4112, + 4224, 4214, 4114, 4232, 4132, 4322, 4312, 4324, 4314, 4332, 4334, 4412, 4422, 4414, 4424, 4432, 4434, 4444}; + + return (std::find(bPdG.begin(), bPdG.end(), std::abs(pc)) != bPdG.end()); +} + /** * returns the globalIndex of the earliest mother of a particle in the shower. returns -1 if a suitable mother is not found * @@ -109,7 +131,7 @@ int getOriginalHFMotherIndex(const typename T::iterator& hfparticle) * @param hftrack track passed as reference which is then replaced by the first track that originated from an HF shower */ template -int jetTrackFromHFShower(T const& jet, U const& /*tracks*/, V const& particles, typename U::iterator& hftrack) +int jetTrackFromHFShower(T const& jet, U const& /*tracks*/, V const& particles, typename U::iterator& hftrack, bool searchUpToQuark) { bool hasMcParticle = false; @@ -120,7 +142,7 @@ int jetTrackFromHFShower(T const& jet, U const& /*tracks*/, V const& particles, } hasMcParticle = true; auto const& particle = track.template mcParticle_as(); - origin = RecoDecay::getCharmHadronOrigin(particles, particle, true); + origin = RecoDecay::getCharmHadronOrigin(particles, particle, searchUpToQuark); if (origin == 1 || origin == 2) { // 1=charm , 2=beauty hftrack = track; if (origin == 1) { @@ -146,12 +168,12 @@ int jetTrackFromHFShower(T const& jet, U const& /*tracks*/, V const& particles, * @param hfparticle particle passed as reference which is then replaced by the first track that originated from an HF shower */ template -int jetParticleFromHFShower(T const& jet, U const& particles, typename U::iterator& hfparticle) +int jetParticleFromHFShower(T const& jet, U const& particles, typename U::iterator& hfparticle, bool searchUpToQuark) { int origin = -1; for (const auto& particle : jet.template tracks_as()) { - origin = RecoDecay::getCharmHadronOrigin(particles, particle, true); + origin = RecoDecay::getCharmHadronOrigin(particles, particle, searchUpToQuark); if (origin == 1 || origin == 2) { // 1=charm , 2=beauty hfparticle = particle; if (origin == 1) { @@ -174,11 +196,11 @@ int jetParticleFromHFShower(T const& jet, U const& particles, typename U::iterat */ template -int mcdJetFromHFShower(T const& jet, U const& tracks, V const& particles, float dRMax = 0.25) +int mcdJetFromHFShower(T const& jet, U const& tracks, V const& particles, float dRMax = 0.25, bool searchUpToQuark = false) { typename U::iterator hftrack; - int origin = jetTrackFromHFShower(jet, tracks, particles, hftrack); + int origin = jetTrackFromHFShower(jet, tracks, particles, hftrack, searchUpToQuark); if (origin == JetTaggingSpecies::charm || origin == JetTaggingSpecies::beauty) { if (!hftrack.has_mcParticle()) { return JetTaggingSpecies::none; @@ -215,11 +237,11 @@ int mcdJetFromHFShower(T const& jet, U const& tracks, V const& particles, float */ template -int mcpJetFromHFShower(T const& jet, U const& particles, float dRMax = 0.25) +int mcpJetFromHFShower(T const& jet, U const& particles, float dRMax = 0.25, bool searchUpToQuark = false) { typename U::iterator hfparticle; - int origin = jetParticleFromHFShower(jet, particles, hfparticle); + int origin = jetParticleFromHFShower(jet, particles, hfparticle, searchUpToQuark); if (origin == JetTaggingSpecies::charm || origin == JetTaggingSpecies::beauty) { int originalHFMotherIndex = getOriginalHFMotherIndex(hfparticle); @@ -292,11 +314,7 @@ int jetOrigin(T const& jet, U const& particles, float dRMax = 0.25) template int16_t getJetFlavor(AnyJet const& jet, AllMCParticles const& mcparticles) { - const int arraySize = 99; - - std::array countpartcode; - int count = 0; - + bool charmQuark = false; for (auto& mcpart : mcparticles) { int pdgcode = mcpart.pdgCode(); if (TMath::Abs(pdgcode) == 21 || (TMath::Abs(pdgcode) >= 1 && TMath::Abs(pdgcode) <= 5)) { @@ -304,23 +322,94 @@ int16_t getJetFlavor(AnyJet const& jet, AllMCParticles const& mcparticles) if (dR < jet.r() / 100.f) { if (TMath::Abs(pdgcode) == 5) { - return 2; // Beauty jet - } else { - if (count > arraySize - 1) - return 0; - countpartcode[count] = pdgcode; - count++; + return JetTaggingSpecies::beauty; // Beauty jet + } else if (TMath::Abs(pdgcode) == 4) { + charmQuark = true; } } } } - for (int ij = 0; ij < count; ij++) { - if (TMath::Abs(countpartcode[ij]) == 4) - return 1; // Charm jet + if (charmQuark) { + return JetTaggingSpecies::charm; // Charm jet } - return 0; // Light flavor jet + return JetTaggingSpecies::lightflavour; // Light flavor jet +} + +/** + * return the jet flavor if it finds a HF hadron inside the jet: 0 for lf-jet, 1 for c-jet, 2 for b-jet + * + * @param AnyJet the jet that we need to study its flavor + * @param AllMCParticles a vector of all the mc particles stack + */ +template +int16_t getJetFlavorHadron(AnyJet const& jet, AllMCParticles const& mcparticles) +{ + bool charmHadron = false; + + for (auto& mcpart : mcparticles) { + int pdgcode = mcpart.pdgCode(); + if (isBHadron(pdgcode) || isCHadron(pdgcode)) { + double dR = jetutilities::deltaR(jet, mcpart); + + if (dR < jet.r() / 100.f) { + if (isBHadron(pdgcode)) { + return JetTaggingSpecies::beauty; // Beauty jet + } else if (isCHadron(pdgcode)) { + charmHadron = true; + } + } + } + } + + if (charmHadron) { + return JetTaggingSpecies::charm; // Charm jet + } + + return JetTaggingSpecies::lightflavour; // Light flavor jet +} + +/** + * return acceptance of track about DCA xy and z due to cut for QualityTracks + */ +template +bool trackAcceptanceWithDca(T const& track, float trackDcaXYMax, float trackDcaZMax) +{ + if (std::abs(track.dcaXY()) > trackDcaXYMax) + return false; + if (std::abs(track.dcaZ()) > trackDcaZMax) + return false; + return true; +} + +/** + * retrun acceptance of prong about chi2 and error of decay length due to cut for high quality secondary vertex + */ +template +bool prongAcceptance(T const& prong, float prongChi2PCAMin, float prongChi2PCAMax, float prongsigmaLxyMax, float prongIPxyMin, float prongIPxyMax, bool doXYZ) +{ + if (prong.chi2PCA() < prongChi2PCAMin) + return false; + if (prong.chi2PCA() > prongChi2PCAMax) + return false; + if (!doXYZ) { + if (prong.errorDecayLengthXY() > prongsigmaLxyMax) + return false; + if (std::abs(prong.impactParameterXY()) < prongIPxyMin) + return false; + if (std::abs(prong.impactParameterXY()) > prongIPxyMax) + return false; + } else { + if (prong.errorDecayLength() > prongsigmaLxyMax) + return false; + // TODO + if (std::abs(prong.impactParameterXY()) < prongIPxyMin) + return false; + if (std::abs(prong.impactParameterXY()) > prongIPxyMax) + return false; + } + return true; } /** @@ -328,18 +417,13 @@ int16_t getJetFlavor(AnyJet const& jet, AllMCParticles const& mcparticles) * positive and negative value are expected from primary vertex * positive value is expected from secondary vertex * - * @param collision which is needed external table of collision due to postion X and Y * @param jet - * @param track which is needed each DCA_X and Y which is measured in jettaggerhfExtension.cxx + * @param jtrack which is needed aod::JTrackExtras */ -template -int getGeoSign(T const& collision, U const& jet, V const& track) +template +int getGeoSign(T const& jet, U const& jtrack) { - auto trackPar = getTrackPar(track); - auto xyz = trackPar.getXYZGlo(); - auto dcaX = xyz.X() - collision.posX(); - auto dcaY = xyz.Y() - collision.posY(); - auto sign = TMath::Sign(1, dcaX * jet.px() + dcaY * jet.py() + track.dcaZ() * jet.pz()); + auto sign = TMath::Sign(1, jtrack.dcaX() * jet.px() + jtrack.dcaY() * jet.py() + jtrack.dcaZ() * jet.pz()); if (sign < -1 || sign > 1) LOGF(info, Form("Sign is %d", sign)); return sign; @@ -349,13 +433,14 @@ int getGeoSign(T const& collision, U const& jet, V const& track) * Orders the tracks associated with a jet based on signed impact parameter significance and stores them * in a vector in descending order. */ -template > -void orderForIPJetTracks(T const& collision, U const& jet, V const& /*jtracks*/, W const& /*tracks*/, Vec& vecSignImpSig) +template > +void orderForIPJetTracks(T const& jet, U const& /*jtracks*/, float const& trackDcaXYMax, float const& trackDcaZMax, Vec& vecSignImpSig) { - for (auto& jtrack : jet.template tracks_as()) { - auto track = jtrack.template track_as(); - auto geoSign = getGeoSign(collision, jet, track); - auto varSignImpXYSig = geoSign * TMath::Abs(track.dcaXY()) / TMath::Sqrt(track.sigmaDcaXY2()); + for (auto& jtrack : jet.template tracks_as()) { + if (!trackAcceptanceWithDca(jtrack, trackDcaXYMax, trackDcaZMax)) + continue; + auto geoSign = getGeoSign(jet, jtrack); + auto varSignImpXYSig = geoSign * std::abs(jtrack.dcaXY()) / jtrack.sigmadcaXY(); vecSignImpSig.push_back(varSignImpXYSig); } std::sort(vecSignImpSig.begin(), vecSignImpSig.end(), std::greater()); @@ -364,16 +449,17 @@ void orderForIPJetTracks(T const& collision, U const& jet, V const& /*jtracks*/, /** * Checks if a jet is greater than the given tagging working point based on the signed impact parameter significances */ -template -bool isGreaterThanTaggingPoint(T const& collision, U const& jet, V const& jtracks, W const& tracks, X const& taggingPoint = 1.0, Y const& cnt = 1) +template +bool isGreaterThanTaggingPoint(T const& jet, U const& jtracks, float const& trackDcaXYMax, float const& trackDcaZMax, float const& taggingPoint = 1.0, int const& cnt = 1) { - if (cnt == 0) + if (cnt == 0) { return true; // untagged + } std::vector vecSignImpSig; - orderForIPJetTracks(collision, jet, jtracks, tracks, vecSignImpSig); - if (vecSignImpSig.size() > cnt - 1) { + orderForIPJetTracks(jet, jtracks, trackDcaXYMax, trackDcaZMax, vecSignImpSig); + if (vecSignImpSig.size() > static_cast::size_type>(cnt) - 1) { for (int i = 0; i < cnt; i++) { - if (0 < vecSignImpSig[i] && vecSignImpSig[i] < taggingPoint) { // tagger point set + if (vecSignImpSig[i] < taggingPoint) { // tagger point set return false; } } @@ -394,7 +480,7 @@ template std::unique_ptr setResolutionFunction(T const& vecParams) { std::unique_ptr fResoFunc(new TF1("fResoFunc", "gaus(0)+expo(3)+expo(5)+expo(7)", -40, 0)); - for (int i = 0; i < vecParams.size(); i++) { + for (typename T::size_type i = 0; i < vecParams.size(); i++) { fResoFunc->SetParameter(i, vecParams[i]); } @@ -419,7 +505,7 @@ template float getTrackProbability(T const& fResoFuncjet, U const& track, const float& minSignImpXYSig = -40) { float probTrack = 0; - auto varSignImpXYSig = TMath::Abs(track.dcaXY()) / TMath::Sqrt(track.sigmaDcaXY2()); + auto varSignImpXYSig = TMath::Abs(track.dcaXY()) / track.sigmadcaXY(); if (-varSignImpXYSig < minSignImpXYSig) varSignImpXYSig = -minSignImpXYSig - 0.01; // To avoid overflow for integral probTrack = fResoFuncjet->Integral(minSignImpXYSig, -varSignImpXYSig) / fResoFuncjet->Integral(minSignImpXYSig, 0); @@ -438,7 +524,6 @@ float getTrackProbability(T const& fResoFuncjet, U const& track, const float& mi * @param collision: The collision event data, necessary for geometric sign calculations. * @param jet: The jet for which the probability is being calculated. * @param jtracks: Tracks in jets - * @param tracks: The original tracks to transform from jtracks. * @param cnt: ordering number of impact parameter cnt=0: untagged, cnt=1: first, cnt=2: seconde, cnt=3: third. * @param tagPoint: tagging working point which is selected by condiered efficiency and puriy * @param minSignImpXYSig: To avoid over fitting @@ -446,24 +531,25 @@ float getTrackProbability(T const& fResoFuncjet, U const& track, const float& mi * specific flavor. Returns -1 if the jet contains fewer than two tracks with a positive * geometric sign. */ -template -float getJetProbability(T const& fResoFuncjet, U const& collision, V const& jet, W const& jtracks, X const& tracks, const int& cnt, const float& tagPoint = 1.0, const float& minSignImpXYSig = -10) +template +float getJetProbability(T const& fResoFuncjet, U const& jet, V const& jtracks, float const& trackDcaXYMax, float const& trackDcaZMax, const int& cnt, const float& tagPoint = 1.0, const float& minSignImpXYSig = -10) { - if (!(isGreaterThanTaggingPoint(collision, jet, jtracks, tracks, tagPoint, cnt))) + if (!(isGreaterThanTaggingPoint(jet, jtracks, trackDcaXYMax, trackDcaZMax, tagPoint, cnt))) return -1; std::vector jetTracksPt; float trackjetProb = 1.; - for (auto& jtrack : jet.template tracks_as()) { - auto track = jtrack.template track_as(); + for (auto& jtrack : jet.template tracks_as()) { + if (!trackAcceptanceWithDca(jtrack, trackDcaXYMax, trackDcaZMax)) + continue; - float probTrack = getTrackProbability(fResoFuncjet, track, minSignImpXYSig); + float probTrack = getTrackProbability(fResoFuncjet, jtrack, minSignImpXYSig); - auto geoSign = getGeoSign(collision, jet, track); + auto geoSign = getGeoSign(jet, jtrack); if (geoSign > 0) { // only take positive sign track for JP calculation trackjetProb *= probTrack; - jetTracksPt.push_back(track.pt()); + jetTracksPt.push_back(jtrack.pt()); } } @@ -472,14 +558,185 @@ float getJetProbability(T const& fResoFuncjet, U const& collision, V const& jet, return -1; float sumjetProb = 0.; - for (int i = 0; i < jetTracksPt.size(); i++) { - sumjetProb += (TMath::Power(-1 * TMath::Log(trackjetProb), i) / TMath::Factorial(i)); + for (std::vector::size_type i = 0; i < jetTracksPt.size(); i++) { + sumjetProb += (TMath::Power(-1 * TMath::Log(trackjetProb), static_cast(i)) / TMath::Factorial(i)); } JP = trackjetProb * sumjetProb; return JP; } +// For secaondy vertex method utilites +class bjetCandSV +{ + public: + bjetCandSV() = default; + + bjetCandSV(float xpv, float ypv, float zpv, float xsv, float ysv, float zsv, + float pxVal, float pyVal, float pzVal, float eVal, float mVal, float chi2Val, + float errDecayLength, float errDecayLengthXY, + float rSecVertex, float ptVal, float pVal, + std::array pVec, float etaVal, float phiVal, + float yVal, float decayLen, float decayLenXY, + float decayLenNorm, float decayLenXYNorm, + float cpaVal, float impParXY) + : m_xPVertex(xpv), m_yPVertex(ypv), m_zPVertex(zpv), m_xSecondaryVertex(xsv), m_ySecondaryVertex(ysv), m_zSecondaryVertex(zsv), m_px(pxVal), m_py(pyVal), m_pz(pzVal), m_e(eVal), m_m(mVal), m_chi2PCA(chi2Val), m_errorDecayLength(errDecayLength), m_errorDecayLengthXY(errDecayLengthXY), m_rSecondaryVertex(rSecVertex), m_pt(ptVal), m_p(pVal), m_pVector(pVec), m_eta(etaVal), m_phi(phiVal), m_y(yVal), m_decayLength(decayLen), m_decayLengthXY(decayLenXY), m_decayLengthNormalised(decayLenNorm), m_decayLengthXYNormalised(decayLenXYNorm), m_cpa(cpaVal), m_impactParameterXY(impParXY) + { + } + + float xPVertex() const { return m_xPVertex; } + float yPVertex() const { return m_yPVertex; } + float zPVertex() const { return m_zPVertex; } + + float xSecondaryVertex() const { return m_xSecondaryVertex; } + float ySecondaryVertex() const { return m_ySecondaryVertex; } + float zSecondaryVertex() const { return m_zSecondaryVertex; } + + float px() const { return m_px; } + float py() const { return m_py; } + float pz() const { return m_pz; } + float e() const { return m_e; } + float m() const { return m_m; } + float chi2PCA() const { return m_chi2PCA; } + + float errorDecayLength() const { return m_errorDecayLength; } + float errorDecayLengthXY() const { return m_errorDecayLengthXY; } + + float rSecondaryVertex() const { return m_rSecondaryVertex; } + float pt() const { return m_pt; } + float p() const { return m_p; } + + std::array pVector() const { return m_pVector; } + + float eta() const { return m_eta; } + float phi() const { return m_phi; } + float y() const { return m_y; } + + float decayLength() const { return m_decayLength; } + float decayLengthXY() const { return m_decayLengthXY; } + float decayLengthNormalised() const { return m_decayLengthNormalised; } + float decayLengthXYNormalised() const { return m_decayLengthXYNormalised; } + + float cpa() const { return m_cpa; } + float impactParameterXY() const { return m_impactParameterXY; } + + private: + float m_xPVertex, m_yPVertex, m_zPVertex; + float m_xSecondaryVertex, m_ySecondaryVertex, m_zSecondaryVertex; + float m_px, m_py, m_pz, m_e, m_m, m_chi2PCA; + float m_errorDecayLength, m_errorDecayLengthXY; + float m_rSecondaryVertex, m_pt, m_p; + std::array m_pVector; + float m_eta, m_phi, m_y; + float m_decayLength, m_decayLengthXY, m_decayLengthNormalised, m_decayLengthXYNormalised; + float m_cpa, m_impactParameterXY; +}; + +template +bjetCandSV jetFromProngMaxDecayLength(const JetType& jet, float const& prongChi2PCAMin, float const& prongChi2PCAMax, float const& prongsigmaLxyMax, float const& prongIPxyMin, float const& prongIPxyMax, const bool& doXYZ = false) +{ + float xPVertex = 0.0f; + float yPVertex = 0.0f; + float zPVertex = 0.0f; + float xSecondaryVertex = 0.0f; + float ySecondaryVertex = 0.0f; + float zSecondaryVertex = 0.0f; + float px = 0.0f; + float py = 0.0f; + float pz = 0.0f; + float e = 0.0f; + float m = 0.0f; + float chi2PCA = 0.0f; + float errorDecayLength = 0.0f; + float errorDecayLengthXY = 0.0f; + + float rSecondaryVertex = 0.0f; + float pt = 0.0f; + float p = 0.0f; + std::array pVector = {0.0f, 0.0f, 0.0f}; + float eta = 0.0f; + float phi = 0.0f; + float y = 0.0f; + float decayLength = 0.0f; + float decayLengthXY = 0.0f; + float decayLengthNormalised = 0.0f; + float decayLengthXYNormalised = 0.0f; + float cpa = 0.0f; + float impactParameterXY = 0.0f; + + float maxSxy = -1.0f; + + for (const auto& prong : jet.template secondaryVertices_as()) { + float Sxy = -1.; + if (!doXYZ) { + Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + } else { + Sxy = prong.decayLength() / prong.errorDecayLength(); + } + + if (maxSxy < Sxy) { + maxSxy = Sxy; + + xPVertex = prong.xPVertex(); + yPVertex = prong.yPVertex(); + zPVertex = prong.zPVertex(); + xSecondaryVertex = prong.xSecondaryVertex(); + ySecondaryVertex = prong.ySecondaryVertex(); + zSecondaryVertex = prong.zSecondaryVertex(); + px = prong.px(); + py = prong.py(); + pz = prong.pz(); + e = prong.e(); + m = prong.m(); + chi2PCA = prong.chi2PCA(); + errorDecayLength = prong.errorDecayLength(); + errorDecayLengthXY = prong.errorDecayLengthXY(); + rSecondaryVertex = prong.rSecondaryVertex(); + pt = prong.pt(); + p = prong.p(); + pVector = prong.pVector(); + eta = prong.eta(); + phi = prong.phi(); + y = prong.y(); + decayLength = prong.decayLength(); + decayLengthXY = prong.decayLengthXY(); + decayLengthNormalised = prong.decayLengthNormalised(); + decayLengthXYNormalised = prong.decayLengthXYNormalised(); + cpa = prong.cpa(); + impactParameterXY = prong.impactParameterXY(); + } + } + + return bjetCandSV( + xPVertex, yPVertex, zPVertex, + xSecondaryVertex, ySecondaryVertex, zSecondaryVertex, + px, py, pz, e, m, chi2PCA, + errorDecayLength, errorDecayLengthXY, + rSecondaryVertex, pt, p, + pVector, eta, phi, + y, decayLength, decayLengthXY, + decayLengthNormalised, decayLengthXYNormalised, + cpa, impactParameterXY); +} + +template +bool isTaggedJetSV(T const jet, U const& /*prongs*/, float const& prongChi2PCAMin, float const& prongChi2PCAMax, float const& prongsigmaLxyMax, float const& prongIPxyMin, float const& prongIPxyMax, float const& doXYZ = false, float const& tagPointForSV = 15.) +{ + auto bjetCand = jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, doXYZ); + if (!prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, doXYZ)) + return false; + if (!doXYZ) { + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + if (maxSxy < tagPointForSV) + return false; + } else { + auto maxSxyz = bjetCand.decayLength() / bjetCand.errorDecayLength(); + if (maxSxyz < tagPointForSV) + return false; + } + return true; +} + }; // namespace jettaggingutilities #endif // PWGJE_CORE_JETTAGGINGUTILITIES_H_ diff --git a/PWGJE/Core/JetUtilities.h b/PWGJE/Core/JetUtilities.h index a681d76bf89..dac55dfbaa1 100644 --- a/PWGJE/Core/JetUtilities.h +++ b/PWGJE/Core/JetUtilities.h @@ -141,12 +141,20 @@ std::tuple>, std::vector>> MatchCl template float deltaR(T const& A, U const& B) { - float dPhi = RecoDecay::constrainAngle(A.phi() - B.phi(), -M_PI); + float dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(A.phi(), -M_PI) - RecoDecay::constrainAngle(B.phi(), -M_PI), -M_PI); float dEta = A.eta() - B.eta(); - return TMath::Sqrt(dEta * dEta + dPhi * dPhi); + return std::sqrt(dEta * dEta + dPhi * dPhi); } +// same as deltaR but explicit specification of the eta and phi components +template +float deltaR(T const& eta1, U const& phi1, V const& eta2, W const& phi2) +{ + float dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(phi1, -M_PI) - RecoDecay::constrainAngle(phi2, -M_PI), -M_PI); + float dEta = eta1 - eta2; + return std::sqrt(dEta * dEta + dPhi * dPhi); +} }; // namespace jetutilities #endif // PWGJE_CORE_JETUTILITIES_H_ diff --git a/PWGJE/Core/JetV0Utilities.h b/PWGJE/Core/JetV0Utilities.h index a5a84a6576b..9e25fb13461 100644 --- a/PWGJE/Core/JetV0Utilities.h +++ b/PWGJE/Core/JetV0Utilities.h @@ -22,6 +22,8 @@ #include #include +#include + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" @@ -83,22 +85,80 @@ constexpr bool isV0McTable() return std::is_same_v, CandidatesV0MCP> || std::is_same_v, o2::soa::Filtered>; // note not optimal way but needed for jetfindingutilities::analyseParticles() } -template -bool isV0Particle(T const& particle) +/** + * returns true if the track is a daughter of the V0 candidate + * + * @param track track that is being checked + * @param candidate V0 candidate that is being checked + * @param tracks the track table + */ +template +bool isV0DaughterTrack(T& track, U& candidate, V const& /*tracks*/) { - - if (TMath::Abs(particle.pdgCode()) == 310) { // k0s - return true; + if constexpr (isV0Candidate()) { + if (candidate.posTrackId() == track.globalIndex() || candidate.negTrackId() == track.globalIndex()) { + return true; + } else { + return false; + } + } else { + return false; } - if (TMath::Abs(particle.pdgCode()) == 3122) { // Lambda - return true; +} + +/** + * returns the index of the JMcParticle matched to the V0 candidate + * + * @param candidate V0 candidate that is being checked + * @param tracks track table + * @param particles particle table + */ +template +auto matchedV0ParticleId(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +{ + const auto candidateDaughterParticle = candidate.template posTrack_as().template mcParticle_as(); + return candidateDaughterParticle.template mothers_first_as().globalIndex(); // can we get the Id directly? +} + +/** + * returns the JMcParticle matched to the V0 candidate + * + * @param candidate v0 candidate that is being checked + * @param tracks track table + * @param particles particle table + */ +template +auto matchedV0Particle(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +{ + const auto candidateDaughterParticle = candidate.template posTrack_as().template mcParticle_as(); + return candidateDaughterParticle.template mothers_first_as(); +} + +/** + * returns a slice of the table depending on the index of the V0 candidate + * + * @param candidate v0 candidate that is being checked + * @param table the table to be sliced + */ +template +auto slicedPerV0Candidate(T const& table, U const& candidate, V const& perV0Candidate) +{ + if constexpr (isV0Candidate()) { + return table.sliceBy(perV0Candidate, candidate.globalIndex()); + } else { + return table; } - return false; +} + +template +bool isV0Particle(T const& particles, U const& particle) +{ + return RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true); } enum JV0ParticleDecays { K0sToPiPi = 0, - LambdaPPi = 1 + LambdaToPPi = 1 }; template @@ -114,37 +174,21 @@ int initialiseV0ParticleDecaySelection(std::string v0ParticleDecaySelection) { if (v0ParticleDecaySelection == "K0sToPiPi") { return JV0ParticleDecays::K0sToPiPi; - } else if (v0ParticleDecaySelection == "LambdaPPi") { - return JV0ParticleDecays::LambdaPPi; + } else if (v0ParticleDecaySelection == "LambdaToPPi") { + return JV0ParticleDecays::LambdaToPPi; } return -1; } -template -uint8_t setV0ParticleDecayBit(T const& particle) +template +uint8_t setV0ParticleDecayBit(T const& particles, U const& particle) { - uint8_t bit = 0; - - if (particle.has_daughters()) { - int daughter1PdgCode = 0; - int daughter2PdgCode = 0; - int i = 0; - for (auto daughter : particle.template daughters_as()) { - if (i == 0) { - daughter1PdgCode = daughter.pdgCode(); - } - if (i == 1) { - daughter2PdgCode = daughter.pdgCode(); - } - i++; - } - if (TMath::Abs(daughter1PdgCode) == 211 && TMath::Abs(daughter2PdgCode) == 211) { - SETBIT(bit, JV0ParticleDecays::K0sToPiPi); - } - if ((TMath::Abs(daughter1PdgCode) == 211 && TMath::Abs(daughter2PdgCode) == 2212) || (TMath::Abs(daughter2PdgCode) == 211 && TMath::Abs(daughter1PdgCode) == 2212)) { - SETBIT(bit, JV0ParticleDecays::LambdaPPi); - } + if (RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true)) { + SETBIT(bit, JV0ParticleDecays::K0sToPiPi); + } + if (RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true)) { + SETBIT(bit, JV0ParticleDecays::LambdaToPPi); } return bit; } diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index c3aa23fac84..0fbefea974f 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -35,6 +35,7 @@ const EMCALClusterDefinition kV1Variation2(ClusterAlgorithm_t::kV3, 2, 1, "kV1Va const EMCALClusterDefinition kV3Default(ClusterAlgorithm_t::kV3, 10, 1, "kV3Default", 0.5, 0.1, -10000, 10000, true, 0.03); const EMCALClusterDefinition kV3Variation1(ClusterAlgorithm_t::kV3, 11, 1, "kV3Variation1", 0.5, 0.1, -10000, 10000, true, 0.); const EMCALClusterDefinition kV3Variation2(ClusterAlgorithm_t::kV3, 12, 1, "kV3Variation2", 0.5, 0.1, -10000, 10000, false, 0.); +const EMCALClusterDefinition kV3Variation3(ClusterAlgorithm_t::kV3, 13, 1, "kV3Variation3", 0.5, 0.1, -10000, 10000, true, 20.); /// \brief function returns EMCALClusterDefinition for the given name /// \param name name of the cluster definition @@ -53,6 +54,8 @@ const EMCALClusterDefinition getClusterDefinitionFromString(const std::string& c return kV3Variation1; } else if (clusterDefinitionName == "kV3Variation2") { return kV3Variation2; + } else if (clusterDefinitionName == "kV3Variation3") { + return kV3Variation3; } else { throw std::invalid_argument("Cluster definition name not recognized"); } diff --git a/PWGJE/DataModel/GammaJetAnalysisTree.h b/PWGJE/DataModel/GammaJetAnalysisTree.h new file mode 100644 index 00000000000..beb927f381c --- /dev/null +++ b/PWGJE/DataModel/GammaJetAnalysisTree.h @@ -0,0 +1,75 @@ +// Copyright 2019-2020 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. + +/// +/// \brief Table definitions for gamma-jet analyses +/// +/// \author Florian Jonas + +#ifndef PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ +#define PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ + +#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" + +namespace o2::aod +{ + +namespace gjevent +{ // TODO add rho //! event index +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); +DECLARE_SOA_COLUMN(Centrality, centrality, float); +DECLARE_SOA_COLUMN(Rho, rho, float); +DECLARE_SOA_COLUMN(EventSel, eventSel, uint8_t); +DECLARE_SOA_BITMAP_COLUMN(Alias, alias, 32); +} // namespace gjevent +DECLARE_SOA_TABLE(GjEvents, "AOD", "GJEVENT", o2::soa::Index<>, gjevent::Multiplicity, gjevent::Centrality, gjevent::Rho, gjevent::EventSel, gjevent::Alias) + +using GjEvent = GjEvents::iterator; + +namespace gjgamma +{ +DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); //! event index +DECLARE_SOA_COLUMN(Energy, energy, float); //! cluster energy (GeV) +DECLARE_SOA_COLUMN(Eta, eta, float); //! cluster pseudorapidity (calculated using vertex) +DECLARE_SOA_COLUMN(Phi, phi, float); //! cluster azimuthal angle (calculated using vertex) +DECLARE_SOA_COLUMN(M02, m02, float); //! shower shape long axis +DECLARE_SOA_COLUMN(M20, m20, float); //! shower shape short axis +DECLARE_SOA_COLUMN(NCells, nCells, ushort); //! number of cells in cluster +DECLARE_SOA_COLUMN(Time, time, float); //! cluster time (ns) +DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag to mark cluster as exotic +DECLARE_SOA_COLUMN(DistanceToBadChannel, distanceToBadChannel, float); //! distance to bad channel +DECLARE_SOA_COLUMN(NLM, nlm, ushort); //! number of local maxima +DECLARE_SOA_COLUMN(IsoRaw, isoraw, ushort); //! isolation in cone not corrected for Rho +DECLARE_SOA_COLUMN(PerpConeRho, perpconerho, float); //! rho in perpendicular cone +DECLARE_SOA_COLUMN(TMdeltaPhi, tmdeltaphi, float); //! delta phi between cluster and closest match +DECLARE_SOA_COLUMN(TMdeltaEta, tmdeltaeta, float); //! delta eta between cluster and closest match +DECLARE_SOA_COLUMN(TMtrackP, tmtrackp, float); //! track momentum of closest match, -1 if no match found +} // namespace gjgamma +DECLARE_SOA_TABLE(GjGammas, "AOD", "GJGAMMA", + gjgamma::GjEventId, gjgamma::Energy, gjgamma::Eta, gjgamma::Phi, gjgamma::M02, gjgamma::M20, gjgamma::NCells, gjgamma::Time, gjgamma::IsExotic, gjgamma::DistanceToBadChannel, gjgamma::NLM, gjgamma::IsoRaw, gjgamma::PerpConeRho, gjgamma::TMdeltaPhi, gjgamma::TMdeltaEta, gjgamma::TMtrackP) +namespace gjchjet +{ +DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(Area, area, float); +DECLARE_SOA_COLUMN(NConstituents, nConstituents, ushort); +} // namespace gjchjet +DECLARE_SOA_TABLE(GjChargedJets, "AOD", "GJCHJET", gjchjet::GjEventId, gjchjet::Pt, gjchjet::Eta, gjchjet::Phi, gjchjet::Energy, gjchjet::Mass, gjchjet::Area, gjchjet::NConstituents) +} // namespace o2::aod + +#endif // PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ diff --git a/PWGJE/DataModel/Jet.h b/PWGJE/DataModel/Jet.h index 4da8733ea72..33b8fdb4320 100644 --- a/PWGJE/DataModel/Jet.h +++ b/PWGJE/DataModel/Jet.h @@ -29,12 +29,13 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataV0.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" #include "PWGJE/DataModel/JetSubtraction.h" #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" - #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" namespace o2::aod { @@ -98,19 +99,19 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! absolute p DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_jet_type_, matchedJetCand, int32_t, _jet_type_##s, "_hf"); \ } -#define DECLARE_CONSTITUENTS_TABLE(_jet_type_, _name_, _Description_, _track_type_, _cand_type_) \ - namespace _name_##constituents \ - { \ - DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ - DECLARE_SOA_ARRAY_INDEX_COLUMN(_track_type_, tracks); \ - DECLARE_SOA_ARRAY_INDEX_COLUMN(JCluster, clusters); \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(HfCandidates, hfcandidates, int32_t, _cand_type_, "_hfcand"); \ - } \ - DECLARE_SOA_TABLE(_jet_type_##Constituents, "AOD", _Description_ "C", \ - _name_##constituents::_jet_type_##Id, \ - _name_##constituents::_track_type_##Ids, \ - _name_##constituents::JClusterIds, \ - _name_##constituents::HfCandidatesIds); +#define DECLARE_CONSTITUENTS_TABLE(_jet_type_, _name_, _Description_, _track_type_, _cand_type_) \ + namespace _name_##constituents \ + { \ + DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ + DECLARE_SOA_ARRAY_INDEX_COLUMN(_track_type_, tracks); \ + DECLARE_SOA_ARRAY_INDEX_COLUMN(JCluster, clusters); \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(Candidates, candidates, int32_t, _cand_type_, "_cand"); \ + } \ + DECLARE_SOA_TABLE(_jet_type_##Constituents, "AOD", _Description_ "C", \ + _name_##constituents::_jet_type_##Id, \ + _name_##constituents::_track_type_##Ids, \ + _name_##constituents::JClusterIds, \ + _name_##constituents::CandidatesIds); // combine definition of tables for jets, constituents #define DECLARE_JET_TABLES(_collision_name_, _jet_type_, _track_type_, _hfcand_type_, _description_) \ @@ -183,7 +184,8 @@ DECLARE_JET_TABLES_LEVELS(Neutral, JTrackSub, HfD0Bases, HfD0PBases, "N"); DECLARE_JET_TABLES_LEVELS(D0Charged, JTrackD0Sub, HfD0Bases, HfD0PBases, "D0"); DECLARE_JET_TABLES_LEVELS(LcCharged, JTrackLcSub, Hf3PBases, Hf3PPBases, "Lc"); DECLARE_JET_TABLES_LEVELS(BplusCharged, JTrackBplusSub, HfCandBplus, HfD0PBases, "BPl"); -DECLARE_JET_TABLES_LEVELS(V0Charged, JTrackSub, V0Cores, JV0McParticles, "V0"); +DECLARE_JET_TABLES_LEVELS(V0Charged, JTrackSub, V0Cores, JV0Mcs, "V0"); +DECLARE_JET_TABLES_LEVELS(DielectronCharged, JTrackSub, Dielectrons, JDielectronMcs, "DIEL"); // duplicate jet tables (added as needed for analyses) DECLARE_JET_DUPLICATE_TABLES_LEVELS(Charged, JTrackSub, HfD0Bases, HfD0PBases, "C", 1); @@ -224,7 +226,15 @@ using CandidatesBplusMCP = o2::soa::Join; using CandidatesV0MCD = o2::soa::Join; -// using V0Daughters = o2::aod::DauTrackExtras; // we need to add the V0Extras table to CandiatesV0Data if we want to use this. Will wait for an analysis use case -using CandidatesV0MCP = o2::aod::JV0McParticles; +// using V0Daughters = o2::aod::DauTrackExtras; +using McCollisionsV0 = o2::soa::Join; +using CandidatesV0MCP = o2::soa::Join; + +using CollisionsDielectron = o2::soa::Join; +using CandidatesDielectronData = o2::soa::Join; +using CandidatesDielectronMCD = o2::soa::Join; +using JetTracksSubDielectron = o2::aod::JTrackDielectronSubs; +using McCollisionsDielectron = o2::soa::Join; +using CandidatesDielectronMCP = o2::soa::Join; #endif // PWGJE_DATAMODEL_JET_H_ diff --git a/PWGJE/DataModel/JetReducedData.h b/PWGJE/DataModel/JetReducedData.h index b5439774663..e5ce626f9a7 100644 --- a/PWGJE/DataModel/JetReducedData.h +++ b/PWGJE/DataModel/JetReducedData.h @@ -32,13 +32,21 @@ DECLARE_SOA_INDEX_COLUMN(BC, bc); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); +DECLARE_SOA_BITMAP_COLUMN(Alias, alias, 32); +DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 64); +DECLARE_SOA_COLUMN(ReadCounts, readCounts, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVX, readCountsWithTVX, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndNoTFB, readCountsWithTVXAndNoTFB, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndNoTFBAndNoITSROFB, readCountsWithTVXAndNoTFBAndNoITSROFB, std::vector); } // namespace jbc DECLARE_SOA_TABLE(JBCs, "AOD", "JBC", o2::soa::Index<>, jbc::RunNumber, jbc::GlobalBC, - jbc::Timestamp); + jbc::Timestamp, + jbc::Alias, + jbc::Selection); using JBC = JBCs::iterator; @@ -47,6 +55,8 @@ DECLARE_SOA_TABLE(StoredJBCs, "AOD1", "JBC", jbc::RunNumber, jbc::GlobalBC, jbc::Timestamp, + jbc::Alias, + jbc::Selection, o2::soa::Marker<1>); using StoredJBC = StoredJBCs::iterator; @@ -58,6 +68,19 @@ DECLARE_SOA_TABLE(StoredJBCPIs, "AOD1", "JBCPI", jbc::BCId, o2::soa::Marker<1>); +DECLARE_SOA_TABLE(BCCounts, "AOD", "BCCOUNT", + jbc::ReadCounts, + jbc::ReadCountsWithTVX, + jbc::ReadCountsWithTVXAndNoTFB, + jbc::ReadCountsWithTVXAndNoTFBAndNoITSROFB); + +DECLARE_SOA_TABLE(StoredBCCounts, "AOD1", "BCCOUNT", + jbc::ReadCounts, + jbc::ReadCountsWithTVX, + jbc::ReadCountsWithTVXAndNoTFB, + jbc::ReadCountsWithTVXAndNoTFBAndNoITSROFB, + o2::soa::Marker<1>); + namespace jcollision { DECLARE_SOA_INDEX_COLUMN(Collision, collision); @@ -67,14 +90,27 @@ DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); DECLARE_SOA_COLUMN(Centrality, centrality, float); -DECLARE_SOA_COLUMN(EventSel, eventSel, uint8_t); +DECLARE_SOA_COLUMN(EventSel, eventSel, uint16_t); DECLARE_SOA_BITMAP_COLUMN(Alias, alias, 32); +DECLARE_SOA_COLUMN(TrackOccupancyInTimeRange, trackOccupancyInTimeRange, int); +DECLARE_SOA_COLUMN(TriggerSel, triggerSel, uint64_t); DECLARE_SOA_COLUMN(ChargedTriggerSel, chargedTriggerSel, uint8_t); DECLARE_SOA_COLUMN(FullTriggerSel, fullTriggerSel, uint32_t); DECLARE_SOA_COLUMN(ChargedHFTriggerSel, chargedHFTriggerSel, uint8_t); DECLARE_SOA_COLUMN(ReadCounts, readCounts, std::vector); -DECLARE_SOA_COLUMN(ReadSelectedCounts, readSelectedCounts, std::vector); -DECLARE_SOA_COLUMN(WrittenCounts, writtenCounts, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVX, readCountsWithTVX, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel8, readCountsWithTVXAndZVertexAndSel8, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel8Full, readCountsWithTVXAndZVertexAndSel8Full, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel8FullPbPb, readCountsWithTVXAndZVertexAndSel8FullPbPb, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSelMC, readCountsWithTVXAndZVertexAndSelMC, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSelMCFull, readCountsWithTVXAndZVertexAndSelMCFull, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSelMCFullPbPb, readCountsWithTVXAndZVertexAndSelMCFullPbPb, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSelUnanchoredMC, readCountsWithTVXAndZVertexAndSelUnanchoredMC, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSelTVX, readCountsWithTVXAndZVertexAndSelTVX, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel7, readCountsWithTVXAndZVertexAndSel7, std::vector); +DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel7KINT7, readCountsWithTVXAndZVertexAndSel7KINT7, std::vector); +DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); +DECLARE_SOA_COLUMN(IsEMCALReadout, isEmcalReadout, bool); } // namespace jcollision DECLARE_SOA_TABLE(JCollisions, "AOD", "JCOLLISION", @@ -84,8 +120,10 @@ DECLARE_SOA_TABLE(JCollisions, "AOD", "JCOLLISION", jcollision::PosZ, jcollision::Multiplicity, jcollision::Centrality, + jcollision::TrackOccupancyInTimeRange, jcollision::EventSel, - jcollision::Alias); + jcollision::Alias, + jcollision::TriggerSel); using JCollision = JCollisions::iterator; @@ -96,12 +134,25 @@ DECLARE_SOA_TABLE(StoredJCollisions, "AOD1", "JCOLLISION", jcollision::PosZ, jcollision::Multiplicity, jcollision::Centrality, + jcollision::TrackOccupancyInTimeRange, jcollision::EventSel, jcollision::Alias, + jcollision::TriggerSel, o2::soa::Marker<1>); using StoredJCollision = StoredJCollisions::iterator; +DECLARE_SOA_TABLE(JEMCCollisionLbs, "AOD", "JEMCCOLLISIONLB", + jcollision::IsAmbiguous, + jcollision::IsEMCALReadout); +using JEMCCollisionLb = JEMCCollisionLbs::iterator; + +DECLARE_SOA_TABLE(StoredJEMCCollisionLbs, "AOD1", "JEMCCOLLISIONLB", + jcollision::IsAmbiguous, + jcollision::IsEMCALReadout, + o2::soa::Marker<1>); +using StoredJEMCCollisionLb = StoredJEMCCollisionLbs::iterator; + DECLARE_SOA_TABLE(JCollisionPIs, "AOD", "JCOLLISIONPI", jcollision::CollisionId); @@ -109,43 +160,49 @@ DECLARE_SOA_TABLE(StoredJCollisionPIs, "AOD1", "JCOLLISIONPI", jcollision::CollisionId, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(JChTrigSels, "AOD", "JCHTRIGSEL", - jcollision::ChargedTriggerSel); +DECLARE_SOA_TABLE(JCollisionBCs, "AOD", "JCOLLISIONBC", + jcollision::JBCId); -DECLARE_SOA_TABLE(StoredJChTrigSels, "AOD1", "JCHTRIGSEL", - jcollision::ChargedTriggerSel, +DECLARE_SOA_TABLE(StoredJCollisionBCs, "AOD1", "JCOLLISIONBC", + jcollision::JBCId, o2::soa::Marker<1>); +DECLARE_SOA_TABLE(JChTrigSels, "AOD", "JCHTRIGSEL", + jcollision::ChargedTriggerSel); + DECLARE_SOA_TABLE(JFullTrigSels, "AOD", "JFULLTRIGSEL", jcollision::FullTriggerSel); -DECLARE_SOA_TABLE(StoredJFullTrigSels, "AOD1", "JFULLTRIGSEL", - jcollision::FullTriggerSel, - o2::soa::Marker<1>); - DECLARE_SOA_TABLE(JChHFTrigSels, "AOD", "JCHHFTRIGSEL", jcollision::ChargedHFTriggerSel); -DECLARE_SOA_TABLE(StoredJChHFTrigSels, "AOD1", "JCHHFTRIGSEL", - jcollision::ChargedHFTriggerSel, - o2::soa::Marker<1>); - -DECLARE_SOA_TABLE(JCollisionBCs, "AOD", "JCOLLISIONBC", - jcollision::JBCId); - -DECLARE_SOA_TABLE(StoredJCollisionBCs, "AOD1", "JCOLLISIONBC", - jcollision::JBCId, - o2::soa::Marker<1>); - DECLARE_SOA_TABLE(CollisionCounts, "AOD", "COLLCOUNT", jcollision::ReadCounts, - jcollision::ReadSelectedCounts, - jcollision::WrittenCounts); + jcollision::ReadCountsWithTVX, + jcollision::ReadCountsWithTVXAndZVertexAndSel8, + jcollision::ReadCountsWithTVXAndZVertexAndSel8Full, + jcollision::ReadCountsWithTVXAndZVertexAndSel8FullPbPb, + jcollision::ReadCountsWithTVXAndZVertexAndSelMC, + jcollision::ReadCountsWithTVXAndZVertexAndSelMCFull, + jcollision::ReadCountsWithTVXAndZVertexAndSelMCFullPbPb, + jcollision::ReadCountsWithTVXAndZVertexAndSelUnanchoredMC, + jcollision::ReadCountsWithTVXAndZVertexAndSelTVX, + jcollision::ReadCountsWithTVXAndZVertexAndSel7, + jcollision::ReadCountsWithTVXAndZVertexAndSel7KINT7); DECLARE_SOA_TABLE(StoredCollisionCounts, "AOD1", "COLLCOUNT", jcollision::ReadCounts, - jcollision::ReadSelectedCounts, - jcollision::WrittenCounts, + jcollision::ReadCountsWithTVX, + jcollision::ReadCountsWithTVXAndZVertexAndSel8, + jcollision::ReadCountsWithTVXAndZVertexAndSel8Full, + jcollision::ReadCountsWithTVXAndZVertexAndSel8FullPbPb, + jcollision::ReadCountsWithTVXAndZVertexAndSelMC, + jcollision::ReadCountsWithTVXAndZVertexAndSelMCFull, + jcollision::ReadCountsWithTVXAndZVertexAndSelMCFullPbPb, + jcollision::ReadCountsWithTVXAndZVertexAndSelUnanchoredMC, + jcollision::ReadCountsWithTVXAndZVertexAndSelTVX, + jcollision::ReadCountsWithTVXAndZVertexAndSel7, + jcollision::ReadCountsWithTVXAndZVertexAndSel7KINT7, o2::soa::Marker<1>); namespace jmccollision @@ -201,8 +258,14 @@ DECLARE_SOA_INDEX_COLUMN(Track, track); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +DECLARE_SOA_COLUMN(DCAX, dcaX, float); +DECLARE_SOA_COLUMN(DCAY, dcaY, float); DECLARE_SOA_COLUMN(DCAZ, dcaZ, float); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +DECLARE_SOA_COLUMN(DCAXYZ, dcaXYZ, float); +DECLARE_SOA_COLUMN(SigmaDCAZ, sigmadcaZ, float); +DECLARE_SOA_COLUMN(SigmaDCAXY, sigmadcaXY, float); +DECLARE_SOA_COLUMN(SigmaDCAXYZ, sigmadcaXYZ, float); DECLARE_SOA_COLUMN(Sigma1Pt, sigma1Pt, float); DECLARE_SOA_COLUMN(TrackSel, trackSel, uint8_t); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, @@ -253,13 +316,25 @@ DECLARE_SOA_TABLE(StoredJTracks, "AOD1", "JTRACK", using StoredJTrack = StoredJTracks::iterator; DECLARE_SOA_TABLE(JTrackExtras, "AOD", "JTRACKEXTRA", - jtrack::DCAXY, + jtrack::DCAX, + jtrack::DCAY, jtrack::DCAZ, + jtrack::DCAXY, + jtrack::DCAXYZ, + jtrack::SigmaDCAZ, + jtrack::SigmaDCAXY, + jtrack::SigmaDCAXYZ, jtrack::Sigma1Pt); DECLARE_SOA_TABLE(StoredJTrackExtras, "AOD1", "JTRACKEXTRA", - jtrack::DCAXY, + jtrack::DCAX, + jtrack::DCAY, jtrack::DCAZ, + jtrack::DCAXY, + jtrack::DCAXYZ, + jtrack::SigmaDCAZ, + jtrack::SigmaDCAXY, + jtrack::SigmaDCAXYZ, jtrack::Sigma1Pt, o2::soa::Marker<1>); diff --git a/PWGJE/DataModel/JetReducedDataDQ.h b/PWGJE/DataModel/JetReducedDataDQ.h new file mode 100644 index 00000000000..21fadaf9e95 --- /dev/null +++ b/PWGJE/DataModel/JetReducedDataDQ.h @@ -0,0 +1,202 @@ +// Copyright 2019-2020 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. + +/// +/// \brief Table definitions for reduced data model for dq jets +/// +/// \author Nima Zardoshti + +#ifndef PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ +#define PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ + +#include +#include +#include "Framework/AnalysisDataModel.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGJE/DataModel/JetReducedData.h" + +namespace o2::aod +{ + +DECLARE_SOA_TABLE(JDielectronMcCollisions, "AOD", "JDIELMCCOLL", + o2::soa::Index<>, + jmccollision::PosX, + jmccollision::PosY, + jmccollision::PosZ, + o2::soa::Marker<3>); + +using JMcCollision = JMcCollisions::iterator; + +DECLARE_SOA_TABLE(StoredJDielectronMcCollisions, "AOD1", "JDIELMCCOLL", + o2::soa::Index<>, + jmccollision::PosX, + jmccollision::PosY, + jmccollision::PosZ, + o2::soa::Marker<4>); + +namespace jdielectronindices +{ +DECLARE_SOA_INDEX_COLUMN(JCollision, collision); +DECLARE_SOA_INDEX_COLUMN_CUSTOM(JDielectronMcCollision, dielectronmccollision, "JDIELMCCOLLS"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, JTracks, "_0"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, JTracks, "_1"); +DECLARE_SOA_INDEX_COLUMN(JMcCollision, mcCollision); +DECLARE_SOA_INDEX_COLUMN(JMcParticle, mcParticle); +} // namespace jdielectronindices + +DECLARE_SOA_TABLE(JDielectronCollisionIds, "AOD", "JDIELCOLLID", + jdielectronindices::JCollisionId); + +DECLARE_SOA_TABLE(StoredJDielectronCollisionIds, "AOD1", "JDIELCOLLID", + jdielectronindices::JCollisionId, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(JDielectronMcCollisionIds, "AOD", "JDIELMCCOLLID", + jdielectronindices::JMcCollisionId); + +DECLARE_SOA_TABLE(StoredJDielectronMcCollisionIds, "AOD1", "JDIELMCCOLLID", + jdielectronindices::JMcCollisionId, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(JDielectronIds, "AOD", "JDIELID", + jdielectronindices::JCollisionId, + jdielectronindices::Prong0Id, + jdielectronindices::Prong1Id); + +DECLARE_SOA_TABLE(StoredJDielectronIds, "AOD1", "JDIELID", + jdielectronindices::JCollisionId, + jdielectronindices::Prong0Id, + jdielectronindices::Prong1Id, + o2::soa::Marker<1>); + +namespace jdielectronmc +{ +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(E, e, float); +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); +DECLARE_SOA_COLUMN(GenStatusCode, getGenStatusCode, int); // TODO : We can look at combining this with the two below +DECLARE_SOA_COLUMN(HepMCStatusCode, getHepMCStatusCode, int); +DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); +DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); +DECLARE_SOA_COLUMN(DecayFlag, decayFlag, int8_t); +DECLARE_SOA_COLUMN(Origin, origin, int); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, + [](float pt, float phi) -> float { return pt * std::cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, + [](float pt, float phi) -> float { return pt * std::sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, + [](float pt, float eta) -> float { return pt * std::sinh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, + [](float pt, float eta) -> float { return pt * std::cosh(eta); }); +} // namespace jdielectronmc + +DECLARE_SOA_TABLE(JDielectronMcs, "AOD", "JDIELMC", + o2::soa::Index<>, + jdielectronindices::JDielectronMcCollisionId, + jdielectronmc::Pt, + jdielectronmc::Eta, + jdielectronmc::Phi, + jdielectronmc::Y, + jdielectronmc::E, + jdielectronmc::M, + jdielectronmc::PdgCode, + jdielectronmc::GenStatusCode, + jdielectronmc::HepMCStatusCode, + jdielectronmc::IsPhysicalPrimary, + jdielectronmc::DecayFlag, + jdielectronmc::Origin, + jdielectronmc::Px, + jdielectronmc::Py, + jdielectronmc::Pz, + jdielectronmc::P); + +using JDielectronMc = JDielectronMcs::iterator; + +DECLARE_SOA_TABLE(StoredJDielectronMcs, "AOD1", "JDIELMC", + o2::soa::Index<>, + jdielectronindices::JDielectronMcCollisionId, + jdielectronmc::Pt, + jdielectronmc::Eta, + jdielectronmc::Phi, + jdielectronmc::Y, + jdielectronmc::E, + jdielectronmc::M, + jdielectronmc::PdgCode, + jdielectronmc::GenStatusCode, + jdielectronmc::HepMCStatusCode, + jdielectronmc::IsPhysicalPrimary, + jdielectronmc::DecayFlag, + jdielectronmc::Origin, + jdielectronmc::Px, + jdielectronmc::Py, + jdielectronmc::Pz, + jdielectronmc::P, + o2::soa::Marker<1>); + +using StoredJDielectronMc = StoredJDielectronMcs::iterator; + +DECLARE_SOA_TABLE(JDielectronMcIds, "AOD", "JDIELMCID", + jdielectronindices::JMcCollisionId, + jdielectronindices::JMcParticleId, + jdielectronmc::MothersIds, + jdielectronmc::DaughtersIdSlice); + +DECLARE_SOA_TABLE(StoredJDielectronMcIds, "AOD1", "JDIELMCID", + jdielectronindices::JMcCollisionId, + jdielectronindices::JMcParticleId, + jdielectronmc::MothersIds, + jdielectronmc::DaughtersIdSlice, + o2::soa::Marker<1>); + +namespace jdummydq +{ + +DECLARE_SOA_COLUMN(DummyDQ, dummyDQ, bool); + +} // namespace jdummydq +DECLARE_SOA_TABLE(JDielectron1Dummys, "AOD", "JDIEL1DUMMY", + o2::soa::Index<>, + jdummydq::DummyDQ, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(JDielectron2Dummys, "AOD", "JDIEL2DUMMY", + o2::soa::Index<>, + jdummydq::DummyDQ, + o2::soa::Marker<2>); + +DECLARE_SOA_TABLE(JDielectron3Dummys, "AOD", "JDIEL3DUMMY", + o2::soa::Index<>, + jdummydq::DummyDQ, + o2::soa::Marker<3>); + +DECLARE_SOA_TABLE(JDielectron4Dummys, "AOD", "JDIEL4DUMMY", + o2::soa::Index<>, + jdummydq::DummyDQ, + o2::soa::Marker<4>); + +DECLARE_SOA_TABLE(JDielectron5Dummys, "AOD", "JDIEL5DUMMY", + o2::soa::Index<>, + jdummydq::DummyDQ, + o2::soa::Marker<5>); + +DECLARE_SOA_TABLE(JDielectron6Dummys, "AOD", "JDIEL6DUMMY", + o2::soa::Index<>, + jdummydq::DummyDQ, + o2::soa::Marker<6>); + +} // namespace o2::aod + +#endif // PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ diff --git a/PWGJE/DataModel/JetReducedDataHF.h b/PWGJE/DataModel/JetReducedDataHF.h index 83118732cd1..13056e0f1fc 100644 --- a/PWGJE/DataModel/JetReducedDataHF.h +++ b/PWGJE/DataModel/JetReducedDataHF.h @@ -35,13 +35,6 @@ DECLARE_SOA_INDEX_COLUMN(JMcCollision, mcCollision); DECLARE_SOA_INDEX_COLUMN(JMcParticle, mcParticle); } // namespace jd0indices -namespace d0collisioncounter -{ -DECLARE_SOA_COLUMN(ReadCounts, readCounts, std::vector); -DECLARE_SOA_COLUMN(ReadSelectedCounts, readSelectedCounts, std::vector); -DECLARE_SOA_COLUMN(WrittenCounts, writtenCounts, std::vector); -} // namespace d0collisioncounter - DECLARE_SOA_TABLE(JD0CollisionIds, "AOD", "JD0COLLID", jd0indices::JCollisionId); @@ -76,11 +69,6 @@ DECLARE_SOA_TABLE(StoredJD0PIds, "AOD1", "JD0PID", jd0indices::JMcParticleId, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(D0CollisionCounts, "AOD", "D0COLLCOUNT", - d0collisioncounter::ReadCounts, - d0collisioncounter::ReadSelectedCounts, - d0collisioncounter::WrittenCounts); - namespace jlcindices { DECLARE_SOA_INDEX_COLUMN(JCollision, collision); @@ -91,13 +79,6 @@ DECLARE_SOA_INDEX_COLUMN(JMcCollision, mcCollision); DECLARE_SOA_INDEX_COLUMN(JMcParticle, mcParticle); } // namespace jlcindices -namespace lccollisioncounter -{ -DECLARE_SOA_COLUMN(ReadCounts, readCounts, std::vector); -DECLARE_SOA_COLUMN(ReadSelectedCounts, readSelectedCounts, std::vector); -DECLARE_SOA_COLUMN(WrittenCounts, writtenCounts, std::vector); -} // namespace lccollisioncounter - DECLARE_SOA_TABLE(JLcCollisionIds, "AOD", "JLCCOLLID", jlcindices::JCollisionId); @@ -134,11 +115,6 @@ DECLARE_SOA_TABLE(StoredJLcPIds, "AOD1", "JLCPID", jlcindices::JMcParticleId, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(LcCollisionCounts, "AOD", "LcCOLLCOUNT", - lccollisioncounter::ReadCounts, - lccollisioncounter::ReadSelectedCounts, - lccollisioncounter::WrittenCounts); - } // namespace o2::aod #endif // PWGJE_DATAMODEL_JETREDUCEDDATAHF_H_ diff --git a/PWGJE/DataModel/JetReducedDataV0.h b/PWGJE/DataModel/JetReducedDataV0.h index 67e2f3a24e8..abd5904b0ec 100644 --- a/PWGJE/DataModel/JetReducedDataV0.h +++ b/PWGJE/DataModel/JetReducedDataV0.h @@ -18,6 +18,7 @@ #define PWGJE_DATAMODEL_JETREDUCEDDATAV0_H_ #include +#include #include "Framework/AnalysisDataModel.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/JetReducedData.h" @@ -25,27 +26,52 @@ namespace o2::aod { +DECLARE_SOA_TABLE(JV0McCollisions, "AOD", "JV0MCCOLL", + o2::soa::Index<>, + jmccollision::PosX, + jmccollision::PosY, + jmccollision::PosZ, + o2::soa::Marker<1>); + +using JMcCollision = JMcCollisions::iterator; + +DECLARE_SOA_TABLE(StoredJV0McCollisions, "AOD1", "JV0MCCOLL", + o2::soa::Index<>, + jmccollision::PosX, + jmccollision::PosY, + jmccollision::PosZ, + o2::soa::Marker<2>); + namespace jv0indices { DECLARE_SOA_INDEX_COLUMN(JCollision, collision); +DECLARE_SOA_INDEX_COLUMN(JV0McCollision, v0mccollision); DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, JTracks, "_0"); DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, JTracks, "_1"); DECLARE_SOA_INDEX_COLUMN(JMcCollision, mcCollision); DECLARE_SOA_INDEX_COLUMN(JMcParticle, mcParticle); } // namespace jv0indices -DECLARE_SOA_TABLE(JV0Ids, "AOD", "JV0ID", +DECLARE_SOA_TABLE(JV0CollisionIds, "AOD", "JV0COLLID", + jv0indices::JCollisionId); + +DECLARE_SOA_TABLE(StoredJV0CollisionIds, "AOD1", "JV0COLLID", jv0indices::JCollisionId, - jv0indices::PosTrackId, - jv0indices::NegTrackId); + o2::soa::Marker<1>); -DECLARE_SOA_TABLE(StoredJV0Ids, "AOD1", "JV0ID", +DECLARE_SOA_TABLE(JV0McCollisionIds, "AOD", "JV0MCCOLLID", + jv0indices::JMcCollisionId); + +DECLARE_SOA_TABLE(StoredJV0McCollisionIds, "AOD1", "JV0MCCOLLID", + jv0indices::JMcCollisionId, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(JV0Ids, "AOD", "JV0ID", jv0indices::JCollisionId, jv0indices::PosTrackId, - jv0indices::NegTrackId, - o2::soa::Marker<1>); + jv0indices::NegTrackId); -namespace jv0mcparticle +namespace jv0mc { DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); @@ -68,57 +94,64 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); -} // namespace jv0mcparticle +} // namespace jv0mc + +DECLARE_SOA_TABLE(JV0Mcs, "AOD", "JV0MC", + o2::soa::Index<>, + jv0indices::JV0McCollisionId, + jv0mc::Pt, + jv0mc::Eta, + jv0mc::Phi, + jv0mc::Y, + jv0mc::E, + jv0mc::M, + jv0mc::PdgCode, + jv0mc::GenStatusCode, + jv0mc::HepMCStatusCode, + jv0mc::IsPhysicalPrimary, + jv0mc::DecayFlag, + jv0mc::Px, + jv0mc::Py, + jv0mc::Pz, + jv0mc::P); + +using JV0Mc = JV0Mcs::iterator; -DECLARE_SOA_TABLE(JV0McParticles, "AOD", "JV0MCPARTICLE", +DECLARE_SOA_TABLE(StoredJV0Mcs, "AOD1", "JV0MC", o2::soa::Index<>, + jv0indices::JV0McCollisionId, + jv0mc::Pt, + jv0mc::Eta, + jv0mc::Phi, + jv0mc::Y, + jv0mc::E, + jv0mc::M, + jv0mc::PdgCode, + jv0mc::GenStatusCode, + jv0mc::HepMCStatusCode, + jv0mc::IsPhysicalPrimary, + jv0mc::DecayFlag, + jv0mc::Px, + jv0mc::Py, + jv0mc::Pz, + jv0mc::P, + o2::soa::Marker<1>); + +using StoredJV0Mc = StoredJV0Mcs::iterator; + +DECLARE_SOA_TABLE(JV0McIds, "AOD", "JV0MCID", jv0indices::JMcCollisionId, jv0indices::JMcParticleId, - jv0mcparticle::Pt, - jv0mcparticle::Eta, - jv0mcparticle::Phi, - jv0mcparticle::Y, - jv0mcparticle::E, - jv0mcparticle::M, - jv0mcparticle::PdgCode, - jv0mcparticle::GenStatusCode, - jv0mcparticle::HepMCStatusCode, - jv0mcparticle::IsPhysicalPrimary, - jv0mcparticle::MothersIds, - jv0mcparticle::DaughtersIdSlice, - jv0mcparticle::DecayFlag, - jv0mcparticle::Px, - jv0mcparticle::Py, - jv0mcparticle::Pz, - jv0mcparticle::P); - -using JV0McParticle = JV0McParticles::iterator; - -DECLARE_SOA_TABLE(StoredJV0McParticles, "AOD1", "JV0MCPARTICLE", - o2::soa::Index<>, + jv0mc::MothersIds, + jv0mc::DaughtersIdSlice); + +DECLARE_SOA_TABLE(StoredJV0McIds, "AOD1", "JV0MCID", jv0indices::JMcCollisionId, jv0indices::JMcParticleId, - jv0mcparticle::Pt, - jv0mcparticle::Eta, - jv0mcparticle::Phi, - jv0mcparticle::Y, - jv0mcparticle::E, - jv0mcparticle::M, - jv0mcparticle::PdgCode, - jv0mcparticle::GenStatusCode, - jv0mcparticle::HepMCStatusCode, - jv0mcparticle::IsPhysicalPrimary, - jv0mcparticle::MothersIds, - jv0mcparticle::DaughtersIdSlice, - jv0mcparticle::DecayFlag, - jv0mcparticle::Px, - jv0mcparticle::Py, - jv0mcparticle::Pz, - jv0mcparticle::P, + jv0mc::MothersIds, + jv0mc::DaughtersIdSlice, o2::soa::Marker<1>); -using StoredJV0McParticle = StoredJV0McParticles::iterator; - } // namespace o2::aod #endif // PWGJE_DATAMODEL_JETREDUCEDDATAV0_H_ diff --git a/PWGJE/DataModel/JetSubstructure.h b/PWGJE/DataModel/JetSubstructure.h index 56cc31a19fc..51bbbe69f6b 100644 --- a/PWGJE/DataModel/JetSubstructure.h +++ b/PWGJE/DataModel/JetSubstructure.h @@ -24,8 +24,6 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGJE/DataModel/Jet.h" -using namespace o2::analysis; - namespace o2::aod { @@ -45,6 +43,10 @@ DECLARE_SOA_COLUMN(Theta, theta, std::vector); //! DECLARE_SOA_COLUMN(NSub2DR, nSub2DR, float); //! DECLARE_SOA_COLUMN(NSub1, nSub1, float); //! DECLARE_SOA_COLUMN(NSub2, nSub2, float); //! +DECLARE_SOA_COLUMN(PairPt, pairPt, std::vector); //! +DECLARE_SOA_COLUMN(PairEnergy, pairEnergy, std::vector); //! +DECLARE_SOA_COLUMN(PairTheta, pairTheta, std::vector); //! +DECLARE_SOA_COLUMN(Angularity, angularity, float); //! } // namespace jetsubstructure namespace jetoutput @@ -59,68 +61,69 @@ DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, int); //! } // namespace jetoutput // Defines the jet substrcuture table definition -#define JETSUBSTRUCTURE_TABLE_DEF(_jet_type_, _cand_type_, _name_, _description_) \ - \ - namespace _name_##collisionoutput \ - { \ - DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ - } \ - \ - DECLARE_SOA_TABLE(_jet_type_##COs, "AOD", _description_ "CO", jetcollision::PosZ, jetcollision::Centrality, jetcollision::EventSel, _name_##collisionoutput::Dummy##_jet_type_<>); \ - using _jet_type_##CO = _jet_type_##COs::iterator; \ - \ - namespace _name_##jetoutput \ - { \ - DECLARE_SOA_INDEX_COLUMN(_jet_type_##CO, collision); \ - DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, _cand_type_, "_0"); \ - } \ - DECLARE_SOA_TABLE(_jet_type_##Os, "AOD", _description_ "O", _name_##jetoutput::_jet_type_##COId, _name_##jetoutput::CandidateId, jetoutput::JetPt, jetoutput::JetPhi, jetoutput::JetEta, jetoutput::JetY, jetoutput::JetR, jetoutput::JetNConstituents); \ - using _jet_type_##O = _jet_type_##Os::iterator; \ - namespace _name_##substructure \ - { \ - DECLARE_SOA_INDEX_COLUMN(_jet_type_##O, outputTable); \ - DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ - } \ - \ - DECLARE_SOA_TABLE(_jet_type_##SSs, "AOD", _description_ "SS", jetsubstructure::EnergyMother, jetsubstructure::PtLeading, jetsubstructure::PtSubLeading, jetsubstructure::Theta, jetsubstructure::NSub2DR, jetsubstructure::NSub1, jetsubstructure::NSub2, _name_##substructure::Dummy##_jet_type_<>); \ - DECLARE_SOA_TABLE(_jet_type_##SSOs, "AOD", _description_ "SSO", _name_##substructure::_jet_type_##OId, jetsubstructure::EnergyMother, jetsubstructure::PtLeading, jetsubstructure::PtSubLeading, jetsubstructure::Theta, jetsubstructure::NSub2DR, jetsubstructure::NSub1, jetsubstructure::NSub2); \ - \ - using _jet_type_##O = _jet_type_##Os::iterator; \ +#define JETSUBSTRUCTURE_TABLE_DEF(_jet_type_, _jet_description_, _name_, _cand_type_, _cand_description_) \ + \ + namespace _name_##collisionoutput \ + { \ + DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ + } \ + \ + DECLARE_SOA_TABLE(_jet_type_##COs, "AOD", _jet_description_ "CO", jetcollision::PosZ, jetcollision::Centrality, jetcollision::EventSel, _name_##collisionoutput::Dummy##_jet_type_<>); \ + using _jet_type_##CO = _jet_type_##COs::iterator; \ + \ + namespace _name_##jetoutput \ + { \ + DECLARE_SOA_INDEX_COLUMN_CUSTOM(_jet_type_##CO, collision, _jet_description_ "COS"); \ + DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(Candidate, candidate, int, _cand_type_, _cand_description_ "S", "_0"); \ + } \ + DECLARE_SOA_TABLE(_jet_type_##Os, "AOD", _jet_description_ "O", _name_##jetoutput::_jet_type_##COId, _name_##jetoutput::CandidateId, jetoutput::JetPt, jetoutput::JetPhi, jetoutput::JetEta, jetoutput::JetY, jetoutput::JetR, jetoutput::JetNConstituents); \ + using _jet_type_##O = _jet_type_##Os::iterator; \ + namespace _name_##substructure \ + { \ + DECLARE_SOA_INDEX_COLUMN_CUSTOM(_jet_type_##O, outputTable, _jet_description_ "OS"); \ + DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ + } \ + \ + DECLARE_SOA_TABLE(_jet_type_##SSs, "AOD", _jet_description_ "SS", jetsubstructure::EnergyMother, jetsubstructure::PtLeading, jetsubstructure::PtSubLeading, jetsubstructure::Theta, jetsubstructure::NSub2DR, jetsubstructure::NSub1, jetsubstructure::NSub2, jetsubstructure::PairPt, jetsubstructure::PairEnergy, jetsubstructure::PairTheta, jetsubstructure::Angularity, _name_##substructure::Dummy##_jet_type_<>); \ + DECLARE_SOA_TABLE(_jet_type_##SSOs, "AOD", _jet_description_ "SSO", _name_##substructure::_jet_type_##OId, jetsubstructure::EnergyMother, jetsubstructure::PtLeading, jetsubstructure::PtSubLeading, jetsubstructure::Theta, jetsubstructure::NSub2DR, jetsubstructure::NSub1, jetsubstructure::NSub2, jetsubstructure::PairPt, jetsubstructure::PairEnergy, jetsubstructure::PairTheta, jetsubstructure::Angularity); \ + \ + using _jet_type_##O = _jet_type_##Os::iterator; \ using _jet_type_##SSO = _jet_type_##SSOs::iterator; // define the mathcing table definition -#define JETMATCHING_TABLE_DEF(_jet_type_, _matched_jet_type_, _name_, _description_) \ +#define JETMATCHING_TABLE_DEF(_jet_type_, _matched_jet_type_, _matched_jet_description_, _name_, _description_) \ namespace _name_##geomatched \ { \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_matched_jet_type_, matchedJetGeo, int32_t, _matched_jet_type_##Os, "_geo"); \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_matched_jet_type_, matchedJetGeo, int32_t, _matched_jet_type_##Os, _matched_jet_description_ "OS", "_geo"); \ } \ \ namespace _name_##ptmatched \ { \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_matched_jet_type_, matchedJetPt, int32_t, _matched_jet_type_##Os, "_pt"); \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_matched_jet_type_, matchedJetPt, int32_t, _matched_jet_type_##Os, _matched_jet_description_ "OS", "_pt"); \ } \ \ namespace _name_##candmatched \ { \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_matched_jet_type_, matchedJetCand, int32_t, _matched_jet_type_##Os, "_hf"); \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_matched_jet_type_, matchedJetCand, int32_t, _matched_jet_type_##Os, _matched_jet_description_ "OS", "_hf"); \ } \ DECLARE_SOA_TABLE(_jet_type_##MOs, "AOD", _description_ "MO", _name_##substructure::_jet_type_##OId, _name_##geomatched::_matched_jet_type_##Ids, _name_##ptmatched::_matched_jet_type_##Ids, _name_##candmatched::_matched_jet_type_##Ids); \ using _jet_type_##MO = _jet_type_##MOs::iterator; -#define JETSUBSTRUCTURE_TABLES_DEF(_jet_type_, _cand_type_data_, _cand_type_ewsdata_, _cand_type_mcd_, _hfparticle_type_, _description_) \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##Jet, _cand_type_data_, _jet_type_##jet, _description_ "JET") \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##EWSJet, _cand_type_ewsdata_, _jet_type_##ewsjet, _description_ "EWSJET") \ - JETMATCHING_TABLE_DEF(_jet_type_##Jet, _jet_type_##EWSJet, _jet_type_##jet, _description_ "JET") \ - JETMATCHING_TABLE_DEF(_jet_type_##EWSJet, _jet_type_##Jet, _jet_type_##ewsjet, _description_ "EWSJET") \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##MCDJet, _cand_type_mcd_, _jet_type_##mcdjet, _description_ "MCDJET") \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##MCPJet, _hfparticle_type_, _jet_type_##mcpjet, _description_ "MCPJET") \ - JETMATCHING_TABLE_DEF(_jet_type_##MCDJet, _jet_type_##MCPJet, _jet_type_##mcdjet, _description_ "MCDJET") \ - JETMATCHING_TABLE_DEF(_jet_type_##MCPJet, _jet_type_##MCDJet, _jet_type_##mcpjet, _description_ "MCPJET") +#define JETSUBSTRUCTURE_TABLES_DEF(_jet_type_, _jet_description_, _cand_type_data_, _cand_description_data_, _cand_type_ewsdata_, _cand_description_ewsdata_, _cand_type_mcd_, _cand_description_mcd_, _hfparticle_type_, _hfparticle_description_) \ + JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##Jet, _jet_description_ "JET", _jet_type_##jet, _cand_type_data_, _cand_description_data_) \ + JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##EWSJet, _jet_description_ "EWSJET", _jet_type_##ewsjet, _cand_type_ewsdata_, _cand_description_ewsdata_) \ + JETMATCHING_TABLE_DEF(_jet_type_##Jet, _jet_type_##EWSJet, _jet_description_ "EWSJET", _jet_type_##jet, _jet_description_ "JET") \ + JETMATCHING_TABLE_DEF(_jet_type_##EWSJet, _jet_type_##Jet, _jet_description_ "JET", _jet_type_##ewsjet, _jet_description_ "EWSJET") \ + JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##MCDJet, _jet_description_ "MCDJET", _jet_type_##mcdjet, _cand_type_mcd_, _cand_description_mcd_) \ + JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##MCPJet, _jet_description_ "MCPJET", _jet_type_##mcpjet, _hfparticle_type_, _hfparticle_description_) \ + JETMATCHING_TABLE_DEF(_jet_type_##MCDJet, _jet_type_##MCPJet, _jet_description_ "MCPJET", _jet_type_##mcdjet, _jet_description_ "MCDJET") \ + JETMATCHING_TABLE_DEF(_jet_type_##MCPJet, _jet_type_##MCDJet, _jet_description_ "MCDJET", _jet_type_##mcpjet, _jet_description_ "MCPJET") -JETSUBSTRUCTURE_TABLES_DEF(C, CJetCOs, CEWSJetCOs, CMCDJetCOs, CMCPJetCOs, "C"); -JETSUBSTRUCTURE_TABLES_DEF(D0C, HfD0Bases, HfD0Bases, HfD0Bases, HfD0PBases, "D0C"); -JETSUBSTRUCTURE_TABLES_DEF(LcC, Hf3PBases, Hf3PBases, Hf3PBases, Hf3PPBases, "LCC"); -JETSUBSTRUCTURE_TABLES_DEF(BplusC, HfD0Bases, HfD0Bases, HfD0Bases, HfD0PBases, "BPLUSC"); +JETSUBSTRUCTURE_TABLES_DEF(C, "C", CJetCOs, "CJETCO", CEWSJetCOs, "CEWSJETCO", CMCDJetCOs, "CMCDJETCO", CMCPJetCOs, "CMCPJETCO"); +JETSUBSTRUCTURE_TABLES_DEF(D0C, "D0C", HfD0Bases, "HFD0BASE", HfD0Bases, "HFD0BASE", HfD0Bases, "HFD0BASE", HfD0PBases, "HFD0PBASE"); +JETSUBSTRUCTURE_TABLES_DEF(LcC, "LCC", Hf3PBases, "HF3PBASE", Hf3PBases, "HF3PBASE", Hf3PBases, "HF3PBASE", Hf3PPBases, "HF3PPBASE"); +JETSUBSTRUCTURE_TABLES_DEF(BplusC, "BPLUSC", HfD0Bases, "HFD0BASE", HfD0Bases, "HFD0BASE", HfD0Bases, "HFD0BASE", HfD0PBases, "HFD0PBASE"); +JETSUBSTRUCTURE_TABLES_DEF(DielectronC, "DIELC", Dielectrons, "RTDIELECTRON", Dielectrons, "RTDIELECTRON", Dielectrons, "RTDIELECTRON", JDielectronMcs, "JDIELMC"); } // namespace o2::aod diff --git a/PWGJE/DataModel/JetSubtraction.h b/PWGJE/DataModel/JetSubtraction.h index e7c58f44867..f789d18637a 100644 --- a/PWGJE/DataModel/JetSubtraction.h +++ b/PWGJE/DataModel/JetSubtraction.h @@ -24,6 +24,7 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" namespace o2::aod { @@ -54,29 +55,40 @@ namespace bkgbplus DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCandBplus, "_0"); } // namespace bkgbplus +namespace bkgdielectron +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, Dielectrons, "_0"); +// DECLARE_SOA_INDEX_COLUMN(Dielectron, candidate); +} // namespace bkgdielectron + DECLARE_SOA_TABLE(BkgChargedRhos, "AOD", "BkgCRho", o2::soa::Index<>, - bkgcharged::JCollisionId, bkgrho::Rho, bkgrho::RhoM); DECLARE_SOA_TABLE(BkgD0Rhos, "AOD", "BkgD0Rho", o2::soa::Index<>, - bkgd0::CandidateId, bkgrho::Rho, - bkgrho::RhoM); + bkgrho::RhoM, + o2::soa::Marker<1>); DECLARE_SOA_TABLE(BkgLcRhos, "AOD", "BkgLcRho", o2::soa::Index<>, - bkglc::CandidateId, bkgrho::Rho, - bkgrho::RhoM); + bkgrho::RhoM, + o2::soa::Marker<2>); DECLARE_SOA_TABLE(BkgBplusRhos, "AOD", "BkgBPlRho", o2::soa::Index<>, - bkgbplus::CandidateId, bkgrho::Rho, - bkgrho::RhoM); + bkgrho::RhoM, + o2::soa::Marker<3>); + +DECLARE_SOA_TABLE(BkgDielectronRhos, "AOD", "BkgDIELRho", + o2::soa::Index<>, + bkgrho::Rho, + bkgrho::RhoM, + o2::soa::Marker<4>); namespace jtracksub { @@ -156,6 +168,21 @@ DECLARE_SOA_TABLE(JTrackBplusSubs, "AOD", "JTrackBPlSubs", using JTrackBplusSub = JTrackBplusSubs::iterator; +DECLARE_SOA_TABLE(JTrackDielectronSubs, "AOD", "JTrackDIELSubs", + o2::soa::Index<>, + bkgdielectron::CandidateId, + jtracksub::Pt, + jtracksub::Eta, + jtracksub::Phi, + jtracksub::Energy, + jtracksub::TrackSel, + jtracksub::Px, + jtracksub::Py, + jtracksub::Pz, + jtracksub::P); + +using JTrackDielectronSub = JTrackDielectronSubs::iterator; + } // namespace o2::aod #endif // PWGJE_DATAMODEL_JETSUBTRACTION_H_ diff --git a/PWGJE/DataModel/JetTagging.h b/PWGJE/DataModel/JetTagging.h index 9f0e36938f1..f94fa49205c 100644 --- a/PWGJE/DataModel/JetTagging.h +++ b/PWGJE/DataModel/JetTagging.h @@ -22,8 +22,6 @@ #include "Framework/AnalysisDataModel.h" #include "PWGJE/DataModel/Jet.h" -using namespace o2::analysis; - namespace o2::aod { @@ -54,6 +52,7 @@ DECLARE_SOA_COLUMN(Pz, pz, float); DECLARE_SOA_COLUMN(E, e, float); DECLARE_SOA_COLUMN(M, m, float); DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); +DECLARE_SOA_COLUMN(Dispersion, dispersion, float); DECLARE_SOA_COLUMN(ErrorDecayLength, errorDecayLength, float); DECLARE_SOA_COLUMN(ErrorDecayLengthXY, errorDecayLengthXY, float); DECLARE_SOA_DYNAMIC_COLUMN(RSecondaryVertex, rSecondaryVertex, [](float xVtxS, float yVtxS) -> float { return RecoDecay::sqrtSumOfSquares(xVtxS, yVtxS); }); @@ -91,6 +90,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, [](float xVtxP, SecondaryVertexParams::E, \ SecondaryVertexParams::M, \ SecondaryVertexParams::Chi2PCA, \ + SecondaryVertexParams::Dispersion, \ SecondaryVertexParams::ErrorDecayLength, \ SecondaryVertexParams::ErrorDecayLengthXY, \ SecondaryVertexParams::RSecondaryVertex, \ @@ -125,10 +125,10 @@ JETSV_TABLES_DEF(Charged, SecondaryVertex2Prong, "2PRONG"); { \ DECLARE_SOA_COLUMN(Origin, origin, int); \ DECLARE_SOA_COLUMN(JetProb, jetProb, std::vector); \ - DECLARE_SOA_COLUMN(Algorithm2, algorithm2, int); \ - DECLARE_SOA_COLUMN(Algorithm3, algorithm3, int); \ + DECLARE_SOA_COLUMN(FlagtaggedjetIP, flagtaggedjetIP, bool); \ + DECLARE_SOA_COLUMN(FlagtaggedjetSV, flagtaggedjetSV, bool); \ } \ - DECLARE_SOA_TABLE(_jet_type_##Tags, "AOD", _description_ "Tags", _name_##tagging::Origin, _name_##tagging::JetProb, _name_##tagging::Algorithm2, _name_##tagging::Algorithm3); + DECLARE_SOA_TABLE(_jet_type_##Tags, "AOD", _description_ "Tags", _name_##tagging::Origin, _name_##tagging::JetProb, _name_##tagging::FlagtaggedjetIP, _name_##tagging::FlagtaggedjetSV); #define JETTAGGING_TABLES_DEF(_jet_type_, _description_) \ JETTAGGING_TABLE_DEF(_jet_type_##Jet, _jet_type_##jet, _description_) \ diff --git a/PWGJE/DataModel/TrackJetQa.h b/PWGJE/DataModel/TrackJetQa.h index 858aa53b0db..913f43c29b0 100644 --- a/PWGJE/DataModel/TrackJetQa.h +++ b/PWGJE/DataModel/TrackJetQa.h @@ -32,11 +32,6 @@ #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -using namespace o2; -using namespace o2::track; -using namespace o2::framework; -using namespace o2::framework::expressions; - // Derived data model for track optimization (and cut variation) namespace o2::aod { diff --git a/PWGJE/JetFinders/CMakeLists.txt b/PWGJE/JetFinders/CMakeLists.txt index c21571c345d..4c63447cf36 100644 --- a/PWGJE/JetFinders/CMakeLists.txt +++ b/PWGJE/JetFinders/CMakeLists.txt @@ -104,4 +104,19 @@ o2physics_add_dpl_workflow(jet-finder-v0-mcp-charged PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-finder-dielectron-data-charged + SOURCES jetfinderDielectrondatacharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-dielectron-mcd-charged + SOURCES jetfinderDielectronmcdcharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-dielectron-mcp-charged + SOURCES jetfinderDielectronmcpcharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + endif() diff --git a/PWGJE/JetFinders/jetfinder.cxx b/PWGJE/JetFinders/jetfinder.cxx index 8a5fd5f8d10..3654e09ca20 100644 --- a/PWGJE/JetFinders/jetfinder.cxx +++ b/PWGJE/JetFinders/jetfinder.cxx @@ -36,6 +36,9 @@ struct JetFinderTask { Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; // track level configurables Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; @@ -44,8 +47,8 @@ struct JetFinderTask { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; + Configurable trackingEfficiency{"trackingEfficiency", 1.0, "tracking efficiency applied to jet finding"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // cluster level configurables @@ -58,6 +61,7 @@ struct JetFinderTask { Configurable clusterTimeMin{"clusterTimeMin", -25., "minimum Cluster time (ns)"}; Configurable clusterTimeMax{"clusterTimeMax", 25., "maximum Cluster time (ns)"}; Configurable clusterRejectExotics{"clusterRejectExotics", true, "Reject exotic clusters"}; + Configurable doEMCALEventSelection{"doEMCALEventSelection", true, "apply the selection to the event alias_bit"}; // jet level configurables Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; @@ -75,6 +79,7 @@ struct JetFinderTask { Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; Configurable jetPtBinWidth{"jetPtBinWidth", 5, "used to define the width of the jetPt bins for the THnSparse"}; Configurable fillTHnSparse{"fillTHnSparse", false, "switch to fill the THnSparse"}; + Configurable jetExtraParam{"jetExtraParam", -99.0, "sets the _extra_param in fastjet"}; Service pdgDatabase; int trackSelection = -1; @@ -84,10 +89,13 @@ struct JetFinderTask { JetFinder jetFinder; std::vector inputParticles; + std::vector triggerMaskBits; + void init(InitContext const&) { - trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); particleSelection = static_cast(particleSelections); jetFinder.etaMin = trackEtaMin; @@ -104,6 +112,7 @@ struct JetFinderTask { if (DoTriggering) { jetFinder.isTriggering = true; } + jetFinder.fastjetExtraParam = jetExtraParam; auto jetRadiiBins = (std::vector)jetRadius; if (jetRadiiBins.size() > 1) { @@ -126,21 +135,21 @@ struct JetFinderTask { } aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); - Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); // do we need eta cut both here and in globalselection? - Filter trackSubCuts = (aod::jtracksub::pt >= trackPtMin && aod::jtracksub::pt < trackPtMax && aod::jtracksub::eta > trackEtaMin && aod::jtracksub::eta < trackEtaMax && aod::jtracksub::phi >= trackPhiMin && aod::jtracksub::phi <= trackPhiMax); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax); + Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); // do we need eta cut both here and in globalselection? + Filter trackSubCuts = (aod::jtracksub::pt >= trackPtMin && aod::jtracksub::pt < trackPtMax && aod::jtracksub::eta >= trackEtaMin && aod::jtracksub::eta <= trackEtaMax && aod::jtracksub::phi >= trackPhiMin && aod::jtracksub::phi <= trackPhiMax); - Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta > trackEtaMin && aod::jmcparticle::eta < trackEtaMax); - Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta > clusterEtaMin && aod::jcluster::eta < clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); + Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); + Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta >= clusterEtaMin && aod::jcluster::eta <= clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); void processChargedJets(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } inputParticles.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, trackingEfficiency); jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, registry.get(HIST("hJet")), fillTHnSparse); } @@ -149,11 +158,11 @@ struct JetFinderTask { void processChargedEvtWiseSubJets(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } inputParticles.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, trackingEfficiency); jetfindingutilities::findJets(jetFinder, inputParticles, jetEWSPtMin, jetEWSPtMax, jetRadius, jetAreaFractionMin, collision, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, registry.get(HIST("hJetEWS")), fillTHnSparse); } @@ -162,7 +171,7 @@ struct JetFinderTask { void processNeutralJets(soa::Filtered::iterator const& collision, soa::Filtered const& clusters) { - if (!jetderiveddatautilities::eventEMCAL(collision)) { + if ((doEMCALEventSelection && !jetderiveddatautilities::eventEMCAL(collision)) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } inputParticles.clear(); @@ -175,11 +184,11 @@ struct JetFinderTask { soa::Filtered const& tracks, soa::Filtered const& clusters) { - if (!jetderiveddatautilities::eventEMCAL(collision)) { + if ((doEMCALEventSelection && !jetderiveddatautilities::eventEMCAL(collision)) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } inputParticles.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, trackingEfficiency); jetfindingutilities::analyseClusters(inputParticles, &clusters); jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, registry.get(HIST("hJet")), fillTHnSparse); } diff --git a/PWGJE/JetFinders/jetfinderDielectrondatacharged.cxx b/PWGJE/JetFinders/jetfinderDielectrondatacharged.cxx new file mode 100644 index 00000000000..2e4e4070875 --- /dev/null +++ b/PWGJE/JetFinders/jetfinderDielectrondatacharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 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. + +// jet finder dielectron data charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetfinderhf.cxx" + +using JetFinderDielectronDataCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsData", true}}}, + TaskName{"jet-finder-dielectron-data-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetfinderDielectronmcdcharged.cxx b/PWGJE/JetFinders/jetfinderDielectronmcdcharged.cxx new file mode 100644 index 00000000000..69cca64919b --- /dev/null +++ b/PWGJE/JetFinders/jetfinderDielectronmcdcharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 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. + +// jet finder dielectron mcd charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetfinderhf.cxx" + +using JetFinderDielectronMCDetectorLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsMCD", true}}}, + TaskName{"jet-finder-dielectron-mcd-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetfinderDielectronmcpcharged.cxx b/PWGJE/JetFinders/jetfinderDielectronmcpcharged.cxx new file mode 100644 index 00000000000..7a5da12fd87 --- /dev/null +++ b/PWGJE/JetFinders/jetfinderDielectronmcpcharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 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. + +// jet finder dielectron mcp charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetfinderhf.cxx" + +using JetFinderDielectronMCParticleLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsMCP", true}}}, + TaskName{"jet-finder-dielectron-mcp-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetfinderhf.cxx b/PWGJE/JetFinders/jetfinderhf.cxx index a635615d667..ac5a224676b 100644 --- a/PWGJE/JetFinders/jetfinderhf.cxx +++ b/PWGJE/JetFinders/jetfinderhf.cxx @@ -56,6 +56,9 @@ struct JetFinderHFTask { Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; // track level configurables Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; @@ -64,8 +67,8 @@ struct JetFinderHFTask { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; + Configurable trackingEfficiency{"trackingEfficiency", 1.0, "tracking efficiency applied to jet finding"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // cluster level configurables @@ -101,9 +104,11 @@ struct JetFinderHFTask { Configurable jetRecombScheme{"jetRecombScheme", 0, "jet recombination scheme. 0 = E-scheme, 1 = pT-scheme, 2 = pT2-scheme"}; Configurable jetGhostArea{"jetGhostArea", 0.005, "jet ghost area"}; Configurable ghostRepeat{"ghostRepeat", 1, "set to 0 to gain speed if you dont need area calculation"}; + Configurable DoTriggering{"DoTriggering", false, "used for the charged jet trigger to remove the eta constraint on the jet axis"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; Configurable jetPtBinWidth{"jetPtBinWidth", 5, "used to define the width of the jetPt bins for the THnSparse"}; Configurable fillTHnSparse{"fillTHnSparse", false, "switch to fill the THnSparse"}; + Configurable jetExtraParam{"jetExtraParam", -99.0, "sets the _extra_param in fastjet"}; Service pdgDatabase; int trackSelection = -1; @@ -113,9 +118,12 @@ struct JetFinderHFTask { JetFinder jetFinder; std::vector inputParticles; + std::vector triggerMaskBits; + void init(InitContext const&) { trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); particleSelection = static_cast(particleSelections); @@ -132,6 +140,10 @@ struct JetFinderHFTask { jetFinder.recombScheme = static_cast(static_cast(jetRecombScheme)); jetFinder.ghostArea = jetGhostArea; jetFinder.ghostRepeatN = ghostRepeat; + if (DoTriggering) { + jetFinder.isTriggering = true; + } + jetFinder.fastjetExtraParam = jetExtraParam; auto jetRadiiBins = (std::vector)jetRadius; if (jetRadiiBins.size() > 1) { @@ -153,41 +165,42 @@ struct JetFinderHFTask { } aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); - Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); - Filter trackSubCuts = (aod::jtracksub::pt >= trackPtMin && aod::jtracksub::pt < trackPtMax && aod::jtracksub::eta > trackEtaMin && aod::jtracksub::eta < trackEtaMax && aod::jtracksub::phi >= trackPhiMin && aod::jtracksub::phi <= trackPhiMax); - Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax); - Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta > clusterEtaMin && aod::jcluster::eta < clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax); + Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); + Filter trackSubCuts = (aod::jtracksub::pt >= trackPtMin && aod::jtracksub::pt < trackPtMax && aod::jtracksub::eta >= trackEtaMin && aod::jtracksub::eta <= trackEtaMax && aod::jtracksub::phi >= trackPhiMin && aod::jtracksub::phi <= trackPhiMax); + Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); + Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta >= clusterEtaMin && aod::jcluster::eta <= clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); // Filter candidateCuts = (aod::hfcand::pt >= candPtMin && aod::hfcand::pt < candPtMax && aod::hfcand::y >= candYMin && aod::hfcand::y < candYMax); PresliceOptional> perD0Candidate = aod::bkgd0::candidateId; PresliceOptional> perLcCandidate = aod::bkglc::candidateId; PresliceOptional> perBplusCandidate = aod::bkgbplus::candidateId; + PresliceOptional> perDielectronCandidate = aod::bkgdielectron::candidateId; // function that generalically processes Data and reco level events template void analyseCharged(T const& collision, U const& tracks, V const& candidate, M& jetsTableInput, N& constituentsTableInput, O& /*originalTracks*/, float minJetPt, float maxJetPt) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } inputParticles.clear(); - if constexpr (jethfutilities::isHFCandidate()) { + if constexpr (jetcandidateutilities::isCandidate()) { if (!jetfindingutilities::analyseCandidate(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax)) { return; } } - if constexpr (jethfutilities::isHFMcCandidate()) { + if constexpr (jetcandidateutilities::isMcCandidate()) { if (!jetfindingutilities::analyseCandidateMC(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates)) { return; } } if constexpr (isEvtWiseSub) { - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency); } else { - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, std::optional{candidate}); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency, std::optional{candidate}); } jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true); } @@ -196,7 +209,7 @@ struct JetFinderHFTask { template void analyseMCP(T const& collision, U const& particles, V const& candidate, int jetTypeParticleLevel, float minJetPt, float maxJetPt) { - if (rejectIncorrectDecaysMCP && !jethfutilities::isMatchedHFCandidate(candidate)) { // is this even needed in the new derived format? it means any simulations run have to force the decay channel + if (rejectIncorrectDecaysMCP && !jetcandidateutilities::isMatchedCandidate(candidate)) { // is this even needed in the new derived format? it means any simulations run have to force the decay channel return; } @@ -224,7 +237,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsData(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, CandidateTableData const& candidates) { for (typename CandidateTableData::iterator const& candidate : candidates) { - analyseCharged(collision, jethfutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perLcCandidate, perBplusCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perLcCandidate, perBplusCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsData, "charged hf jet finding on data with event-wise constituent subtraction", false); @@ -240,7 +253,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsMCD(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, CandidateTableMCD const& candidates) { for (typename CandidateTableMCD::iterator const& candidate : candidates) { - analyseCharged(collision, jethfutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perLcCandidate, perBplusCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perLcCandidate, perBplusCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsMCD, "charged hf jet finding on MC detector level with event-wise constituent subtraction", false); diff --git a/PWGJE/JetFinders/jetfinderv0.cxx b/PWGJE/JetFinders/jetfinderv0.cxx index 07c41a2060a..a83d06d9082 100644 --- a/PWGJE/JetFinders/jetfinderv0.cxx +++ b/PWGJE/JetFinders/jetfinderv0.cxx @@ -38,6 +38,9 @@ struct JetFinderV0Task { Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; // track level configurables Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; @@ -46,8 +49,8 @@ struct JetFinderV0Task { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; + Configurable trackingEfficiency{"trackingEfficiency", 1.0, "tracking efficiency applied to jet finding"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // V0 candidate level configurables @@ -55,7 +58,7 @@ struct JetFinderV0Task { Configurable candPtMax{"candPtMax", 100.0, "maximum candidate pT"}; Configurable candYMin{"candYMin", -0.8, "minimum candidate eta"}; Configurable candYMax{"candYMax", 0.8, "maximum candidate eta"}; - Configurable candPDGMass{"candPDGMass", 310, "candidate PDG for mass in clustering"}; + Configurable candPDG{"candPDG", 310, "candidate PDG for mass in clustering"}; // jet level configurables Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; @@ -68,9 +71,11 @@ struct JetFinderV0Task { Configurable jetRecombScheme{"jetRecombScheme", 0, "jet recombination scheme. 0 = E-scheme, 1 = pT-scheme, 2 = pT2-scheme"}; Configurable jetGhostArea{"jetGhostArea", 0.005, "jet ghost area"}; Configurable ghostRepeat{"ghostRepeat", 1, "set to 0 to gain speed if you dont need area calculation"}; + Configurable DoTriggering{"DoTriggering", false, "used for the charged jet trigger to remove the eta constraint on the jet axis"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; Configurable jetPtBinWidth{"jetPtBinWidth", 5, "used to define the width of the jetPt bins for the THnSparse"}; Configurable fillTHnSparse{"fillTHnSparse", true, "switch to fill the THnSparse"}; + Configurable jetExtraParam{"jetExtraParam", -99.0, "sets the _extra_param in fastjet"}; Service pdgDatabase; int trackSelection = -1; @@ -80,11 +85,14 @@ struct JetFinderV0Task { JetFinder jetFinder; std::vector inputParticles; + std::vector triggerMaskBits; + int candIndex; void init(InitContext const&) { trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); particleSelection = static_cast(particleSelections); @@ -101,11 +109,15 @@ struct JetFinderV0Task { jetFinder.recombScheme = static_cast(static_cast(jetRecombScheme)); jetFinder.ghostArea = jetGhostArea; jetFinder.ghostRepeatN = ghostRepeat; + if (DoTriggering) { + jetFinder.isTriggering = true; + } + jetFinder.fastjetExtraParam = jetExtraParam; - if (candPDGMass == 310) { + if (candPDG == 310) { candIndex = 0; } - if (candPDGMass == 3122) { + if (candPDG == 3122) { candIndex = 1; } @@ -128,16 +140,16 @@ struct JetFinderV0Task { registry.add("hJetMCP", "sparse for mcp jets", {HistType::kTHnC, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); } - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); - Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); - Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax); + Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); + Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); // Filter candidateCuts = (aod::hfcand::pt >= candPtMin && aod::hfcand::pt < candPtMax && aod::hfcand::y >= candYMin && aod::hfcand::y < candYMax); // function that generalically processes Data and reco level events template void analyseCharged(T const& collision, U const& tracks, V const& candidates, M& jetsTableInput, N& constituentsTableInput, float minJetPt, float maxJetPt) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } inputParticles.clear(); @@ -152,7 +164,7 @@ struct JetFinderV0Task { } } */ - jetfindingutilities::analyseTracksMultipleCandidates(inputParticles, tracks, trackSelection, candidates); + jetfindingutilities::analyseTracksMultipleCandidates(inputParticles, tracks, trackSelection, trackingEfficiency, candidates); jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true); } diff --git a/PWGJE/TableProducer/CMakeLists.txt b/PWGJE/TableProducer/CMakeLists.txt index 1b803c66c62..12fa8359820 100644 --- a/PWGJE/TableProducer/CMakeLists.txt +++ b/PWGJE/TableProducer/CMakeLists.txt @@ -14,7 +14,7 @@ if(FastJet_FOUND) o2physics_add_dpl_workflow(jet-deriveddata-producer SOURCES jetderiveddataproducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-deriveddata-trigger-producer @@ -37,11 +37,26 @@ o2physics_add_dpl_workflow(jet-deriveddata-producer-dummy-lc PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-deriveddata-producer-dummy-dielectron + SOURCES jetderiveddataproducerdummydielectron.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-deriveddata-writer SOURCES jetderiveddatawriter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-luminosity-producer + SOURCES luminosityproducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-luminosity-calculator + SOURCES luminositycalculator.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-mc SOURCES jetmatchingmc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore diff --git a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx index 4545796031c..a749da6dcd3 100644 --- a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx +++ b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx @@ -34,6 +34,7 @@ struct eventWiseConstituentSubtractorTask { Produces trackSubtractedD0Table; Produces trackSubtractedLcTable; Produces trackSubtractedBplusTable; + Produces trackSubtractedDielectronTable; Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; Configurable trackPtMax{"trackPtMax", 1000.0, "maximum track pT"}; @@ -41,6 +42,7 @@ struct eventWiseConstituentSubtractorTask { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; + Configurable trackingEfficiency{"trackingEfficiency", 1.0, "tracking efficiency applied to jet finding"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable alpha{"alpha", 1.0, "exponent of transverse momentum in calculating the distance measure between pairs"}; @@ -65,24 +67,16 @@ struct eventWiseConstituentSubtractorTask { Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); - Preslice perD0Candidate = aod::bkgd0::candidateId; - Preslice perLcCandidate = aod::bkglc::candidateId; - Preslice perBplusCandidate = aod::bkgbplus::candidateId; - - template - void analyseHF(T const& tracks, U const& candidates, V const& bkgRhos, M& trackSubtractedTable) + template + void analyseHF(T const& tracks, U const& candidates, V& trackSubtractedTable) { for (auto& candidate : candidates) { - - auto const bkgRhosSliced = jethfutilities::slicedPerCandidate(bkgRhos, candidate, perD0Candidate, perLcCandidate, perBplusCandidate); - auto const bkgRho = bkgRhosSliced.iteratorAt(0); - inputParticles.clear(); tracksSubtracted.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, std::optional{candidate}); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency, std::optional{candidate}); - tracksSubtracted = eventWiseConstituentSubtractor.JetBkgSubUtils::doEventConstSub(inputParticles, bkgRho.rho(), bkgRho.rhoM()); + tracksSubtracted = eventWiseConstituentSubtractor.JetBkgSubUtils::doEventConstSub(inputParticles, candidate.rho(), candidate.rhoM()); for (auto const& trackSubtracted : tracksSubtracted) { trackSubtractedTable(candidate.globalIndex(), trackSubtracted.pt(), trackSubtracted.eta(), trackSubtracted.phi(), trackSubtracted.E(), jetderiveddatautilities::setSingleTrackSelectionBit(trackSelection)); @@ -95,7 +89,7 @@ struct eventWiseConstituentSubtractorTask { inputParticles.clear(); tracksSubtracted.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, trackingEfficiency); tracksSubtracted = eventWiseConstituentSubtractor.JetBkgSubUtils::doEventConstSub(inputParticles, collision.rho(), collision.rhoM()); @@ -105,23 +99,29 @@ struct eventWiseConstituentSubtractorTask { } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processCollisions, "Fill table of subtracted tracks for collisions", true); - void processD0Collisions(JetCollision const&, aod::BkgD0Rhos const& bkgRhos, soa::Filtered const& tracks, CandidatesD0Data const& candidates) + void processD0Collisions(JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) { - analyseHF(tracks, candidates, bkgRhos, trackSubtractedD0Table); + analyseHF(tracks, candidates, trackSubtractedD0Table); } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processD0Collisions, "Fill table of subtracted tracks for collisions with D0 candidates", false); - void processLcCollisions(JetCollision const&, aod::BkgLcRhos const& bkgRhos, soa::Filtered const& tracks, CandidatesLcData const& candidates) + void processLcCollisions(JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) { - analyseHF(tracks, candidates, bkgRhos, trackSubtractedLcTable); + analyseHF(tracks, candidates, trackSubtractedLcTable); } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processLcCollisions, "Fill table of subtracted tracks for collisions with Lc candidates", false); - void processBplusCollisions(JetCollision const&, aod::BkgBplusRhos const& bkgRhos, soa::Filtered const& tracks, CandidatesBplusData const& candidates) + void processBplusCollisions(JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) { - analyseHF(tracks, candidates, bkgRhos, trackSubtractedBplusTable); + analyseHF(tracks, candidates, trackSubtractedBplusTable); } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusCollisions, "Fill table of subtracted tracks for collisions with Bplus candidates", false); + + void processDielectronCollisions(JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHF(tracks, candidates, trackSubtractedDielectronTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processDielectronCollisions, "Fill table of subtracted tracks for collisions with Dielectron candidates", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"subtractor-eventwiseconstituent"})}; } diff --git a/PWGJE/TableProducer/jetderiveddataproducer.cxx b/PWGJE/TableProducer/jetderiveddataproducer.cxx index 032f2b666e6..8c97f2b73bf 100644 --- a/PWGJE/TableProducer/jetderiveddataproducer.cxx +++ b/PWGJE/TableProducer/jetderiveddataproducer.cxx @@ -23,27 +23,42 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "TDatabasePDG.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/PVertexer.h" +#include "ReconstructionDataFormats/Vertex.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "EventFiltering/filterTables.h" +#include "EventFiltering/Zorro.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetV0Utilities.h" +#include "PWGJE/Core/JetDQUtilities.h" + +#include "PWGHF/Utils/utilsBfieldCCDB.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct JetDerivedDataProducerTask { + Produces bcCountsTable; Produces collisionCountsTable; Produces jDummysTable; Produces jBCsTable; @@ -51,6 +66,7 @@ struct JetDerivedDataProducerTask { Produces jCollisionsTable; Produces jCollisionsParentIndexTable; Produces jCollisionsBunchCrossingIndexTable; + Produces jCollisionsEMCalLabelTable; Produces jMcCollisionsLabelTable; Produces jMcCollisionsTable; Produces jMcCollisionsParentIndexTable; @@ -73,35 +89,91 @@ struct JetDerivedDataProducerTask { Produces jLcIdsTable; Produces jLcParticleIdsTable; Produces jV0IdsTable; - Produces jV0McParticlesTable; + Produces jV0McCollisionsTable; + Produces jV0McCollisionIdsTable; + Produces jV0McsTable; + Produces jV0McIdsTable; + Produces jDielectronCollisionIdsTable; + Produces jDielectronIdsTable; + Produces jDielectronMcCollisionsTable; + Produces jDielectronMcCollisionIdsTable; + Produces jDielectronMcsTable; + Produces jDielectronMcIdsTable; + + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + Configurable dcaZMax{"dcaZMax", 0.2, "maximum DCAZ selection for tracks - only applied for reassociation"}; + + Configurable ccdbURL{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable includeTriggers{"includeTriggers", false, "fill the collision information with software trigger decisions"}; Preslice perClusterCells = aod::emcalclustercell::emcalclusterId; Preslice perClusterTracks = aod::emcalclustercell::emcalclusterId; + Preslice perCollisionTrackIndices = aod::track_association::collisionId; + std::map, int32_t> trackCollisionMapping; + Service ccdb; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; Service pdgDatabase; + Zorro triggerDecider; + int runNumber; + bool withCollisionAssociator; void init(InitContext const&) { + if (doprocessTracksWithCollisionAssociator || includeTriggers) { + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + runNumber = 0; + if (doprocessTracksWithCollisionAssociator) { + withCollisionAssociator = true; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); + } else { + withCollisionAssociator = false; + } + } + } + + void processClearMaps(aod::Collisions const&) + { + trackCollisionMapping.clear(); } + PROCESS_SWITCH(JetDerivedDataProducerTask, processClearMaps, "clears all maps", true); - void processBunchCrossings(soa::Join::iterator const& bc) + void processBunchCrossings(soa::Join::iterator const& bc) { - jBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp()); + jBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp(), bc.alias_raw(), bc.selection_raw()); jBCParentIndexTable(bc.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processBunchCrossings, "produces derived bunch crossing table", false); - void processCollisions(soa::Join::iterator const& collision) + void processCollisions(soa::Join::iterator const& collision, soa::Join const&) { - jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFT0C(), collision.centFT0C(), jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw()); // note change multFT0C to multFT0M when problems with multFT0A are fixed + uint64_t triggerBit = 0; + if (includeTriggers) { + auto bc = collision.bc_as>(); + triggerDecider.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), jetderiveddatautilities::JTriggerMasks); + triggerBit = jetderiveddatautilities::setTriggerSelectionBit(triggerDecider.getTriggerOfInterestResults(bc.globalBC())); + } + jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFT0C(), collision.centFT0C(), collision.trackOccupancyInTimeRange(), jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), triggerBit); // note change multFT0C to multFT0M when problems with multFT0A are fixed jCollisionsParentIndexTable(collision.globalIndex()); jCollisionsBunchCrossingIndexTable(collision.bcId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisions, "produces derived collision tables", true); - void processCollisionsWithoutCentralityAndMultiplicity(soa::Join::iterator const& collision) + void processCollisionsWithoutCentralityAndMultiplicity(soa::Join::iterator const& collision, soa::Join const&) { - jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw()); + uint64_t triggerBit = 0; + if (includeTriggers) { + auto bc = collision.bc_as>(); + triggerDecider.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), jetderiveddatautilities::JTriggerMasks); + triggerBit = jetderiveddatautilities::setTriggerSelectionBit(triggerDecider.getTriggerOfInterestResults(bc.globalBC())); + } + jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), triggerBit); jCollisionsParentIndexTable(collision.globalIndex()); jCollisionsBunchCrossingIndexTable(collision.bcId()); } @@ -109,12 +181,32 @@ struct JetDerivedDataProducerTask { void processCollisionsRun2(soa::Join::iterator const& collision) { - jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFT0C(), collision.centRun2V0M(), jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw()); // note change multFT0C to multFT0M when problems with multFT0A are fixed + jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFT0C(), collision.centRun2V0M(), -1, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), 0); // note change multFT0C to multFT0M when problems with multFT0A are fixed jCollisionsParentIndexTable(collision.globalIndex()); jCollisionsBunchCrossingIndexTable(collision.bcId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisionsRun2, "produces derived collision tables for Run 2 data", false); + void processCollisionsALICE3(aod::Collision const& collision) + { + jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1, -1.0, 0, 0); + jCollisionsParentIndexTable(collision.globalIndex()); + jCollisionsBunchCrossingIndexTable(-1); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisionsALICE3, "produces derived collision tables for ALICE 3 simulations", false); + + void processWithoutEMCalCollisionLabels(aod::Collision const&) + { + jCollisionsEMCalLabelTable(false, false); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processWithoutEMCalCollisionLabels, "produces dummy derived collision labels for EMCal", true); + + void processEMCalCollisionLabels(aod::EMCALMatchedCollision const& collision) + { + jCollisionsEMCalLabelTable(collision.ambiguous(), collision.isemcreadout()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processEMCalCollisionLabels, "produces derived collision labels for EMCal", false); + void processMcCollisionLabels(soa::Join::iterator const& collision) { @@ -133,14 +225,73 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisions, "produces derived MC collision table", false); - void processTracks(soa::Join::iterator const& track) + void processTracks(soa::Join::iterator const& track, aod::Collisions const&) { - jTracksTable(track.collisionId(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track)); - jTracksExtraTable(track.dcaXY(), track.dcaZ(), track.sigma1Pt()); // these need to be recalculated when we add the track to collision associator + jTracksTable(track.collisionId(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), dcaZMax)); + auto trackParCov = getTrackParCov(track); + auto xyzTrack = trackParCov.getXYZGlo(); + float sigmaDCAXYZ; + float dcaXYZ = getDcaXYZ(track, &sigmaDCAXYZ); + float dcaX = -99.0; + float dcaY = -99.0; + if (track.collisionId() >= 0) { + auto const& collision = track.collision_as(); + dcaX = xyzTrack.X() - collision.posX(); + dcaY = xyzTrack.Y() - collision.posY(); + } + + jTracksExtraTable(dcaX, dcaY, track.dcaZ(), track.dcaXY(), dcaXYZ, std::sqrt(track.sigmaDcaZ2()), std::sqrt(track.sigmaDcaXY2()), sigmaDCAXYZ, track.sigma1Pt()); // why is this getSigmaZY jTracksParentIndexTable(track.globalIndex()); + trackCollisionMapping[{track.globalIndex(), track.collisionId()}] = jTracksTable.lastIndex(); } PROCESS_SWITCH(JetDerivedDataProducerTask, processTracks, "produces derived track table", true); + void processTracksWithCollisionAssociator(aod::Collisions const& collisions, soa::Join const&, soa::Join const&, aod::TrackAssoc const& assocCollisions) + { + for (auto const& collision : collisions) { + auto collisionTrackIndices = assocCollisions.sliceBy(perCollisionTrackIndices, collision.globalIndex()); + for (auto const& collisionTrackIndex : collisionTrackIndices) { + auto track = collisionTrackIndex.track_as>(); + auto trackParCov = getTrackParCov(track); + if (track.collisionId() == collision.globalIndex()) { + jTracksTable(collision.globalIndex(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), dcaZMax)); + jTracksParentIndexTable(track.globalIndex()); + auto xyzTrack = trackParCov.getXYZGlo(); + float sigmaDCAXYZ; + float dcaXYZ = getDcaXYZ(track, &sigmaDCAXYZ); + jTracksExtraTable(xyzTrack.X() - collision.posX(), xyzTrack.Y() - collision.posY(), track.dcaZ(), track.dcaXY(), dcaXYZ, std::sqrt(track.sigmaDcaZ2()), std::sqrt(track.sigmaDcaXY2()), sigmaDCAXYZ, track.sigma1Pt()); // why is this getSigmaZY + } else { + auto bc = collision.bc_as>(); + initCCDB(bc, runNumber, ccdb, doprocessCollisionsRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, doprocessCollisionsRun2); + o2::dataformats::DCA dcaCovInfo; + dcaCovInfo.set(-999., -999., -999., -999., -999.); + o2::dataformats::VertexBase collisionInfo; + collisionInfo.setPos({collision.posX(), collision.posY(), collision.posZ()}); + collisionInfo.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(collisionInfo, trackParCov, 2.f, noMatCorr, &dcaCovInfo); + jTracksTable(collision.globalIndex(), trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), jetderiveddatautilities::setTrackSelectionBit(track, dcaCovInfo.getZ(), dcaZMax)); // only qualitytracksWDCA are a reliable selection + jTracksParentIndexTable(track.globalIndex()); + auto xyzTrack = trackParCov.getXYZGlo(); + float dcaXY = dcaCovInfo.getY(); + float dcaZ = dcaCovInfo.getZ(); + float dcaXYZ = std::sqrt(dcaXY * dcaXY + dcaZ * dcaZ); + float covYY = dcaCovInfo.getSigmaY2(); + float covZZ = dcaCovInfo.getSigmaZ2(); + float covYZ = dcaCovInfo.getSigmaYZ(); + float sigmaDCAXYZ; + if (dcaXYZ < o2::constants::math::Almost0) { + sigmaDCAXYZ = o2::constants::math::VeryBig; // Protection against division by zero + } else { + sigmaDCAXYZ = covYY * (2.f * dcaXY / dcaXYZ) * (2.f * dcaXY / dcaXYZ) + covZZ * (2.f * dcaZ / dcaXYZ) * (2.f * dcaZ / dcaXYZ) + 2.f * covYZ * (2.f * dcaXY / dcaXYZ) * (2.f * dcaZ / dcaXYZ); + } + jTracksExtraTable(xyzTrack.X() - collision.posX(), xyzTrack.Y() - collision.posY(), dcaZ, dcaXY, dcaXYZ, std::sqrt(covZZ), std::sqrt(covYY), std::sqrt(sigmaDCAXYZ), std::sqrt(trackParCov.getSigma1Pt2())); + } + trackCollisionMapping[{track.globalIndex(), collision.globalIndex()}] = jTracksTable.lastIndex(); + } + } + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processTracksWithCollisionAssociator, "produces derived track table taking into account track-to-collision associations", false); + void processMcTrackLabels(soa::Join::iterator const& track) { if (track.has_mcParticle()) { @@ -151,9 +302,25 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcTrackLabels, "produces derived track labels table", false); + void processMcTrackLabelsWithCollisionAssociator(aod::Collisions const& collisions, soa::Join const&, aod::TrackAssoc const& assocCollisions) + { + for (auto const& collision : collisions) { + auto collisionTrackIndices = assocCollisions.sliceBy(perCollisionTrackIndices, collision.globalIndex()); + for (auto const& collisionTrackIndex : collisionTrackIndices) { + auto track = collisionTrackIndex.track_as>(); + if (track.collisionId() == collision.globalIndex() && track.has_mcParticle()) { + jMcTracksLabelTable(track.mcParticleId()); + } else { + jMcTracksLabelTable(-1); + } + } + } + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processMcTrackLabelsWithCollisionAssociator, "produces derived track labels table taking into account track-to-collision associations", false); + void processParticles(aod::McParticle const& particle) { - std::vector mothersId; + std::vector mothersId; if (particle.has_mothers()) { auto mothersIdTemps = particle.mothersIds(); for (auto mothersIdTemp : mothersIdTemps) { @@ -206,9 +373,10 @@ struct JetDerivedDataProducerTask { jClustersParentIndexTable(cluster.globalIndex()); auto const clusterTracks = matchedTracks.sliceBy(perClusterTracks, cluster.globalIndex()); - std::vector clusterTrackIDs; + std::vector clusterTrackIDs; for (const auto& clusterTrack : clusterTracks) { - clusterTrackIDs.push_back(clusterTrack.trackId()); + auto JClusterID = trackCollisionMapping.find({clusterTrack.trackId(), cluster.collisionId()}); // does EMCal use its own associator? + clusterTrackIDs.push_back(JClusterID->second); } jClustersMatchedTracksTable(clusterTrackIDs); } @@ -217,7 +385,7 @@ struct JetDerivedDataProducerTask { void processMcClusterLabels(aod::EMCALMCCluster const& cluster) { - std::vector particleIds; + std::vector particleIds; for (auto particleId : cluster.mcParticleIds()) { particleIds.push_back(particleId); } @@ -240,9 +408,15 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processD0McCollisions, "produces derived index for D0 MC collisions", false); - void processD0(aod::HfD0Ids::iterator const& D0) + void processD0(aod::HfD0Ids::iterator const& D0, aod::Tracks const&) { - jD0IdsTable(D0.collisionId(), D0.prong0Id(), D0.prong1Id()); + auto JProng0ID = trackCollisionMapping.find({D0.prong0Id(), D0.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({D0.prong1Id(), D0.prong1_as().collisionId()}); + if (withCollisionAssociator) { + JProng0ID = trackCollisionMapping.find({D0.prong0Id(), D0.collisionId()}); + JProng1ID = trackCollisionMapping.find({D0.prong1Id(), D0.collisionId()}); + } + jD0IdsTable(D0.collisionId(), JProng0ID->second, JProng1ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processD0, "produces derived index for D0 candidates", false); @@ -264,9 +438,17 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processLcMcCollisions, "produces derived index for Lc MC collisions", false); - void processLc(aod::Hf3PIds::iterator const& Lc) + void processLc(aod::Hf3PIds::iterator const& Lc, aod::Tracks const&) { - jLcIdsTable(Lc.collisionId(), Lc.prong0Id(), Lc.prong1Id(), Lc.prong2Id()); + auto JProng0ID = trackCollisionMapping.find({Lc.prong0Id(), Lc.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({Lc.prong1Id(), Lc.prong1_as().collisionId()}); + auto JProng2ID = trackCollisionMapping.find({Lc.prong2Id(), Lc.prong2_as().collisionId()}); + if (withCollisionAssociator) { + JProng0ID = trackCollisionMapping.find({Lc.prong0Id(), Lc.collisionId()}); + JProng1ID = trackCollisionMapping.find({Lc.prong1Id(), Lc.collisionId()}); + JProng2ID = trackCollisionMapping.find({Lc.prong2Id(), Lc.collisionId()}); + } + jLcIdsTable(Lc.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processLc, "produces derived index for Lc candidates", false); @@ -276,38 +458,107 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processLcMC, "produces derived index for Lc particles", false); - void processV0(aod::V0Indices::iterator const& V0) + void processV0(aod::V0Indices::iterator const& V0, aod::Tracks const&) { - jV0IdsTable(V0.collisionId(), V0.posTrackId(), V0.negTrackId()); + auto JPosTrackID = trackCollisionMapping.find({V0.posTrackId(), V0.posTrack_as().collisionId()}); + auto JNegTrackID = trackCollisionMapping.find({V0.negTrackId(), V0.negTrack_as().collisionId()}); + if (withCollisionAssociator) { + JPosTrackID = trackCollisionMapping.find({V0.posTrackId(), V0.collisionId()}); + JNegTrackID = trackCollisionMapping.find({V0.negTrackId(), V0.collisionId()}); + } + jV0IdsTable(V0.collisionId(), JPosTrackID->second, JNegTrackID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processV0, "produces derived index for V0 candidates", false); - void processV0MC(aod::McParticle const& particle) + void processV0MC(aod::McCollision const& mcCollision, aod::McParticles const& particles) { // can loop over McV0Labels tables if we want to only store matched V0Particles - if (jetv0utilities::isV0Particle(particle)) { - std::vector mothersId; - if (particle.has_mothers()) { - auto mothersIdTemps = particle.mothersIds(); - for (auto mothersIdTemp : mothersIdTemps) { - mothersId.push_back(mothersIdTemp); + bool filledV0McCollisionTable = false; + for (auto const& particle : particles) { + if (jetv0utilities::isV0Particle(particles, particle)) { + if (!filledV0McCollisionTable) { + jV0McCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + jV0McCollisionIdsTable(mcCollision.globalIndex()); + filledV0McCollisionTable = true; } - } - int daughtersId[2] = {-1, -1}; - auto i = 0; - if (particle.has_daughters()) { - for (auto daughterId : particle.daughtersIds()) { - if (i > 1) { - break; + std::vector mothersId; + if (particle.has_mothers()) { + auto mothersIdTemps = particle.mothersIds(); + for (auto mothersIdTemp : mothersIdTemps) { + mothersId.push_back(mothersIdTemp); + } + } + int daughtersId[2] = {-1, -1}; + auto i = 0; + if (particle.has_daughters()) { + for (auto daughterId : particle.daughtersIds()) { + if (i > 1) { + break; + } + daughtersId[i] = daughterId; + i++; } - daughtersId[i] = daughterId; - i++; } + auto pdgParticle = pdgDatabase->GetParticle(particle.pdgCode()); + jV0McsTable(jV0McCollisionsTable.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.y(), particle.e(), pdgParticle->Mass(), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), jetv0utilities::setV0ParticleDecayBit(particles, particle)); + jV0McIdsTable(mcCollision.globalIndex(), particle.globalIndex(), mothersId, daughtersId); } - auto pdgParticle = pdgDatabase->GetParticle(particle.pdgCode()); - jV0McParticlesTable(particle.mcCollisionId(), particle.globalIndex(), particle.pt(), particle.eta(), particle.phi(), particle.y(), particle.e(), pdgParticle->Mass(), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), mothersId, daughtersId, jetv0utilities::setV0ParticleDecayBit(particle)); } } PROCESS_SWITCH(JetDerivedDataProducerTask, processV0MC, "produces V0 particles", false); + + void processDielectronCollisions(aod::ReducedEventsInfo::iterator const& DielectronCollision) + { + jDielectronCollisionIdsTable(DielectronCollision.collisionId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDielectronCollisions, "produces derived index for Dielectron collisions", false); + + void processDielectron(aod::DielectronInfo const& Dielectron, aod::Tracks const&) + { + auto JProng0ID = trackCollisionMapping.find({Dielectron.prong0Id(), Dielectron.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({Dielectron.prong1Id(), Dielectron.prong1_as().collisionId()}); + if (withCollisionAssociator) { + JProng0ID = trackCollisionMapping.find({Dielectron.prong0Id(), Dielectron.collisionId()}); + JProng1ID = trackCollisionMapping.find({Dielectron.prong1Id(), Dielectron.collisionId()}); + } + jDielectronIdsTable(Dielectron.collisionId(), JProng0ID->second, JProng1ID->second); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDielectron, "produces derived index for Dielectron candidates", false); + + void processDielectronMc(aod::McCollision const& mcCollision, aod::McParticles const& particles) + { + bool filledDielectronMcCollisionTable = false; + for (auto const& particle : particles) { + if (jetdqutilities::isDielectronParticle(particles, particle)) { + if (!filledDielectronMcCollisionTable) { + jDielectronMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + jDielectronMcCollisionIdsTable(mcCollision.globalIndex()); + filledDielectronMcCollisionTable = true; + } + std::vector mothersId; + if (particle.has_mothers()) { + auto mothersIdTemps = particle.mothersIds(); + for (auto mothersIdTemp : mothersIdTemps) { + mothersId.push_back(mothersIdTemp); + } + } + int daughtersId[2] = {-1, -1}; + auto i = 0; + if (particle.has_daughters()) { + for (auto daughterId : particle.daughtersIds()) { + if (i > 1) { + break; + } + daughtersId[i] = daughterId; + i++; + } + } + auto pdgParticle = pdgDatabase->GetParticle(particle.pdgCode()); + jDielectronMcsTable(jDielectronMcCollisionsTable.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.y(), particle.e(), pdgParticle->Mass(), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), jetdqutilities::setDielectronParticleDecayBit(particles, particle), RecoDecay::getCharmHadronOrigin(particles, particle, false)); // Todo: should the last thing be false? + jDielectronMcIdsTable(mcCollision.globalIndex(), particle.globalIndex(), mothersId, daughtersId); + } + } + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDielectronMc, "produces Dielectron mccollisions and particles", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/TableProducer/jetderiveddataproducerdummy.cxx b/PWGJE/TableProducer/jetderiveddataproducerdummy.cxx index 1bcb3ec2674..efbd1fa4cf5 100644 --- a/PWGJE/TableProducer/jetderiveddataproducerdummy.cxx +++ b/PWGJE/TableProducer/jetderiveddataproducerdummy.cxx @@ -19,6 +19,7 @@ #include "Framework/runDataProcessing.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGHF/DataModel/DerivedTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" using namespace o2; using namespace o2::framework; @@ -48,6 +49,9 @@ struct JetDerivedDataProducerDummyTask { Produces lcMcCollisionsTable; Produces lcParticlesTable; + Produces dielectronCollisionsTable; + Produces dielectronTable; + void init(InitContext const&) { } diff --git a/PWGJE/TableProducer/jetderiveddataproducerdummyd0.cxx b/PWGJE/TableProducer/jetderiveddataproducerdummyd0.cxx index 37102a57b1a..8b02d7cdeab 100644 --- a/PWGJE/TableProducer/jetderiveddataproducerdummyd0.cxx +++ b/PWGJE/TableProducer/jetderiveddataproducerdummyd0.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// temporary task to produce HF tables needed when making inclusive derived data - should become obsolete when tables are able to be prouduced based on a configurable +// temporary task to produce HF and DQ tables needed when making D0 jet derived data - should become obsolete when tables are able to be prouduced based on a configurable // /// \author Nima Zardoshti @@ -19,6 +19,7 @@ #include "Framework/runDataProcessing.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGHF/DataModel/DerivedTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" using namespace o2; using namespace o2::framework; @@ -37,6 +38,9 @@ struct JetDerivedDataProducerDummyD0Task { Produces lcMcCollisionsTable; Produces lcParticlesTable; + Produces dielectronCollisionsTable; + Produces dielectronTable; + void init(InitContext const&) { } diff --git a/PWGJE/TableProducer/jetderiveddataproducerdummydielectron.cxx b/PWGJE/TableProducer/jetderiveddataproducerdummydielectron.cxx new file mode 100644 index 00000000000..784fa3e4826 --- /dev/null +++ b/PWGJE/TableProducer/jetderiveddataproducerdummydielectron.cxx @@ -0,0 +1,66 @@ +// Copyright 2019-2020 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. + +// temporary task to produce HF tables needed when making dielectron jet derived data - should become obsolete when tables are able to be prouduced based on a configurable +// +/// \author Nima Zardoshti + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/runDataProcessing.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct JetDerivedDataProducerDummyDielectronTask { + + Produces d0CollisionsTable; + Produces d0CollisionsMatchingTable; + Produces d0sTable; + Produces d0ParsTable; + Produces d0ParExtrasTable; + Produces d0SelsTable; + Produces d0MlsTable; + Produces d0McsTable; + Produces d0McCollisionsTable; + Produces d0ParticlesTable; + + Produces lcCollisionsTable; + Produces lcCollisionsMatchingTable; + Produces lcsTable; + Produces lcParsTable; + Produces lcParExtrasTable; + Produces lcSelsTable; + Produces lcMlsTable; + Produces lcMcsTable; + Produces lcMcCollisionsTable; + Produces lcParticlesTable; + + void init(InitContext const&) + { + } + + void processDummy(aod::JDummys const&) + { + } + PROCESS_SWITCH(JetDerivedDataProducerDummyDielectronTask, processDummy, "leaves all tables empty", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"jet-deriveddata-producer-dummy-dielectron"})}; +} diff --git a/PWGJE/TableProducer/jetderiveddataproducerdummylc.cxx b/PWGJE/TableProducer/jetderiveddataproducerdummylc.cxx index f41f2fb26ad..05e1384deac 100644 --- a/PWGJE/TableProducer/jetderiveddataproducerdummylc.cxx +++ b/PWGJE/TableProducer/jetderiveddataproducerdummylc.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// temporary task to produce HF tables needed when making inclusive derived data - should become obsolete when tables are able to be prouduced based on a configurable +// temporary task to produce HF and DQ tables needed when making Lc jet derived data - should become obsolete when tables are able to be prouduced based on a configurable // /// \author Nima Zardoshti @@ -19,6 +19,7 @@ #include "Framework/runDataProcessing.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGHF/DataModel/DerivedTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" using namespace o2; using namespace o2::framework; @@ -37,6 +38,9 @@ struct JetDerivedDataProducerDummyLcTask { Produces d0McCollisionsTable; Produces d0ParticlesTable; + Produces dielectronCollisionsTable; + Produces dielectronTable; + void init(InitContext const&) { } diff --git a/PWGJE/TableProducer/jetderiveddatatriggerproducer.cxx b/PWGJE/TableProducer/jetderiveddatatriggerproducer.cxx index 4d7dcccce96..a1a1636dd1b 100644 --- a/PWGJE/TableProducer/jetderiveddatatriggerproducer.cxx +++ b/PWGJE/TableProducer/jetderiveddatatriggerproducer.cxx @@ -47,35 +47,17 @@ struct JetDerivedDataTriggerProducerTask { } PROCESS_SWITCH(JetDerivedDataTriggerProducerTask, processChargedJetTriggers, "produces derived charged trigger table", false); - void processNoChargedJetTriggers(aod::Collision const&) - { - jChargedTriggerSelsTable(jetderiveddatautilities::JTrigSelCh::noChargedTigger); - } - PROCESS_SWITCH(JetDerivedDataTriggerProducerTask, processNoChargedJetTriggers, "produces derived charged trigger table when sample is not triggered", true); - void processFullJetTriggers(soa::Join::iterator const& collision) { jFullTriggerSelsTable(jetderiveddatautilities::setFullTriggerSelectionBit(collision)); } PROCESS_SWITCH(JetDerivedDataTriggerProducerTask, processFullJetTriggers, "produces derived full trigger table", false); - void processNoFullJetTriggers(aod::Collision const&) - { - jFullTriggerSelsTable(jetderiveddatautilities::JTrigSelFull::noFullTrigger); - } - PROCESS_SWITCH(JetDerivedDataTriggerProducerTask, processNoFullJetTriggers, "produces derived full trigger table table when sample is not triggered", true); - void processChargedHFJetTriggers(soa::Join::iterator const& collision) { jChargedHFTriggerSelsTable(jetderiveddatautilities::setChargedHFTriggerSelectionBit(collision)); } PROCESS_SWITCH(JetDerivedDataTriggerProducerTask, processChargedHFJetTriggers, "produces derived charged hf trigger table", false); - - void processNoChargedHFJetTriggers(aod::Collision const&) - { - jChargedHFTriggerSelsTable(jetderiveddatautilities::JTrigSelChHF::noChargedHFTigger); - } - PROCESS_SWITCH(JetDerivedDataTriggerProducerTask, processNoChargedHFJetTriggers, "produces derived charged hf trigger table when sample is not triggered", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/TableProducer/jetderiveddatawriter.cxx b/PWGJE/TableProducer/jetderiveddatawriter.cxx index bed97a8afb1..d8beca77b65 100644 --- a/PWGJE/TableProducer/jetderiveddatawriter.cxx +++ b/PWGJE/TableProducer/jetderiveddatawriter.cxx @@ -19,12 +19,15 @@ #include #include +#include + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" #include "Framework/runDataProcessing.h" #include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/Core/JetDQUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" @@ -35,78 +38,104 @@ using namespace o2::framework::expressions; struct JetDerivedDataWriter { struct : ConfigurableGroup { - Configurable chargedJetPtMin{"chargedJetPtMin", 0.0, "Minimum charged jet pt to accept event"}; - Configurable chargedEventWiseSubtractedJetPtMin{"chargedEventWiseSubtractedJetPtMin", 0.0, "Minimum charged event-wise subtracted jet pt to accept event"}; - Configurable chargedMCPJetPtMin{"chargedMCPJetPtMin", 0.0, "Minimum charged mcp jet pt to accept event"}; - Configurable neutralJetPtMin{"neutralJetPtMin", 0.0, "Minimum charged jet pt to accept event"}; - Configurable fullJetPtMin{"fullJetPtMin", 0.0, "Minimum full jet pt to accept event"}; - Configurable chargedEventWiseSubtractedD0JetPtMin{"chargedEventWiseSubtractedD0JetPtMin", 0.0, "Minimum charged event-wise subtracted D0 jet pt to accept event"}; - Configurable chargedD0JetPtMin{"chargedD0JetPtMin", 0.0, "Minimum charged D0 jet pt to accept event"}; - Configurable chargedEventWiseSubtractedLcJetPtMin{"chargedEventWiseSubtractedLcJetPtMin", 0.0, "Minimum charged event-wise subtracted Lc jet pt to accept event"}; - Configurable chargedLcJetPtMin{"chargedLcJetPtMin", 0.0, "Minimum charged Lc jet pt to accept event"}; - + Configurable thresholdChargedJetPtMin{"thresholdChargedJetPtMin", 0.0, "Minimum charged jet pt to accept event"}; + Configurable thresholdChargedEventWiseSubtractedJetPtMin{"thresholdChargedEventWiseSubtractedJetPtMin", 0.0, "Minimum charged event-wise subtracted jet pt to accept event"}; + Configurable thresholdChargedMCPJetPtMin{"thresholdChargedMCPJetPtMin", 0.0, "Minimum charged mcp jet pt to accept event"}; + Configurable thresholdNeutralJetPtMin{"thresholdNeutralJetPtMin", 0.0, "Minimum neutral jet pt to accept event"}; + Configurable thresholdNeutralMCPJetPtMin{"thresholdNeutralMCPJetPtMin", 0.0, "Minimum neutal mcp jet pt to accept event"}; + Configurable thresholdFullJetPtMin{"thresholdFullJetPtMin", 0.0, "Minimum full jet pt to accept event"}; + Configurable thresholdFullMCPJetPtMin{"thresholdFullMCPJetPtMin", 0.0, "Minimum full mcp jet pt to accept event"}; + Configurable thresholdChargedD0JetPtMin{"thresholdChargedD0JetPtMin", 0.0, "Minimum charged D0 jet pt to accept event"}; + Configurable thresholdChargedEventWiseSubtractedD0JetPtMin{"thresholdChargedEventWiseSubtractedD0JetPtMin", 0.0, "Minimum charged event-wise subtracted D0 jet pt to accept event"}; + Configurable thresholdChargedD0MCPJetPtMin{"thresholdChargedD0MCPJetPtMin", 0.0, "Minimum charged D0 mcp jet pt to accept event"}; + Configurable thresholdChargedLcJetPtMin{"thresholdChargedLcJetPtMin", 0.0, "Minimum charged Lc jet pt to accept event"}; + Configurable thresholdChargedEventWiseSubtractedLcJetPtMin{"thresholdChargedEventWiseSubtractedLcJetPtMin", 0.0, "Minimum charged event-wise subtracted Lc jet pt to accept event"}; + Configurable thresholdChargedLcMCPJetPtMin{"thresholdChargedLcMCPJetPtMin", 0.0, "Minimum charged Lc mcp jet pt to accept event"}; + Configurable thresholdChargedDielectronJetPtMin{"thresholdChargedDielectronJetPtMin", 0.0, "Minimum charged Dielectron jet pt to accept event"}; + Configurable thresholdChargedEventWiseSubtractedDielectronJetPtMin{"thresholdChargedEventWiseSubtractedDielectronJetPtMin", 0.0, "Minimum charged event-wise subtracted Dielectron jet pt to accept event"}; + Configurable thresholdChargedDielectronMCPJetPtMin{"thresholdChargedDielectronMCPJetPtMin", 0.0, "Minimum charged Dielectron mcp jet pt to accept event"}; + Configurable thresholdTriggerTrackPtMin{"thresholdTriggerTrackPtMin", 0.0, "Minimum trigger track pt to accept event"}; + Configurable thresholdClusterEnergyMin{"thresholdClusterEnergyMin", 0.0, "Minimum cluster energy to accept event"}; + Configurable downscaleFactor{"downscaleFactor", 1, "random downscale of selected events"}; + + Configurable vertexZCut{"vertexZCut", 10.0, "z-vertex cut on event"}; + Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; + Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; Configurable performTrackSelection{"performTrackSelection", true, "only save tracks that pass one of the track selections"}; + Configurable trackPtSelectionMin{"trackPtSelectionMin", 0.15, "only save tracks that have a pT larger than this pT"}; + Configurable trackEtaSelectionMax{"trackEtaSelectionMax", 0.9, "only save tracks that have an eta smaller than this eta"}; Configurable saveBCsTable{"saveBCsTable", true, "save the bunch crossing table to the output"}; - Configurable saveClustersTable{"saveClustersTable", true, "save the clusters table to the output"}; + Configurable saveClustersTable{"saveClustersTable", false, "save the clusters table to the output"}; Configurable saveD0Table{"saveD0Table", false, "save the D0 table to the output"}; Configurable saveLcTable{"saveLcTable", false, "save the Lc table to the output"}; + Configurable saveDielectronTable{"saveDielectronTable", false, "save the Dielectron table to the output"}; - Configurable eventSelectionForCounting{"eventSelectionForCounting", "sel8", "choose event selection for collision counter"}; + Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; } config; - Produces storedCollisionCountsTable; - Produces storedJDummysTable; - Produces storedJBCsTable; - Produces storedJBCParentIndexTable; - Produces storedJCollisionsTable; - Produces storedJCollisionsParentIndexTable; - Produces storedJCollisionsBunchCrossingIndexTable; - Produces storedJChargedTriggerSelsTable; - Produces storedJFullTriggerSelsTable; - Produces storedJChargedHFTriggerSelsTable; - Produces storedJMcCollisionsLabelTable; - Produces storedJMcCollisionsTable; - Produces storedJMcCollisionsParentIndexTable; - Produces storedJTracksTable; - Produces storedJTracksExtraTable; - Produces storedJTracksParentIndexTable; - Produces storedJMcTracksLabelTable; - Produces storedJMcParticlesTable; - Produces storedJParticlesParentIndexTable; - Produces storedJClustersTable; - Produces storedJClustersParentIndexTable; - Produces storedJClustersMatchedTracksTable; - Produces storedJMcClustersLabelTable; - - Produces storedD0CollisionsTable; - Produces storedD0CollisionIdsTable; - Produces storedD0sTable; - Produces storedD0ParsTable; - Produces storedD0ParExtrasTable; - Produces storedD0SelsTable; - Produces storedD0MlsTable; - Produces storedD0McsTable; - Produces storedD0IdsTable; - Produces storedD0McCollisionsTable; - Produces storedD0McCollisionIdsTable; - Produces storedD0McCollisionsMatchingTable; - Produces storedD0ParticlesTable; - Produces storedD0ParticleIdsTable; - - Produces storedLcCollisionsTable; - Produces storedLcCollisionIdsTable; - Produces storedLcsTable; - Produces storedLcParsTable; - Produces storedLcParExtrasTable; - Produces storedLcSelsTable; - Produces storedLcMlsTable; - Produces storedLcMcsTable; - Produces storedLcIdsTable; - Produces storedLcMcCollisionsTable; - Produces storedLcMcCollisionIdsTable; - Produces storedLcMcCollisionsMatchingTable; - Produces storedLcParticlesTable; - Produces storedLcParticleIdsTable; + struct : ProducesGroup { + Produces storedJDummysTable; + Produces storedJBCsTable; + Produces storedJBCParentIndexTable; + Produces storedJCollisionsTable; + Produces storedJCollisionsParentIndexTable; + Produces storedJCollisionsBunchCrossingIndexTable; + Produces storedJCollisionsEMCalLabelTable; + Produces storedJMcCollisionsLabelTable; + Produces storedJMcCollisionsTable; + Produces storedJMcCollisionsParentIndexTable; + Produces storedJTracksTable; + Produces storedJTracksExtraTable; + Produces storedJTracksParentIndexTable; + Produces storedJMcTracksLabelTable; + Produces storedJMcParticlesTable; + Produces storedJParticlesParentIndexTable; + Produces storedJClustersTable; + Produces storedJClustersParentIndexTable; + Produces storedJClustersMatchedTracksTable; + Produces storedJMcClustersLabelTable; + + Produces storedD0CollisionsTable; + Produces storedD0CollisionIdsTable; + Produces storedD0sTable; + Produces storedD0ParsTable; + Produces storedD0ParExtrasTable; + Produces storedD0SelsTable; + Produces storedD0MlsTable; + Produces storedD0McsTable; + Produces storedD0IdsTable; + Produces storedD0McCollisionsTable; + Produces storedD0McCollisionIdsTable; + Produces storedD0McCollisionsMatchingTable; + Produces storedD0ParticlesTable; + Produces storedD0ParticleIdsTable; + + Produces storedLcCollisionsTable; + Produces storedLcCollisionIdsTable; + Produces storedLcsTable; + Produces storedLcParsTable; + Produces storedLcParExtrasTable; + Produces storedLcSelsTable; + Produces storedLcMlsTable; + Produces storedLcMcsTable; + Produces storedLcIdsTable; + Produces storedLcMcCollisionsTable; + Produces storedLcMcCollisionIdsTable; + Produces storedLcMcCollisionsMatchingTable; + Produces storedLcParticlesTable; + Produces storedLcParticleIdsTable; + + Produces storedDielectronCollisionsTable; + Produces storedDielectronCollisionIdsTable; + Produces storedDielectronsTable; + Produces storedDielectronIdsTable; + Produces storedDielectronMcCollisionsTable; + Produces storedDielectronMcCollisionIdsTable; + // Produces storedD0McCollisionsMatchingTable; //this doesnt exist for Dileptons yet + Produces storedDielectronParticlesTable; + Produces storedDielectronParticleIdsTable; + } products; PresliceUnsorted> CollisionsPerMcCollision = aod::jmccollisionlb::mcCollisionId; PresliceUnsorted> ParticlesPerMcCollision = aod::jmcparticle::mcCollisionId; @@ -114,24 +143,30 @@ struct JetDerivedDataWriter { Preslice> ClustersPerCollision = aod::jcluster::collisionId; Preslice> D0McCollisionsPerMcCollision = aod::jd0indices::mcCollisionId; Preslice> LcMcCollisionsPerMcCollision = aod::jlcindices::mcCollisionId; + Preslice DielectronMcCollisionsPerMcCollision = aod::jdielectronindices::mcCollisionId; Preslice D0CollisionsPerCollision = aod::jd0indices::collisionId; Preslice LcCollisionsPerCollision = aod::jlcindices::collisionId; + Preslice DielectronCollisionsPerCollision = aod::jdielectronindices::collisionId; Preslice D0sPerCollision = aod::jd0indices::collisionId; Preslice LcsPerCollision = aod::jlcindices::collisionId; + Preslice DielectronsPerCollision = aod::jdielectronindices::collisionId; std::vector collisionFlag; std::vector McCollisionFlag; - std::vector bcIndicies; + std::vector bcIndicies; uint32_t precisionPositionMask; uint32_t precisionMomentumMask; - int eventSelection = -1; + TRandom3 randomNumber; + + std::vector triggerMaskBits; void init(InitContext&) { precisionPositionMask = 0xFFFFFC00; // 13 bits precisionMomentumMask = 0xFFFFFC00; // 13 bits this is currently keept at 13 bits wihich gives roughly a resolution of 1/8000. This can be increased to 15 bits if really needed - eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(config.eventSelectionForCounting)); + randomNumber.SetSeed(0); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(config.triggerMasks); } bool acceptCollision(aod::JCollision const&) @@ -139,117 +174,189 @@ struct JetDerivedDataWriter { return true; } - void processCollisions(aod::JCollisions const& collisions) + void processSetupCollisions(aod::JCollisions const& collisions) { collisionFlag.clear(); collisionFlag.resize(collisions.size()); std::fill(collisionFlag.begin(), collisionFlag.end(), false); } - void processMcCollisions(aod::JMcCollisions const& Mccollisions) + void processSetupMcCollisions(aod::JMcCollisions const& McCollisions) { McCollisionFlag.clear(); - McCollisionFlag.resize(Mccollisions.size()); + McCollisionFlag.resize(McCollisions.size()); std::fill(McCollisionFlag.begin(), McCollisionFlag.end(), false); } - template - void processJets(T& jets) + void processSetupAllCollisionsWithDownscaling(aod::JCollisions const& collisions) { - float jetPtMin = 0.0; - if constexpr (std::is_same_v, aod::ChargedJets> || std::is_same_v, aod::ChargedMCDetectorLevelJets>) { - jetPtMin = config.chargedJetPtMin; - } else if constexpr (std::is_same_v, aod::ChargedEventWiseSubtractedJets>) { - jetPtMin = config.chargedEventWiseSubtractedJetPtMin; - } else if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets>) { - jetPtMin = config.chargedMCPJetPtMin; - } else if constexpr (std::is_same_v, aod::NeutralJets>) { - jetPtMin = config.neutralJetPtMin; - } else if constexpr (std::is_same_v, aod::FullJets>) { - jetPtMin = config.fullJetPtMin; - } else if constexpr (std::is_same_v, aod::D0ChargedJets>) { - jetPtMin = config.chargedD0JetPtMin; - } else if constexpr (std::is_same_v, aod::D0ChargedEventWiseSubtractedJets>) { - jetPtMin = config.chargedEventWiseSubtractedD0JetPtMin; - } else if constexpr (std::is_same_v, aod::LcChargedJets>) { - jetPtMin = config.chargedLcJetPtMin; - } else if constexpr (std::is_same_v, aod::LcChargedEventWiseSubtractedJets>) { - jetPtMin = config.chargedEventWiseSubtractedLcJetPtMin; - } else { - jetPtMin = 0.0; - } - for (const auto& jet : jets) { - if (jet.pt() >= jetPtMin) { - if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::NeutralMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::BplusChargedMCParticleLevelJets>) { - McCollisionFlag[jet.mcCollisionId()] = true; - } else { - collisionFlag[jet.collisionId()] = true; - } + collisionFlag.clear(); + collisionFlag.resize(collisions.size()); + for (const auto& collision : collisions) { + if (randomNumber.Integer(config.downscaleFactor) == 0) { + collisionFlag[collision.globalIndex()] = true; + } else { + collisionFlag[collision.globalIndex()] = false; } } } - PROCESS_SWITCH(JetDerivedDataWriter, processCollisions, "setup the writing for data and MCD", true); - PROCESS_SWITCH(JetDerivedDataWriter, processMcCollisions, "setup the writing for MCP", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processChargedJets, "process charged jets", true); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processChargedEventWiseSubtractedJets, "process charged event-wise subtracted jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processChargedMCDJets, "process charged mcd jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processChargedMCPJets, "process charged mcp jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processNeutralJets, "process neutral jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processFullJets, "process full jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processD0ChargedJets, "process D0 charged jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processD0ChargedEventWiseSubtractedJets, "process D0 event-wise subtracted charged jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processLcChargedJets, "process Lc charged jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataWriter, processJets, processLcChargedEventWiseSubtractedJets, "process Lc event-wise subtracted charged jets", false); - - void processDummyTable(aod::JDummys const&) + + void processSetupAllMcCollisionsWithDownscaling(aod::JMcCollisions const& McCollisions) { - storedJDummysTable(1); + McCollisionFlag.clear(); + McCollisionFlag.resize(McCollisions.size()); + for (const auto& mcCollision : McCollisions) { + if (randomNumber.Integer(config.downscaleFactor) == 0) { + McCollisionFlag[mcCollision.globalIndex()] = true; + } else { + McCollisionFlag[mcCollision.globalIndex()] = false; + } + } } - PROCESS_SWITCH(JetDerivedDataWriter, processDummyTable, "write out dummy output table", true); - void processCollisionCounting(aod::JCollisions const& collisions, aod::CollisionCounts const& collisionCounts) + template + void processDoDownscaling(T const& collisions) { - int readCollisionCounter = 0; - int readSelectedCollisionCounter = 0; - int writtenCollisionCounter = 0; for (const auto& collision : collisions) { - readCollisionCounter++; - if (jetderiveddatautilities::selectCollision(collision, eventSelection)) { - readSelectedCollisionCounter++; + if constexpr (std::is_same_v, aod::JCollisions>) { + if (collisionFlag[collision.globalIndex()] && randomNumber.Integer(config.downscaleFactor) != 0) { + collisionFlag[collision.globalIndex()] = false; + } } - if (collisionFlag[collision.globalIndex()]) { - writtenCollisionCounter++; + if constexpr (std::is_same_v, aod::JMcCollisions>) { + if (McCollisionFlag[collision.globalIndex()] && randomNumber.Integer(config.downscaleFactor) != 0) { + McCollisionFlag[collision.globalIndex()] = false; + } } } - std::vector previousReadCounts; - std::vector previousReadSelectedCounts; - std::vector previousWrittenCounts; - int iPreviousDataFrame = 0; - for (const auto& collisionCount : collisionCounts) { - auto readCollisionCounterSpan = collisionCount.readCounts(); - auto readSelectedCollisionCounterSpan = collisionCount.readSelectedCounts(); - auto writtenCollisionCounterSpan = collisionCount.writtenCounts(); - if (iPreviousDataFrame == 0) { - std::copy(readCollisionCounterSpan.begin(), readCollisionCounterSpan.end(), std::back_inserter(previousReadCounts)); - std::copy(readSelectedCollisionCounterSpan.begin(), readSelectedCollisionCounterSpan.end(), std::back_inserter(previousReadSelectedCounts)); - std::copy(writtenCollisionCounterSpan.begin(), writtenCollisionCounterSpan.end(), std::back_inserter(previousWrittenCounts)); + } + + void processSetupEventTriggering(aod::JCollision const& collision) + { + if (jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + collisionFlag[collision.globalIndex()] = true; + } + } + + void processDoCollisionSelections(aod::JCollision const& collision) + { // can also add event selection like sel8 but goes a little against the derived data idea + if (collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + collisionFlag[collision.globalIndex()] = false; + } + } + + template + void processSelectionObjects(T& selectionObjects) + { + float selectionObjectPtMin = 0.0; + if constexpr (std::is_same_v, aod::ChargedJets> || std::is_same_v, aod::ChargedMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdChargedJetPtMin; + } else if constexpr (std::is_same_v, aod::ChargedEventWiseSubtractedJets> || std::is_same_v, aod::ChargedMCDetectorLevelEventWiseSubtractedJets>) { + selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedJetPtMin; + } else if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdChargedMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::NeutralJets> || std::is_same_v, aod::NeutralMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdNeutralJetPtMin; + } else if constexpr (std::is_same_v, aod::NeutralMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdNeutralMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::FullJets> || std::is_same_v, aod::FullMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdFullJetPtMin; + } else if constexpr (std::is_same_v, aod::FullMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdFullMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::D0ChargedJets> || std::is_same_v, aod::D0ChargedMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdChargedD0JetPtMin; + } else if constexpr (std::is_same_v, aod::D0ChargedEventWiseSubtractedJets> || std::is_same_v, aod::D0ChargedMCDetectorLevelEventWiseSubtractedJets>) { + selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedD0JetPtMin; + } else if constexpr (std::is_same_v, aod::D0ChargedMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdChargedD0MCPJetPtMin; + } else if constexpr (std::is_same_v, aod::LcChargedJets> || std::is_same_v, aod::LcChargedMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdChargedLcJetPtMin; + } else if constexpr (std::is_same_v, aod::LcChargedEventWiseSubtractedJets> || std::is_same_v, aod::LcChargedMCDetectorLevelEventWiseSubtractedJets>) { + selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedLcJetPtMin; + } else if constexpr (std::is_same_v, aod::LcChargedMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdChargedLcMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::DielectronChargedJets> || std::is_same_v, aod::DielectronChargedMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdChargedDielectronJetPtMin; + } else if constexpr (std::is_same_v, aod::DielectronChargedEventWiseSubtractedJets> || std::is_same_v, aod::DielectronChargedMCDetectorLevelEventWiseSubtractedJets>) { + selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedDielectronJetPtMin; + } else if constexpr (std::is_same_v, aod::DielectronChargedMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdChargedDielectronMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::JTracks>) { + selectionObjectPtMin = config.thresholdTriggerTrackPtMin; + } else if constexpr (std::is_same_v, aod::JClusters>) { + selectionObjectPtMin = config.thresholdClusterEnergyMin; + } else { + selectionObjectPtMin = 0.0; + } + for (const auto& selectionObject : selectionObjects) { + bool isTriggerObject = false; + if constexpr (std::is_same_v, aod::JClusters>) { + if (selectionObject.energy() >= selectionObjectPtMin) { + isTriggerObject = true; + } } else { - for (unsigned int i = 0; i < previousReadCounts.size(); i++) { - previousReadCounts[i] += readCollisionCounterSpan[i]; - previousReadSelectedCounts[i] += readSelectedCollisionCounterSpan[i]; - previousWrittenCounts[i] += writtenCollisionCounterSpan[i]; + if (selectionObject.pt() >= selectionObjectPtMin) { + isTriggerObject = true; + } + } + if (isTriggerObject) { + if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::NeutralMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets>) { + if (selectionObject.mcCollisionId() >= 0) { + McCollisionFlag[selectionObject.mcCollisionId()] = true; + } + } else { + if (selectionObject.collisionId() >= 0) { + collisionFlag[selectionObject.collisionId()] = true; + } } } - iPreviousDataFrame++; } - previousReadCounts.push_back(readCollisionCounter); - previousReadSelectedCounts.push_back(readSelectedCollisionCounter); - previousWrittenCounts.push_back(writtenCollisionCounter); - storedCollisionCountsTable(previousReadCounts, previousReadSelectedCounts, previousWrittenCounts); } - PROCESS_SWITCH(JetDerivedDataWriter, processCollisionCounting, "write out collision counting output table", false); + // Todo : Check memory consumption of having so many Process Switches + PROCESS_SWITCH(JetDerivedDataWriter, processSetupCollisions, "setup the writing for data and MCD based on collisions", true); + PROCESS_SWITCH(JetDerivedDataWriter, processSetupMcCollisions, "setup the writing for MCP based on mcCollisions", false); + PROCESS_SWITCH(JetDerivedDataWriter, processSetupAllCollisionsWithDownscaling, "setup the writing of untriggered collisions with downscaling", false); + PROCESS_SWITCH(JetDerivedDataWriter, processSetupAllMcCollisionsWithDownscaling, "setup the writing of untriggered mccollisions with downscaling", false); + PROCESS_SWITCH(JetDerivedDataWriter, processSetupEventTriggering, "process software triggers", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingChargedJets, "process charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingChargedEventWiseSubtractedJets, "process charged event-wise subtracted jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingChargedMCDJets, "process charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingChargedMCDetectorLevelEventWiseSubtractedJets, "process charged event-wise subtracted mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingChargedMCPJets, "process charged mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingNeutralJets, "process neutral jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingNeutralMCDJets, "process neutral mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingNeutralMCPJets, "process neutral mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingFullJets, "process full jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingFullMCDJets, "process full mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingFullMCPJets, "process full mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingD0ChargedJets, "process D0 charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingD0ChargedEventWiseSubtractedJets, "process D0 event-wise subtracted charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingD0ChargedMCDJets, "process D0 charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingD0ChargedMCDetectorLevelEventWiseSubtractedJets, "process D0 event-wise subtracted charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingD0ChargedMCPJets, "process D0 charged mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingLcChargedJets, "process Lc charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingLcChargedEventWiseSubtractedJets, "process Lc event-wise subtracted charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingLcChargedMCDJets, "process Lc charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingLcChargedMCDetectorLevelEventWiseSubtractedJets, "process Lc event-wise subtracted charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingLcChargedMCPJets, "process Lc charged mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingDielectronChargedJets, "process Dielectron charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingDielectronChargedEventWiseSubtractedJets, "process Dielectron event-wise subtracted charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingDielectronChargedMCDJets, "process Dielectron charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingDielectronChargedMCDetectorLevelEventWiseSubtractedJets, "process Dielectron event-wise subtracted charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingDielectronChargedMCPJets, "process Dielectron charged mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingClusters, "process EMCal clusters", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processSelectionObjects, processSelectingTracks, "process high pt tracks", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processDoDownscaling, processCollisionDownscaling, "process downsaling of triggered collisions", false); + PROCESS_SWITCH_FULL(JetDerivedDataWriter, processDoDownscaling, processMcCollisionDownscaling, "process downsaling of triggered mccollisions", false); + PROCESS_SWITCH(JetDerivedDataWriter, processDoCollisionSelections, "process event selections for saved events", false); + + void processStoreDummyTable(aod::JDummys const&) + { + products.storedJDummysTable(1); + } + PROCESS_SWITCH(JetDerivedDataWriter, processStoreDummyTable, "write out dummy output table", true); - void processData(soa::Join::iterator const& collision, soa::Join const&, soa::Join const& tracks, soa::Join const& clusters, CollisionsD0 const& D0Collisions, CandidatesD0Data const& D0s, CollisionsLc const& LcCollisions, CandidatesLcData const& Lcs) + void processStoreData(soa::Join::iterator const& collision, soa::Join const&, soa::Join const& tracks, soa::Join const& clusters, CollisionsD0 const& D0Collisions, CandidatesD0Data const& D0s, CollisionsLc const& LcCollisions, CandidatesLcData const& Lcs, CollisionsDielectron const& DielectronCollisions, CandidatesDielectronData const& Dielectrons) { std::map bcMapping; std::map trackMapping; @@ -258,63 +365,66 @@ struct JetDerivedDataWriter { if (config.saveBCsTable) { auto bc = collision.bc_as>(); if (std::find(bcIndicies.begin(), bcIndicies.end(), bc.globalIndex()) == bcIndicies.end()) { - storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp()); - storedJBCParentIndexTable(bc.bcId()); + products.storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp(), bc.alias_raw(), bc.selection_raw()); + products.storedJBCParentIndexTable(bc.bcId()); bcIndicies.push_back(bc.globalIndex()); - bcMapping.insert(std::make_pair(bc.globalIndex(), storedJBCsTable.lastIndex())); + bcMapping.insert(std::make_pair(bc.globalIndex(), products.storedJBCsTable.lastIndex())); } } - storedJCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multiplicity(), collision.centrality(), collision.eventSel(), collision.alias_raw()); - storedJCollisionsParentIndexTable(collision.collisionId()); + products.storedJCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multiplicity(), collision.centrality(), collision.trackOccupancyInTimeRange(), collision.eventSel(), collision.alias_raw(), collision.triggerSel()); + products.storedJCollisionsParentIndexTable(collision.collisionId()); if (config.saveBCsTable) { int32_t storedBCID = -1; auto JBCIndex = bcMapping.find(collision.bcId()); if (JBCIndex != bcMapping.end()) { storedBCID = JBCIndex->second; } - storedJCollisionsBunchCrossingIndexTable(storedBCID); + products.storedJCollisionsBunchCrossingIndexTable(storedBCID); + } + if (config.saveClustersTable) { + products.storedJCollisionsEMCalLabelTable(collision.isAmbiguous(), collision.isEmcalReadout()); } - storedJChargedTriggerSelsTable(collision.chargedTriggerSel()); - storedJFullTriggerSelsTable(collision.fullTriggerSel()); - storedJChargedHFTriggerSelsTable(collision.chargedHFTriggerSel()); for (const auto& track : tracks) { - if (config.performTrackSelection && !(track.trackSel() & ~(1 << jetderiveddatautilities::JTrackSel::trackSign))) { // skips tracks that pass no selections. This might cause a problem with tracks matched with clusters. We should generate a track selection purely for cluster matched tracks so that they are kept + if (config.performTrackSelection && !(track.trackSel() & ~(1 << jetderiveddatautilities::JTrackSel::trackSign))) { // skips tracks that pass no selections. This might cause a problem with tracks matched with clusters. We should generate a track selection purely for cluster matched tracks so that they are kept. This includes also the track pT selction. continue; } - storedJTracksTable(storedJCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(track.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(track.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.phi(), precisionPositionMask), track.trackSel()); - storedJTracksExtraTable(o2::math_utils::detail::truncateFloatFraction(track.dcaXY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigma1Pt(), precisionMomentumMask)); - storedJTracksParentIndexTable(track.trackId()); - trackMapping.insert(std::make_pair(track.globalIndex(), storedJTracksTable.lastIndex())); + if (track.pt() < config.trackPtSelectionMin || std::abs(track.eta()) > config.trackEtaSelectionMax) { + continue; + } + products.storedJTracksTable(products.storedJCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(track.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(track.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.phi(), precisionPositionMask), track.trackSel()); + products.storedJTracksExtraTable(o2::math_utils::detail::truncateFloatFraction(track.dcaX(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaXY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaXYZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigmadcaZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigmadcaXY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigmadcaXYZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigma1Pt(), precisionMomentumMask)); + products.storedJTracksParentIndexTable(track.trackId()); + trackMapping.insert(std::make_pair(track.globalIndex(), products.storedJTracksTable.lastIndex())); } if (config.saveClustersTable) { for (const auto& cluster : clusters) { - storedJClustersTable(storedJCollisionsTable.lastIndex(), cluster.id(), cluster.energy(), cluster.coreEnergy(), cluster.rawEnergy(), - cluster.eta(), cluster.phi(), cluster.m02(), cluster.m20(), cluster.nCells(), cluster.time(), cluster.isExotic(), cluster.distanceToBadChannel(), - cluster.nlm(), cluster.definition(), cluster.leadingCellEnergy(), cluster.subleadingCellEnergy(), cluster.leadingCellNumber(), cluster.subleadingCellNumber()); - storedJClustersParentIndexTable(cluster.clusterId()); + products.storedJClustersTable(products.storedJCollisionsTable.lastIndex(), cluster.id(), cluster.energy(), cluster.coreEnergy(), cluster.rawEnergy(), + cluster.eta(), cluster.phi(), cluster.m02(), cluster.m20(), cluster.nCells(), cluster.time(), cluster.isExotic(), cluster.distanceToBadChannel(), + cluster.nlm(), cluster.definition(), cluster.leadingCellEnergy(), cluster.subleadingCellEnergy(), cluster.leadingCellNumber(), cluster.subleadingCellNumber()); + products.storedJClustersParentIndexTable(cluster.clusterId()); - std::vector clusterStoredJTrackIDs; + std::vector clusterStoredJTrackIDs; for (const auto& clusterTrack : cluster.matchedTracks_as>()) { auto JtrackIndex = trackMapping.find(clusterTrack.globalIndex()); if (JtrackIndex != trackMapping.end()) { clusterStoredJTrackIDs.push_back(JtrackIndex->second); } } - storedJClustersMatchedTracksTable(clusterStoredJTrackIDs); + products.storedJClustersMatchedTracksTable(clusterStoredJTrackIDs); } } if (config.saveD0Table) { int32_t collisionD0Index = -1; for (const auto& D0Collision : D0Collisions) { // should only ever be one - jethfutilities::fillD0CollisionTable(D0Collision, storedD0CollisionsTable, collisionD0Index); - storedD0CollisionIdsTable(storedJCollisionsTable.lastIndex()); + jethfutilities::fillD0CollisionTable(D0Collision, products.storedD0CollisionsTable, collisionD0Index); + products.storedD0CollisionIdsTable(products.storedJCollisionsTable.lastIndex()); } for (const auto& D0 : D0s) { int32_t D0Index = -1; - jethfutilities::fillD0CandidateTable(D0, collisionD0Index, storedD0sTable, storedD0ParsTable, storedD0ParExtrasTable, storedD0SelsTable, storedD0MlsTable, storedD0McsTable, D0Index); + jethfutilities::fillD0CandidateTable(D0, collisionD0Index, products.storedD0sTable, products.storedD0ParsTable, products.storedD0ParExtrasTable, products.storedD0SelsTable, products.storedD0MlsTable, products.storedD0McsTable, D0Index); int32_t prong0Id = -1; int32_t prong1Id = -1; @@ -326,19 +436,19 @@ struct JetDerivedDataWriter { if (JtrackIndex != trackMapping.end()) { prong1Id = JtrackIndex->second; } - storedD0IdsTable(storedJCollisionsTable.lastIndex(), prong0Id, prong1Id); + products.storedD0IdsTable(products.storedJCollisionsTable.lastIndex(), prong0Id, prong1Id); } } if (config.saveLcTable) { int32_t collisionLcIndex = -1; for (const auto& LcCollision : LcCollisions) { // should only ever be one - jethfutilities::fillLcCollisionTable(LcCollision, storedLcCollisionsTable, collisionLcIndex); - storedLcCollisionIdsTable(storedJCollisionsTable.lastIndex()); + jethfutilities::fillLcCollisionTable(LcCollision, products.storedLcCollisionsTable, collisionLcIndex); + products.storedLcCollisionIdsTable(products.storedJCollisionsTable.lastIndex()); } for (const auto& Lc : Lcs) { int32_t LcIndex = -1; - jethfutilities::fillLcCandidateTable(Lc, collisionLcIndex, storedLcsTable, storedLcParsTable, storedLcParExtrasTable, storedLcSelsTable, storedLcMlsTable, storedLcMcsTable, LcIndex); + jethfutilities::fillLcCandidateTable(Lc, collisionLcIndex, products.storedLcsTable, products.storedLcParsTable, products.storedLcParExtrasTable, products.storedLcSelsTable, products.storedLcMlsTable, products.storedLcMcsTable, LcIndex); int32_t prong0Id = -1; int32_t prong1Id = -1; @@ -355,16 +465,39 @@ struct JetDerivedDataWriter { if (JtrackIndex != trackMapping.end()) { prong2Id = JtrackIndex->second; } - storedLcIdsTable(storedJCollisionsTable.lastIndex(), prong0Id, prong1Id, prong2Id); + products.storedLcIdsTable(products.storedJCollisionsTable.lastIndex(), prong0Id, prong1Id, prong2Id); + } + } + if (config.saveDielectronTable) { + int32_t collisionDielectronIndex = -1; + for (const auto& DielectronCollision : DielectronCollisions) { // should only ever be one + jetdqutilities::fillDielectronCollisionTable(DielectronCollision, products.storedDielectronCollisionsTable, collisionDielectronIndex); + products.storedDielectronCollisionIdsTable(products.storedJCollisionsTable.lastIndex()); + } + for (const auto& Dielectron : Dielectrons) { + int32_t DielectronIndex = -1; + jetdqutilities::fillDielectronCandidateTable(Dielectron, collisionDielectronIndex, products.storedDielectronsTable, DielectronIndex); + + int32_t prong0Id = -1; + int32_t prong1Id = -1; + auto JtrackIndex = trackMapping.find(Dielectron.prong0Id()); + if (JtrackIndex != trackMapping.end()) { + prong0Id = JtrackIndex->second; + } + JtrackIndex = trackMapping.find(Dielectron.prong1Id()); + if (JtrackIndex != trackMapping.end()) { + prong1Id = JtrackIndex->second; + } + products.storedDielectronIdsTable(products.storedJCollisionsTable.lastIndex(), prong0Id, prong1Id); } } } } // process switch for output writing must be last // to run after all jet selections - PROCESS_SWITCH(JetDerivedDataWriter, processData, "write out data output tables", false); + PROCESS_SWITCH(JetDerivedDataWriter, processStoreData, "write out data output tables", false); - void processMC(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const&, soa::Join const& tracks, soa::Join const& clusters, soa::Join const& particles, CollisionsD0 const& D0Collisions, CandidatesD0MCD const& D0s, soa::Join const& D0McCollisions, CandidatesD0MCP const& D0Particles, CollisionsLc const& LcCollisions, CandidatesLcMCD const& Lcs, soa::Join const& LcMcCollisions, CandidatesLcMCP const& LcParticles) + void processStoreMC(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const&, soa::Join const& tracks, soa::Join const& clusters, soa::Join const& particles, CollisionsD0 const& D0Collisions, CandidatesD0MCD const& D0s, soa::Join const& D0McCollisions, CandidatesD0MCP const& D0Particles, CollisionsLc const& LcCollisions, CandidatesLcMCD const& Lcs, soa::Join const& LcMcCollisions, CandidatesLcMCP const& LcParticles, CollisionsDielectron const& DielectronCollisions, CandidatesDielectronMCD const& Dielectrons, McCollisionsDielectron const& DielectronMcCollisions, CandidatesDielectronMCP const& DielectronParticles) { std::map bcMapping; std::map paticleMapping; @@ -385,9 +518,9 @@ struct JetDerivedDataWriter { const auto particlesPerMcCollision = particles.sliceBy(ParticlesPerMcCollision, mcCollision.globalIndex()); - storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight()); - storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); - mcCollisionMapping.insert(std::make_pair(mcCollision.globalIndex(), storedJMcCollisionsTable.lastIndex())); + products.storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight()); + products.storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); + mcCollisionMapping.insert(std::make_pair(mcCollision.globalIndex(), products.storedJMcCollisionsTable.lastIndex())); for (auto particle : particlesPerMcCollision) { paticleMapping.insert(std::make_pair(particle.globalIndex(), particleTableIndex)); @@ -395,7 +528,7 @@ struct JetDerivedDataWriter { } for (auto particle : particlesPerMcCollision) { - std::vector mothersId; + std::vector mothersId; if (particle.has_mothers()) { auto mothersIdTemps = particle.mothersIds(); for (auto mothersIdTemp : mothersIdTemps) { @@ -420,26 +553,26 @@ struct JetDerivedDataWriter { i++; } } - storedJMcParticlesTable(storedJMcCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(particle.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(particle.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.phi(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.y(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.e(), precisionMomentumMask), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), mothersId, daughtersId); - storedJParticlesParentIndexTable(particle.mcParticleId()); + products.storedJMcParticlesTable(products.storedJMcCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(particle.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(particle.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.phi(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.y(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.e(), precisionMomentumMask), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), mothersId, daughtersId); + products.storedJParticlesParentIndexTable(particle.mcParticleId()); } if (config.saveD0Table) { const auto d0McCollisionsPerMcCollision = D0McCollisions.sliceBy(D0McCollisionsPerMcCollision, mcCollision.globalIndex()); int32_t mcCollisionD0Index = -1; for (const auto& d0McCollisionPerMcCollision : d0McCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillD0McCollisionTable(d0McCollisionPerMcCollision, storedD0McCollisionsTable, mcCollisionD0Index); - storedD0McCollisionIdsTable(storedJMcCollisionsTable.lastIndex()); + jethfutilities::fillD0McCollisionTable(d0McCollisionPerMcCollision, products.storedD0McCollisionsTable, mcCollisionD0Index); + products.storedD0McCollisionIdsTable(products.storedJMcCollisionsTable.lastIndex()); } for (const auto& D0Particle : D0Particles) { int32_t D0ParticleIndex = -1; - jethfutilities::fillD0CandidateMcTable(D0Particle, mcCollisionD0Index, storedD0ParticlesTable, D0ParticleIndex); - int32_t d0ParticleId = -1; + jethfutilities::fillD0CandidateMcTable(D0Particle, mcCollisionD0Index, products.storedD0ParticlesTable, D0ParticleIndex); + int32_t D0ParticleId = -1; auto JParticleIndex = paticleMapping.find(D0Particle.mcParticleId()); if (JParticleIndex != paticleMapping.end()) { - d0ParticleId = JParticleIndex->second; + D0ParticleId = JParticleIndex->second; } - storedD0ParticleIdsTable(storedJMcCollisionsTable.lastIndex(), d0ParticleId); + products.storedD0ParticleIdsTable(products.storedJMcCollisionsTable.lastIndex(), D0ParticleId); } } @@ -447,18 +580,59 @@ struct JetDerivedDataWriter { const auto lcMcCollisionsPerMcCollision = LcMcCollisions.sliceBy(LcMcCollisionsPerMcCollision, mcCollision.globalIndex()); int32_t mcCollisionLcIndex = -1; for (const auto& lcMcCollisionPerMcCollision : lcMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillLcMcCollisionTable(lcMcCollisionPerMcCollision, storedLcMcCollisionsTable, mcCollisionLcIndex); - storedLcMcCollisionIdsTable(storedJMcCollisionsTable.lastIndex()); + jethfutilities::fillLcMcCollisionTable(lcMcCollisionPerMcCollision, products.storedLcMcCollisionsTable, mcCollisionLcIndex); + products.storedLcMcCollisionIdsTable(products.storedJMcCollisionsTable.lastIndex()); } for (const auto& LcParticle : LcParticles) { int32_t LcParticleIndex = -1; - jethfutilities::fillLcCandidateMcTable(LcParticle, mcCollisionLcIndex, storedLcParticlesTable, LcParticleIndex); + jethfutilities::fillLcCandidateMcTable(LcParticle, mcCollisionLcIndex, products.storedLcParticlesTable, LcParticleIndex); int32_t LcParticleId = -1; auto JParticleIndex = paticleMapping.find(LcParticle.mcParticleId()); if (JParticleIndex != paticleMapping.end()) { LcParticleId = JParticleIndex->second; } - storedLcParticleIdsTable(storedJMcCollisionsTable.lastIndex(), LcParticleId); + products.storedLcParticleIdsTable(products.storedJMcCollisionsTable.lastIndex(), LcParticleId); + } + } + if (config.saveDielectronTable) { + const auto dielectronMcCollisionsPerMcCollision = DielectronMcCollisions.sliceBy(DielectronMcCollisionsPerMcCollision, mcCollision.globalIndex()); + int32_t mcCollisionDielectronIndex = -1; + for (const auto& dielectronMcCollisionPerMcCollision : dielectronMcCollisionsPerMcCollision) { // should only ever be one + jetdqutilities::fillDielectronMcCollisionTable(dielectronMcCollisionPerMcCollision, products.storedDielectronMcCollisionsTable, mcCollisionDielectronIndex); + products.storedDielectronMcCollisionIdsTable(products.storedJMcCollisionsTable.lastIndex()); + } + for (const auto& DielectronParticle : DielectronParticles) { + int32_t DielectronParticleIndex = -1; + jetdqutilities::fillDielectronCandidateMcTable(DielectronParticle, mcCollisionDielectronIndex, products.storedDielectronParticlesTable, DielectronParticleIndex); + int32_t DielectronParticleId = -1; + auto JParticleIndex = paticleMapping.find(DielectronParticle.mcParticleId()); + if (JParticleIndex != paticleMapping.end()) { + DielectronParticleId = JParticleIndex->second; + } + std::vector DielectronMothersId; + int DielectronDaughtersId[2]; + if (DielectronParticle.has_mothers()) { + for (auto const& DielectronMother : DielectronParticle.template mothers_as>()) { + auto JDielectronMotherIndex = paticleMapping.find(DielectronMother.globalIndex()); + if (JDielectronMotherIndex != paticleMapping.end()) { + DielectronMothersId.push_back(JDielectronMotherIndex->second); + } + } + } + auto i = 0; + if (DielectronParticle.has_daughters()) { + for (auto const& DielectronDaughter : DielectronParticle.template daughters_as>()) { + if (i > 1) { + break; + } + auto JDielectronDaughterIndex = paticleMapping.find(DielectronDaughter.globalIndex()); + if (JDielectronDaughterIndex != paticleMapping.end()) { + DielectronDaughtersId[i] = JDielectronDaughterIndex->second; + } + i++; + } + } + products.storedDielectronParticleIdsTable(products.storedJMcCollisionsTable.lastIndex(), DielectronParticleId, DielectronMothersId, DielectronDaughtersId); } } } @@ -480,19 +654,19 @@ struct JetDerivedDataWriter { if (config.saveBCsTable) { auto bc = collision.bc_as>(); if (std::find(bcIndicies.begin(), bcIndicies.end(), bc.globalIndex()) == bcIndicies.end()) { - storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp()); - storedJBCParentIndexTable(bc.bcId()); + products.storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp(), bc.alias_raw(), bc.selection_raw()); + products.storedJBCParentIndexTable(bc.bcId()); bcIndicies.push_back(bc.globalIndex()); - bcMapping.insert(std::make_pair(bc.globalIndex(), storedJBCsTable.lastIndex())); + bcMapping.insert(std::make_pair(bc.globalIndex(), products.storedJBCsTable.lastIndex())); } } - storedJCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multiplicity(), collision.centrality(), collision.eventSel(), collision.alias_raw()); - storedJCollisionsParentIndexTable(collision.collisionId()); + products.storedJCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multiplicity(), collision.centrality(), collision.trackOccupancyInTimeRange(), collision.eventSel(), collision.alias_raw(), collision.triggerSel()); + products.storedJCollisionsParentIndexTable(collision.collisionId()); auto JMcCollisionIndex = mcCollisionMapping.find(mcCollision.globalIndex()); if (JMcCollisionIndex != mcCollisionMapping.end()) { - storedJMcCollisionsLabelTable(JMcCollisionIndex->second); + products.storedJMcCollisionsLabelTable(JMcCollisionIndex->second); } if (config.saveBCsTable) { int32_t storedBCID = -1; @@ -500,51 +674,54 @@ struct JetDerivedDataWriter { if (JBCIndex != bcMapping.end()) { storedBCID = JBCIndex->second; } - storedJCollisionsBunchCrossingIndexTable(storedBCID); + products.storedJCollisionsBunchCrossingIndexTable(storedBCID); + } + if (config.saveClustersTable) { + products.storedJCollisionsEMCalLabelTable(collision.isAmbiguous(), collision.isEmcalReadout()); } - storedJChargedTriggerSelsTable(collision.chargedTriggerSel()); - storedJFullTriggerSelsTable(collision.fullTriggerSel()); - storedJChargedHFTriggerSelsTable(collision.chargedHFTriggerSel()); const auto tracksPerCollision = tracks.sliceBy(TracksPerCollision, collision.globalIndex()); for (const auto& track : tracksPerCollision) { if (config.performTrackSelection && !(track.trackSel() & ~(1 << jetderiveddatautilities::JTrackSel::trackSign))) { // skips tracks that pass no selections. This might cause a problem with tracks matched with clusters. We should generate a track selection purely for cluster matched tracks so that they are kept continue; } - storedJTracksTable(storedJCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(track.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(track.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.phi(), precisionPositionMask), track.trackSel()); - storedJTracksExtraTable(o2::math_utils::detail::truncateFloatFraction(track.dcaXY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigma1Pt(), precisionMomentumMask)); - storedJTracksParentIndexTable(track.trackId()); + if (track.pt() < config.trackPtSelectionMin || std::abs(track.eta()) > config.trackEtaSelectionMax) { + continue; + } + products.storedJTracksTable(products.storedJCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(track.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(track.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.phi(), precisionPositionMask), track.trackSel()); + products.storedJTracksExtraTable(o2::math_utils::detail::truncateFloatFraction(track.dcaX(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaXY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.dcaXYZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigmadcaZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigmadcaXY(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigmadcaXYZ(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(track.sigma1Pt(), precisionMomentumMask)); + products.storedJTracksParentIndexTable(track.trackId()); if (track.has_mcParticle()) { auto JParticleIndex = paticleMapping.find(track.mcParticleId()); if (JParticleIndex != paticleMapping.end()) { - storedJMcTracksLabelTable(JParticleIndex->second); + products.storedJMcTracksLabelTable(JParticleIndex->second); } else { - storedJMcTracksLabelTable(-1); // this can happen because there are some tracks that are reconstucted in a wrong collision, but their original McCollision did not pass the required cuts so that McParticle is not saved. These are very few but we should look into them further and see what to do about them + products.storedJMcTracksLabelTable(-1); // this can happen because there are some tracks that are reconstucted in a wrong collision, but their original McCollision did not pass the required cuts so that McParticle is not saved. These are very few but we should look into them further and see what to do about them } } else { - storedJMcTracksLabelTable(-1); + products.storedJMcTracksLabelTable(-1); } - trackMapping.insert(std::make_pair(track.globalIndex(), storedJTracksTable.lastIndex())); + trackMapping.insert(std::make_pair(track.globalIndex(), products.storedJTracksTable.lastIndex())); } if (config.saveClustersTable) { const auto clustersPerCollision = clusters.sliceBy(ClustersPerCollision, collision.globalIndex()); for (const auto& cluster : clustersPerCollision) { - storedJClustersTable(storedJCollisionsTable.lastIndex(), cluster.id(), cluster.energy(), cluster.coreEnergy(), cluster.rawEnergy(), - cluster.eta(), cluster.phi(), cluster.m02(), cluster.m20(), cluster.nCells(), cluster.time(), cluster.isExotic(), cluster.distanceToBadChannel(), - cluster.nlm(), cluster.definition(), cluster.leadingCellEnergy(), cluster.subleadingCellEnergy(), cluster.leadingCellNumber(), cluster.subleadingCellNumber()); - storedJClustersParentIndexTable(cluster.clusterId()); + products.storedJClustersTable(products.storedJCollisionsTable.lastIndex(), cluster.id(), cluster.energy(), cluster.coreEnergy(), cluster.rawEnergy(), + cluster.eta(), cluster.phi(), cluster.m02(), cluster.m20(), cluster.nCells(), cluster.time(), cluster.isExotic(), cluster.distanceToBadChannel(), + cluster.nlm(), cluster.definition(), cluster.leadingCellEnergy(), cluster.subleadingCellEnergy(), cluster.leadingCellNumber(), cluster.subleadingCellNumber()); + products.storedJClustersParentIndexTable(cluster.clusterId()); - std::vector clusterStoredJTrackIDs; + std::vector clusterStoredJTrackIDs; for (const auto& clusterTrack : cluster.matchedTracks_as>()) { auto JtrackIndex = trackMapping.find(clusterTrack.globalIndex()); if (JtrackIndex != trackMapping.end()) { clusterStoredJTrackIDs.push_back(JtrackIndex->second); } } - storedJClustersMatchedTracksTable(clusterStoredJTrackIDs); + products.storedJClustersMatchedTracksTable(clusterStoredJTrackIDs); - std::vector clusterStoredJParticleIDs; + std::vector clusterStoredJParticleIDs; for (const auto& clusterParticleId : cluster.mcParticleIds()) { auto JParticleIndex = paticleMapping.find(clusterParticleId); if (JParticleIndex != paticleMapping.end()) { @@ -554,7 +731,7 @@ struct JetDerivedDataWriter { std::vector amplitudeA; auto amplitudeASpan = cluster.amplitudeA(); std::copy(amplitudeASpan.begin(), amplitudeASpan.end(), std::back_inserter(amplitudeA)); - storedJMcClustersLabelTable(clusterStoredJParticleIDs, amplitudeA); + products.storedJMcClustersLabelTable(clusterStoredJParticleIDs, amplitudeA); } } @@ -562,14 +739,14 @@ struct JetDerivedDataWriter { const auto d0CollisionsPerCollision = D0Collisions.sliceBy(D0CollisionsPerCollision, collision.globalIndex()); int32_t collisionD0Index = -1; for (const auto& d0CollisionPerCollision : d0CollisionsPerCollision) { // should only ever be one - jethfutilities::fillD0CollisionTable(d0CollisionPerCollision, storedD0CollisionsTable, collisionD0Index); - storedD0CollisionIdsTable(storedJCollisionsTable.lastIndex()); - D0CollisionMapping.insert(std::make_pair(d0CollisionPerCollision.globalIndex(), storedD0CollisionsTable.lastIndex())); + jethfutilities::fillD0CollisionTable(d0CollisionPerCollision, products.storedD0CollisionsTable, collisionD0Index); + products.storedD0CollisionIdsTable(products.storedJCollisionsTable.lastIndex()); + D0CollisionMapping.insert(std::make_pair(d0CollisionPerCollision.globalIndex(), products.storedD0CollisionsTable.lastIndex())); } const auto d0sPerCollision = D0s.sliceBy(D0sPerCollision, collision.globalIndex()); for (const auto& D0 : d0sPerCollision) { int32_t D0Index = -1; - jethfutilities::fillD0CandidateTable(D0, collisionD0Index, storedD0sTable, storedD0ParsTable, storedD0ParExtrasTable, storedD0SelsTable, storedD0MlsTable, storedD0McsTable, D0Index); + jethfutilities::fillD0CandidateTable(D0, collisionD0Index, products.storedD0sTable, products.storedD0ParsTable, products.storedD0ParExtrasTable, products.storedD0SelsTable, products.storedD0MlsTable, products.storedD0McsTable, D0Index); int32_t prong0Id = -1; int32_t prong1Id = -1; @@ -581,23 +758,22 @@ struct JetDerivedDataWriter { if (JtrackIndex != trackMapping.end()) { prong1Id = JtrackIndex->second; } - storedD0IdsTable(storedJCollisionsTable.lastIndex(), prong0Id, prong1Id); + products.storedD0IdsTable(products.storedJCollisionsTable.lastIndex(), prong0Id, prong1Id); } } if (config.saveLcTable) { - const auto lcCollisionsPerCollision = LcCollisions.sliceBy(LcCollisionsPerCollision, collision.globalIndex()); int32_t collisionLcIndex = -1; for (const auto& lcCollisionPerCollision : lcCollisionsPerCollision) { // should only ever be one - jethfutilities::fillLcCollisionTable(lcCollisionPerCollision, storedLcCollisionsTable, collisionLcIndex); - storedLcCollisionIdsTable(storedJCollisionsTable.lastIndex()); - LcCollisionMapping.insert(std::make_pair(lcCollisionPerCollision.globalIndex(), storedLcCollisionsTable.lastIndex())); + jethfutilities::fillLcCollisionTable(lcCollisionPerCollision, products.storedLcCollisionsTable, collisionLcIndex); + products.storedLcCollisionIdsTable(products.storedJCollisionsTable.lastIndex()); + LcCollisionMapping.insert(std::make_pair(lcCollisionPerCollision.globalIndex(), products.storedLcCollisionsTable.lastIndex())); } const auto lcsPerCollision = Lcs.sliceBy(LcsPerCollision, collision.globalIndex()); for (const auto& Lc : lcsPerCollision) { int32_t LcIndex = -1; - jethfutilities::fillLcCandidateTable(Lc, collisionLcIndex, storedLcsTable, storedLcParsTable, storedLcParExtrasTable, storedLcSelsTable, storedLcMlsTable, storedLcMcsTable, LcIndex); + jethfutilities::fillLcCandidateTable(Lc, collisionLcIndex, products.storedLcsTable, products.storedLcParsTable, products.storedLcParExtrasTable, products.storedLcSelsTable, products.storedLcMlsTable, products.storedLcMcsTable, LcIndex); int32_t prong0Id = -1; int32_t prong1Id = -1; @@ -614,7 +790,34 @@ struct JetDerivedDataWriter { if (JtrackIndex != trackMapping.end()) { prong2Id = JtrackIndex->second; } - storedLcIdsTable(storedJCollisionsTable.lastIndex(), prong0Id, prong1Id, prong2Id); + products.storedLcIdsTable(products.storedJCollisionsTable.lastIndex(), prong0Id, prong1Id, prong2Id); + } + } + + if (config.saveDielectronTable) { + const auto dielectronCollisionsPerCollision = DielectronCollisions.sliceBy(DielectronCollisionsPerCollision, collision.globalIndex()); + int32_t collisionDielectronIndex = -1; + for (const auto& dielectronCollisionPerCollision : dielectronCollisionsPerCollision) { // should only ever be one + jetdqutilities::fillDielectronCollisionTable(dielectronCollisionPerCollision, products.storedDielectronCollisionsTable, collisionDielectronIndex); + products.storedDielectronCollisionIdsTable(products.storedJCollisionsTable.lastIndex()); + // D0CollisionMapping.insert(std::make_pair(d0CollisionPerCollision.globalIndex(), products.storedD0CollisionsTable.lastIndex())); // if DielectronMCCollisions are indexed to Dielectron Collisions then this can be added + } + const auto dielectronsPerCollision = Dielectrons.sliceBy(DielectronsPerCollision, collision.globalIndex()); + for (const auto& Dielectron : dielectronsPerCollision) { + int32_t DielectronIndex = -1; + jetdqutilities::fillDielectronCandidateTable(Dielectron, collisionDielectronIndex, products.storedDielectronsTable, DielectronIndex); + + int32_t prong0Id = -1; + int32_t prong1Id = -1; + auto JtrackIndex = trackMapping.find(Dielectron.prong0Id()); + if (JtrackIndex != trackMapping.end()) { + prong0Id = JtrackIndex->second; + } + JtrackIndex = trackMapping.find(Dielectron.prong1Id()); + if (JtrackIndex != trackMapping.end()) { + prong1Id = JtrackIndex->second; + } + products.storedDielectronIdsTable(products.storedJCollisionsTable.lastIndex(), prong0Id, prong1Id); } } } @@ -629,7 +832,7 @@ struct JetDerivedDataWriter { d0CollisionIDs.push_back(d0CollisionIndex->second); } } - storedD0McCollisionsMatchingTable(d0CollisionIDs); + products.storedD0McCollisionsMatchingTable(d0CollisionIDs); } } @@ -643,7 +846,7 @@ struct JetDerivedDataWriter { lcCollisionIDs.push_back(lcCollisionIndex->second); } } - storedLcMcCollisionsMatchingTable(lcCollisionIDs); + products.storedLcMcCollisionsMatchingTable(lcCollisionIDs); } } } @@ -651,9 +854,9 @@ struct JetDerivedDataWriter { } // process switch for output writing must be last // to run after all jet selections - PROCESS_SWITCH(JetDerivedDataWriter, processMC, "write out data output tables for mc", false); + PROCESS_SWITCH(JetDerivedDataWriter, processStoreMC, "write out data output tables for mc", false); - void processMCP(soa::Join const& mcCollisions, soa::Join const& particles, McCollisionsD0 const& D0McCollisions, CandidatesD0MCP const& D0Particles, McCollisionsLc const& LcMcCollisions, CandidatesLcMCP const& LcParticles) + void processStoreMCP(soa::Join const& mcCollisions, soa::Join const& particles, McCollisionsD0 const& D0McCollisions, CandidatesD0MCP const& D0Particles, McCollisionsLc const& LcMcCollisions, CandidatesLcMCP const& LcParticles, McCollisionsDielectron const& DielectronMcCollisions, CandidatesDielectronMCP const& DielectronParticles) { int particleTableIndex = 0; @@ -661,8 +864,8 @@ struct JetDerivedDataWriter { if (McCollisionFlag[mcCollision.globalIndex()]) { // you can also check if any of its detector level counterparts are correct std::map paticleMapping; - storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight()); - storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); + products.storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight()); + products.storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); const auto particlesPerMcCollision = particles.sliceBy(ParticlesPerMcCollision, mcCollision.globalIndex()); @@ -671,12 +874,10 @@ struct JetDerivedDataWriter { particleTableIndex++; } for (auto particle : particlesPerMcCollision) { - - std::vector mothersId; + std::vector mothersId; int daughtersId[2]; if (particle.has_mothers()) { for (auto const& mother : particle.template mothers_as>()) { - auto JMotherIndex = paticleMapping.find(mother.globalIndex()); if (JMotherIndex != paticleMapping.end()) { mothersId.push_back(JMotherIndex->second); @@ -696,44 +897,85 @@ struct JetDerivedDataWriter { i++; } } - storedJMcParticlesTable(storedJMcCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(particle.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(particle.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.phi(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.y(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.e(), precisionMomentumMask), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), mothersId, daughtersId); - storedJParticlesParentIndexTable(particle.mcParticleId()); + products.storedJMcParticlesTable(products.storedJMcCollisionsTable.lastIndex(), o2::math_utils::detail::truncateFloatFraction(particle.pt(), precisionMomentumMask), o2::math_utils::detail::truncateFloatFraction(particle.eta(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.phi(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.y(), precisionPositionMask), o2::math_utils::detail::truncateFloatFraction(particle.e(), precisionMomentumMask), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), mothersId, daughtersId); + products.storedJParticlesParentIndexTable(particle.mcParticleId()); } if (config.saveD0Table) { const auto d0McCollisionsPerMcCollision = D0McCollisions.sliceBy(D0McCollisionsPerMcCollision, mcCollision.globalIndex()); int32_t mcCollisionD0Index = -1; for (const auto& d0McCollisionPerMcCollision : d0McCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillD0McCollisionTable(d0McCollisionPerMcCollision, storedD0McCollisionsTable, mcCollisionD0Index); - storedD0McCollisionIdsTable(storedJMcCollisionsTable.lastIndex()); + jethfutilities::fillD0McCollisionTable(d0McCollisionPerMcCollision, products.storedD0McCollisionsTable, mcCollisionD0Index); + products.storedD0McCollisionIdsTable(products.storedJMcCollisionsTable.lastIndex()); } for (const auto& D0Particle : D0Particles) { int32_t D0ParticleIndex = -1; - jethfutilities::fillD0CandidateMcTable(D0Particle, mcCollisionD0Index, storedD0ParticlesTable, D0ParticleIndex); - int32_t d0ParticleId = -1; + jethfutilities::fillD0CandidateMcTable(D0Particle, mcCollisionD0Index, products.storedD0ParticlesTable, D0ParticleIndex); + int32_t D0ParticleId = -1; auto JParticleIndex = paticleMapping.find(D0Particle.mcParticleId()); if (JParticleIndex != paticleMapping.end()) { - d0ParticleId = JParticleIndex->second; + D0ParticleId = JParticleIndex->second; } - storedD0ParticleIdsTable(storedJMcCollisionsTable.lastIndex(), d0ParticleId); + products.storedD0ParticleIdsTable(products.storedJMcCollisionsTable.lastIndex(), D0ParticleId); } } if (config.saveLcTable) { const auto lcMcCollisionsPerMcCollision = LcMcCollisions.sliceBy(LcMcCollisionsPerMcCollision, mcCollision.globalIndex()); int32_t mcCollisionLcIndex = -1; for (const auto& lcMcCollisionPerMcCollision : lcMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillLcMcCollisionTable(lcMcCollisionPerMcCollision, storedLcMcCollisionsTable, mcCollisionLcIndex); - storedLcMcCollisionIdsTable(storedJMcCollisionsTable.lastIndex()); + jethfutilities::fillLcMcCollisionTable(lcMcCollisionPerMcCollision, products.storedLcMcCollisionsTable, mcCollisionLcIndex); + products.storedLcMcCollisionIdsTable(products.storedJMcCollisionsTable.lastIndex()); } for (const auto& LcParticle : LcParticles) { int32_t LcParticleIndex = -1; - jethfutilities::fillLcCandidateMcTable(LcParticle, mcCollisionLcIndex, storedLcParticlesTable, LcParticleIndex); + jethfutilities::fillLcCandidateMcTable(LcParticle, mcCollisionLcIndex, products.storedLcParticlesTable, LcParticleIndex); int32_t LcParticleId = -1; auto JParticleIndex = paticleMapping.find(LcParticle.mcParticleId()); if (JParticleIndex != paticleMapping.end()) { LcParticleId = JParticleIndex->second; } - storedLcParticleIdsTable(storedJMcCollisionsTable.lastIndex(), LcParticleId); + products.storedLcParticleIdsTable(products.storedJMcCollisionsTable.lastIndex(), LcParticleId); + } + } + if (config.saveDielectronTable) { + const auto dielectronMcCollisionsPerMcCollision = DielectronMcCollisions.sliceBy(DielectronMcCollisionsPerMcCollision, mcCollision.globalIndex()); + int32_t mcCollisionDielectronIndex = -1; + for (const auto& dielectronMcCollisionPerMcCollision : dielectronMcCollisionsPerMcCollision) { // should only ever be one + jetdqutilities::fillDielectronMcCollisionTable(dielectronMcCollisionPerMcCollision, products.storedDielectronMcCollisionsTable, mcCollisionDielectronIndex); + products.storedDielectronMcCollisionIdsTable(products.storedJMcCollisionsTable.lastIndex()); + } + for (const auto& DielectronParticle : DielectronParticles) { + int32_t DielectronParticleIndex = -1; + jetdqutilities::fillDielectronCandidateMcTable(DielectronParticle, mcCollisionDielectronIndex, products.storedDielectronParticlesTable, DielectronParticleIndex); + int32_t DielectronParticleId = -1; + auto JParticleIndex = paticleMapping.find(DielectronParticle.mcParticleId()); + if (JParticleIndex != paticleMapping.end()) { + DielectronParticleId = JParticleIndex->second; + } + std::vector DielectronMothersId; + int DielectronDaughtersId[2]; + if (DielectronParticle.has_mothers()) { + for (auto const& DielectronMother : DielectronParticle.template mothers_as>()) { + auto JDielectronMotherIndex = paticleMapping.find(DielectronMother.globalIndex()); + if (JDielectronMotherIndex != paticleMapping.end()) { + DielectronMothersId.push_back(JDielectronMotherIndex->second); + } + } + } + auto i = 0; + if (DielectronParticle.has_daughters()) { + for (auto const& DielectronDaughter : DielectronParticle.template daughters_as>()) { + if (i > 1) { + break; + } + auto JDielectronDaughterIndex = paticleMapping.find(DielectronDaughter.globalIndex()); + if (JDielectronDaughterIndex != paticleMapping.end()) { + DielectronDaughtersId[i] = JDielectronDaughterIndex->second; + } + i++; + } + } + products.storedDielectronParticleIdsTable(products.storedJMcCollisionsTable.lastIndex(), DielectronParticleId, DielectronMothersId, DielectronDaughtersId); } } } @@ -741,7 +983,7 @@ struct JetDerivedDataWriter { } // process switch for output writing must be last // to run after all jet selections - PROCESS_SWITCH(JetDerivedDataWriter, processMCP, "write out data output tables for mcp", false); + PROCESS_SWITCH(JetDerivedDataWriter, processStoreMCP, "write out data output tables for mcp", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/TableProducer/jetmatchingmc.cxx b/PWGJE/TableProducer/jetmatchingmc.cxx index c582f09004e..5c9e85d3640 100644 --- a/PWGJE/TableProducer/jetmatchingmc.cxx +++ b/PWGJE/TableProducer/jetmatchingmc.cxx @@ -34,7 +34,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -template +template struct JetMatchingMc { Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; @@ -67,7 +67,7 @@ struct JetMatchingMc { void processJets(JetMcCollisions const& mcCollisions, JetCollisionsMCD const& collisions, JetsBase const& jetsBase, JetsTag const& jetsTag, JetTracksMCD const& tracks, - JetClustersMCD const& clusters, + ClustersBase const& clusters, JetParticles const& particles, CandidatesBase const& candidatesBase, CandidatesTag const& candidatesTag) @@ -111,44 +111,58 @@ using ChargedJetMatching = JetMatchingMc; + aod::JMcCollisions, + JetTracks>; using FullJetMatching = JetMatchingMc, soa::Join, aod::FullMCDetectorLevelJetsMatchedToFullMCParticleLevelJets, aod::FullMCParticleLevelJetsMatchedToFullMCDetectorLevelJets, aod::JCollisions, - aod::JMcCollisions>; + aod::JMcCollisions, + JetClustersMCD>; using NeutralJetMatching = JetMatchingMc, soa::Join, aod::NeutralMCDetectorLevelJetsMatchedToNeutralMCParticleLevelJets, aod::NeutralMCParticleLevelJetsMatchedToNeutralMCDetectorLevelJets, aod::JCollisions, - aod::JMcCollisions>; + aod::JMcCollisions, + JetClustersMCD>; using D0ChargedJetMatching = JetMatchingMc, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCParticleLevelJets, aod::D0ChargedMCParticleLevelJetsMatchedToD0ChargedMCDetectorLevelJets, CandidatesD0MCD, - CandidatesD0MCP>; + CandidatesD0MCP, + JetTracks>; using LcChargedJetMatching = JetMatchingMc, soa::Join, aod::LcChargedMCDetectorLevelJetsMatchedToLcChargedMCParticleLevelJets, aod::LcChargedMCParticleLevelJetsMatchedToLcChargedMCDetectorLevelJets, CandidatesLcMCD, - CandidatesLcMCP>; + CandidatesLcMCP, + JetTracks>; /*using BplusChargedJetMatching = JetMatchingMc, soa::Join, aod::BplusChargedMCDetectorLevelJetsMatchedToBplusChargedMCParticleLevelJets, aod::BplusChargedMCParticleLevelJetsMatchedToBplusChargedMCDetectorLevelJets, CandidatesBplusMCD, - CandidatesBplusMCP>;*/ + CandidatesBplusMCP, + JetTracksMCD>>;*/ using V0ChargedJetMatching = JetMatchingMc, soa::Join, aod::V0ChargedMCDetectorLevelJetsMatchedToV0ChargedMCParticleLevelJets, aod::V0ChargedMCParticleLevelJetsMatchedToV0ChargedMCDetectorLevelJets, CandidatesV0MCD, - CandidatesV0MCP>; - + CandidatesV0MCP, + JetTracks>; + +using DielectronChargedJetMatching = JetMatchingMc, + soa::Join, + aod::DielectronChargedMCDetectorLevelJetsMatchedToDielectronChargedMCParticleLevelJets, + aod::DielectronChargedMCParticleLevelJetsMatchedToDielectronChargedMCDetectorLevelJets, + CandidatesDielectronMCD, + CandidatesDielectronMCP, + JetTracks>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::vector tasks; @@ -160,6 +174,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-lc-ch"})); // tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-bplus-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-v0-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-dielectron-ch"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/TableProducer/jetmatchingmcsub.cxx b/PWGJE/TableProducer/jetmatchingmcsub.cxx index 1a04e94282d..81e2b6f41ce 100644 --- a/PWGJE/TableProducer/jetmatchingmcsub.cxx +++ b/PWGJE/TableProducer/jetmatchingmcsub.cxx @@ -114,6 +114,11 @@ using LcChargedJetMatching = JetMatchingMcSub;*/ +using DielectronChargedJetMatching = JetMatchingMcSub, + soa::Join, + aod::DielectronChargedMCDetectorLevelJetsMatchedToDielectronChargedMCDetectorLevelEventWiseSubtractedJets, + aod::DielectronChargedMCDetectorLevelEventWiseSubtractedJetsMatchedToDielectronChargedMCDetectorLevelJets, + CandidatesDielectronMCD>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { @@ -123,6 +128,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-sub-d0-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-sub-lc-ch"})); // tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-sub-bplus-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-sub-dielectron-ch"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/TableProducer/jetmatchingsub.cxx b/PWGJE/TableProducer/jetmatchingsub.cxx index 42ffa581f60..6a8b106d89a 100644 --- a/PWGJE/TableProducer/jetmatchingsub.cxx +++ b/PWGJE/TableProducer/jetmatchingsub.cxx @@ -116,7 +116,12 @@ using LcChargedJetMatching = JetMatchingSub;*/ - +using DielectronChargedJetMatching = JetMatchingSub, + soa::Join, + aod::DielectronChargedJetsMatchedToDielectronChargedEventWiseSubtractedJets, + aod::DielectronChargedEventWiseSubtractedJetsMatchedToDielectronChargedJets, + aod::JTrackDielectronSubs, + CandidatesDielectronData>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::vector tasks; @@ -125,6 +130,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-sub-d0-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-sub-lc-ch"})); // tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-sub-bplus-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-sub-dielectron-ch"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/TableProducer/jettaggerhf.cxx b/PWGJE/TableProducer/jettaggerhf.cxx index 225f7919db6..a034c8ca5c3 100644 --- a/PWGJE/TableProducer/jettaggerhf.cxx +++ b/PWGJE/TableProducer/jettaggerhf.cxx @@ -33,17 +33,31 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -template +template struct JetTaggerHFTask { Produces taggingTableData; Produces taggingTableMCD; + Produces taggingTableMCP; + // configuration topological cut for track and sv + Configurable trackDcaXYMax{"trackDcaXYMax", 1, "minimum DCA xy acceptance for tracks [cm]"}; + Configurable trackDcaZMax{"trackDcaZMax", 2, "minimum DCA z acceptance for tracks [cm]"}; + Configurable prongsigmaLxyMax{"prongsigmaLxyMax", 100, "maximum sigma of decay length of prongs on xy plane"}; + Configurable prongsigmaLxyzMax{"prongsigmaLxyzMax", 100, "maximum sigma of decay length of prongs on xyz plane"}; + Configurable prongIPxyMin{"prongIPxyMin", 0.008, "maximum impact paramter of prongs on xy plane [cm]"}; + Configurable prongIPxyMax{"prongIpxyMax", 1, "minimum impact parmeter of prongs on xy plane [cm]"}; + Configurable prongChi2PCAMin{"prongChi2PCAMin", 4, "minimum Chi2 PCA of decay length of prongs"}; + Configurable prongChi2PCAMax{"prongChi2PCAMax", 100, "maximum Chi2 PCA of decay length of prongs"}; + + // jet flavour definition Configurable maxDeltaR{"maxDeltaR", 0.25, "maximum distance of jet axis from flavour initiating parton"}; Configurable removeGluonShower{"removeGluonShower", true, "find jet origin removed gluon spliting"}; // true:: remove gluon spliting + Configurable searchUpToQuark{"searchUpToQuark", true, "Finding first mother in particles to quark"}; + + // configuration about IP method Configurable useJetProb{"useJetProb", false, "fill table for track counting algorithm"}; Configurable trackProbQA{"trackProbQA", false, "fill track probability histograms separately for geometric positive and negative tracks for QA"}; - Configurable doSV{"doSV", false, "fill table for secondary vertex algorithm"}; Configurable numCount{"numCount", 3, "number of track counting"}; Configurable resoFuncMatching{"resoFuncMatching", 0, "matching parameters of resolution function as MC samble (0: custom, 1: custom & inc, 2: MB, 3: MB & inc, 4: JJ, 5: JJ & inc)"}; Configurable> paramsResoFuncData{"paramsResoFuncData", std::vector{1306800, -0.1049, 0.861425, 13.7547, 0.977967, 8.96823, 0.151595, 6.94499, 0.0250301}, "parameters of gaus(0)+expo(3)+expo(5)+expo(7))"}; @@ -52,15 +66,19 @@ struct JetTaggerHFTask { Configurable> paramsResoFuncBeautyJetMC{"paramsResoFuncBeautyJetMC", std::vector{74901.583, -0.082, 0.874, 10.332, 0.941, 7.352, 0.097, 6.220, 0.022}, "parameters of gaus(0)+expo(3)+expo(5)+expo(7)))"}; Configurable> paramsResoFuncLfJetMC{"paramsResoFuncLfJetMC", std::vector{1539435.343, -0.061, 0.896, 13.272, 1.034, 5.884, 0.004, 7.843, 0.090}, "parameters of gaus(0)+expo(3)+expo(5)+expo(7)))"}; Configurable minSignImpXYSig{"minsIPs", -40.0, "minimum of signed impact parameter significance"}; - Configurable tagPoint{"tagPoint", 2.5, "tagging working point"}; + Configurable tagPointForIP{"tagPointForIP", 2.5, "tagging working point for IP"}; + Configurable minIPCount{"minSipCount", 2, "Select at least N signed impact parameter significance in jets"}; // default 2 + // configuration about SV method + Configurable doSV{"doSV", false, "fill table for secondary vertex algorithm"}; + Configurable useXYZForTagging{"useXYZForTagging", false, "Enable tagging decision using full XYZ DCA for secondary vertex algorithm"}; + Configurable tagPointForSV{"tagPointForSV", 15, "tagging working point for SV"}; + // axis spec ConfigurableAxis binTrackProbability{"binTrackProbability", {100, 0.f, 1.f}, ""}; ConfigurableAxis binJetFlavour{"binJetFlavour", {6, -0.5, 5.5}, ""}; - using JetTagTracksData = soa::Join; - using JetTagTracksMCD = soa::Join; - using OriTracksData = soa::Join; - using OriTracksMCD = soa::Join; + using JetTagTracksData = soa::Join; + using JetTagTracksMCD = soa::Join; std::vector vecParamsData; std::vector vecParamsIncJetMC; @@ -77,6 +95,71 @@ struct JetTaggerHFTask { std::unique_ptr fSignImpXYSigBeautyJetMC = nullptr; std::unique_ptr fSignImpXYSigLfJetMC = nullptr; + template + void calculateJetProbability(int origin, T const& jet, U const& jtracks, std::vector& jetProb, bool const& isMC = true) + { + jetProb.clear(); + jetProb.reserve(maxOrder); + for (int order = 0; order < maxOrder; order++) { + if (!isMC) { + jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigData, jet, jtracks, trackDcaXYMax, trackDcaZMax, order, tagPointForIP, minSignImpXYSig)); + } else { + if (useResoFuncFromIncJet) { + jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigIncJetMC, jet, jtracks, trackDcaXYMax, trackDcaZMax, order, tagPointForIP, minSignImpXYSig)); + } else { + if (origin == JetTaggingSpecies::charm) { + jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigCharmJetMC, jet, jtracks, trackDcaXYMax, trackDcaZMax, order, tagPointForIP, minSignImpXYSig)); + } + if (origin == JetTaggingSpecies::beauty) { + jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigBeautyJetMC, jet, jtracks, trackDcaXYMax, trackDcaZMax, order, tagPointForIP, minSignImpXYSig)); + } + if (origin == JetTaggingSpecies::lightflavour) { + jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigLfJetMC, jet, jtracks, trackDcaXYMax, trackDcaZMax, order, tagPointForIP, minSignImpXYSig)); + } + if (origin != JetTaggingSpecies::charm && origin != JetTaggingSpecies::beauty && origin != JetTaggingSpecies::lightflavour) { + jetProb.push_back(-1); + } + } + } + } + } + + template + void evaluateTrackProbQA(int origin, T const& jet, U const& /*jtracks*/, bool const& isMC = true) + { + for (auto& jtrack : jet.template tracks_as()) { + if (!jettaggingutilities::trackAcceptanceWithDca(jtrack, trackDcaXYMax, trackDcaZMax)) + continue; + auto geoSign = jettaggingutilities::getGeoSign(jet, jtrack); + float probTrack = -1; + if (!isMC) { + probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigData, jtrack, minSignImpXYSig); + if (geoSign > 0) + registry.fill(HIST("h_pos_track_probability"), probTrack); + else + registry.fill(HIST("h_neg_track_probability"), probTrack); + } else { + if (useResoFuncFromIncJet) { + probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigIncJetMC, jtrack, minSignImpXYSig); + } else { + if (origin == JetTaggingSpecies::charm) { + probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigCharmJetMC, jtrack, minSignImpXYSig); + } + if (origin == JetTaggingSpecies::beauty) { + probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigBeautyJetMC, jtrack, minSignImpXYSig); + } + if (origin == JetTaggingSpecies::lightflavour) { + probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigLfJetMC, jtrack, minSignImpXYSig); + } + } + if (geoSign > 0) + registry.fill(HIST("h2_pos_track_probability_flavour"), probTrack, origin); + else + registry.fill(HIST("h2_neg_track_probability_flavour"), probTrack, origin); + } + } + } + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext const&) { @@ -87,14 +170,14 @@ struct JetTaggerHFTask { switch (resoFuncMatch) { case 0: vecParamsData = (std::vector)paramsResoFuncData; - vecParamsIncJetMC = (std::vector)paramsResoFuncIncJetMC; + vecParamsCharmJetMC = (std::vector)paramsResoFuncCharmJetMC; + vecParamsBeautyJetMC = (std::vector)paramsResoFuncBeautyJetMC; + vecParamsLfJetMC = (std::vector)paramsResoFuncLfJetMC; LOG(info) << "defined parameters of resolution function: custom"; break; case 1: vecParamsData = (std::vector)paramsResoFuncData; - vecParamsCharmJetMC = (std::vector)paramsResoFuncCharmJetMC; - vecParamsBeautyJetMC = (std::vector)paramsResoFuncBeautyJetMC; - vecParamsLfJetMC = (std::vector)paramsResoFuncLfJetMC; + vecParamsIncJetMC = (std::vector)paramsResoFuncIncJetMC; useResoFuncFromIncJet = true; LOG(info) << "defined parameters of resolution function: custom & use inclusive distribution"; break; @@ -139,8 +222,14 @@ struct JetTaggerHFTask { if (trackProbQA) { AxisSpec trackProbabilityAxis = {binTrackProbability, "Track proability"}; AxisSpec jetFlavourAxis = {binJetFlavour, "Jet flavour"}; - registry.add("h2_pos_track_probability_flavour", "positive track probability", {HistType::kTH2F, {{trackProbabilityAxis}, {jetFlavourAxis}}}); - registry.add("h2_neg_track_probability_flavour", "negative track probability", {HistType::kTH2F, {{trackProbabilityAxis}, {jetFlavourAxis}}}); + if (doprocessData || doprocessDataWithSV) { + registry.add("h_pos_track_probability", "positive track probability", {HistType::kTH1F, {{trackProbabilityAxis}}}); + registry.add("h_neg_track_probability", "negative track probability", {HistType::kTH1F, {{trackProbabilityAxis}}}); + } + if (doprocessMCD || doprocessMCDWithSV) { + registry.add("h2_pos_track_probability_flavour", "positive track probability", {HistType::kTH2F, {{trackProbabilityAxis}, {jetFlavourAxis}}}); + registry.add("h2_neg_track_probability_flavour", "negative track probability", {HistType::kTH2F, {{trackProbabilityAxis}, {jetFlavourAxis}}}); + } } } @@ -149,112 +238,136 @@ struct JetTaggerHFTask { } PROCESS_SWITCH(JetTaggerHFTask, processDummy, "Dummy process", true); - void processData(JetCollision const& collision, JetTableData const& jets, JetTagTracksData const& jtracks, OriTracksData const& tracks) + void processData(JetCollision const& /*collision*/, JetTableData const& jets, JetTagTracksData const& jtracks) { for (auto& jet : jets) { - int algorithm2 = 0; - int algorithm3 = 0; + bool flagtaggedjetIP = 0; + bool flagtaggedjetSV = 0; if (useJetProb) { - jetProb.clear(); - jetProb.reserve(maxOrder); - for (int order = 0; order < maxOrder; order++) { - jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigData, collision, jet, jtracks, tracks, order, tagPoint, minSignImpXYSig)); + calculateJetProbability(0, jet, jtracks, jetProb, false); + if (trackProbQA) { + evaluateTrackProbQA(0, jet, jtracks, false); } } - // if (doSV) algorithm2 = jettaggingutilities::Algorithm2((mcdjet, tracks); - taggingTableData(0, jetProb, algorithm2, algorithm3); + if (jettaggingutilities::isGreaterThanTaggingPoint(jet, jtracks, trackDcaXYMax, trackDcaZMax, tagPointForIP, minIPCount)) + flagtaggedjetIP = true; + taggingTableData(0, jetProb, flagtaggedjetIP, flagtaggedjetSV); } } PROCESS_SWITCH(JetTaggerHFTask, processData, "Fill tagging decision for data jets", false); - void processMCD(JetCollision const& collision, JetTableMCD const& mcdjets, JetTagTracksMCD const& jtracks, OriTracksMCD const& tracks, JetParticles const& particles) + void processDataWithSV(JetCollision const& /*collision*/, soa::Join const& jets, JetTagTracksData const& jtracks, aod::DataSecondaryVertex3Prongs const& prongs) + { + for (auto& jet : jets) { + bool flagtaggedjetIP = 0; + bool flagtaggedjetSV = 0; + if (useJetProb) { + calculateJetProbability(0, jet, jtracks, jetProb, false); + if (trackProbQA) { + evaluateTrackProbQA(0, jet, jtracks, false); + } + } + if (jettaggingutilities::isGreaterThanTaggingPoint(jet, jtracks, trackDcaXYMax, trackDcaZMax, tagPointForIP, minIPCount)) + flagtaggedjetIP = true; + if (!useXYZForTagging) { + flagtaggedjetSV = jettaggingutilities::isTaggedJetSV(jet, prongs, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, useXYZForTagging, tagPointForSV); + } else { + flagtaggedjetSV = jettaggingutilities::isTaggedJetSV(jet, prongs, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, useXYZForTagging, tagPointForSV); + } + taggingTableData(0, jetProb, flagtaggedjetIP, flagtaggedjetSV); + } + } + PROCESS_SWITCH(JetTaggerHFTask, processDataWithSV, "Fill tagging decision for data jets", false); + + void processMCD(JetCollision const& /*collision*/, JetTableMCD const& mcdjets, JetTagTracksMCD const& jtracks, JetParticles const& particles) { for (auto& mcdjet : mcdjets) { + bool flagtaggedjetIP = 0; + bool flagtaggedjetSV = 0; typename JetTagTracksMCD::iterator hftrack; int origin = 0; if (removeGluonShower) - origin = jettaggingutilities::mcdJetFromHFShower(mcdjet, jtracks, particles, maxDeltaR); + origin = jettaggingutilities::mcdJetFromHFShower(mcdjet, jtracks, particles, maxDeltaR, searchUpToQuark); else - origin = jettaggingutilities::jetTrackFromHFShower(mcdjet, jtracks, particles, hftrack); - int algorithm2 = 0; - int algorithm3 = 0; + origin = jettaggingutilities::jetTrackFromHFShower(mcdjet, jtracks, particles, hftrack, searchUpToQuark); if (useJetProb) { - jetProb.clear(); - jetProb.reserve(maxOrder); - for (int order = 0; order < maxOrder; order++) { - if (useResoFuncFromIncJet) { - jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigIncJetMC, collision, mcdjet, jtracks, tracks, order, tagPoint, minSignImpXYSig)); - } else { - if (origin == JetTaggingSpecies::charm) { - jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigCharmJetMC, collision, mcdjet, jtracks, tracks, order, tagPoint, minSignImpXYSig)); - } - if (origin == JetTaggingSpecies::beauty) { - jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigBeautyJetMC, collision, mcdjet, jtracks, tracks, order, tagPoint, minSignImpXYSig)); - } - if (origin == JetTaggingSpecies::lightflavour) { - jetProb.push_back(jettaggingutilities::getJetProbability(fSignImpXYSigLfJetMC, collision, mcdjet, jtracks, tracks, order, tagPoint, minSignImpXYSig)); - } - } - } + calculateJetProbability(origin, mcdjet, jtracks, jetProb); if (trackProbQA) { - for (auto& jtrack : mcdjet.template tracks_as()) { - auto track = jtrack.template track_as(); - auto geoSign = jettaggingutilities::getGeoSign(collision, mcdjet, track); - float probTrack = -1; - if (useResoFuncFromIncJet) { - probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigIncJetMC, track, minSignImpXYSig); - } else { - if (origin == JetTaggingSpecies::charm) { - probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigCharmJetMC, track, minSignImpXYSig); - } - if (origin == JetTaggingSpecies::beauty) { - probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigBeautyJetMC, track, minSignImpXYSig); - } - if (origin == JetTaggingSpecies::lightflavour) { - probTrack = jettaggingutilities::getTrackProbability(fSignImpXYSigLfJetMC, track, minSignImpXYSig); - } - } - if (geoSign > 0) { - registry.fill(HIST("h2_pos_track_probability_flavour"), probTrack, origin); - } else { - registry.fill(HIST("h2_neg_track_probability_flavour"), probTrack, origin); - } - } + evaluateTrackProbQA(origin, mcdjet, jtracks); } } - // if (doSV) algorithm2 = jettaggingutilities::Algorithm2((mcdjet, tracks); - taggingTableMCD(origin, jetProb, algorithm2, algorithm3); + if (jettaggingutilities::isGreaterThanTaggingPoint(mcdjet, jtracks, trackDcaXYMax, trackDcaZMax, tagPointForIP, minIPCount)) + flagtaggedjetIP = true; + taggingTableMCD(origin, jetProb, flagtaggedjetIP, flagtaggedjetSV); } } PROCESS_SWITCH(JetTaggerHFTask, processMCD, "Fill tagging decision for mcd jets", false); - void processTraining(JetCollision const& /*collision*/, JetTableMCD const& /*mcdjets*/, JetTagTracksMCD const& /*tracks*/) + void processMCDWithSV(JetCollision const& /*collision*/, soa::Join const& mcdjets, JetTagTracksMCD const& jtracks, aod::MCDSecondaryVertex3Prongs const& prongs, JetParticles const& particles) { - // To create table for ML + for (auto& mcdjet : mcdjets) { + bool flagtaggedjetIP = 0; + bool flagtaggedjetSV = 0; + typename JetTagTracksMCD::iterator hftrack; + int origin = 0; + if (removeGluonShower) + origin = jettaggingutilities::mcdJetFromHFShower(mcdjet, jtracks, particles, maxDeltaR, searchUpToQuark); + else + origin = jettaggingutilities::jetTrackFromHFShower(mcdjet, jtracks, particles, hftrack, searchUpToQuark); + if (useJetProb) { + calculateJetProbability(origin, mcdjet, jtracks, jetProb); + if (trackProbQA) { + evaluateTrackProbQA(origin, mcdjet, jtracks); + } + } + if (jettaggingutilities::isGreaterThanTaggingPoint(mcdjet, jtracks, trackDcaXYMax, trackDcaZMax, tagPointForIP, minIPCount)) + flagtaggedjetIP = true; + if (!useXYZForTagging) { + flagtaggedjetSV = jettaggingutilities::isTaggedJetSV(mcdjet, prongs, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, useXYZForTagging, tagPointForSV); + } else { + flagtaggedjetSV = jettaggingutilities::isTaggedJetSV(mcdjet, prongs, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, useXYZForTagging, tagPointForSV); + } + taggingTableMCD(origin, jetProb, flagtaggedjetIP, flagtaggedjetSV); + } } - PROCESS_SWITCH(JetTaggerHFTask, processTraining, "Fill tagging decision for mcd jets", false); -}; - -struct JetTaggerHFExtTask { + PROCESS_SWITCH(JetTaggerHFTask, processMCDWithSV, "Fill tagging decision for mcd jets with sv", false); - Produces jTracksTagTable; - - void init(InitContext const&) + void processMCP(JetMcCollision const& /*collision*/, JetTableMCP const& mcpjets, JetParticles const& particles) { + for (auto& mcpjet : mcpjets) { + bool flagtaggedjetIP = 0; + bool flagtaggedjetSV = 0; + typename JetParticles::iterator hfparticle; + int origin = 0; + // TODO + if (removeGluonShower) { + if (jettaggingutilities::mcpJetFromHFShower(mcpjet, particles, maxDeltaR, searchUpToQuark)) + origin = jettaggingutilities::mcpJetFromHFShower(mcpjet, particles, maxDeltaR, searchUpToQuark); + else + origin = 0; + } else { + if (jettaggingutilities::jetParticleFromHFShower(mcpjet, particles, hfparticle, searchUpToQuark)) + origin = jettaggingutilities::jetParticleFromHFShower(mcpjet, particles, hfparticle, searchUpToQuark); + else + origin = 0; + } + jetProb.clear(); + jetProb.reserve(maxOrder); + jetProb.push_back(-1); + taggingTableMCP(origin, jetProb, flagtaggedjetIP, flagtaggedjetSV); + } } + PROCESS_SWITCH(JetTaggerHFTask, processMCP, "Fill tagging decision for mcp jets with sv", false); - void processTracks(soa::Join::iterator const& track) + void processTraining(JetCollision const& /*collision*/, JetTableMCD const& /*mcdjets*/, JetTagTracksMCD const& /*tracks*/) { - float sigmaDcaXYZ2 = 0; - float dcaXYZ = getDcaXYZ(track, &sigmaDcaXYZ2); - - jTracksTagTable(dcaXYZ, sigmaDcaXYZ2); + // To create table for ML } - PROCESS_SWITCH(JetTaggerHFExtTask, processTracks, "produces derived track table for tagging", true); + PROCESS_SWITCH(JetTaggerHFTask, processTraining, "Fill tagging decision for mcd jets", false); }; -using JetTaggerChargedJets = JetTaggerHFTask, soa::Join, aod::ChargedJetTags, aod::ChargedMCDetectorLevelJetTags>; -using JetTaggerFullJets = JetTaggerHFTask, soa::Join, aod::FullJetTags, aod::FullMCDetectorLevelJetTags>; +using JetTaggerChargedJets = JetTaggerHFTask, soa::Join, soa::Join, aod::ChargedJetTags, aod::ChargedMCDetectorLevelJetTags, aod::ChargedMCParticleLevelJetTags>; +using JetTaggerFullJets = JetTaggerHFTask, soa::Join, soa::Join, aod::FullJetTags, aod::FullMCDetectorLevelJetTags, aod::FullMCParticleLevelJetTags>; // using JetTaggerNeutralJets = JetTaggerHFTask,soa::Join, aod::NeutralJetTags, aod::NeutralMCDetectorLevelJetTags>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) @@ -262,10 +375,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) std::vector tasks; - tasks.emplace_back( - adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, TaskName{"jet-taggerhf-extension"})); - tasks.emplace_back( adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-taggerhf-charged"})); diff --git a/PWGJE/TableProducer/luminositycalculator.cxx b/PWGJE/TableProducer/luminositycalculator.cxx new file mode 100644 index 00000000000..c818ad6b3b2 --- /dev/null +++ b/PWGJE/TableProducer/luminositycalculator.cxx @@ -0,0 +1,112 @@ +// Copyright 2019-2020 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. + +/// \file luminositycalculator.cxx +/// \brief Task to calculate luminosity of measured data. The luminosity per TVX trigger can be obtained from the eventselectiontask (at the time of writing the variable csTVX) +/// +/// \author Nima Zardoshti + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" + +#include "PWGJE/DataModel/JetReducedData.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct LuminosityCalculator { + + HistogramRegistry registry; + void init(InitContext&) + { + + std::vector histLabels = {"BC", "BC+TVX", "BC+TVX+NoTFB", "BC+TVX+NoTFB+NoITSROFB", "Coll", "Coll+TVX", "Coll+TVX+VtxZ+Sel8", "Coll+TVX+VtxZ+Sel8Full", "Coll+TVX+VtxZ+Sel8FullPbPb", "Coll+TVX+VtxZ+SelMC", "Coll+TVX+VtxZ+SelMCFull", "Coll+TVX+VtxZ+SelMCFullPbPb", "Coll+TVX+VtxZ+SelUnanchoredMC", "Coll+TVX+VtxZ+SelTVX", "Coll+TVX+VtxZ+Sel7", "Coll+TVX+VtxZ+Sel7KINT7"}; + registry.add("counter", "BCs and Collisions", HistType::kTH1D, {{static_cast(histLabels.size()), -0.5, static_cast(histLabels.size()) - 0.5}}); + auto counter = registry.get(HIST("counter")); + for (std::vector::size_type iCounter = 0; iCounter < histLabels.size(); iCounter++) { + counter->GetXaxis()->SetBinLabel(iCounter + 1, histLabels[iCounter].data()); + } + } + + void processCalculateLuminosity(aod::StoredBCCounts const& bcCounts, aod::StoredCollisionCounts const& collisionCounts) + { + int readBC = 0; + int readBCWithTVXCounter = 0; + int readBCWithTVXAndNoTFBCounter = 0; + int readBCWithTVXAndNoTFBAndNoITSROFB = 0; + + for (const auto& bcCount : bcCounts) { + readBC += bcCount.readCounts().front(); + readBCWithTVXCounter += bcCount.readCountsWithTVX().front(); + readBCWithTVXAndNoTFBCounter += bcCount.readCountsWithTVXAndNoTFB().front(); + readBCWithTVXAndNoTFBAndNoITSROFB += bcCount.readCountsWithTVXAndNoTFBAndNoITSROFB().front(); + } + + int readCollision = 0; + int readCollisionWithTVXCounter = 0; + int readCollisionWithTVXAndZVertexAndSel8Counter = 0; + int readCollisionWithTVXAndZVertexAndSel8FullCounter = 0; + int readCollisionWithTVXAndZVertexAndSel8FullPbPbCounter = 0; + int readCollisionWithTVXAndZVertexAndSelMCCounter = 0; + int readCollisionWithTVXAndZVertexAndSelMCFullCounter = 0; + int readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounter = 0; + int readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounter = 0; + int readCollisionWithTVXAndZVertexAndSelTVXCounter = 0; + int readCollisionWithTVXAndZVertexAndSel7Counter = 0; + int readCollisionWithTVXAndZVertexAndSel7KINT7Counter = 0; + + for (const auto& collisionCount : collisionCounts) { + readCollision += collisionCount.readCounts().front(); + readCollisionWithTVXCounter += collisionCount.readCountsWithTVX().front(); + readCollisionWithTVXAndZVertexAndSel8Counter += collisionCount.readCountsWithTVXAndZVertexAndSel8().front(); + readCollisionWithTVXAndZVertexAndSel8FullCounter += collisionCount.readCountsWithTVXAndZVertexAndSel8Full().front(); + readCollisionWithTVXAndZVertexAndSel8FullPbPbCounter += collisionCount.readCountsWithTVXAndZVertexAndSel8FullPbPb().front(); + readCollisionWithTVXAndZVertexAndSelMCCounter += collisionCount.readCountsWithTVXAndZVertexAndSelMC().front(); + readCollisionWithTVXAndZVertexAndSelMCFullCounter += collisionCount.readCountsWithTVXAndZVertexAndSelMCFull().front(); + readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounter += collisionCount.readCountsWithTVXAndZVertexAndSelMCFullPbPb().front(); + readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounter += collisionCount.readCountsWithTVXAndZVertexAndSelUnanchoredMC().front(); + readCollisionWithTVXAndZVertexAndSelTVXCounter += collisionCount.readCountsWithTVXAndZVertexAndSelTVX().front(); + readCollisionWithTVXAndZVertexAndSel7Counter += collisionCount.readCountsWithTVXAndZVertexAndSel7().front(); + readCollisionWithTVXAndZVertexAndSel7KINT7Counter += collisionCount.readCountsWithTVXAndZVertexAndSel7KINT7().front(); + } + + registry.get(HIST("counter"))->SetBinContent(1, registry.get(HIST("counter"))->GetBinContent(1) + readBC); + registry.get(HIST("counter"))->SetBinContent(2, registry.get(HIST("counter"))->GetBinContent(2) + readBCWithTVXCounter); + registry.get(HIST("counter"))->SetBinContent(3, registry.get(HIST("counter"))->GetBinContent(3) + readBCWithTVXAndNoTFBCounter); + registry.get(HIST("counter"))->SetBinContent(4, registry.get(HIST("counter"))->GetBinContent(4) + readBCWithTVXAndNoTFBAndNoITSROFB); + registry.get(HIST("counter"))->SetBinContent(5, registry.get(HIST("counter"))->GetBinContent(5) + readCollision); + registry.get(HIST("counter"))->SetBinContent(6, registry.get(HIST("counter"))->GetBinContent(6) + readCollisionWithTVXCounter); + registry.get(HIST("counter"))->SetBinContent(7, registry.get(HIST("counter"))->GetBinContent(7) + readCollisionWithTVXAndZVertexAndSel8Counter); + registry.get(HIST("counter"))->SetBinContent(8, registry.get(HIST("counter"))->GetBinContent(8) + readCollisionWithTVXAndZVertexAndSel8FullCounter); + registry.get(HIST("counter"))->SetBinContent(9, registry.get(HIST("counter"))->GetBinContent(9) + readCollisionWithTVXAndZVertexAndSel8FullPbPbCounter); + registry.get(HIST("counter"))->SetBinContent(10, registry.get(HIST("counter"))->GetBinContent(10) + readCollisionWithTVXAndZVertexAndSelMCCounter); + registry.get(HIST("counter"))->SetBinContent(11, registry.get(HIST("counter"))->GetBinContent(11) + readCollisionWithTVXAndZVertexAndSelMCFullCounter); + registry.get(HIST("counter"))->SetBinContent(12, registry.get(HIST("counter"))->GetBinContent(12) + readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounter); + registry.get(HIST("counter"))->SetBinContent(13, registry.get(HIST("counter"))->GetBinContent(13) + readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounter); + registry.get(HIST("counter"))->SetBinContent(14, registry.get(HIST("counter"))->GetBinContent(14) + readCollisionWithTVXAndZVertexAndSelTVXCounter); + registry.get(HIST("counter"))->SetBinContent(15, registry.get(HIST("counter"))->GetBinContent(15) + readCollisionWithTVXAndZVertexAndSel7Counter); + registry.get(HIST("counter"))->SetBinContent(16, registry.get(HIST("counter"))->GetBinContent(16) + readCollisionWithTVXAndZVertexAndSel7KINT7Counter); + } + PROCESS_SWITCH(LuminosityCalculator, processCalculateLuminosity, "calculate ingredients for luminosity and fill a histogram", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-luminosity-calculator"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/luminosityproducer.cxx b/PWGJE/TableProducer/luminosityproducer.cxx new file mode 100644 index 00000000000..45592ba5d87 --- /dev/null +++ b/PWGJE/TableProducer/luminosityproducer.cxx @@ -0,0 +1,228 @@ +// Copyright 2019-2020 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. + +/// \file luminosityproducer.cxx +/// \brief Task to produce tables needed for normalisation and luminosity calculation +/// +/// \author Nima Zardoshti + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/runDataProcessing.h" + +#include "PWGJE/DataModel/JetReducedData.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct LuminosityProducer { + + Produces storedBCCountsTable; + Produces storedCollisionCountsTable; + + Configurable vertexZCutForCounting{"vertexZCutForCounting", 10.0, "choose z-vertex cut for collision counter"}; + + void init(InitContext&) + { + } + + void processStoreBCCounting(aod::JBCs const& bcs, aod::BCCounts const& bcCounts) + { + int readBCCounter = 0; + int readBCWithTVXCounter = 0; + int readBCWithTVXAndNoTFBCounter = 0; + int readBCWithTVXAndNoTFBAndNoITSROFBCounter = 0; + for (const auto& bc : bcs) { + readBCCounter++; + if (bc.selection_bit(aod::evsel::EventSelectionFlags::kIsTriggerTVX)) { + readBCWithTVXCounter++; + if (bc.selection_bit(aod::evsel::EventSelectionFlags::kNoTimeFrameBorder)) { + readBCWithTVXAndNoTFBCounter++; + if (bc.selection_bit(aod::evsel::EventSelectionFlags::kNoITSROFrameBorder)) { + readBCWithTVXAndNoTFBAndNoITSROFBCounter++; + } + } + } + } + std::vector previousReadCounts; + std::vector previousReadCountsWithTVX; + std::vector previousReadCountsWithTVXAndNoTFB; + std::vector previousReadCountsWithTVXAndNoTFBAndNoITSROFB; + int iPreviousDataFrame = 0; + for (const auto& bcCount : bcCounts) { + auto readBCCounterSpan = bcCount.readCounts(); + auto readBCWithTVXCounterSpan = bcCount.readCountsWithTVX(); + auto readBCWithTVXAndNoTFBCounterSpan = bcCount.readCountsWithTVXAndNoTFB(); + auto readBCWithTVXAndNoTFBAndNoITSROFBCounterSpan = bcCount.readCountsWithTVXAndNoTFBAndNoITSROFB(); + if (iPreviousDataFrame == 0) { + std::copy(readBCCounterSpan.begin(), readBCCounterSpan.end(), std::back_inserter(previousReadCounts)); + std::copy(readBCWithTVXCounterSpan.begin(), readBCWithTVXCounterSpan.end(), std::back_inserter(previousReadCountsWithTVX)); + std::copy(readBCWithTVXAndNoTFBCounterSpan.begin(), readBCWithTVXAndNoTFBCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndNoTFB)); + std::copy(readBCWithTVXAndNoTFBAndNoITSROFBCounterSpan.begin(), readBCWithTVXAndNoTFBAndNoITSROFBCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndNoTFBAndNoITSROFB)); + } else { + for (unsigned int i = 0; i < previousReadCounts.size(); i++) { // in principle we only care about the first element, but might be interesting information to keep + previousReadCounts[i] += readBCCounterSpan[i]; + previousReadCountsWithTVX[i] += readBCWithTVXCounterSpan[i]; + previousReadCountsWithTVXAndNoTFB[i] += readBCWithTVXAndNoTFBCounterSpan[i]; + previousReadCountsWithTVXAndNoTFBAndNoITSROFB[i] += readBCWithTVXAndNoTFBAndNoITSROFBCounterSpan[i]; + } + } + iPreviousDataFrame++; + } + previousReadCounts.push_back(readBCCounter); + previousReadCountsWithTVX.push_back(readBCWithTVXCounter); + previousReadCountsWithTVXAndNoTFB.push_back(readBCWithTVXAndNoTFBCounter); + previousReadCountsWithTVXAndNoTFBAndNoITSROFB.push_back(readBCWithTVXAndNoTFBAndNoITSROFBCounter); + storedBCCountsTable(previousReadCounts, previousReadCountsWithTVX, previousReadCountsWithTVXAndNoTFB, previousReadCountsWithTVXAndNoTFBAndNoITSROFB); + } + PROCESS_SWITCH(LuminosityProducer, processStoreBCCounting, "write out bc counting output table", true); + + void processStoreCollisionCounting(aod::JCollisions const& collisions, aod::CollisionCounts const& collisionCounts) + { + int readCollisionCounter = 0; + int readCollisionWithTVXCounter = 0; + int readCollisionWithTVXAndZVertexAndSel8Counter = 0; + int readCollisionWithTVXAndZVertexAndSel8FullCounter = 0; + int readCollisionWithTVXAndZVertexAndSel8FullPbPbCounter = 0; + int readCollisionWithTVXAndZVertexAndSelMCCounter = 0; + int readCollisionWithTVXAndZVertexAndSelMCFullCounter = 0; + int readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounter = 0; + int readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounter = 0; + int readCollisionWithTVXAndZVertexAndSelTVXCounter = 0; // redundant but we keep it + int readCollisionWithTVXAndZVertexAndSel7Counter = 0; + int readCollisionWithTVXAndZVertexAndSel7KINT7Counter = 0; + for (const auto& collision : collisions) { + readCollisionCounter++; + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::selTVX)) { // asuumes all selections include the TVX trigger + readCollisionWithTVXCounter++; + if (std::abs(collision.posZ()) > vertexZCutForCounting) { + continue; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel8)) { + readCollisionWithTVXAndZVertexAndSel8Counter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel8Full)) { + readCollisionWithTVXAndZVertexAndSel8FullCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel8FullPbPb)) { + readCollisionWithTVXAndZVertexAndSel8FullPbPbCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::selMC)) { + readCollisionWithTVXAndZVertexAndSelMCCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::selMCFull)) { + readCollisionWithTVXAndZVertexAndSelMCFullCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::selMCFullPbPb)) { + readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::selUnanchoredMC)) { + readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::selTVX)) { + readCollisionWithTVXAndZVertexAndSelTVXCounter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel7)) { + readCollisionWithTVXAndZVertexAndSel7Counter++; + } + if (jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel7KINT7)) { + readCollisionWithTVXAndZVertexAndSel7KINT7Counter++; + } + } + } + std::vector previousReadCounts; + std::vector previousReadCountsWithTVX; + std::vector previousReadCountsWithTVXAndZVertexAndSel8; + std::vector previousReadCountsWithTVXAndZVertexAndSel8Full; + std::vector previousReadCountsWithTVXAndZVertexAndSel8FullPbPb; + std::vector previousReadCountsWithTVXAndZVertexAndSelMC; + std::vector previousReadCountsWithTVXAndZVertexAndSelMCFull; + std::vector previousReadCountsWithTVXAndZVertexAndSelMCFullPbPb; + std::vector previousReadCountsWithTVXAndZVertexAndSelUnanchoredMC; + std::vector previousReadCountsWithTVXAndZVertexAndSelTVX; + std::vector previousReadCountsWithTVXAndZVertexAndSel7; + std::vector previousReadCountsWithTVXAndZVertexAndSel7KINT7; + + int iPreviousDataFrame = 0; + for (const auto& collisionCount : collisionCounts) { + auto readCollisionCounterSpan = collisionCount.readCounts(); + auto readCollisionWithTVXCounterSpan = collisionCount.readCountsWithTVX(); + auto readCollisionWithTVXAndZVertexAndSel8CounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSel8(); + auto readCollisionWithTVXAndZVertexAndSel8FullCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSel8Full(); + auto readCollisionWithTVXAndZVertexAndSel8FullPbPbCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSel8FullPbPb(); + auto readCollisionWithTVXAndZVertexAndSelMCCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSelMC(); + auto readCollisionWithTVXAndZVertexAndSelMCFullCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSelMCFull(); + auto readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSelMCFullPbPb(); + auto readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSelUnanchoredMC(); + auto readCollisionWithTVXAndZVertexAndSelTVXCounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSelTVX(); + auto readCollisionWithTVXAndZVertexAndSel7CounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSel7(); + auto readCollisionWithTVXAndZVertexAndSel7KINT7CounterSpan = collisionCount.readCountsWithTVXAndZVertexAndSel7KINT7(); + + if (iPreviousDataFrame == 0) { + std::copy(readCollisionCounterSpan.begin(), readCollisionCounterSpan.end(), std::back_inserter(previousReadCounts)); + std::copy(readCollisionWithTVXCounterSpan.begin(), readCollisionWithTVXCounterSpan.end(), std::back_inserter(previousReadCountsWithTVX)); + std::copy(readCollisionWithTVXAndZVertexAndSel8CounterSpan.begin(), readCollisionWithTVXAndZVertexAndSel8CounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSel8)); + std::copy(readCollisionWithTVXAndZVertexAndSel8FullCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSel8FullCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSel8Full)); + std::copy(readCollisionWithTVXAndZVertexAndSel8FullPbPbCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSel8FullPbPbCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSel8FullPbPb)); + std::copy(readCollisionWithTVXAndZVertexAndSelMCCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSelMCCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSelMC)); + std::copy(readCollisionWithTVXAndZVertexAndSelMCFullCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSelMCFullCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSelMCFull)); + std::copy(readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSelMCFullPbPb)); + std::copy(readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSelUnanchoredMC)); + std::copy(readCollisionWithTVXAndZVertexAndSelTVXCounterSpan.begin(), readCollisionWithTVXAndZVertexAndSelTVXCounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSelTVX)); + std::copy(readCollisionWithTVXAndZVertexAndSel7CounterSpan.begin(), readCollisionWithTVXAndZVertexAndSel7CounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSel7)); + std::copy(readCollisionWithTVXAndZVertexAndSel7KINT7CounterSpan.begin(), readCollisionWithTVXAndZVertexAndSel7KINT7CounterSpan.end(), std::back_inserter(previousReadCountsWithTVXAndZVertexAndSel7KINT7)); + + } else { + for (unsigned int i = 0; i < previousReadCounts.size(); i++) { // in principle we only care about the first element, but might be interesting information to keep + previousReadCounts[i] += readCollisionCounterSpan[i]; + previousReadCountsWithTVX[i] += readCollisionWithTVXCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSel8[i] += readCollisionWithTVXAndZVertexAndSel8CounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSel8Full[i] += readCollisionWithTVXAndZVertexAndSel8FullCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSel8FullPbPb[i] += readCollisionWithTVXAndZVertexAndSel8FullPbPbCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSelMC[i] += readCollisionWithTVXAndZVertexAndSelMCCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSelMCFull[i] += readCollisionWithTVXAndZVertexAndSelMCFullCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSelMCFullPbPb[i] += readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSelUnanchoredMC[i] += readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSelTVX[i] += readCollisionWithTVXAndZVertexAndSelTVXCounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSel7[i] += readCollisionWithTVXAndZVertexAndSel7CounterSpan[i]; + previousReadCountsWithTVXAndZVertexAndSel7KINT7[i] += readCollisionWithTVXAndZVertexAndSel7KINT7CounterSpan[i]; + } + } + iPreviousDataFrame++; + } + previousReadCounts.push_back(readCollisionCounter); + previousReadCountsWithTVX.push_back(readCollisionWithTVXCounter); + previousReadCountsWithTVXAndZVertexAndSel8.push_back(readCollisionWithTVXAndZVertexAndSel8Counter); + previousReadCountsWithTVXAndZVertexAndSel8Full.push_back(readCollisionWithTVXAndZVertexAndSel8FullCounter); + previousReadCountsWithTVXAndZVertexAndSel8FullPbPb.push_back(readCollisionWithTVXAndZVertexAndSel8FullPbPbCounter); + previousReadCountsWithTVXAndZVertexAndSelMC.push_back(readCollisionWithTVXAndZVertexAndSelMCCounter); + previousReadCountsWithTVXAndZVertexAndSelMCFull.push_back(readCollisionWithTVXAndZVertexAndSelMCFullCounter); + previousReadCountsWithTVXAndZVertexAndSelMCFullPbPb.push_back(readCollisionWithTVXAndZVertexAndSelMCFullPbPbCounter); + previousReadCountsWithTVXAndZVertexAndSelUnanchoredMC.push_back(readCollisionWithTVXAndZVertexAndSelUnanchoredMCCounter); + previousReadCountsWithTVXAndZVertexAndSelTVX.push_back(readCollisionWithTVXAndZVertexAndSelTVXCounter); + previousReadCountsWithTVXAndZVertexAndSel7.push_back(readCollisionWithTVXAndZVertexAndSel7Counter); + previousReadCountsWithTVXAndZVertexAndSel7KINT7.push_back(readCollisionWithTVXAndZVertexAndSel7KINT7Counter); + + storedCollisionCountsTable(previousReadCounts, previousReadCountsWithTVX, previousReadCountsWithTVXAndZVertexAndSel8, previousReadCountsWithTVXAndZVertexAndSel8Full, previousReadCountsWithTVXAndZVertexAndSel8FullPbPb, previousReadCountsWithTVXAndZVertexAndSelMC, previousReadCountsWithTVXAndZVertexAndSelMCFull, previousReadCountsWithTVXAndZVertexAndSelMCFullPbPb, previousReadCountsWithTVXAndZVertexAndSelUnanchoredMC, previousReadCountsWithTVXAndZVertexAndSelTVX, previousReadCountsWithTVXAndZVertexAndSel7, previousReadCountsWithTVXAndZVertexAndSel7KINT7); + } + PROCESS_SWITCH(LuminosityProducer, processStoreCollisionCounting, "write out collision counting output table", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-luminosity-producer"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index 2e1adf810de..7a5be53476e 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -34,6 +34,7 @@ struct RhoEstimatorTask { Produces rhoD0Table; Produces rhoLcTable; Produces rhoBplusTable; + Produces rhoDielectronTable; Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; Configurable trackPtMax{"trackPtMax", 1000.0, "maximum track pT"}; @@ -41,6 +42,7 @@ struct RhoEstimatorTask { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; + Configurable trackingEfficiency{"trackingEfficiency", 1.0, "tracking efficiency applied to jet finding"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable bkgjetR{"bkgjetR", 0.2, "jet resolution parameter for determining background density"}; @@ -72,9 +74,9 @@ struct RhoEstimatorTask { void processChargedCollisions(JetCollision const& collision, soa::Filtered const& tracks) { inputParticles.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, trackingEfficiency); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, doSparse); - rhoChargedTable(collision.globalIndex(), rho, rhoM); + rhoChargedTable(rho, rhoM); } PROCESS_SWITCH(RhoEstimatorTask, processChargedCollisions, "Fill rho tables for collisions using charged tracks", true); @@ -83,10 +85,10 @@ struct RhoEstimatorTask { inputParticles.clear(); for (auto& candidate : candidates) { inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, std::optional{candidate}); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency, std::optional{candidate}); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, doSparse); - rhoD0Table(candidate.globalIndex(), rho, rhoM); + rhoD0Table(rho, rhoM); } } PROCESS_SWITCH(RhoEstimatorTask, processD0Collisions, "Fill rho tables for collisions with D0 candidates", false); @@ -96,10 +98,10 @@ struct RhoEstimatorTask { inputParticles.clear(); for (auto& candidate : candidates) { inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, std::optional{candidate}); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency, std::optional{candidate}); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, doSparse); - rhoLcTable(candidate.globalIndex(), rho, rhoM); + rhoLcTable(rho, rhoM); } } PROCESS_SWITCH(RhoEstimatorTask, processLcCollisions, "Fill rho tables for collisions with Lc candidates", false); @@ -109,13 +111,26 @@ struct RhoEstimatorTask { inputParticles.clear(); for (auto& candidate : candidates) { inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, std::optional{candidate}); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency, std::optional{candidate}); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, doSparse); - rhoBplusTable(candidate.globalIndex(), rho, rhoM); + rhoBplusTable(rho, rhoM); } } PROCESS_SWITCH(RhoEstimatorTask, processBplusCollisions, "Fill rho tables for collisions with Bplus candidates", false); + + void processDielectronCollisions(JetCollision const&, soa::Filtered const& tracks, CandidatesDielectronData const& candidates) + { + inputParticles.clear(); + for (auto& candidate : candidates) { + inputParticles.clear(); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, trackingEfficiency, std::optional{candidate}); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, doSparse); + rhoDielectronTable(rho, rhoM); + } + } + PROCESS_SWITCH(RhoEstimatorTask, processDielectronCollisions, "Fill rho tables for collisions with Dielectron candidates", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"estimator-rho"})}; } diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index 87ffc344003..c772bd51b51 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -56,11 +56,14 @@ struct SecondaryVertexReconstruction { Produces sv2prongTableMCD; Produces sv2prongIndicesTableMCD; + Configurable magneticField{"magneticField", 20.0f, "magnetic field in kG"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxRsv{"maxRsv", 999., "max. radius of the reconstruced SV"}; + Configurable maxZsv{"maxZsv", 999., "max. Z coordinates of the reconstruced SV"}; Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable ptMinTrack{"ptMinTrack", -1., "min. track pT"}; @@ -93,6 +96,7 @@ struct SecondaryVertexReconstruction { registry.add("hFeNProngs", "n-prong Energy fraction carried by the SV from the jet;#it{f}_{E};nProngs;entries", {HistType::kTH2F, {{100, 0., 1.0}, nProngsBins}}); registry.add("hDcaXYNProngs", "DCAxy of n-prong candidate daughters;#it{p}_{T} (GeV/#it{c});#it{d}_{xy} (#mum);nProngs;entries", {HistType::kTH3F, {{100, 0., 20.}, {200, -500., 500.}, nProngsBins}}); registry.add("hDcaZNProngs", "DCAz of n-prong candidate daughters;#it{p}_{T} (GeV/#it{c});#it{d}_{z} (#mum);nProngs;entries", {HistType::kTH3F, {{100, 0., 20.}, {200, -500., 500.}, nProngsBins}}); + registry.add("hDispersion", "Vertex dispersion;#sigma_{vtx};nProngs;entries", {HistType::kTH2F, {{200, 0., 1.0}, nProngsBins}}); } df2.setPropagateToPCA(propagateToPCA); @@ -125,7 +129,7 @@ struct SecondaryVertexReconstruction { using JetTracksMCDwPIs = soa::Filtered>; using OriginalTracks = soa::Join; - template + template void runCreatorNProng(AnyCollision const& collision, AnyJet const& analysisJet, AnyParticles const& listoftracks, @@ -147,10 +151,14 @@ struct SecondaryVertexReconstruction { trackParVars[inum] = getTrackParCov(prong); } - auto bc = collision.template bc_as(); - if (runNumber != bc.runNumber()) { - initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); - bz = o2::base::Propagator::Instance()->getNominalBz(); + if constexpr (externalMagneticField) { + bz = magneticField; + } else { + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); + bz = o2::base::Propagator::Instance()->getNominalBz(); + } } // Use a different fitter depending on the number of prongs @@ -158,15 +166,36 @@ struct SecondaryVertexReconstruction { // Reconstruct the secondary vertex int processResult = 0; - std::apply([&df, &processResult](const auto&... elems) { processResult = df.process(elems...); }, trackParVars); + try { + std::apply([&df, &processResult](const auto&... elems) { processResult = df.process(elems...); }, trackParVars); + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + return; + } if (processResult == 0) { return; } - const auto& secondaryVertex = df.getPCACandidate(); + const auto& secondaryVertex = df.getPCACandidatePos(); + if (std::sqrt(secondaryVertex[0] * secondaryVertex[0] + secondaryVertex[1] * secondaryVertex[1]) > maxRsv || std::abs(secondaryVertex[2]) > maxZsv) { + return; + } + + float dispersion = 0.; + for (unsigned int inum = 0; inum < numProngs; ++inum) { + o2::dataformats::VertexBase sv(o2::math_utils::Point3D{secondaryVertex[0], secondaryVertex[1], secondaryVertex[2]}, std::array{0}); + o2::dataformats::DCA dcaSV; + auto& prong = df.getTrack(inum); + prong.propagateToDCA(sv, bz, &dcaSV); + dispersion += (dcaSV.getY() * dcaSV.getY() + dcaSV.getZ() * dcaSV.getZ()); + } + dispersion = std::sqrt(dispersion / numProngs); + auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrixFlat(); + registry.fill(HIST("hDispersion"), dispersion, numProngs); + // get track impact parameters // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); @@ -198,41 +227,41 @@ struct SecondaryVertexReconstruction { double massSV = RecoDecay::m(std::move(arrayMomenta), massArray); // fill candidate table rows - if (doprocessData3Prongs && numProngs == 3) { + if ((doprocessData3Prongs || doprocessData3ProngsExternalMagneticField) && numProngs == 3) { sv3prongTableData(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], arrayMomenta[0][0] + arrayMomenta[1][0] + arrayMomenta[2][0], arrayMomenta[0][1] + arrayMomenta[1][1] + arrayMomenta[2][1], arrayMomenta[0][2] + arrayMomenta[1][2] + arrayMomenta[2][2], - energySV, massSV, chi2PCA, errorDecayLength, errorDecayLengthXY); + energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv3prongTableData.lastIndex()); - } else if (doprocessData2Prongs && numProngs == 2) { + } else if ((doprocessData2Prongs || doprocessData2ProngsExternalMagneticField) && numProngs == 2) { sv2prongTableData(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], arrayMomenta[0][0] + arrayMomenta[1][0], arrayMomenta[0][1] + arrayMomenta[1][1], arrayMomenta[0][2] + arrayMomenta[1][2], - energySV, massSV, chi2PCA, errorDecayLength, errorDecayLengthXY); + energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv2prongTableData.lastIndex()); - } else if (doprocessMCD3Prongs && numProngs == 3) { + } else if ((doprocessMCD3Prongs || doprocessMCD3ProngsExternalMagneticField) && numProngs == 3) { sv3prongTableMCD(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], arrayMomenta[0][0] + arrayMomenta[1][0] + arrayMomenta[2][0], arrayMomenta[0][1] + arrayMomenta[1][1] + arrayMomenta[2][1], arrayMomenta[0][2] + arrayMomenta[1][2] + arrayMomenta[2][2], - energySV, massSV, chi2PCA, errorDecayLength, errorDecayLengthXY); + energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv3prongTableMCD.lastIndex()); - } else if (doprocessMCD2Prongs && numProngs == 2) { + } else if ((doprocessMCD2Prongs || doprocessMCD2ProngsExternalMagneticField) && numProngs == 2) { sv2prongTableMCD(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], arrayMomenta[0][0] + arrayMomenta[1][0], arrayMomenta[0][1] + arrayMomenta[1][1], arrayMomenta[0][2] + arrayMomenta[1][2], - energySV, massSV, chi2PCA, errorDecayLength, errorDecayLengthXY); + energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv2prongTableMCD.lastIndex()); } else { LOG(error) << "No process specified\n"; @@ -261,7 +290,7 @@ struct SecondaryVertexReconstruction { } currentCombination.push_back(iprong); - runCreatorNProng( + runCreatorNProng( collision, analysisJet, listoftracks, svIndices, df, iprong + 1, currentCombination); currentCombination.pop_back(); } @@ -276,41 +305,81 @@ struct SecondaryVertexReconstruction { { for (auto& jet : jets) { std::vector svIndices; - runCreatorNProng<3>(collision.template collision_as(), jet, jtracks, svIndices, df3); + runCreatorNProng<3, false>(collision.template collision_as(), jet, jtracks, svIndices, df3); sv3prongIndicesTableData(svIndices); } } PROCESS_SWITCH(SecondaryVertexReconstruction, processData3Prongs, "Reconstruct the data 3-prong secondary vertex", false); + void processData3ProngsExternalMagneticField(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& jets, JetTracksData const& jtracks, OriginalTracks const& /*tracks*/) + { + for (auto& jet : jets) { + std::vector svIndices; + runCreatorNProng<3, true>(collision.template collision_as(), jet, jtracks, svIndices, df3); + sv3prongIndicesTableData(svIndices); + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processData3ProngsExternalMagneticField, "Reconstruct the data 3-prong secondary vertex with external magnetic field", false); + void processData2Prongs(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& jets, JetTracksData const& jtracks, OriginalTracks const& /*tracks*/, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { for (auto& jet : jets) { std::vector svIndices; - runCreatorNProng<2>(collision.template collision_as(), jet, jtracks, svIndices, df2); + runCreatorNProng<2, false>(collision.template collision_as(), jet, jtracks, svIndices, df2); sv2prongIndicesTableData(svIndices); } } PROCESS_SWITCH(SecondaryVertexReconstruction, processData2Prongs, "Reconstruct the data 2-prong secondary vertex", false); + void processData2ProngsExternalMagneticField(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& jets, JetTracksData const& jtracks, OriginalTracks const& /*tracks*/) + { + for (auto& jet : jets) { + std::vector svIndices; + runCreatorNProng<2, true>(collision.template collision_as(), jet, jtracks, svIndices, df2); + sv2prongIndicesTableData(svIndices); + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processData2ProngsExternalMagneticField, "Reconstruct the data 2-prong secondary vertex with extrernal magnetic field", false); + void processMCD3Prongs(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& jtracks, OriginalTracks const& /*tracks*/, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { for (auto& jet : mcdjets) { std::vector svIndices; - runCreatorNProng<3>(collision.template collision_as(), jet, jtracks, svIndices, df3); + runCreatorNProng<3, false>(collision.template collision_as(), jet, jtracks, svIndices, df3); sv3prongIndicesTableMCD(svIndices); } } PROCESS_SWITCH(SecondaryVertexReconstruction, processMCD3Prongs, "Reconstruct the MCD 3-prong secondary vertex", false); + void processMCD3ProngsExternalMagneticField(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& jtracks, OriginalTracks const& /*tracks*/) + { + for (auto& jet : mcdjets) { + std::vector svIndices; + runCreatorNProng<3, true>(collision.template collision_as(), jet, jtracks, svIndices, df3); + sv3prongIndicesTableMCD(svIndices); + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processMCD3ProngsExternalMagneticField, "Reconstruct the MCD 3-prong secondary vertex with external magnetic field", false); + void processMCD2Prongs(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& jtracks, OriginalTracks const& /*tracks*/, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { for (auto& jet : mcdjets) { std::vector svIndices; - runCreatorNProng<2>(collision.template collision_as(), jet, jtracks, svIndices, df2); + runCreatorNProng<2, false>(collision.template collision_as(), jet, jtracks, svIndices, df2); sv2prongIndicesTableMCD(svIndices); } } PROCESS_SWITCH(SecondaryVertexReconstruction, processMCD2Prongs, "Reconstruct the MCD 2-prong secondary vertex", false); + + void processMCD2ProngsExternalMagneticField(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& jtracks, OriginalTracks const& /*tracks*/) + { + for (auto& jet : mcdjets) { + std::vector svIndices; + runCreatorNProng<2, true>(collision.template collision_as(), jet, jtracks, svIndices, df2); + sv2prongIndicesTableMCD(svIndices); + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processMCD2ProngsExternalMagneticField, "Reconstruct the MCD 2-prong secondary vertex with external magnetic field", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 050decc2ba7..6ed5d05d548 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -68,6 +68,10 @@ if(FastJet_FOUND) SOURCES v0jetspectra.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-v0qa + SOURCES v0qa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-finder-charged-qa SOURCES jetfinderQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -132,6 +136,10 @@ if(FastJet_FOUND) SOURCES phiInJets.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(nuclei-in-jets + SOURCES nucleiInJets.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-taggerhf-qa SOURCES jettaggerhfQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -156,5 +164,21 @@ if(FastJet_FOUND) SOURCES bjetTreeCreator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(stat-prompt-photon + SOURCES statPromptPhoton.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(full-jet-spectra-pp + SOURCES fulljetspectrapp.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(gamma-jet-tree-producer + SOURCES gammajettreeproducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(bjet-tagging-ml + SOURCES bjetTaggingML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) endif() diff --git a/PWGJE/Tasks/ChJetTriggerQATask.cxx b/PWGJE/Tasks/ChJetTriggerQATask.cxx index c575736a8dd..8a7d95e7907 100644 --- a/PWGJE/Tasks/ChJetTriggerQATask.cxx +++ b/PWGJE/Tasks/ChJetTriggerQATask.cxx @@ -44,6 +44,11 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using filteredColl = soa::Filtered>::iterator; +using filteredJTracks = soa::Filtered>; +using filteredJets = soa::Filtered>; +using joinedTracks = soa::Join; + // What this task should do // Event by event fill // 1) pT spectrum of tracks in TPC volume @@ -57,15 +62,10 @@ using namespace o2::framework::expressions; struct ChJetTriggerQATask { Configurable evSel{"evSel", "sel8", "choose event selection"}; - Configurable cfgVertexCut{"cfgVertexCut", 10.0, - "Accepted z-vertex range"}; - Configurable cfgTPCVolume{"cfgTPCVolume", 0.9, - "Full eta range"}; // eta range of TPC - Configurable cfgJetR{"cfgJetR", 0.4, - "jet resolution parameter"}; // jet cone radius - Configurable cfgJetPtMin{ - "cfgJetPtMin", 0.15, - "minimum jet pT constituent cut"}; // minimum jet constituent pT + Configurable cfgVertexCut{"cfgVertexCut", 10.0, "Accepted z-vertex range"}; + Configurable cfgTPCVolume{"cfgTPCVolume", 0.9, "Full eta range"}; // eta range of TPC + Configurable cfgJetR{"cfgJetR", 0.4, "jet resolution parameter"}; // jet cone radius + Configurable cfgJetPtMin{"cfgJetPtMin", 0.15, "minimum jet pT constituent cut"}; // minimum jet constituent pT Configurable cfgTrackPhiMinCut{"cfgTrackPhiMinCut", -999, "track min phi cut"}; Configurable cfgTrackPhiMaxCut{"cfgTrackPhiMaxCut", 999, "track max phi cut"}; @@ -75,16 +75,21 @@ struct ChJetTriggerQATask { Configurable bHighPtTrigger{"bHighPtTrigger", false, "charged jet high pT trigger selection"}; Configurable bTrackLowPtTrigger{"bTrackLowPtTrigger", false, "track low pT trigger selection"}; Configurable bTrackHighPtTrigger{"bTrackHighPtTrigger", false, "track high pT trigger selection"}; - Configurable bAddSupplementHistosToOutput{"bAddAdditionalHistosToOutput", false, "add supplementary histos to the output"}; + Configurable phiAngleRestriction{"phiAngleRestriction", 0.3, "angle to restrict track phi for plotting tpc momentum"}; + + ConfigurableAxis dcaXY_Binning{"dcaXY_Binning", {100, -5., 5.}, ""}; + ConfigurableAxis dcaZ_Binning{"dcaZ_Binning", {100, -5., 5.}, ""}; + float fiducialVolume; // 0.9 - jetR HistogramRegistry spectra; int eventSelection = -1; int trackSelection = -1; - void init(o2::framework::InitContext&) + + void init(InitContext&) { fiducialVolume = static_cast(cfgTPCVolume) - static_cast(cfgJetR); eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(evSel)); @@ -103,6 +108,19 @@ struct ChJetTriggerQATask { spectra.add("ptetaLeadingJetFullVol", "pT vs eta leading jet", {HistType::kTH2F, {{100, 0., +100.}, {80, -1., 1.}}}); spectra.add("ptphiLeadingJetFullVol", "pT vs phi leading jet", {HistType::kTH2F, {{100, 0., +100.}, {60, 0, TMath::TwoPi()}}}); + spectra.add("globalP_tpcglobalPDiff_withoutcuts", "difference of global and TPC inner momentum vs global momentum without any selection applied", {HistType::kTH2F, {{100, 0., +100.}, {200, -100., +100.}}}); + spectra.add("globalP_tpcglobalPDiff", "difference of global and TPC inner momentum vs global momentum with selection applied", {HistType::kTH2F, {{100, 0., +100.}, {200, -100., +100.}}}); + spectra.add("global1overP_tpcglobalPDiff", "difference of global and TPC inner momentum vs global momentum with selection applied", {HistType::kTH2F, {{100, 0., +100.}, {500, -8., +8.}}}); + + spectra.add("globalP_tpcglobalPDiff_withoutcuts_phirestrict", "difference of global and TPC inner momentum vs global momentum without any selection applied in a restricted phi", {HistType::kTH2F, {{100, 0., +100.}, {200, -100., +100.}}}); + spectra.add("globalP_tpcglobalPDiff_phirestrict", "difference of global and TPC inner momentum vs global momentum with selection applied restricted phi", {HistType::kTH2F, {{100, 0., +100.}, {200, -100., +100.}}}); + spectra.add("global1overP_tpcglobalPDiff_phirestrict", "difference of 1/p global and TPC inner momentum vs global momentum with selection applied restricted phi", {HistType::kTH2F, {{100, 0., +100.}, {500, -8., +8.}}}); + + spectra.add("DCAx_track_Phi_pT", "track DCAx vs phi & pT of global tracks w. nITSClusters #ge 4", kTH3F, {dcaXY_Binning, {60, 0., TMath::TwoPi()}, {100, 0., 100.}}); + spectra.add("DCAy_track_Phi_pT", "track DCAy vs phi & pT of global tracks w. nITSClusters #ge 4", kTH3F, {dcaXY_Binning, {60, 0., TMath::TwoPi()}, {100, 0., 100.}}); + spectra.add("DCAz_track_Phi_pT", "track DCAz vs phi & pT of global tracks w. nITSClusters #ge 4", kTH3F, {dcaZ_Binning, {60, 0., TMath::TwoPi()}, {100, 0., 100.}}); + spectra.add("nITSClusters_TrackPt", "Number of ITS hits vs phi & pT of global tracks", kTH3F, {{7, 1., 8.}, {60, 0., TMath::TwoPi()}, {100, 0., 100.}}); + // Supplementary plots if (bAddSupplementHistosToOutput) { spectra.add("ptJetChInclFullVol", "inclusive charged jet pT in full volume", {HistType::kTH1F, {{200, 0., +200.}}}); @@ -127,14 +145,9 @@ struct ChJetTriggerQATask { Filter trackFilter = (nabs(aod::jtrack::eta) < static_cast(cfgTPCVolume)) && (aod::jtrack::phi > static_cast(cfgTrackPhiMinCut)) && (aod::jtrack::phi < static_cast(cfgTrackPhiMaxCut)) && (aod::jtrack::pt > static_cast(cfgJetPtMin)); // declare filters on jets - Filter jetRadiusSelection = (o2::aod::jet::r == nround(cfgJetR.node() * 100.0f)); - - using filteredJets = o2::soa::Filtered; + Filter jetRadiusSelection = (aod::jet::r == nround(cfgJetR.node() * 100.0f)); - void - process(soa::Filtered>::iterator const& collision, - soa::Filtered const& tracks, o2::soa::Filtered> const& jets) + void process(filteredColl const& collision, filteredJTracks const& tracks, filteredJets const& jets, joinedTracks const&) { if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { @@ -145,8 +158,8 @@ struct ChJetTriggerQATask { return; } - bool bLowPtJet = (bLowPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)); - bool bHighPtJet = (bHighPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)); + bool bLowPtJet = (bLowPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::jetChLowPt)); + bool bHighPtJet = (bHighPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::jetChHighPt)); bool bLowPtTrack = (bTrackLowPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::trackLowPt)); bool bHighPtTrack = (bTrackHighPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::trackHighPt)); bool bMinimumBias = ((!bLowPtTrigger) && (!bHighPtTrigger) && (!bTrackLowPtTrigger) && (!bTrackHighPtTrigger)); @@ -169,36 +182,64 @@ struct ChJetTriggerQATask { spectra.fill(HIST("vertexZ"), collision.posZ()); // Inclusive Track Cross TPC Rows - for (auto& trk : tracks) { // loop over filtered tracks in full TPC volume having pT > 100 MeV + for (auto const& track : tracks) { // loop over filtered tracks in full TPC volume having pT > 100 MeV + + auto const& originalTrack = track.track_as(); + + spectra.fill(HIST("globalP_tpcglobalPDiff_withoutcuts"), track.p(), track.p() - originalTrack.tpcInnerParam()); - if (!jetderiveddatautilities::selectTrack(trk, trackSelection)) { + if (TMath::Abs(track.phi() - TMath::Pi()) < phiAngleRestriction) { + spectra.fill(HIST("globalP_tpcglobalPDiff_withoutcuts_phirestrict"), track.p(), track.p() - originalTrack.tpcInnerParam()); + } + + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } + if (originalTrack.itsNCls() >= 4) { // correspond to number of track hits in ITS layers + spectra.fill(HIST("DCAx_track_Phi_pT"), track.dcaX(), track.phi(), track.pt()); + spectra.fill(HIST("DCAy_track_Phi_pT"), track.dcaY(), track.phi(), track.pt()); + spectra.fill(HIST("DCAz_track_Phi_pT"), track.dcaZ(), track.phi(), track.pt()); + } + + spectra.fill(HIST("nITSClusters_TrackPt"), originalTrack.itsNCls(), track.phi(), track.pt()); + + spectra.fill(HIST("globalP_tpcglobalPDiff"), track.p(), track.p() - originalTrack.tpcInnerParam()); + if (track.p() > 0 && originalTrack.tpcInnerParam() > 0) { + spectra.fill(HIST("global1overP_tpcglobalPDiff"), track.p(), 1. / track.p() - 1. / originalTrack.tpcInnerParam()); + } + if (TMath::Abs(track.phi() - TMath::Pi()) < phiAngleRestriction) { + spectra.fill(HIST("globalP_tpcglobalPDiff_phirestrict"), track.p(), track.p() - originalTrack.tpcInnerParam()); + + if (track.p() > 0 && originalTrack.tpcInnerParam() > 0) { + spectra.fill(HIST("global1overP_tpcglobalPDiff_phirestrict"), track.p(), 1. / track.p() - 1. / originalTrack.tpcInnerParam()); + } + } + spectra.fill( - HIST("ptphiTrackInclGood"), trk.pt(), - trk.phi()); // Inclusive Track pT vs phi spectrum in TPC volume + HIST("ptphiTrackInclGood"), track.pt(), + track.phi()); // Inclusive Track pT vs phi spectrum in TPC volume spectra.fill( - HIST("ptetaTrackInclGood"), trk.pt(), - trk.eta()); // Inclusive Track pT vs eta spectrum in TPC volume + HIST("ptetaTrackInclGood"), track.pt(), + track.eta()); // Inclusive Track pT vs eta spectrum in TPC volume if (bAddSupplementHistosToOutput) { spectra.fill( - HIST("phietaTrackAllInclGood"), trk.eta(), - trk.phi()); // Inclusive Track pT vs eta spectrum in TPC volume + HIST("phietaTrackAllInclGood"), track.eta(), + track.phi()); // Inclusive Track pT vs eta spectrum in TPC volume - if (trk.pt() > 5.0) { + if (track.pt() > 5.0) { spectra.fill( - HIST("phietaTrackHighPtInclGood"), trk.eta(), - trk.phi()); // Inclusive Track pT vs eta spectrum in TPC volume + HIST("phietaTrackHighPtInclGood"), track.eta(), + track.phi()); // Inclusive Track pT vs eta spectrum in TPC volume } } - if (trk.pt() > + if (track.pt() > leadingTrackPt) { // Find leading track pT in full TPC volume - leadingTrackPt = trk.pt(); - leadingTrackEta = trk.eta(); - leadingTrackPhi = trk.phi(); + leadingTrackPt = track.pt(); + leadingTrackEta = track.eta(); + leadingTrackPhi = track.phi(); } } diff --git a/PWGJE/Tasks/FullJetTriggerQATask.cxx b/PWGJE/Tasks/FullJetTriggerQATask.cxx index 9dad8d604b5..6b47c2b5c7e 100644 --- a/PWGJE/Tasks/FullJetTriggerQATask.cxx +++ b/PWGJE/Tasks/FullJetTriggerQATask.cxx @@ -688,55 +688,51 @@ struct JetTriggerQA { setTrigger(TriggerType_t::kEmcalMB); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::fullHigh)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::jetFullHighPt)) { fillEventSelectionCounter(3); setTrigger(TriggerType_t::kEmcalJetFull); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::fullLow)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::jetFullLowPt)) { fillEventSelectionCounter(4); setTrigger(TriggerType_t::kEmcalJetFullLow); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::neutralHigh)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::jetNeutralHighPt)) { fillEventSelectionCounter(5); setTrigger(TriggerType_t::kEmcalJetNeutral); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::neutralLow)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::jetNeutralLowPt)) { fillEventSelectionCounter(6); setTrigger(TriggerType_t::kEmcalJetNeutralLow); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::neutralLow)) { - fillEventSelectionCounter(6); - setTrigger(TriggerType_t::kEmcalJetNeutralLow); - } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryHighEMCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryHighPtEMCAL)) { fillEventSelectionCounter(7); setTrigger(TriggerType_t::kEmcalGammaVeryHigh); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryHighDCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryHighPtDCAL)) { fillEventSelectionCounter(8); setTrigger(TriggerType_t::kDcalGammaVeryHigh); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaHighEMCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaHighPtEMCAL)) { fillEventSelectionCounter(9); setTrigger(TriggerType_t::kEmcalGammaHigh); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaHighDCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaHighPtDCAL)) { fillEventSelectionCounter(10); setTrigger(TriggerType_t::kDcalGammaHigh); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaLowEMCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaLowPtEMCAL)) { fillEventSelectionCounter(11); setTrigger(TriggerType_t::kEmcalGammaLow); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaLowDCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaLowPtDCAL)) { fillEventSelectionCounter(12); setTrigger(TriggerType_t::kDcalGammaLow); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryLowEMCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryLowPtEMCAL)) { fillEventSelectionCounter(13); setTrigger(TriggerType_t::kEmcalGammaVeryLow); } - if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryLowDCAL)) { + if (jetderiveddatautilities::selectFullTrigger(collision, jetderiveddatautilities::JTrigSelFull::gammaVeryLowPtDCAL)) { fillEventSelectionCounter(14); setTrigger(TriggerType_t::kDcalGammaVeryLow); } diff --git a/PWGJE/Tasks/PhotonIsolationQA.cxx b/PWGJE/Tasks/PhotonIsolationQA.cxx index 5ad4b5ce554..e25d9e11094 100644 --- a/PWGJE/Tasks/PhotonIsolationQA.cxx +++ b/PWGJE/Tasks/PhotonIsolationQA.cxx @@ -77,7 +77,6 @@ struct PhotonIsolationQA { Configurable minNCells{"minNCelss", 2, "Minimal amount of cells per cluster"}; Configurable maxNLM{"maxNLM", 2, "Maximal amount of local maxima per cluster"}; Configurable ExoticContribution{"ExoticContribution", false, "Exotic cluster in the data"}; - Configurable TrackMatchingRadius{"TrackMatchingRadius", 0.05, "maximum radius between track and cluster in eta phi plane"}; Configurable minDPhi{"minDPhi", 0.01, "Minimum dPhi between track and cluster"}; Filter PosZFilter = nabs(aod::collision::posZ) < maxPosZ; @@ -104,7 +103,7 @@ struct PhotonIsolationQA { const o2Axis Phi_Axis{100, 1, 6, "#phi"}; const o2Axis Eta_Axis{100, -0.9, 0.9, "#eta"}; const o2Axis Energy_Axis{100, 0, 100, "E (GeV/c)"}; - const o2Axis NCells_Axis{30, 0, 30, "N Cells"}; + const o2Axis NCells_Axis{50, 0, 50, "N Cells"}; const o2Axis Pt_Axis{100, 0, 100, "P_{T} (GeV/c)"}; const o2Axis P_Axis{100, 0, 100, "P (GeV/c)"}; const o2Axis RatioP_Axis{50, 0, 10, "E/P"}; @@ -112,6 +111,8 @@ struct PhotonIsolationQA { const o2Axis PtIso_Axis{100, -10, 15, "P_{T, Iso} (GeV/c)"}; const o2Axis Rho_Axis{100, 0, 100, "#rho (#frac{GeV/c}{A})"}; const o2Axis ABCD_Axis{5, 0, 5, "ABCD"}; + const o2Axis NLM_Axis{3, 0, 3, "NLM"}; + const o2Axis Fraction_Axis{50, 0, 2}; Data_Info.add("hPosZ", "Z Position of collision", o2HistType::kTH1F, {PosZ_Axis}); Data_Info.add("hNumClusters", "Number of cluster per collision", o2HistType::kTH1F, {Num_Cluster_Axis}); @@ -119,6 +120,7 @@ struct PhotonIsolationQA { Data_Info.add("hEnergy", "Energy of the cluster", o2HistType::kTH1F, {Energy_Axis}); Data_Info.add("hEnergy_ShowerShapeLong", "Energy vs Shower shape long axis", o2HistType::kTH2F, {{Energy_Axis}, {Shower_Shape_Long_Axis}}); Data_Info.add("hEnergy_ShowerShapeShort", "Energy vs Shower shape short axis", o2HistType::kTH2F, {{Energy_Axis}, {Shower_Shape_Short_Axis}}); + Data_Info.add("hEnergy_m02_m20", "Energy cluster Vs m02 vs m20", o2HistType::kTHnSparseL, {{Energy_Axis}, {Shower_Shape_Long_Axis}, {Shower_Shape_Short_Axis}}); Data_Info.add("hEnergy_NCells", "Energy vs Number of cells in cluster", o2HistType::kTH2F, {{Energy_Axis}, {NCells_Axis}}); Data_Info.add("hEvsNumTracks", "Energy of cluster vs matched tracks", o2HistType::kTH2F, {{Energy_Axis}, {Num_Track_Axis}}); @@ -133,6 +135,7 @@ struct PhotonIsolationQA { Data_Info.add("hShowerShape", "Shower shape", o2HistType::kTH2F, {{Shower_Shape_Long_Axis}, {Shower_Shape_Short_Axis}}); Data_Info.add("hSigmaLongvsPtIso", "Long shower shape vs Pt_Iso", o2HistType::kTH2F, {{Shower_Shape_Long_Axis}, {PtIso_Axis}}); Data_Info.add("hABCDControlRegion", "Yield Control Regions", o2HistType::kTH2F, {{ABCD_Axis}, {Energy_Axis}}); + Data_Info.add("hE_M02_M20_NLM_NCells_PtIso", "Energy vs M02 vs M20 vs NLM vs NCells vs PtIso", o2HistType::kTHnSparseL, {{Energy_Axis}, {Shower_Shape_Long_Axis}, {Shower_Shape_Short_Axis}, {NLM_Axis}, {NCells_Axis}, {PtIso_Axis}}); MC_Info.add("hPosZ", "Z Position of collision", o2HistType::kTH1F, {PosZ_Axis}); MC_Info.add("hNumClusters", "Number of cluster per collision", o2HistType::kTH1F, {Num_Cluster_Axis}); @@ -140,6 +143,7 @@ struct PhotonIsolationQA { MC_Info.add("hEnergy", "Energy of the cluster", o2HistType::kTH1F, {Energy_Axis}); MC_Info.add("hEnergy_ShowerShapeLong", "Energy vs Shower shape long axis", o2HistType::kTH2F, {{Energy_Axis}, {Shower_Shape_Long_Axis}}); MC_Info.add("hEnergy_ShowerShapeShort", "Energy vs Shower shape short axis", o2HistType::kTH2F, {{Energy_Axis}, {Shower_Shape_Short_Axis}}); + MC_Info.add("hEnergy_m02_m20", "Energy cluster Vs m02 vs m20", o2HistType::kTHnSparseL, {{Energy_Axis}, {Shower_Shape_Long_Axis}, {Shower_Shape_Short_Axis}}); MC_Info.add("hEnergy_NCells", "Energy vs Number of cells in cluster", o2HistType::kTH2F, {{Energy_Axis}, {NCells_Axis}}); MC_Info.add("hEvsNumTracks", "Energy of cluster vs matched tracks", o2HistType::kTH2F, {{Energy_Axis}, {Num_Track_Axis}}); @@ -148,17 +152,19 @@ struct PhotonIsolationQA { MC_Info.add("hTrackPhi", "Phi of matched track", o2HistType::kTH1F, {Phi_Axis}); MC_Info.add("hRatioClusterETrackP", "Ratio between energy of cluster and P of tracks", o2HistType::kTH1F, {RatioP_Axis}); MC_Info.add("hRatioClusterETrackPrackPt", "Ratio between E and P vs Pt of matched tracks", o2HistType::kTH2F, {{RatioP_Axis}, {Pt_Axis}}); + MC_Info.add("hE_M02_M20_NLM_NCells_PtIso", "Energy vs M02 vs M20 vs NLM vs NCells vs PtIso", o2HistType::kTHnSparseL, {{Energy_Axis}, {Shower_Shape_Long_Axis}, {Shower_Shape_Short_Axis}, {NLM_Axis}, {NCells_Axis}, {PtIso_Axis}}); MC_Info.add("hEvsPtIso", "Pt_Iso", o2HistType::kTH2F, {{Energy_Axis}, {PtIso_Axis}}); MC_Info.add("hRho_Perpen_Cone", "Density of perpendicular cone", o2HistType::kTH1F, {Rho_Axis}); MC_Info.add("hShowerShape", "Shower shape", o2HistType::kTH2F, {{Shower_Shape_Long_Axis}, {Shower_Shape_Short_Axis}}); MC_Info.add("hSigmaLongvsPtIso", "Long shower shape vs Pt_Iso", o2HistType::kTH2F, {{Shower_Shape_Long_Axis}, {PtIso_Axis}}); MC_Info.add("hABCDControlRegion", "Yield Control Regions", o2HistType::kTH2F, {{ABCD_Axis}, {Energy_Axis}}); - MC_Info.add("hMcParticlesToCluster", "Energy of particles linked to mc cluster", o2HistType::kTH1F, {{100, 0, 20}}); - MC_Info.add("hMcParticleStatusCode", "status code of mc particle linked to mc cluster", o2HistType::kTH1F, {{100, 0, 100}}); + MC_Info.add("hMcParticlesToCluster", "Energy of particles linked to mc cluster", o2HistType::kTH1F, {{100, 0, 100}}); + MC_Info.add("hMcParticleStatusCode", "generator status code of mc particle linked to mc cluster", o2HistType::kTH1F, {{200, 0, 200}}); + MC_Info.add("hMcParticleProcessCode", "physical process code of mc particle linked to mc cluster", o2HistType::kTH1F, {{200, 0, 200}}); std::vector bin_names = {"A", "B", "C", "D", "True Bckgr A"}; - for (int i = 0; i < bin_names.size(); i++) { + for (size_t i = 0; i < bin_names.size(); i++) { MC_Info.get(HIST("hABCDControlRegion"))->GetXaxis()->SetBinLabel(i + 1, bin_names[i].c_str()); Data_Info.get(HIST("hABCDControlRegion"))->GetXaxis()->SetBinLabel(i + 1, bin_names[i].c_str()); } @@ -168,17 +174,9 @@ struct PhotonIsolationQA { bool track_matching(const auto& cluster, o2::aod::EMCALMatchedTracks const& matched_tracks) { for (const auto& match : matched_tracks) { - double dEta = abs(match.track_as().trackEtaEmcal() - cluster.eta()); - double dPhi = match.track_as().trackPhiEmcal() - cluster.phi(); - if (dPhi < 0) { - dPhi = 2. * M_PI - dPhi; - } - double distance = sqrt(pow(dEta, 2) + pow(dPhi, 2)); - if (distance <= TrackMatchingRadius) { - double abs_p = abs(match.track_as().p()); - if ((cluster.energy() / abs_p) < 1.75) { - return true; - } + double abs_pt = abs(match.track_as().pt()); + if ((cluster.energy() / abs_pt) < 1.75) { + return true; } } return false; @@ -190,8 +188,8 @@ struct PhotonIsolationQA { double sum_Pt = 0.; for (const auto& track : tracks) { double dphi = cluster.phi() - track.phi(); - if (dphi < 0) { - dphi = 2. * M_PI - dphi; + if (abs(dphi) > M_PI) { + dphi = 2. * M_PI - abs(dphi); } double distance = sqrt(pow((cluster.eta() - track.eta()), 2) + pow(dphi, 2)); if (distance < Cone_Radius) { @@ -207,20 +205,20 @@ struct PhotonIsolationQA { double sum_Pt = 0.; double Perpendicular_Phi1 = cluster.phi() + (1. / 2.) * M_PI; double Perpendicular_Phi2 = cluster.phi() - (1. / 2.) * M_PI; - if (Perpendicular_Phi1 > 2 * M_PI) { - Perpendicular_Phi1 = Perpendicular_Phi1 - 2 * M_PI; + if (Perpendicular_Phi1 > 2. * M_PI) { + Perpendicular_Phi1 = Perpendicular_Phi1 - 2. * M_PI; } if (Perpendicular_Phi2 < 0.) { - Perpendicular_Phi2 = 2 * M_PI + Perpendicular_Phi2; + Perpendicular_Phi2 = 2. * M_PI + Perpendicular_Phi2; } for (const auto& track : tracks) { double dphi1 = Perpendicular_Phi1 - track.phi(); double dphi2 = Perpendicular_Phi2 - track.phi(); - if (dphi1 < 0) { - dphi1 = 2. * M_PI - dphi1; + if (abs(dphi1) > M_PI) { + dphi1 = 2. * M_PI - abs(dphi1); } - if (dphi2 < 0) { - dphi2 = 2. * M_PI - dphi2; + if (abs(dphi2) > M_PI) { + dphi2 = 2. * M_PI - abs(dphi2); } double distance1 = sqrt(pow((cluster.eta() - track.eta()), 2) + pow(dphi1, 2)); double distance2 = sqrt(pow((cluster.eta() - track.eta()), 2) + pow(dphi2, 2)); @@ -231,7 +229,7 @@ struct PhotonIsolationQA { sum_Pt += track.pt(); } } - double Rho = sum_Pt / (2 * M_PI * pow(Perpendicular_Cone_Radius, 2)); + double Rho = sum_Pt / (2. * M_PI * pow(Perpendicular_Cone_Radius, 2)); return Rho; } @@ -249,6 +247,7 @@ struct PhotonIsolationQA { registry.fill(HIST("hEnergy_ShowerShapeLong"), cluster.energy(), cluster.m02()); registry.fill(HIST("hEnergy_ShowerShapeShort"), cluster.energy(), cluster.m20()); registry.fill(HIST("hEnergy_NCells"), cluster.energy(), cluster.nCells()); + registry.fill(HIST("hEnergy_m02_m20"), cluster.energy(), cluster.m02(), cluster.m20()); } void fillABCDHisto(HistogramRegistry registry, const auto& cluster, double Pt_iso) @@ -279,7 +278,7 @@ struct PhotonIsolationQA { } // process monte carlo data - void processMC(selectedCollisions::iterator const& theCollision, selectedMCClusters const& mcclusters, aod::StoredMcParticles_001 const&, myGlobTracks const& tracks, o2::aod::EMCALClusterCells const& emccluscells, o2::aod::EMCALMatchedTracks const& matchedtracks) + void processMC(selectedCollisions::iterator const& theCollision, selectedMCClusters const& mcclusters, aod::StoredMcParticles_001 const&, myGlobTracks const& tracks, o2::aod::EMCALClusterCells const& /*emccluscells*/, o2::aod::EMCALMatchedTracks const& matchedtracks) { MC_Info.fill(HIST("hPosZ"), theCollision.posZ()); @@ -302,23 +301,23 @@ struct PhotonIsolationQA { MC_Info.fill(HIST("hRho_Perpen_Cone"), Rho_Perpen_Cone); MC_Info.fill(HIST("hShowerShape"), mccluster.m02(), mccluster.m20()); MC_Info.fill(HIST("hSigmaLongvsPtIso"), mccluster.m02(), Pt_iso); + MC_Info.fill(HIST("hE_M02_M20_NLM_NCells_PtIso"), mccluster.energy(), mccluster.m02(), mccluster.m20(), mccluster.nlm(), mccluster.nCells(), Pt_iso); fillABCDHisto(MC_Info, mccluster, Pt_iso); - // acces mc true info auto ClusterParticles = mccluster.mcParticle_as(); bool background = true; for (auto& clusterparticle : ClusterParticles) { if (clusterparticle.pdgCode() == 22) { MC_Info.fill(HIST("hMcParticlesToCluster"), clusterparticle.e()); + MC_Info.fill(HIST("hMcParticleProcessCode"), clusterparticle.getProcess()); MC_Info.fill(HIST("hMcParticleStatusCode"), clusterparticle.getGenStatusCode()); - if ((clusterparticle.getGenStatusCode() >= 21) && (clusterparticle.getGenStatusCode() <= 29)) + if ((clusterparticle.getProcess() >= 21) && (clusterparticle.getProcess() <= 29)) background = false; // Particles from the hardest subprocess } } if (background) { if ((Pt_iso < 1.5) && (mccluster.m02() < 0.3) && (mccluster.m02() > 0.1)) { - // fillABCDHistograms(MC_Info, 4.5, mccluster); MC_Info.fill(HIST("hABCDControlRegion"), 4.5, mccluster.energy()); } } @@ -328,7 +327,7 @@ struct PhotonIsolationQA { PROCESS_SWITCH(PhotonIsolationQA, processMC, "proces MC data", true); - void processData(selectedCollisions::iterator const& theCollision, selectedClusters const& clusters, o2::aod::EMCALClusterCells const& emccluscells, o2::aod::EMCALMatchedTracks const& matchedtracks, myGlobTracks const& alltracks) + void processData(selectedCollisions::iterator const& theCollision, selectedClusters const& clusters, o2::aod::EMCALClusterCells const& /*emccluscells*/, o2::aod::EMCALMatchedTracks const& matchedtracks, myGlobTracks const& alltracks) { Data_Info.fill(HIST("hPosZ"), theCollision.posZ()); @@ -350,6 +349,7 @@ struct PhotonIsolationQA { Data_Info.fill(HIST("hRho_Perpen_Cone"), Rho_Perpen_Cone); Data_Info.fill(HIST("hShowerShape"), cluster.m02(), cluster.m20()); Data_Info.fill(HIST("hSigmaLongvsPtIso"), cluster.m02(), Pt_iso); + Data_Info.fill(HIST("hE_M02_M20_NLM_NCells_PtIso"), cluster.energy(), cluster.m02(), cluster.m20(), cluster.nlm(), cluster.nCells(), Pt_iso); fillABCDHisto(Data_Info, cluster, Pt_iso); } } diff --git a/PWGJE/Tasks/bjetTaggingML.cxx b/PWGJE/Tasks/bjetTaggingML.cxx new file mode 100644 index 00000000000..8bee32b1aff --- /dev/null +++ b/PWGJE/Tasks/bjetTaggingML.cxx @@ -0,0 +1,614 @@ +// Copyright 2019-2020 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. + +/// \file bjetTaggingML.cxx +/// \brief Task for tagging the beauty jets using ML algorithm (in onnx format) loaded from ccdb +/// +/// \author Hadi Hassan , University of JyvĂ€skylĂ€ + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoA.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/JetTagging.h" +#include "PWGJE/DataModel/Jet.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Tools/ML/MlResponse.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct BJetTaggingML { + + struct bjetParams { + float mJetpT = 0.0; + float mJetEta = 0.0; + float mJetPhi = 0.0; + int mNTracks = -1; + int mNSV = -1; + float mJetMass = 0.0; + }; + + struct bjetTrackParams { + double mTrackpT = 0.0; + double mTrackEta = 0.0; + double mDotProdTrackJet = 0.0; + double mDotProdTrackJetOverJet = 0.0; + double mDeltaRJetTrack = 0.0; + double mSignedIP2D = 0.0; + double mSignedIP2DSign = 0.0; + double mSignedIP3D = 0.0; + double mSignedIP3DSign = 0.0; + double mMomFraction = 0.0; + double mDeltaRTrackVertex = 0.0; + }; + + struct bjetSVParams { + double mSVpT = 0.0; + double mDeltaRSVJet = 0.0; + double mSVMass = 0.0; + double mSVfE = 0.0; + double mIPXY = 0.0; + double mCPA = 0.0; + double mChi2PCA = 0.0; + double mDispersion = 0.0; + double mDecayLength2D = 0.0; + double mDecayLength2DError = 0.0; + double mDecayLength3D = 0.0; + double mDecayLength3DError = 0.0; + }; + + HistogramRegistry registry; + + static constexpr double defaultCutsMl[1][2] = {{0.5, 0.5}}; + + // event level configurables + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + + Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + + // track level configurables + Configurable trackPtMin{"trackPtMin", 0.5, "minimum track pT"}; + Configurable trackPtMax{"trackPtMax", 1000.0, "maximum track pT"}; + Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track eta"}; + Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; + + // track level configurables + Configurable svPtMin{"svPtMin", 0.5, "minimum SV pT"}; + + // jet level configurables + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT"}; + Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; + Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; + Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; + Configurable nJetConst{"nJetConst", 10, "maximum number of jet consistuents to be used for ML evaluation"}; + + Configurable useQuarkDef{"useQuarkDef", true, "Flag whether to use quarks or hadrons for determining the jet flavor"}; + + Configurable svReductionFactor{"svReductionFactor", 1.0, "factor for how many SVs to keep"}; + + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; + + Configurable> binsPtMl{"binsPtMl", std::vector{5., 1000.}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{cuts_ml::CutSmaller, cuts_ml::CutNot}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {defaultCutsMl[0], 1, 2, {"pT bin 0"}, {"score for default b-jet tagging", "uncer 1"}}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", (int8_t)2, "Number of classes in ML model"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"Users/h/hahassan"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ML_bjets/01-MVA/Models/LHC23d4_5_20_90Percent/model.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + o2::analysis::MlResponse bMlResponse; + o2::ccdb::CcdbApi ccdbApi; + + int eventSelection = -1; + + std::vector jetRadiiValues; + + void init(InitContext const&) + { + // Seed the random number generator using current time + std::srand(static_cast(std::time(nullptr))); + + jetRadiiValues = (std::vector)jetRadii; + + eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); + + registry.add("h_vertexZ", "Vertex Z;#it{Z} (cm)", {HistType::kTH1F, {{40, -20.0, 20.0}}}); + + registry.add("h2_score_jetpT", "ML scores for inclusive jets;#it{p}_{T,jet} (GeV/#it{c});Score", {HistType::kTH2F, {{200, 0., 200.}, {120, -0.1, 1.1}}}); + + registry.add("h2_nTracks_jetpT", "Number of tracks;#it{p}_{T,jet} (GeV/#it{c});nTracks", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 100.0}}}); + registry.add("h2_nSV_jetpT", "Number of secondary vertices;#it{p}_{T,jet} (GeV/#it{c});nSVs", {HistType::kTH2F, {{200, 0., 200.}, {250, 0, 250.0}}}); + + registry.add("h2_SIPs2D_jetpT", "2D IP significance;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_SIPs3D_jetpT", "3D IP significance;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_LxyS_jetpT", "Decay length in XY;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); + registry.add("h2_Dispersion_jetpT", "SV dispersion;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); + registry.add("h2_jetMass_jetpT", "Jet mass;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); + registry.add("h2_SVMass_jetpT", "Secondary vertex mass;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10}}}); + + if (doprocessMCJets) { + + registry.add("h2_score_jetpT_bjet", "ML scores for b-jets;#it{p}_{T,jet} (GeV/#it{c});Score", {HistType::kTH2F, {{200, 0., 200.}, {120, -0.1, 1.1}}}); + registry.add("h2_SIPs2D_jetpT_bjet", "2D IP significance b-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_SIPs3D_jetpT_bjet", "3D IP significance b-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_LxyS_jetpT_bjet", "Decay length in XY b-jets;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); + registry.add("h2_Dispersion_jetpT_bjet", "SV dispersion b-jets;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); + registry.add("h2_jetMass_jetpT_bjet", "Jet mass b-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); + registry.add("h2_SVMass_jetpT_bjet", "Secondary vertex mass b-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10.0}}}); + + registry.add("h2_score_jetpT_cjet", "ML scores for c-jets;#it{p}_{T,jet} (GeV/#it{c});Score", {HistType::kTH2F, {{200, 0., 200.}, {120, -0.1, 1.1}}}); + registry.add("h2_SIPs2D_jetpT_cjet", "2D IP significance c-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_SIPs3D_jetpT_cjet", "3D IP significance c-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_LxyS_jetpT_cjet", "Decay length in XY c-jets;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); + registry.add("h2_Dispersion_jetpT_cjet", "SV dispersion c-jets;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); + registry.add("h2_jetMass_jetpT_cjet", "Jet mass c-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); + registry.add("h2_SVMass_jetpT_cjet", "Secondary vertex mass c-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10.0}}}); + + registry.add("h2_score_jetpT_lfjet", "ML scores for lf-jets;#it{p}_{T,jet} (GeV/#it{c});Score", {HistType::kTH2F, {{200, 0., 200.}, {120, -0.1, 1.1}}}); + registry.add("h2_SIPs2D_jetpT_lfjet", "2D IP significance lf-jet;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_SIPs3D_jetpT_lfjet", "3D IP significance lf-jet;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); + registry.add("h2_LxyS_jetpT_lfjet", "Decay length in XY lf-jet;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); + registry.add("h2_Dispersion_jetpT_lfjet", "SV dispersion lf-jet;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); + registry.add("h2_jetMass_jetpT_lfjet", "Jet mass lf-jet;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); + registry.add("h2_SVMass_jetpT_lfjet", "Secondary vertex mass lf-jet;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10.0}}}); + + registry.add("h_jetpT_detector_bjet", "Jet transverse momentum b-jets;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_detector_cjet", "Jet transverse momentum c-jets;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_detector_lfjet", "Jet transverse momentum lf-jet;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + + registry.add("h_jetpT_particle_DetColl", "Jet transverse momentum particle level inclusive jets (Detector-level collisions);#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_particle_DetColl_bjet", "Jet transverse momentum particle level b-jets (Detector-level collisions);#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_particle_DetColl_cjet", "Jet transverse momentum particle level c-jets (Detector-level collisions);#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_particle_DetColl_lfjet", "Jet transverse momentum particle level lf-jet (Detector-level collisions);#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + + registry.add("h_jetpT_particle_bjet", "Jet transverse momentum particle level b-jets;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_particle_cjet", "Jet transverse momentum particle level c-jets;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("h_jetpT_particle_lfjet", "Jet transverse momentum particle level lf-jet;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); + + registry.add("h2_Response_DetjetpT_PartjetpT_bjet", "Response matrix b-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h2_Response_DetjetpT_PartjetpT_cjet", "Response matrix c-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h2_Response_DetjetpT_PartjetpT_lfjet", "Response matrix lf-jet;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); + } + + bMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + bMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + bMlResponse.setModelPathsLocal(onnxFileNames); + } + // bMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + bMlResponse.init(); + } + + // FIXME filtering only works when you loop directly over the list, but if you loop over it as a constituent they will not be filtered + Filter collisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; + Filter trackCuts = (aod::jtrack::pt > trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); + Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax); + Filter jetFilter = (aod::jet::pt >= jetPtMin && aod::jet::pt <= jetPtMax && aod::jet::eta < jetEtaMax - aod::jet::r / 100.f && aod::jet::eta > jetEtaMin + aod::jet::r / 100.f); + + using FilteredCollision = soa::Filtered>; + using JetTrackswID = soa::Join; + using JetTracksMCDwID = soa::Join; + using DataJets = soa::Filtered>; + + std::vector> getInputsForML(bjetParams jetparams, std::vector& tracksParams, std::vector& svsParams) + { + std::vector jetInput = {jetparams.mJetpT, jetparams.mJetEta, jetparams.mJetPhi, static_cast(jetparams.mNTracks), static_cast(jetparams.mNSV), jetparams.mJetMass}; + std::vector tracksInputFlat; + std::vector svsInputFlat; + + for (int iconstit = 0; iconstit < nJetConst; iconstit++) { + + tracksInputFlat.push_back(tracksParams[iconstit].mTrackpT); + tracksInputFlat.push_back(tracksParams[iconstit].mTrackEta); + tracksInputFlat.push_back(tracksParams[iconstit].mDotProdTrackJet); + tracksInputFlat.push_back(tracksParams[iconstit].mDotProdTrackJetOverJet); + tracksInputFlat.push_back(tracksParams[iconstit].mDeltaRJetTrack); + tracksInputFlat.push_back(tracksParams[iconstit].mSignedIP2D); + tracksInputFlat.push_back(tracksParams[iconstit].mSignedIP2DSign); + tracksInputFlat.push_back(tracksParams[iconstit].mSignedIP3D); + tracksInputFlat.push_back(tracksParams[iconstit].mSignedIP3DSign); + tracksInputFlat.push_back(tracksParams[iconstit].mMomFraction); + tracksInputFlat.push_back(tracksParams[iconstit].mDeltaRTrackVertex); + + svsInputFlat.push_back(svsParams[iconstit].mSVpT); + svsInputFlat.push_back(svsParams[iconstit].mDeltaRSVJet); + svsInputFlat.push_back(svsParams[iconstit].mSVMass); + svsInputFlat.push_back(svsParams[iconstit].mSVfE); + svsInputFlat.push_back(svsParams[iconstit].mIPXY); + svsInputFlat.push_back(svsParams[iconstit].mCPA); + svsInputFlat.push_back(svsParams[iconstit].mChi2PCA); + svsInputFlat.push_back(svsParams[iconstit].mDispersion); + svsInputFlat.push_back(svsParams[iconstit].mDecayLength2D); + svsInputFlat.push_back(svsParams[iconstit].mDecayLength2DError); + svsInputFlat.push_back(svsParams[iconstit].mDecayLength3D); + svsInputFlat.push_back(svsParams[iconstit].mDecayLength3DError); + } + + std::vector> totalInput; + totalInput.push_back(jetInput); + totalInput.push_back(tracksInputFlat); + totalInput.push_back(svsInputFlat); + + return totalInput; + } + + // Looping over the SV info and writing them to a table + template + void analyzeJetSVInfo(AnalysisJet const& myJet, AnyTracks const& /*allTracks*/, SecondaryVertices const& /*allSVs*/, std::vector& svsParams, int jetFlavor = 0, double eventweight = 1.0) + { + using SVType = typename SecondaryVertices::iterator; + + // Min-heap to store the top 30 SVs by decayLengthXY/errorDecayLengthXY + auto compare = [](SVType& sv1, SVType& sv2) { + return (sv1.decayLengthXY() / sv1.errorDecayLengthXY()) > (sv2.decayLengthXY() / sv2.errorDecayLengthXY()); + }; + + auto svs = myJet.template secondaryVertices_as(); + + // Sort the SVs based on their decay length significance in descending order + // This is needed in order to select longest SVs since some jets could have thousands of SVs + std::sort(svs.begin(), svs.end(), compare); + + for (const auto& candSV : svs) { + + if (candSV.pt() < svPtMin) { + continue; + } + + double deltaRJetSV = jetutilities::deltaR(myJet, candSV); + double massSV = candSV.m(); + double energySV = candSV.e(); + + if (svsParams.size() < (svReductionFactor * myJet.template tracks_as().size())) { + svsParams.emplace_back(bjetSVParams{candSV.pt(), deltaRJetSV, massSV, energySV / myJet.energy(), candSV.impactParameterXY(), candSV.cpa(), candSV.chi2PCA(), candSV.dispersion(), candSV.decayLengthXY(), candSV.errorDecayLengthXY(), candSV.decayLength(), candSV.errorDecayLength()}); + } + + registry.fill(HIST("h2_LxyS_jetpT"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); + registry.fill(HIST("h2_Dispersion_jetpT"), myJet.pt(), candSV.dispersion(), eventweight); + registry.fill(HIST("h2_SVMass_jetpT"), myJet.pt(), massSV, eventweight); + + if (doprocessMCJets) { + if (jetFlavor == 2) { + registry.fill(HIST("h2_LxyS_jetpT_bjet"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); + registry.fill(HIST("h2_Dispersion_jetpT_bjet"), myJet.pt(), candSV.dispersion(), eventweight); + registry.fill(HIST("h2_SVMass_jetpT_bjet"), myJet.pt(), massSV, eventweight); + } else if (jetFlavor == 1) { + registry.fill(HIST("h2_LxyS_jetpT_cjet"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); + registry.fill(HIST("h2_Dispersion_jetpT_cjet"), myJet.pt(), candSV.dispersion(), eventweight); + registry.fill(HIST("h2_SVMass_jetpT_cjet"), myJet.pt(), massSV, eventweight); + } else { + registry.fill(HIST("h2_LxyS_jetpT_lfjet"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); + registry.fill(HIST("h2_Dispersion_jetpT_lfjet"), myJet.pt(), candSV.dispersion(), eventweight); + registry.fill(HIST("h2_SVMass_jetpT_lfjet"), myJet.pt(), massSV, eventweight); + } + } + } + } + + template + void analyzeJetTrackInfo(AnyCollision const& /*collision*/, AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, SecondaryVertices const& /*allSVs*/, std::vector& tracksParams, int jetFlavor = 0, double eventweight = 1.0) + { + + for (auto& constituent : analysisJet.template tracks_as()) { + + if (constituent.pt() < trackPtMin) { + continue; + } + + double deltaRJetTrack = jetutilities::deltaR(analysisJet, constituent); + double dotProduct = RecoDecay::dotProd(std::array{analysisJet.px(), analysisJet.py(), analysisJet.pz()}, std::array{constituent.px(), constituent.py(), constituent.pz()}); + int sign = jettaggingutilities::getGeoSign(analysisJet, constituent); + + float RClosestSV = 10.; + for (const auto& candSV : analysisJet.template secondaryVertices_as()) { + double deltaRTrackSV = jetutilities::deltaR(constituent, candSV); + if (deltaRTrackSV < RClosestSV) { + RClosestSV = deltaRTrackSV; + } + } + + registry.fill(HIST("h2_SIPs2D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); + + if (doprocessMCJets) { + if (jetFlavor == 2) { + registry.fill(HIST("h2_SIPs2D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); + } else if (jetFlavor == 1) { + registry.fill(HIST("h2_SIPs2D_jetpT_cjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT_cjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); + } else { + registry.fill(HIST("h2_SIPs2D_jetpT_lfjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT_lfjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); + } + } + + tracksParams.emplace_back(bjetTrackParams{constituent.pt(), constituent.eta(), dotProduct, dotProduct / analysisJet.p(), deltaRJetTrack, std::abs(constituent.dcaXY()) * sign, constituent.sigmadcaXY(), std::abs(constituent.dcaXYZ()) * sign, constituent.sigmadcaXYZ(), constituent.p() / analysisJet.p(), RClosestSV}); + } + + auto compare = [](bjetTrackParams& tr1, bjetTrackParams& tr2) { + return (tr1.mSignedIP2D / tr1.mSignedIP2DSign) > (tr2.mSignedIP2D / tr2.mSignedIP2DSign); + }; + + // Sort the tracks based on their IP significance in descending order + std::sort(tracksParams.begin(), tracksParams.end(), compare); + } + + void processDummy(FilteredCollision::iterator const& /*collision*/) + { + } + PROCESS_SWITCH(BJetTaggingML, processDummy, "Dummy process function turned on by default", true); + + void processDataJets(FilteredCollision::iterator const& collision, DataJets const& alljets, JetTrackswID const& allTracks, aod::DataSecondaryVertex3Prongs const& allSVs) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + + registry.fill(HIST("h_vertexZ"), collision.posZ()); + + for (const auto& analysisJet : alljets) { + + bool jetIncluded = false; + for (auto jetR : jetRadiiValues) { + if (analysisJet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + std::vector tracksParams; + std::vector SVsParams; + + analyzeJetSVInfo(analysisJet, allTracks, allSVs, SVsParams); + analyzeJetTrackInfo(collision, analysisJet, allTracks, allSVs, tracksParams); + + int nSVs = analysisJet.template secondaryVertices_as().size(); + + registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), tracksParams.size()); + registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); + + bjetParams jetparam = {analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), static_cast(tracksParams.size()), static_cast(nSVs), analysisJet.mass()}; + tracksParams.resize(nJetConst); // resize to the number of inputs of the ML + SVsParams.resize(nJetConst); // resize to the number of inputs of the ML + + auto inputML = getInputsForML(jetparam, tracksParams, SVsParams); + + std::vector output; + // bool isSelectedMl = bMlResponse.isSelectedMl(inputML, analysisJet.pt(), output); + bMlResponse.isSelectedMl(inputML, analysisJet.pt(), output); + + registry.fill(HIST("h2_score_jetpT"), analysisJet.pt(), output[0]); + + registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass()); + } + } + PROCESS_SWITCH(BJetTaggingML, processDataJets, "jet information in Data", false); + + using MCDJetTable = soa::Filtered>; + using MCPJetTable = soa::Filtered>; + using FilteredCollisionMCD = soa::Filtered>; + + Preslice McParticlesPerCollision = aod::jmcparticle::mcCollisionId; + Preslice McPJetsPerCollision = aod::jet::mcCollisionId; + + void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, JetParticles const& MCParticles, aod::MCDSecondaryVertex3Prongs const& allSVs) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + + registry.fill(HIST("h_vertexZ"), collision.posZ()); + + auto const mcParticlesPerColl = MCParticles.sliceBy(McParticlesPerCollision, collision.mcCollisionId()); + auto const mcPJetsPerColl = MCPjets.sliceBy(McPJetsPerCollision, collision.mcCollisionId()); + + for (const auto& analysisJet : MCDjets) { + + bool jetIncluded = false; + for (auto jetR : jetRadiiValues) { + if (analysisJet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + float eventWeight = analysisJet.eventWeight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (analysisJet.pt() > pTHatMaxMCD * pTHat) { + continue; + } + + std::vector tracksParams; + std::vector SVsParams; + + int jetFlavor = 0; + + for (auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + if (useQuarkDef) { + jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, mcParticlesPerColl); + } else { + jetFlavor = jettaggingutilities::getJetFlavorHadron(mcpjet, mcParticlesPerColl); + } + } + + analyzeJetSVInfo(analysisJet, allTracks, allSVs, SVsParams, jetFlavor, eventWeight); + analyzeJetTrackInfo(collision, analysisJet, allTracks, allSVs, tracksParams, jetFlavor, eventWeight); + + int nSVs = analysisJet.template secondaryVertices_as().size(); + + registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), tracksParams.size()); + registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); + + bjetParams jetparam = {analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), static_cast(tracksParams.size()), static_cast(nSVs), analysisJet.mass()}; + tracksParams.resize(nJetConst); // resize to the number of inputs of the ML + SVsParams.resize(nJetConst); // resize to the number of inputs of the ML + + auto inputML = getInputsForML(jetparam, tracksParams, SVsParams); + + std::vector output; + // bool isSelectedMl = bMlResponse.isSelectedMl(inputML, analysisJet.pt(), output); + bMlResponse.isSelectedMl(inputML, analysisJet.pt(), output); + + registry.fill(HIST("h2_score_jetpT"), analysisJet.pt(), output[0], eventWeight); + + registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass(), eventWeight); + + if (jetFlavor == 2) { + registry.fill(HIST("h2_score_jetpT_bjet"), analysisJet.pt(), output[0], eventWeight); + registry.fill(HIST("h2_jetMass_jetpT_bjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_bjet"), analysisJet.pt(), eventWeight); + } else if (jetFlavor == 1) { + registry.fill(HIST("h2_score_jetpT_cjet"), analysisJet.pt(), output[0], eventWeight); + registry.fill(HIST("h2_jetMass_jetpT_cjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_cjet"), analysisJet.pt(), eventWeight); + } else { + registry.fill(HIST("h2_score_jetpT_lfjet"), analysisJet.pt(), output[0], eventWeight); + registry.fill(HIST("h2_jetMass_jetpT_lfjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_lfjet"), analysisJet.pt(), eventWeight); + } + + for (auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { + continue; + } + + if (jetFlavor == 2) { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_bjet"), analysisJet.pt(), mcpjet.pt(), eventWeight); + } else if (jetFlavor == 1) { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_cjet"), analysisJet.pt(), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_lfjet"), analysisJet.pt(), mcpjet.pt(), eventWeight); + } + } + } + + // For filling histograms used for the jet matching efficiency + for (const auto& mcpjet : mcPJetsPerColl) { + + bool jetIncluded = false; + for (auto jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + float eventWeight = mcpjet.eventWeight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { + continue; + } + + int8_t jetFlavor = 0; + + if (useQuarkDef) { + jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, mcParticlesPerColl); + } else { + jetFlavor = jettaggingutilities::getJetFlavorHadron(mcpjet, mcParticlesPerColl); + } + + registry.fill(HIST("h_jetpT_particle_DetColl"), mcpjet.pt(), eventWeight); + + if (jetFlavor == 2) { + registry.fill(HIST("h_jetpT_particle_DetColl_bjet"), mcpjet.pt(), eventWeight); + } else if (jetFlavor == 1) { + registry.fill(HIST("h_jetpT_particle_DetColl_cjet"), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h_jetpT_particle_DetColl_lfjet"), mcpjet.pt(), eventWeight); + } + } + } + PROCESS_SWITCH(BJetTaggingML, processMCJets, "jet information in MC", false); + + Filter mccollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; + using FilteredCollisionMCP = soa::Filtered; + + void processMCTruthJets(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTable const& MCPjets, JetParticles const& MCParticles) + { + + for (const auto& mcpjet : MCPjets) { + + bool jetIncluded = false; + for (auto jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + float eventWeight = mcpjet.eventWeight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { + continue; + } + + int8_t jetFlavor = 0; + + if (useQuarkDef) { + jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, MCParticles); + } else { + jetFlavor = jettaggingutilities::getJetFlavorHadron(mcpjet, MCParticles); + } + + if (jetFlavor == 2) { + registry.fill(HIST("h_jetpT_particle_bjet"), mcpjet.pt(), eventWeight); + } else if (jetFlavor == 1) { + registry.fill(HIST("h_jetpT_particle_cjet"), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h_jetpT_particle_lfjet"), mcpjet.pt(), eventWeight); + } + } + } + PROCESS_SWITCH(BJetTaggingML, processMCTruthJets, "truth jet information", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"bjet-tagging-ml"})}; +} diff --git a/PWGJE/Tasks/bjetTreeCreator.cxx b/PWGJE/Tasks/bjetTreeCreator.cxx index 509bdc87450..4cf44d6e9ad 100644 --- a/PWGJE/Tasks/bjetTreeCreator.cxx +++ b/PWGJE/Tasks/bjetTreeCreator.cxx @@ -54,7 +54,7 @@ DECLARE_SOA_COLUMN(JetFlavor, jetFl, int16_t); //! The jet flavor (b, c, or lf) DECLARE_SOA_COLUMN(JetR, jetR, int16_t); //! The jet radius } // namespace jetInfo -DECLARE_SOA_TABLE(bjetParams, "AOD", "BJETPARAMS", +DECLARE_SOA_TABLE(bjetParams, "AOD", "BJETPARAM", o2::soa::Index<>, jetInfo::JetpT, jetInfo::JetEta, @@ -84,7 +84,7 @@ DECLARE_SOA_COLUMN(DeltaRTrackVertex, rtrackvertex, float); //! DR be // DECLARE_SOA_COLUMN(DCATrackJet, dcatrackjet, float); //! The distance between track and jet, unfortunately it cannot be calculated in O2 } // namespace trackInfo -DECLARE_SOA_TABLE(bjetTracksParams, "AOD", "BJETTRACKPARAMS", +DECLARE_SOA_TABLE(bjetTracksParams, "AOD", "BJETTRACKSPARAM", o2::soa::Index<>, trackInfo::bjetParamId, trackInfo::TrackpT, @@ -111,14 +111,14 @@ DECLARE_SOA_COLUMN(SVfE, svfe, float); //! The SV energy frac DECLARE_SOA_COLUMN(IPXY, ipxy, float); //! The SV 2D IP DECLARE_SOA_COLUMN(CPA, cpa, float); //! Cosine pointing angle between the SV direction and momentum DECLARE_SOA_COLUMN(Chi2PCA, chi2pca, float); //! Sum of (non-weighted) distances of the secondary vertex to its prongsm +DECLARE_SOA_COLUMN(Dispersion, dispersion, float); //! The SV dispersion DECLARE_SOA_COLUMN(DecayLength2D, lxy, float); //! The decay length of the SV in XY DECLARE_SOA_COLUMN(DecayLength2DError, lxysigma, float); //! The decay length of the SV in XY significance DECLARE_SOA_COLUMN(DecayLength3D, lxyz, float); //! The decay length of the SV in 3D DECLARE_SOA_COLUMN(DecayLength3DError, lxyzsigma, float); //! The decay length of the SV in 3d significance -// DECLARE_SOA_COLUMN(SVDispersion, svdispersion, float); //! The SV dispersion, unfortunately it cannot be calculated in O2 } // namespace SVInfo -DECLARE_SOA_TABLE(bjetSVParams, "AOD", "BJETSVPARAMS", +DECLARE_SOA_TABLE(bjetSVParams, "AOD", "BJETSVPARAM", o2::soa::Index<>, SVInfo::bjetParamId, SVInfo::SVpT, @@ -128,6 +128,7 @@ DECLARE_SOA_TABLE(bjetSVParams, "AOD", "BJETSVPARAMS", SVInfo::IPXY, SVInfo::CPA, SVInfo::Chi2PCA, + SVInfo::Dispersion, SVInfo::DecayLength2D, SVInfo::DecayLength2DError, SVInfo::DecayLength3D, @@ -162,12 +163,21 @@ struct BJetTreeCreator { Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable> jetPtBins{"jetPtBins", std::vector{5, 1000}, "jet pT bins for reduction"}; + Configurable> jetReductionFactors{"jetReductionFactors", std::vector{0.0}, "jet reduction factors"}; + + Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + // track level configurables Configurable trackPtMin{"trackPtMin", 0.5, "minimum track pT"}; Configurable trackPtMax{"trackPtMax", 1000.0, "maximum track pT"}; Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track eta"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; + Configurable useQuarkDef{"useQuarkDef", true, "Flag whether to use quarks or hadrons for determining the jet flavor"}; + // track level configurables Configurable svPtMin{"svPtMin", 0.5, "minimum SV pT"}; @@ -177,6 +187,11 @@ struct BJetTreeCreator { Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; + Configurable maxConstSV{"maxConstSV", 999.0, "maximum number of SVs to be stored in the table"}; + + Configurable svReductionFactor{"svReductionFactor", 1.0, "factor for how many SVs to keep"}; + Configurable eventReductionFactor{"eventReductionFactor", 0.0, "Percentage of events to be removed"}; + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; Configurable produceTree{"produceTree", true, "produce the jet TTree"}; @@ -184,10 +199,17 @@ struct BJetTreeCreator { int eventSelection = -1; std::vector jetRadiiValues; + std::vector jetPtBinsReduction; + std::vector jetReductionFactorsPt; void init(InitContext const&) { + // Seed the random number generator using current time + std::srand(static_cast(std::time(nullptr))); + jetRadiiValues = (std::vector)jetRadii; + jetPtBinsReduction = (std::vector)jetPtBins; + jetReductionFactorsPt = (std::vector)jetReductionFactors; eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); @@ -199,7 +221,7 @@ struct BJetTreeCreator { registry.add("h2_SIPs2D_jetpT", "2D IP significance;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_SIPs3D_jetpT", "3D IP significance;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_LxyS_jetpT", "Decay length in XY;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); - registry.add("h2_Dispersion_jetpT", "SV dispersion;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 50.0}}}); + registry.add("h2_Dispersion_jetpT", "SV dispersion;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); registry.add("h2_jetMass_jetpT", "Jet mass;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); registry.add("h2_SVMass_jetpT", "Secondary vertex mass;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10}}}); @@ -207,21 +229,21 @@ struct BJetTreeCreator { registry.add("h2_SIPs2D_jetpT_bjet", "2D IP significance b-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_SIPs3D_jetpT_bjet", "3D IP significance b-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_LxyS_jetpT_bjet", "Decay length in XY b-jets;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); - registry.add("h2_Dispersion_jetpT_bjet", "SV dispersion b-jets;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 50.0}}}); + registry.add("h2_Dispersion_jetpT_bjet", "SV dispersion b-jets;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); registry.add("h2_jetMass_jetpT_bjet", "Jet mass b-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); registry.add("h2_SVMass_jetpT_bjet", "Secondary vertex mass b-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10.0}}}); registry.add("h2_SIPs2D_jetpT_cjet", "2D IP significance c-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_SIPs3D_jetpT_cjet", "3D IP significance c-jets;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_LxyS_jetpT_cjet", "Decay length in XY c-jets;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); - registry.add("h2_Dispersion_jetpT_cjet", "SV dispersion c-jets;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 50.0}}}); + registry.add("h2_Dispersion_jetpT_cjet", "SV dispersion c-jets;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); registry.add("h2_jetMass_jetpT_cjet", "Jet mass c-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); registry.add("h2_SVMass_jetpT_cjet", "Secondary vertex mass c-jets;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10.0}}}); registry.add("h2_SIPs2D_jetpT_lfjet", "2D IP significance lf-jet;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_SIPs3D_jetpT_lfjet", "3D IP significance lf-jet;#it{p}_{T,jet} (GeV/#it{c});IPs", {HistType::kTH2F, {{200, 0., 200.}, {100, -50.0, 50.0}}}); registry.add("h2_LxyS_jetpT_lfjet", "Decay length in XY lf-jet;#it{p}_{T,jet} (GeV/#it{c});S#it{L}_{xy}", {HistType::kTH2F, {{200, 0., 200.}, {100, 0., 100.0}}}); - registry.add("h2_Dispersion_jetpT_lfjet", "SV dispersion lf-jet;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 50.0}}}); + registry.add("h2_Dispersion_jetpT_lfjet", "SV dispersion lf-jet;#it{p}_{T,jet} (GeV/#it{c});Dispersion", {HistType::kTH2F, {{200, 0., 200.}, {100, 0, 0.5}}}); registry.add("h2_jetMass_jetpT_lfjet", "Jet mass lf-jet;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{jet} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 50.0}}}); registry.add("h2_SVMass_jetpT_lfjet", "Secondary vertex mass lf-jet;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10.0}}}); @@ -246,16 +268,47 @@ struct BJetTreeCreator { Filter jetFilter = (aod::jet::pt >= jetPtMin && aod::jet::pt <= jetPtMax && aod::jet::eta < jetEtaMax - aod::jet::r / 100.f && aod::jet::eta > jetEtaMin + aod::jet::r / 100.f); using FilteredCollision = soa::Filtered>; - using JetTrackswID = soa::Filtered>; - using JetTracksMCDwID = soa::Filtered>; - using OriginalTracks = soa::Join; + using JetTrackswID = soa::Filtered>; + using JetTracksMCDwID = soa::Filtered>; using DataJets = soa::Filtered>; + // Function to get the reduction factor based on jet pT + double getReductionFactor(double jetPT) + { + // Loop through the jetPtBins vector + for (size_t ibin = 0; ibin < jetPtBinsReduction.size() - 1; ++ibin) { + if (jetPT >= jetPtBinsReduction[ibin] && jetPT < jetPtBinsReduction[ibin + 1]) { + return jetReductionFactorsPt[ibin]; + } + } + + // If jetPT is above the last bin, use the last reduction factor + if (jetPT >= jetPtBinsReduction.back()) { + return jetReductionFactorsPt.back(); + } + + // If jetPT is below the first bin, return the first reduction factor + return jetReductionFactorsPt.front(); + } + // Looping over the SV info and writing them to a table - template - void analyzeJetSVInfo(AnalysisJet const& myJet, SecondaryVertices const& allSVs, std::vector& svIndices, int jetFlavor = 0, double eventweight = 1.0) + template + void analyzeJetSVInfo(AnalysisJet const& myJet, AnyTracks const& /*allTracks*/, SecondaryVertices const& /*allSVs*/, std::vector& svIndices, int jetFlavor = 0, double eventweight = 1.0) { - for (const auto& candSV : myJet.template secondaryVertices_as()) { + using SVType = typename SecondaryVertices::iterator; + + // Min-heap to store the top 30 SVs by decayLengthXY/errorDecayLengthXY + auto compare = [](SVType& sv1, SVType& sv2) { + return (sv1.decayLengthXY() / sv1.errorDecayLengthXY()) > (sv2.decayLengthXY() / sv2.errorDecayLengthXY()); + }; + + auto svs = myJet.template secondaryVertices_as(); + + // Sort the SVs based on their decay length significance in descending order + // This is needed in order to select longest SVs since some jets could have thousands of SVs + std::sort(svs.begin(), svs.end(), compare); + + for (const auto& candSV : svs) { if (candSV.pt() < svPtMin) { continue; @@ -265,10 +318,12 @@ struct BJetTreeCreator { double massSV = candSV.m(); double energySV = candSV.e(); - if (produceTree) { - bjetSVParamsTable(bjetParamsTable.lastIndex() + 1, candSV.pt(), deltaRJetSV, massSV, energySV / myJet.energy(), candSV.impactParameterXY(), candSV.cpa(), candSV.chi2PCA(), candSV.decayLengthXY(), candSV.errorDecayLengthXY(), candSV.decayLength(), candSV.errorDecayLength()); + if (svIndices.size() < (svReductionFactor * myJet.template tracks_as().size()) && svIndices.size() < maxConstSV) { + if (produceTree) { + bjetSVParamsTable(bjetParamsTable.lastIndex() + 1, candSV.pt(), deltaRJetSV, massSV, energySV / myJet.energy(), candSV.impactParameterXY(), candSV.cpa(), candSV.chi2PCA(), candSV.dispersion(), candSV.decayLengthXY(), candSV.errorDecayLengthXY(), candSV.decayLength(), candSV.errorDecayLength()); + } + svIndices.push_back(bjetSVParamsTable.lastIndex()); } - svIndices.push_back(bjetSVParamsTable.lastIndex()); registry.fill(HIST("h2_LxyS_jetpT"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); registry.fill(HIST("h2_Dispersion_jetpT"), myJet.pt(), candSV.chi2PCA(), eventweight); @@ -293,19 +348,18 @@ struct BJetTreeCreator { } template - void analyzeJetTrackInfo(AnyCollision const& collision, AnalysisJet const& analysisJet, AnyTracks const& allTracks, SecondaryVertices const& allSVs, std::vector& trackIndices, int jetFlavor = 0, double eventweight = 1.0) + void analyzeJetTrackInfo(AnyCollision const& /*collision*/, AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, SecondaryVertices const& /*allSVs*/, std::vector& trackIndices, int jetFlavor = 0, double eventweight = 1.0) { - for (auto& jconstituent : analysisJet.template tracks_as()) { + for (auto& constituent : analysisJet.template tracks_as()) { - if (jconstituent.pt() < trackPtMin) { + if (constituent.pt() < trackPtMin) { continue; } - auto constituent = jconstituent.template track_as(); double deltaRJetTrack = jetutilities::deltaR(analysisJet, constituent); double dotProduct = RecoDecay::dotProd(std::array{analysisJet.px(), analysisJet.py(), analysisJet.pz()}, std::array{constituent.px(), constituent.py(), constituent.pz()}); - int sign = jettaggingutilities::getGeoSign(collision, analysisJet, constituent); + int sign = jettaggingutilities::getGeoSign(analysisJet, constituent); float RClosestSV = 10.; for (const auto& candSV : analysisJet.template secondaryVertices_as()) { @@ -315,41 +369,37 @@ struct BJetTreeCreator { } } - float dcaXYZ(0.), sigmaDcaXYZ2(0.); - dcaXYZ = getDcaXYZ(constituent, &sigmaDcaXYZ2); - // jettaggingutilities::calculateDcaXYZ(dcaXYZ, sigmaDcaXYZ2, constituent.dcaXY(), constituent.dcaZ(), constituent.cYY(), constituent.cZY(), constituent.cZZ(), constituent.sigmaDcaXY2(), constituent.sigmaDcaZ2()); - - registry.fill(HIST("h2_SIPs2D_jetpT"), analysisJet.pt(), sign * TMath::Abs(constituent.dcaXY()) / TMath::Sqrt(constituent.sigmaDcaXY2()), eventweight); - registry.fill(HIST("h2_SIPs3D_jetpT"), analysisJet.pt(), sign * dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2), eventweight); + registry.fill(HIST("h2_SIPs2D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); if (doprocessMCJets) { if (jetFlavor == 2) { - registry.fill(HIST("h2_SIPs2D_jetpT_bjet"), analysisJet.pt(), sign * TMath::Abs(constituent.dcaXY()) / TMath::Sqrt(constituent.sigmaDcaXY2()), eventweight); - registry.fill(HIST("h2_SIPs3D_jetpT_bjet"), analysisJet.pt(), sign * dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2), eventweight); + registry.fill(HIST("h2_SIPs2D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); } else if (jetFlavor == 1) { - registry.fill(HIST("h2_SIPs2D_jetpT_cjet"), analysisJet.pt(), sign * TMath::Abs(constituent.dcaXY()) / TMath::Sqrt(constituent.sigmaDcaXY2()), eventweight); - registry.fill(HIST("h2_SIPs3D_jetpT_cjet"), analysisJet.pt(), sign * dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2), eventweight); + registry.fill(HIST("h2_SIPs2D_jetpT_cjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT_cjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); } else { - registry.fill(HIST("h2_SIPs2D_jetpT_lfjet"), analysisJet.pt(), sign * TMath::Abs(constituent.dcaXY()) / TMath::Sqrt(constituent.sigmaDcaXY2()), eventweight); - registry.fill(HIST("h2_SIPs3D_jetpT_lfjet"), analysisJet.pt(), sign * dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2), eventweight); + registry.fill(HIST("h2_SIPs2D_jetpT_lfjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); + registry.fill(HIST("h2_SIPs3D_jetpT_lfjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); } } if (produceTree) { - bjetTracksParamsTable(bjetParamsTable.lastIndex() + 1, constituent.pt(), constituent.eta(), dotProduct, dotProduct / analysisJet.p(), deltaRJetTrack, TMath::Abs(constituent.dcaXY()) * sign, TMath::Sqrt(constituent.sigmaDcaXY2()), dcaXYZ * sign, TMath::Sqrt(sigmaDcaXYZ2), constituent.p() / analysisJet.p(), RClosestSV); + bjetTracksParamsTable(bjetParamsTable.lastIndex() + 1, constituent.pt(), constituent.eta(), dotProduct, dotProduct / analysisJet.p(), deltaRJetTrack, std::abs(constituent.dcaXY()) * sign, constituent.sigmadcaXY(), std::abs(constituent.dcaXYZ()) * sign, constituent.sigmadcaXYZ(), constituent.p() / analysisJet.p(), RClosestSV); } trackIndices.push_back(bjetTracksParamsTable.lastIndex()); } } - void processDummy(FilteredCollision::iterator const& collision) + void processDummy(FilteredCollision::iterator const& /*collision*/) { } PROCESS_SWITCH(BJetTreeCreator, processDummy, "Dummy process function turned on by default", true); - void processDataJets(FilteredCollision::iterator const& collision, DataJets const& alljets, JetTrackswID const& allTracks, OriginalTracks const& allOrigTracks, aod::DataSecondaryVertex3Prongs const& allSVs) + void processDataJets(FilteredCollision::iterator const& collision, DataJets const& alljets, JetTrackswID const& allTracks, aod::DataSecondaryVertex3Prongs const& allSVs) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || (static_cast(std::rand()) / RAND_MAX < eventReductionFactor)) { return; } @@ -369,20 +419,26 @@ struct BJetTreeCreator { continue; } + if (static_cast(std::rand()) / RAND_MAX < getReductionFactor(analysisJet.pt())) { + continue; + } + std::vector tracksIndices; std::vector SVsIndices; - analyzeJetSVInfo(analysisJet, allSVs, SVsIndices); + analyzeJetSVInfo(analysisJet, allTracks, allSVs, SVsIndices); analyzeJetTrackInfo(collision, analysisJet, allTracks, allSVs, tracksIndices); registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass()); + int nSVs = analysisJet.template secondaryVertices_as().size(); + registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), tracksIndices.size()); - registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), SVsIndices.size() < 250 ? SVsIndices.size() : 249); + registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); if (produceTree) { bjetConstituentsTable(bjetParamsTable.lastIndex() + 1, tracksIndices, SVsIndices); - bjetParamsTable(analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), tracksIndices.size(), SVsIndices.size(), analysisJet.mass(), 0, analysisJet.r()); + bjetParamsTable(analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), tracksIndices.size(), nSVs, analysisJet.mass(), 0, analysisJet.r()); } } } @@ -395,9 +451,9 @@ struct BJetTreeCreator { Preslice McParticlesPerCollision = aod::jmcparticle::mcCollisionId; Preslice McPJetsPerCollision = aod::jet::mcCollisionId; - void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, JetParticles const& MCParticles, aod::MCDSecondaryVertex3Prongs const& allSVs, OriginalTracks const& origTracks) + void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, JetParticles const& MCParticles, aod::MCDSecondaryVertex3Prongs const& allSVs) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || (static_cast(std::rand()) / RAND_MAX < eventReductionFactor)) { return; } @@ -420,10 +476,15 @@ struct BJetTreeCreator { continue; } + float eventWeight = analysisJet.eventWeight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (analysisJet.pt() > pTHatMaxMCD * pTHat) { + continue; + } + std::vector tracksIndices; std::vector SVsIndices; - float eventWeight = analysisJet.eventWeight(); int16_t jetFlavor = 0; // JetTracksMCDwID::iterator hftrack; @@ -431,16 +492,27 @@ struct BJetTreeCreator { // jetFlavor = jettaggingutilities::jetTrackFromHFShower(analysisJet, nonFilteredTracks, mcParticlesPerColl, hftrack); for (auto& mcpjet : analysisJet.template matchedJetGeo_as()) { - jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, mcParticlesPerColl); - // jetFlavor = jettaggingutilities::mcpJetFromHFShower(mcpjet, mcParticlesPerColl, (float)(mcpjet.r() / 100.)); + if (useQuarkDef) { + jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, mcParticlesPerColl); + } else { + jetFlavor = jettaggingutilities::getJetFlavorHadron(mcpjet, mcParticlesPerColl); + // jetFlavor = jettaggingutilities::mcpJetFromHFShower(mcpjet, mcParticlesPerColl, (float)(mcpjet.r() / 100.)); + } + } + + if ((jetFlavor != JetTaggingSpecies::charm && jetFlavor != JetTaggingSpecies::beauty) && (static_cast(std::rand()) / RAND_MAX < getReductionFactor(analysisJet.pt()))) { + continue; } - analyzeJetSVInfo(analysisJet, allSVs, SVsIndices, jetFlavor, eventWeight); + + analyzeJetSVInfo(analysisJet, allTracks, allSVs, SVsIndices, jetFlavor, eventWeight); analyzeJetTrackInfo(collision, analysisJet, allTracks, allSVs, tracksIndices, jetFlavor, eventWeight); + int nSVs = analysisJet.template secondaryVertices_as().size(); + registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass(), eventWeight); registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), tracksIndices.size()); - registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), SVsIndices.size() < 250 ? SVsIndices.size() : 249); + registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); if (jetFlavor == 2) { registry.fill(HIST("h2_jetMass_jetpT_bjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); @@ -454,6 +526,11 @@ struct BJetTreeCreator { } for (auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { + continue; + } + if (jetFlavor == 2) { registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_bjet"), analysisJet.pt(), mcpjet.pt(), eventWeight); } else if (jetFlavor == 1) { @@ -465,7 +542,7 @@ struct BJetTreeCreator { if (produceTree) { bjetConstituentsTable(bjetParamsTable.lastIndex() + 1, tracksIndices, SVsIndices); - bjetParamsTable(analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), tracksIndices.size(), SVsIndices.size(), analysisJet.mass(), jetFlavor, analysisJet.r()); + bjetParamsTable(analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), tracksIndices.size(), nSVs, analysisJet.mass(), jetFlavor, analysisJet.r()); } } } @@ -474,7 +551,7 @@ struct BJetTreeCreator { Filter mccollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; using FilteredCollisionMCP = soa::Filtered; - void processMCTruthJets(FilteredCollisionMCP::iterator const& collision, MCPJetTable const& MCPjets, JetParticles const& MCParticles) + void processMCTruthJets(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTable const& MCPjets, JetParticles const& MCParticles) { for (const auto& mcpjet : MCPjets) { @@ -491,11 +568,19 @@ struct BJetTreeCreator { continue; } - int16_t jetFlavor = 0; - jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, MCParticles); - // jetFlavor = jettaggingutilities::mcpJetFromHFShower(mcpjet, mcParticlesPerColl, (float)(mcpjet.r() / 100.)); - float eventWeight = mcpjet.eventWeight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { + continue; + } + + int16_t jetFlavor = 0; + if (useQuarkDef) { + jetFlavor = jettaggingutilities::getJetFlavor(mcpjet, MCParticles); + } else { + jetFlavor = jettaggingutilities::getJetFlavorHadron(mcpjet, MCParticles); + // jetFlavor = jettaggingutilities::mcpJetFromHFShower(mcpjet, MCParticles, (float)(mcpjet.r() / 100.)); + } if (jetFlavor == 2) { registry.fill(HIST("h_jetpT_particle_bjet"), mcpjet.pt(), eventWeight); diff --git a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx index 2a298d0a44b..610e890cf20 100644 --- a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx +++ b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx @@ -201,7 +201,7 @@ struct Pi0EnergyScaleCalibTask { Configurable mMinEnergyCut{"MinEnergyCut", 0.7, "apply min cluster energy cut"}; Configurable mMinNCellsCut{"MinNCellsCut", 1, "apply min cluster number of cell cut"}; Configurable mMinOpenAngleCut{"OpeningAngleCut", 0.0202, "apply min opening angle cut"}; - Configurable mClusterDefinition{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + Configurable mClusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10 = kV3Default"}; Configurable mRequireBothPhotonsFromAcceptance{"RequireBothPhotonsFromAcceptance", 0, "Require both photons to be from the same acceptance category"}; Configurable mAcceptanceRestrictionType{"AcceptanceRestrictionType", 0, "0: No restriction, 1: Ignore behind TRD, 2: Only Behind TRD, 3: Only EMCal, 4: OnlyDCal, 5: Remove clusters on edges"}; @@ -213,8 +213,7 @@ struct Pi0EnergyScaleCalibTask { // define cluster filter. It selects only those clusters which are of the type // specified in the string mClusterDefinition,e.g. kV3Default, which is V3 clusterizer with default // clusterization parameters - o2::aod::EMCALClusterDefinition clusDef = o2::aod::emcalcluster::getClusterDefinitionFromString(mClusterDefinition.value); - Filter clusterDefinitionSelection = o2::aod::emcalcluster::definition == static_cast(clusDef); + Filter clusterDefinitionSelection = o2::aod::emcalcluster::definition == mClusterDefinition; // define container for photons std::vector mPhotons; diff --git a/PWGJE/Tasks/emcvertexselectionqa.cxx b/PWGJE/Tasks/emcvertexselectionqa.cxx index 9d3a33a2443..b5664f32a3f 100644 --- a/PWGJE/Tasks/emcvertexselectionqa.cxx +++ b/PWGJE/Tasks/emcvertexselectionqa.cxx @@ -66,6 +66,10 @@ struct EmcVertexSelectionQA { mHistManager.add("hVertexRelDiffRobustStdDevDCA", "Relative Difference of Robust StdDev DCA to StdDev DCA of Vertex vs its Quality", o2HistType::kTH2F, {{200, 0, 2}, qualityAxis}); mHistManager.add("hVertexRelDiffRobustStdDevTrackTime", "Relative Difference of Robust Standard Deviation to Standard Deviation of Tracks Contributing to the Vertex vs its Quality", o2HistType::kTH2F, {{200, 0, 2}, qualityAxis}); + // Z vertex positions of two vertices in the same BC (to look for two collisions in the same BC with similar z-vertex positions) + mHistManager.add("hDoubleZVertex", "Z Vertex Position Correlation of two Collions in the same BC", o2HistType::kTH2F, {{300, -15., 15.}, {300, -15., 15.}}); + mHistManager.add("hZVertexDiff", "Difference Z Vertex Position of two Collions in the same BC", o2HistType::kTH1F, {{40000, -20., 20., "Z_{vtx 1}-Z_{vtx 2} (cm)"}}); + // Set axis labels and bin titles initVertexHistogram(mHistManager.get(HIST("hCollisionMatching")).get()); initVertexHistogram(mHistManager.get(HIST("hCollisionMatchingReadout")).get()); @@ -84,6 +88,8 @@ struct EmcVertexSelectionQA { mHistManager.get(HIST("hnVertexContributors")).get()->GetXaxis()->SetTitle("N_{contr} to Vtx 1"); mHistManager.get(HIST("hnVertexContributors")).get()->GetYaxis()->SetTitle("N_{contr} to Vtx 2"); + mHistManager.get(HIST("hDoubleZVertex")).get()->GetXaxis()->SetTitle("Z_{vtx 1} (cm)"); + mHistManager.get(HIST("hDoubleZVertex")).get()->GetYaxis()->SetTitle("Z_{vtx 2} (cm)"); } Preslice perCollision = aod::track::collisionId; @@ -91,21 +97,7 @@ struct EmcVertexSelectionQA { void process(bcEvSels const& bcs, collEventSels const& collisions, FullTracksIU const& tracks) { for (const auto& bc : bcs) { - bool isEMCALreadout = false; - - if (bc.runNumber() > 300000) { - // in case of run3 not all BCs contain EMCAL data, require trigger selection also for min. bias - // in addition select also L0/L1 triggers as triggers with EMCAL in reaodut - if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)) { - isEMCALreadout = true; - } - } else { - // run1/2: rely on trigger cluster, runlist must contain only runs with EMCAL in readout - // Select min. bias trigger and EMCAL L0/L1 triggers - if (bc.alias_bit(kINT7) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2)) { - isEMCALreadout = true; - } - } + bool isEMCALreadout = (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)); auto colsinbc = collisions.sliceBy(perFoundBC, bc.globalIndex()); int collisionStatus = -1; @@ -127,6 +119,7 @@ struct EmcVertexSelectionQA { if (collisionStatus > 0) { int nVtx = 0; int nVtxwithTOForTRDcontr = 0; + std::vector zVertexPositions; std::vector nVtxContributors; for (auto& col : colsinbc) { // Loop over all collisions/vertices int ivtxquality = 0; // 0: TPC/ITS contributor, 1: TRD contributor , 2: TOF contributor @@ -184,12 +177,16 @@ struct EmcVertexSelectionQA { nVtxwithTOForTRDcontr++; } nVtxContributors.push_back(nPVContributorTracks); + zVertexPositions.push_back(col.posZ()); } mHistManager.fill(HIST("hnVerticeswithTOForTRDcontr"), nVtx, nVtxwithTOForTRDcontr); if (collisionStatus == 2) { mHistManager.fill(HIST("hnVertexContributors"), nVtxContributors.at(0), nVtxContributors.at(1)); + mHistManager.fill(HIST("hDoubleZVertex"), zVertexPositions.at(0), zVertexPositions.at(1)); + mHistManager.fill(HIST("hZVertexDiff"), zVertexPositions.at(0) - zVertexPositions.at(1)); } nVtxContributors.clear(); + zVertexPositions.clear(); } } } diff --git a/PWGJE/Tasks/fulljetspectrapp.cxx b/PWGJE/Tasks/fulljetspectrapp.cxx new file mode 100644 index 00000000000..b93f05ca427 --- /dev/null +++ b/PWGJE/Tasks/fulljetspectrapp.cxx @@ -0,0 +1,897 @@ +// Copyright 2019-2020 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. + +// FullJet Spectra in pp +// +// TO DO: +// 1. implement HadCorr +// +/// \author Archita Rani Dash +#include +#include +#include + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/Core/HfHelper.h" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" + +#include "EventFiltering/filterTables.h" + +using namespace std; +using namespace o2; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using EMCCollisions = o2::soa::Join; // needed for the workaround to access EMCAL trigger bits + +struct FullJetSpectrapp { + + HistogramRegistry registry; + + // Event configurables + Configurable VertexZCut{"VertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; + Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; + Configurable doEMCALEventWorkaround{"doEMCALEventWorkaround", false, "apply the workaround to read the EMC trigger bit by requiring a cell content in the EMCAL"}; + Configurable doMBGapTrigger{"doMBGapTrigger", false, "set to true only when using MB-Gap Trigger JJ MC"}; + Configurable doJJMC{"doJJMC", false, "set to true only when using JJ MC"}; + + // Jet configurables + Configurable selectedJetsRadius{"selectedJetsRadius", 0.4, "resolution parameter for histograms without radius"}; + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; + Configurable jetpTMin{"jetpTMin", 20.0, "minimum jet pT"}; + Configurable jetpTMax{"jetpTMax", 350., "maximum jet pT"}; + Configurable jetEtaMin{"jetEtaMin", -0.3, "minimum jet eta"}; // each of these jet configurables are for the fiducial emcal cuts + Configurable jetEtaMax{"jetEtaMax", 0.3, "maximum jet eta"}; // for R = 0.4 (EMCAL eta acceptance: eta_jet = 0.7 - R) + Configurable jetPhiMin{"jetPhiMin", 1.80, "minimum jet phi"}; // phi_jet_min for R = 0.4 is 1.80 + Configurable jetPhiMax{"jetPhiMax", 2.86, "maximum jet phi"}; // phi_jet_min for R = 0.4 is 2.86 + Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; + Configurable leadingConstituentPtMin{"leadingConstituentPtMin", -99.0, "minimum pT selection on jet constituent"}; + + // Track configurables + Configurable trackpTMin{"trackpTMin", 0.15, "minimum track pT"}; + Configurable trackpTMax{"trackpTMax", 350., "maximum track pT"}; + Configurable trackEtaMin{"trackEtaMin", -0.7, "minimum track eta"}; + Configurable trackEtaMax{"trackEtaMax", 0.7, "maximum track eta"}; + Configurable trackPhiMin{"trackPhiMin", 1.396, "minimum track phi"}; + Configurable trackPhiMax{"trackPhiMax", 3.283, "maximum track phi"}; + Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable eventSelections{"eventSelections", "sel8Full", "choose event selection"}; + Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; + + // Cluster configurables + + Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + Configurable clusterEtaMin{"clusterEtaMin", -0.7, "minimum cluster eta"}; + Configurable clusterEtaMax{"clusterEtaMax", 0.7, "maximum cluster eta"}; + Configurable clusterPhiMin{"clusterPhiMin", 1.396, "minimum cluster phi"}; + Configurable clusterPhiMax{"clusterPhiMax", 3.283, "maximum cluster phi"}; + Configurable clusterEnergyMin{"clusterEnergyMin", 0.3, "minimum cluster energy in EMCAL (GeV)"}; + Configurable clusterTimeMin{"clusterTimeMin", -20., "minimum cluster time (ns)"}; + Configurable clusterTimeMax{"clusterTimeMax", 15., "maximum cluster time (ns)"}; + Configurable clusterRejectExotics{"clusterRejectExotics", true, "Reject exotic clusters"}; + + Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + Configurable pTHatExponent{"pTHatExponent", 4.0, "exponent of the event weight for the calculation of pTHat"}; // 6 for MB MC and 4 for JJ MC + + int trackSelection = -1; + int eventSelection = -1; + std::vector filledJetR; + std::vector jetRadiiValues; + + std::string particleSelection; + + Service pdgDatabase; + + // Add Collision Histograms' Bin Labels for clarity + void labelCollisionHistograms(HistogramRegistry& registry) + { + if (doprocessTracks) { + auto h_collisions_unweighted = registry.get(HIST("h_collisions_unweighted")); + h_collisions_unweighted->GetXaxis()->SetBinLabel(1, "total events"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(2, "JetsData with kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(3, "JetsMCD with kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(4, "Tracks with kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(5, "JetsMCPMCDMatched with kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(6, "JetsData w/o kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(7, "JetsMCD w/o kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(8, "Tracks w/o kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(9, "JetsMCPMCDMatched w/o kTVXinEMC"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(10, "Fake Matched MCD Jets"); + h_collisions_unweighted->GetXaxis()->SetBinLabel(11, "Fake Matched MCP Jets"); + } + + if (doprocessTracksWeighted) { + auto h_collisions_weighted = registry.get(HIST("h_collisions_weighted")); + h_collisions_weighted->GetXaxis()->SetBinLabel(1, "total events"); + h_collisions_weighted->GetXaxis()->SetBinLabel(2, "JetsMCDWeighted with kTVXinEMC"); + h_collisions_weighted->GetXaxis()->SetBinLabel(3, "JetsMCPMCDMatchedWeighted with kTVXinEMC"); + h_collisions_weighted->GetXaxis()->SetBinLabel(4, "TracksWeighted with kTVXinEMC"); + h_collisions_weighted->GetXaxis()->SetBinLabel(5, "JetsMCDWeighted w/o kTVXinEMC"); + h_collisions_weighted->GetXaxis()->SetBinLabel(6, "JetsMCPMCDMatchedWeighted w/o kTVXinEMC"); + h_collisions_weighted->GetXaxis()->SetBinLabel(7, "TracksWeighted w/o kTVXinEMC"); + h_collisions_weighted->GetXaxis()->SetBinLabel(8, "Fake Matched Weighted MCD Jets"); + h_collisions_weighted->GetXaxis()->SetBinLabel(9, "Fake Matched Weighted MCP Jets"); + } + } + + void init(o2::framework::InitContext&) + { + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); + particleSelection = static_cast(particleSelections); + jetRadiiValues = (std::vector)jetRadii; + + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + filledJetR.push_back(0.0); + } + auto jetRadiiBins = (std::vector)jetRadii; + if (jetRadiiBins.size() > 1) { + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + (TMath::Abs(jetRadiiBins[jetRadiiBins.size() - 1] - jetRadiiBins[jetRadiiBins.size() - 2]))); + } else { + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); + } + + // Track QA histograms + if (doprocessTracks || doprocessTracksWeighted) { + registry.add("h_collisions_unweighted", "event status; event status;entries", {HistType::kTH1F, {{12, 0., 12.0}}}); + + registry.add("h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h_track_energy", "track energy;Energy of tracks;entries", {HistType::kTH1F, {{400, 0., 400.}}}); + registry.add("h_track_energysum", "track energy sum;Sum of track energy per event;entries", {HistType::kTH1F, {{400, 0., 400.}}}); + + // registry.add("h_gaptrig_track_pt", "gap triggered track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + // registry.add("h_gaptrig_track_eta", "gap triggered track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + // registry.add("h_gaptrig_track_phi", "gap triggered track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + + // Cluster QA histograms + registry.add("h_cluster_pt", "cluster pT;#it{p}_{T_cluster} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_cluster_eta", "cluster #eta;#eta_{cluster};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_cluster_phi", "cluster #varphi;#varphi_{cluster};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h_cluster_energy", "cluster energy;Energy of cluster;entries", {HistType::kTH1F, {{400, 0., 400.}}}); + registry.add("h_cluster_energysum", "cluster energy sum;Sum of cluster energy per event;entries", {HistType::kTH1F, {{400, 0., 400.}}}); + + // registry.add("h_gaptrig_cluster_pt", "gap triggered cluster pT;#it{p}_{T_cluster} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + // registry.add("h_gaptrig_cluster_eta", "gap triggered cluster #eta;#eta_{cluster};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + // registry.add("h_gaptrig_cluster_phi", "gap triggered cluster #varphi;#varphi_{cluster};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + // registry.add("h_gaptrig_cluster_energy", "gap triggered cluster #varphi;#varphi_{cluster};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + + if (doprocessTracksWeighted) { + registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{12, 0.0, 12.0}}}); + registry.add("h_gaptrig_collisions", "event status; event status; entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + + // registry.add("h_gaptrig_track_pt", "gap triggered track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + // registry.add("h_gaptrig_track_eta", "gap triggered track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + // registry.add("h_gaptrig_track_phi", "gap triggered track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + // + // registry.add("h_gaptrig_cluster_pt", "gap triggered cluster pT;#it{p}_{T_cluster} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + // registry.add("h_gaptrig_cluster_eta", "gap triggered cluster #eta;#eta_{cluster};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + // registry.add("h_gaptrig_cluster_phi", "gap triggered cluster #varphi;#varphi_{cluster};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + // registry.add("h_gaptrig_cluster_energy", "gap triggered cluster #varphi;#varphi_{cluster};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + } + } + + // Jet QA histograms + if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { + registry.add("h_full_jet_pt", "#it{p}_{T,jet};#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_full_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_full_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h2_full_jet_NEF", "#it{p}_{T,jet} vs NEF at Det Level; #it{p}_{T,jet} (GeV/#it{c});NEF", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); + registry.add("h2_full_jet_NEF_rejected", "#it{p}_{T,jet} vs NEF at Det Level for rejected events; #it{p}_{T,jet} (GeV/#it{c});NEF", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); + + registry.add("h_Detjet_ntracks", "#it{p}_{T,track};#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h2_full_jet_chargedconstituents", "Number of charged constituents at Det Level;#it{p}_{T,jet} (GeV/#it{c});N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2_full_jet_neutralconstituents", "Number of neutral constituents at Det Level;#it{p}_{T,jet} (GeV/#it{c});N_{ne}", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2_full_jettrack_pt", "#it{p}_{T,jet} vs #it{p}_{T,track}; #it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{350, 0., 350.}, {200, 0., 200.}}}); + registry.add("h2_full_jettrack_eta", "jet #eta vs jet_track #eta; #eta_{jet};#eta_{track}", {HistType::kTH2F, {{100, -1., 1.}, {500, -5., 5.}}}); + registry.add("h2_full_jettrack_phi", "jet #varphi vs jet_track #varphi; #varphi_{jet}; #varphi_{track}", {HistType::kTH2F, {{160, 0., 7.}, {160, -1., 7.}}}); + + registry.add("h2_track_etaphi", "jet_track #eta vs jet_track #varphi; #eta_{track};#varphi_{track}", {HistType::kTH2F, {{500, -5., 5.}, {160, -1., 7.}}}); + registry.add("h2_jet_etaphi", "jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); + // registry.add("h_full_mcdjet_tablesize", "", {HistType::kTH1F, {{4, 0., 5.}}}); + // registry.add("h_gaptrig_full_jet_pt", "gap triggered jet pT;#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + // registry.add("h_gaptrig_full_jet_eta", "gap triggered jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + // registry.add("h_gaptrig_full_jet_phi", "gap triggered jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + } + if (doprocessJetsMCP || doprocessJetsMCPWeighted) { + registry.add("h_full_mcpjet_tablesize", "", {HistType::kTH1F, {{4, 0., 5.}}}); + registry.add("h_full_mcpjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); + registry.add("h_full_jet_pt_part", "jet pT;#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_full_jet_eta_part", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_full_jet_phi_part", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h2_full_jet_NEF_part", "#it{p}_{T,jet} vs NEF at Part Level;#it{p}_{T,jet} (GeV/#it{c});NEF", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); + + registry.add("h_Partjet_ntracks", "#it{p}_{T,constituent};#it{p}_{T_constituent} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h2_full_jet_chargedconstituents_part", "Number of charged constituents at Part Level;#it{p}_{T,jet} (GeV/#it{c});N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2_full_jet_neutralconstituents_part", "Number of neutral constituents at Part Level;#it{p}_{T,jet} (GeV/#it{c});N_{ne}", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2_jettrack_pt_part", "#it{p}_{T,jet} vs #it{p}_{T_track}; #it{p}_{T_jet} (GeV/#it{c});#it{p}_{T_track} (GeV/#it{c})", {HistType::kTH2F, {{350, 0., 350.}, {200, 0., 200.}}}); + registry.add("h2_jettrack_eta_part", "jet #eta vs jet_track #eta; #eta_{jet};#eta_{track}", {HistType::kTH2F, {{100, -1., 1.}, {500, -5., 5.}}}); + registry.add("h2_jettrack_phi_part", "jet #varphi vs jet_track #varphi; #varphi_{jet}; #varphi_{track}", {HistType::kTH2F, {{160, 0., 7.}, {160, -1., 7.}}}); + + registry.add("h2_track_etaphi_part", "jet_track #eta vs jet_track #varphi; #eta_{track};#varphi_{track}", {HistType::kTH2F, {{500, -5., 5.}, {160, -1., 7.}}}); + registry.add("h2_jet_etaphi_part", "jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); + // registry.add("h_gaptrig_full_mcpjet_tablesize", "", {HistType::kTH1F, {{4, 0., 5.}}}); + // registry.add("h_gaptrig_full_mcpjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); + // registry.add("h_gaptrig_full_jet_pt_part", "jet pT;#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + // registry.add("h_gaptrig_full_jet_eta_part", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + // registry.add("h_gaptrig_full_jet_phi_part", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + } + + if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted) { + registry.add("h_full_matchedmcdjet_tablesize", "", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_full_matchedmcpjet_tablesize", "", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_full_matchedmcdjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); + registry.add("h_full_matchedmcpjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); + registry.add("h_full_matchedmcdjet_eta", "Matched MCD jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_full_matchedmcdjet_phi", "Matched MCD jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h_full_matchedmcpjet_eta", "Matched MCP jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_full_matchedmcpjet_phi", "Matched MCP jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h_full_jet_deltaR", "Distance between matched Det Jet and Part Jet; \\Delta R; entries", {HistType::kTH1F, {{100, 0., 1.}}}); + + registry.add("h2_full_jet_energyscaleDet", "Jet Energy Scale (det); p_{T,det} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH2F, {{400, 0., 400.}, {200, -1., 1.}}}); + + // registry.add("h2_matchedjettrack_eta", "jet #eta vs jet_track #eta; #eta_{jet};#eta_{track}", {HistType::kTH2F, {{100, -1., 1.}, {500, -5., 5.}}}); + // registry.add("h2_matchedjettrack_phi", "jet #varphi vs jet_track #varphi; #varphi_{jet}; #varphi_{track}", {HistType::kTH2F, {{160, 0., 7.}, {160, -1., 7.}}}); + + registry.add("h2_matchedjet_etaphiDet", "Det jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); + registry.add("h2_matchedjet_etaphiPart", "Part jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); + + // registry.add("h_full_jet_energyscaleDetCharged", "Jet Energy Scale (det, charged part); p_{t,det} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + // registry.add("h_full_jet_energyscaleDetNeutral", "Jet Energy Scale (det, neutral part); p_{t,det} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + // registry.add("h_full_jet_energyscaleDetChargedVsFull", "Jet Energy Scale (det, charged part, vs. full jet pt); p_{t,det} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + // registry.add("h_full_jet_energyscaleDetNeutralVsFull", "Jet Energy Scale (det, neutral part, vs. full jet pt); p_{t,det} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + registry.add("h2_full_jet_energyscalePart", "Jet Energy Scale (part); p_{T,part} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH2F, {{400, 0., 400.}, {200, -1., 1.}}}); + registry.add("h3_full_jet_energyscalePart", "R dependence of Jet Energy Scale (Part); #it{R}_{jet};p_{T,det} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, 0., 400.}, {200, -1., 1.}}}); + registry.add("h2_full_jet_etaresolutionPart", ";p_{T,part} (GeV/c); (#eta_{jet,det} - #eta_{jet,part})/#eta_{jet,part}", {HistType::kTH2F, {{400, 0., 400.}, {100, -1., 1.}}}); + registry.add("h2_full_jet_phiresolutionPart", ";p_{T,part} (GeV/c); (#varphi_{jet,det} - #varphi_{jet,part})/#varphi_{jet,part}", {HistType::kTH2F, {{400, 0., 400.}, {160, -1., 7.}}}); + // registry.add("h_full_jet_energyscaleCharged", "Jet Energy Scale (charged part); p_{t,part} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + // registry.add("h_full_jet_energyscaleNeutral", "Jet Energy Scale (neutral part); p_{t,part} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + // registry.add("h_full_jet_energyscaleChargedVsFull", "Jet Energy Scale (charged part, vs. full jet pt); p_{t,part} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + // registry.add("h_full_jet_energyscaleNeutralVsFull", "Jet Energy Scale (neutral part, vs. full jet pt); p_{t,part} (GeV/c); (p_{t,det} - p_{t,part})/p_{t,part}", {HistType::kTH2F,{{400, 0., 400., 200, -1.,1.}}}); + registry.add("h2_full_fakemcdjets", "Fake MCD Jets; p_{T,det} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2_full_fakemcpjets", "Fake MCP Jets; p_{T,part} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + // Response Matrix + registry.add("h_full_jet_ResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); + + // registry.add("h_gaptrig_full_matchedmcdjet_tablesize", "", {HistType::kTH1F, {{4, 0., 5.}}}); + // registry.add("h_gaptrig_full_matchedmcdjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); + // registry.add("h_gaptrig_full_jet_energyscaleDet", "Jet Energy Scale (det); p_{T,det} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH2F,{{400, 0., 400.}, {200, -1.,1.}}}); + // registry.add("h_gaptrig_full_jet_energyscalePart", "Jet Energy Scale (part); p_{T,part} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH2F,{{400, 0., 400.}, {200, -1.,1.}}}); + // registry.add("h_gaptrig_full_jet_ResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F,{{400, 0., 400.}, {400,0.,400.}}}); + } + + // Label the histograms + labelCollisionHistograms(registry); + + } // init + + using FullJetTableDataJoined = soa::Join; + using JetTableMCDJoined = soa::Join; + using JetTableMCDWeightedJoined = soa::Join; + using JetTableMCPJoined = soa::Join; + using JetTableMCPWeightedJoined = soa::Join; + + using JetTableMCDMatchedJoined = soa::Join; + using JetTableMCPMatchedJoined = soa::Join; + + using JetTableMCDMatchedWeightedJoined = soa::Join; + using JetTableMCPMatchedWeightedJoined = soa::Join; + + // Applying some cuts(filters) on collisions, tracks, clusters + + Filter eventCuts = (nabs(aod::jcollision::posZ) < VertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + // Filter EMCeventCuts = (nabs(aod::collision::posZ) < VertexZCut && aod::collision::centrality >= centralityMin && aod::collision::centrality < centralityMax); + Filter trackCuts = (aod::jtrack::pt >= trackpTMin && aod::jtrack::pt < trackpTMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); + aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); + Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta > clusterEtaMin && aod::jcluster::eta < clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); + Preslice JetMCPPerMcCollision = aod::jet::mcCollisionId; + + template + bool isAcceptedJet(U const& jet) + { + + if (jetAreaFractionMin > -98.0) { + if (jet.area() < jetAreaFractionMin * M_PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + return false; + } + } + if (leadingConstituentPtMin > -98.0) { + bool isMinleadingConstituent = false; + for (auto& constituent : jet.template tracks_as()) { + if (constituent.pt() >= leadingConstituentPtMin) { + isMinleadingConstituent = true; + break; + } + } + + if (!isMinleadingConstituent) { + return false; + } + } + return true; + } + template + void fillJetHistograms(T const& jet, float weight = 1.0) + { + float neutralEnergy = 0.0; + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_full_jet_pt"), jet.pt(), weight); + registry.fill(HIST("h_full_jet_eta"), jet.eta(), weight); + registry.fill(HIST("h_full_jet_phi"), jet.phi(), weight); + // registry.fill(HIST("h_full_mcdjet_tablesize"), jet.size(), weight); + // registry.fill(HIST("h_full_mcdjet_ntracks"), jet.tracksIds().size(), weight); + // } + registry.fill(HIST("h2_jet_etaphi"), jet.eta(), jet.phi(), weight); + + for (auto& cluster : jet.template clusters_as()) { + registry.fill(HIST("h2_full_jet_neutralconstituents"), jet.pt(), jet.clustersIds().size(), weight); + neutralEnergy += cluster.energy(); + } + auto NEF = neutralEnergy / jet.energy(); + registry.fill(HIST("h2_full_jet_NEF"), jet.pt(), NEF, weight); + + for (auto& jettrack : jet.template tracks_as()) { + registry.fill(HIST("h_Detjet_ntracks"), jettrack.pt(), weight); + registry.fill(HIST("h2_full_jet_chargedconstituents"), jet.pt(), jet.tracksIds().size(), weight); + registry.fill(HIST("h2_full_jettrack_pt"), jet.pt(), jettrack.pt(), weight); + registry.fill(HIST("h2_full_jettrack_eta"), jet.eta(), jettrack.eta(), weight); + registry.fill(HIST("h2_full_jettrack_phi"), jet.phi(), jettrack.phi(), weight); + + registry.fill(HIST("h2_track_etaphi"), jettrack.eta(), jettrack.phi(), weight); + } + } // jet.r() + } + + // check for NEF distribution for rejected events + template + void fillRejectedJetHistograms(T const& jet, float weight = 1.0) + { + float neutralEnergy = 0.0; + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + for (auto& cluster : jet.template clusters_as()) { + neutralEnergy += cluster.energy(); + } + auto NEF = neutralEnergy / jet.energy(); + registry.fill(HIST("h2_full_jet_NEF_rejected"), jet.pt(), NEF, weight); + } // jet.r() + } + + template + void fillMCPHistograms(T const& jet, float weight = 1.0) + { + float neutralEnergy = 0.0; + int neutralconsts = 0; + int chargedconsts = 0; + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_full_mcpjet_tablesize"), jet.size(), weight); + registry.fill(HIST("h_full_mcpjet_ntracks"), jet.tracksIds().size(), weight); + registry.fill(HIST("h_full_jet_pt_part"), jet.pt(), weight); + registry.fill(HIST("h_full_jet_eta_part"), jet.eta(), weight); + registry.fill(HIST("h_full_jet_phi_part"), jet.phi(), weight); + // registry.fill(HIST("h_full_jet_ntracks_part"), jet.tracksIds().size(), weight); + // } + registry.fill(HIST("h2_jet_etaphi_part"), jet.eta(), jet.phi(), weight); + + for (auto& constituent : jet.template tracks_as()) { + auto pdgParticle = pdgDatabase->GetParticle(constituent.pdgCode()); + if (pdgParticle->Charge() == 0) { + neutralconsts++; + neutralEnergy += constituent.e(); // neutral jet constituents at particle level + registry.fill(HIST("h2_full_jet_neutralconstituents_part"), jet.pt(), neutralconsts, weight); + } else { + chargedconsts++; + registry.fill(HIST("h2_full_jet_chargedconstituents_part"), jet.pt(), chargedconsts, weight); // charged jet constituents at particle level + registry.fill(HIST("h2_jettrack_pt_part"), jet.pt(), constituent.pt(), weight); + registry.fill(HIST("h2_jettrack_eta_part"), jet.eta(), constituent.eta(), weight); + registry.fill(HIST("h2_jettrack_phi_part"), jet.phi(), constituent.phi(), weight); + registry.fill(HIST("h2_track_etaphi_part"), constituent.eta(), constituent.phi(), weight); + } + } // constituent loop + auto NEF = neutralEnergy / jet.energy(); + registry.fill(HIST("h2_full_jet_NEF_part"), jet.pt(), NEF, weight); + } + } + + template + void fillTrackHistograms(T const& tracks, U const& clusters, float weight = 1.0) + { + double sumtrackE = 0.0; + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + sumtrackE += track.energy(); + registry.fill(HIST("h_track_pt"), track.pt(), weight); + registry.fill(HIST("h_track_eta"), track.eta(), weight); + registry.fill(HIST("h_track_phi"), track.phi(), weight); + registry.fill(HIST("h_track_energysum"), sumtrackE, weight); + } + double sumclusterE = 0.0; + for (auto const& cluster : clusters) { + double clusterpt = cluster.energy() / std::cosh(cluster.eta()); + sumclusterE += cluster.energy(); + + registry.fill(HIST("h_cluster_pt"), clusterpt, weight); + registry.fill(HIST("h_cluster_eta"), cluster.eta(), weight); + registry.fill(HIST("h_cluster_phi"), cluster.phi(), weight); + registry.fill(HIST("h_cluster_energy"), cluster.energy(), weight); + registry.fill(HIST("h_cluster_energysum"), sumclusterE, weight); + } + } + + template + void fillMatchedHistograms(T const& jetBase, float weight = 1.0) + { + if (doJJMC) { + + if (jetBase.has_matchedJetGeo()) { // geometrical jet matching only needed for pp - here,matching Base(Det.level) with Tag (Part. level) jets + registry.fill(HIST("h_full_matchedmcdjet_tablesize"), jetBase.size(), weight); + registry.fill(HIST("h_full_matchedmcdjet_ntracks"), jetBase.tracksIds().size(), weight); + registry.fill(HIST("h2_matchedjet_etaphiDet"), jetBase.eta(), jetBase.phi(), weight); + + for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { + + auto deltaEta = jetBase.eta() - jetTag.eta(); + auto deltaPhi = jetBase.phi() - jetTag.phi(); + auto deltaR = jetutilities::deltaR(jetBase, jetTag); + + registry.fill(HIST("h_full_jet_deltaR"), deltaR, weight); + registry.fill(HIST("h_full_matchedmcpjet_tablesize"), jetTag.size(), weight); + registry.fill(HIST("h_full_matchedmcpjet_ntracks"), jetTag.tracksIds().size(), weight); + registry.fill(HIST("h2_matchedjet_etaphiPart"), jetTag.eta(), jetTag.phi(), weight); + // JES + registry.fill(HIST("h2_full_jet_energyscaleDet"), jetBase.pt(), (jetBase.pt() - jetTag.pt()) / jetTag.pt(), weight); + registry.fill(HIST("h2_full_jet_energyscalePart"), jetTag.pt(), (jetBase.pt() - jetTag.pt()) / jetTag.pt(), weight); + registry.fill(HIST("h3_full_jet_energyscalePart"), jetBase.r() / 100.0, jetTag.pt(), (jetBase.pt() - jetTag.pt()) / jetTag.pt(), weight); + registry.fill(HIST("h2_full_jet_etaresolutionPart"), jetTag.pt(), deltaEta / jetTag.eta(), weight); + registry.fill(HIST("h2_full_jet_phiresolutionPart"), jetTag.pt(), deltaPhi / jetTag.phi(), weight); + + // Response Matrix + registry.fill(HIST("h_full_jet_ResponseMatrix"), jetBase.pt(), jetTag.pt(), weight); // MCD vs MCP jet pT + } // jetTag + } // jetBase + } else { + if (jetBase.has_matchedJetGeo()) { // geometrical jet matching only needed for pp - here,matching Base(Det.level) with Tag (Part. level) jets + registry.fill(HIST("h_full_matchedmcdjet_tablesize"), jetBase.size(), weight); + registry.fill(HIST("h_full_matchedmcdjet_ntracks"), jetBase.tracksIds().size(), weight); + registry.fill(HIST("h2_matchedjet_etaphiDet"), jetBase.eta(), jetBase.phi(), weight); + + for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { + + auto deltaEta = jetBase.eta() - jetTag.eta(); + auto deltaPhi = jetBase.phi() - jetTag.phi(); + auto deltaR = jetutilities::deltaR(jetBase, jetTag); + + registry.fill(HIST("h_full_jet_deltaR"), deltaR, weight); + registry.fill(HIST("h_full_matchedmcpjet_tablesize"), jetTag.size(), weight); + registry.fill(HIST("h_full_matchedmcpjet_ntracks"), jetTag.tracksIds().size(), weight); + + registry.fill(HIST("h2_matchedjet_etaphiPart"), jetTag.eta(), jetTag.phi(), weight); + // JES + registry.fill(HIST("h2_full_jet_energyscaleDet"), jetBase.pt(), (jetBase.pt() - jetTag.pt()) / jetTag.pt(), weight); + registry.fill(HIST("h2_full_jet_energyscalePart"), jetTag.pt(), (jetBase.pt() - jetTag.pt()) / jetTag.pt(), weight); + registry.fill(HIST("h3_full_jet_energyscalePart"), jetBase.r() / 100.0, jetTag.pt(), (jetBase.pt() - jetTag.pt()) / jetTag.pt(), weight); + registry.fill(HIST("h2_full_jet_etaresolutionPart"), jetTag.pt(), deltaEta / jetTag.eta(), weight); + registry.fill(HIST("h2_full_jet_phiresolutionPart"), jetTag.pt(), deltaPhi / jetTag.phi(), weight); + + // Response Matrix + registry.fill(HIST("h_full_jet_ResponseMatrix"), jetBase.pt(), jetTag.pt(), weight); // MCD vs MCP jet pT + } // jetTag + } // jetBase + } // else + } + + void processDummy(JetCollisions const&) + { + } + PROCESS_SWITCH(FullJetSpectrapp, processDummy, "dummy task", true); + + void processJetsData(soa::Filtered::iterator const& collision, FullJetTableDataJoined const& jets, JetTracks const&, JetClusters const&) + { + registry.fill(HIST("h_collisions_unweighted"), 1.0); // total events + bool eventAccepted = false; + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_unweighted"), 2.0); // JetsData with kTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_unweighted"), 2.0); // JetsData with kTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("h_collisions_unweighted"), 6.0); // JetsData w/o kTVXinEMC + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedJet(jet)) { + fillRejectedJetHistograms(jet, 1.0); + } + } + return; + } + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillJetHistograms(jet, 1.0); + } + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsData, "Full Jets Data", false); + + void processJetsMCD(soa::Filtered::iterator const& collision, JetTableMCDJoined const& jets, JetTracks const&, JetClusters const&) + { + registry.fill(HIST("h_collisions_unweighted"), 1.0); // total events + bool eventAccepted = false; + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_unweighted"), 3.0); // JetsMCD with kTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_unweighted"), 3.0); // JetsMCD with kTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("h_collisions_unweighted"), 7.0); // JetsMCD w/o kTVXinEMC + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedJet(jet)) { + fillRejectedJetHistograms(jet, 1.0); + } + } + return; + } + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillJetHistograms(jet, 1.0); + } + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsMCD, "Full Jets at Detector Level", false); + + void processJetsMCDWeighted(soa::Filtered::iterator const& collision, JetTableMCDWeightedJoined const& jets, JetTracks const&, JetClusters const&) + { + registry.fill(HIST("h_collisions_weighted"), 1.0); // total events + bool eventAccepted = false; + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_weighted"), 2.0); // JetsMCDWeighted with kTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_weighted"), 2.0); // JetsMCDWeighted with kTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("h_collisions_weighted"), 5.0); // JetsMCDWeighted w/o kTVXinEMC + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedJet(jet)) { + fillRejectedJetHistograms(jet, jet.eventWeight()); + } + } + return; + } + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + + fillJetHistograms(jet, jet.eventWeight()); + } + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsMCDWeighted, "Full Jets at Detector Level on weighted events", false); + + void processJetsMCP(typename JetTableMCPJoined::iterator const& jet, JetParticles const&, JetMcCollisions const&) + { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + return; + } + if (!isAcceptedJet(jet)) { + return; + } + fillMCPHistograms(jet, 1.0); + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsMCP, "Full Jets at Particle Level", false); + + void processJetsMCPWeighted(typename JetTableMCPWeightedJoined::iterator const& jet, JetParticles const&) + { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + return; + } + if (!isAcceptedJet(jet)) { + return; + } + + fillMCPHistograms(jet, jet.eventWeight()); + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsMCPWeighted, "Full Jets at Particle Level on weighted events", false); + + void processTracks(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& clusters) + { + registry.fill(HIST("h_collisions_unweighted"), 1.0); // total events + bool eventAccepted = false; + // needed for the workaround to access EMCAL trigger bits. - This is needed for the MC productions in which the EMC trigger bits are missing. (MB MC LHC24f3, for ex.) + // It first requires for atleast a cell in EMCAL to have energy content. + // Once it finds a cell content, + // it then checks if the collision is not an ambiguous collision (i.e. it has to be a unique collision = no bunch pile up) + // If all of these conditions are satisfied then it checks for the required trigger bit in EMCAL. + // For LHC22o, since the EMCAL didn't have hardware triggers, one would only require MB trigger (kTVXinEMC) in the EMCAL. + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_unweighted"), 4.0); // Tracks with kTVXinEMC + } + } + } else { + // Check if EMCAL was readout with the MB trigger(kTVXinEMC) fired. If not then reject the event and exit the function. + // This is the default check for the simulations with proper trigger flags not requiring the above workaround. + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_unweighted"), 4.0); // Tracks with kTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("h_collisions_unweighted"), 8.0); // Tracks w/o kTVXinEMC + return; + } + // Fill Accepted events histos + fillTrackHistograms(tracks, clusters, 1.0); + } + PROCESS_SWITCH(FullJetSpectrapp, processTracks, "Full Jet tracks", false); + + void processJetsMCPMCDMatched(soa::Filtered>::iterator const& collision, JetTableMCDMatchedJoined const& mcdjets, JetTableMCPMatchedJoined const&, aod::JMcCollisions const&, JetTracks const&, JetClusters const&, JetParticles const&) + { + registry.fill(HIST("h_collisions_unweighted"), 1.0); // total events + bool eventAccepted = false; + int fakemcdjet = 0; + int fakemcpjet = 0; + + if (fabs(collision.posZ()) > VertexZCut) { // making double sure this condition is satisfied + return; + } + if (!collision.has_mcCollision()) { + return; + } + //**start of event selection** + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_unweighted"), 5.0); // JetsMCPMCDMatched with kTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_unweighted"), 5.0); // JetsMCPMCDMatched with kTVXinEMC + } + } + if (!eventAccepted) { + registry.fill(HIST("h_collisions_unweighted"), 9.0); // JetsMCPMCDMatched w/o kTVXinEMC + return; + } + //**end of event selection** + + for (const auto& mcdjet : mcdjets) { + // Check if MCD jet is within the EMCAL fiducial region + if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax || mcdjet.eta() < jetEtaMin || mcdjet.eta() > jetEtaMax) { + fakemcdjet++; + registry.fill(HIST("h_collisions_unweighted"), 10.0); // Fake Matched MCD Jets + registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakemcdjet, 1.0); + continue; + } + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + // apply emcal fiducial cuts to the matched particle level jets + if (mcpjet.eta() > jetEtaMax || mcpjet.eta() < jetEtaMin || mcpjet.phi() > jetPhiMax || mcpjet.phi() < jetPhiMin) { + fakemcpjet++; + registry.fill(HIST("h_collisions_unweighted"), 11.0); // Fake Matched MCP Jets + registry.fill(HIST("h2_full_fakemcpjets"), mcpjet.pt(), fakemcpjet, 1.0); + continue; + } + // Fill MCD jet histograms if a valid MCP jet match was found within the EMCAL region + registry.fill(HIST("h_full_matchedmcpjet_eta"), mcpjet.eta(), 1.0); + registry.fill(HIST("h_full_matchedmcpjet_phi"), mcpjet.phi(), 1.0); + fillMatchedHistograms(mcdjet); + } // mcpjet loop + registry.fill(HIST("h_full_matchedmcdjet_eta"), mcdjet.eta(), 1.0); + registry.fill(HIST("h_full_matchedmcdjet_phi"), mcdjet.phi(), 1.0); + } // mcdjet loop + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsMCPMCDMatched, "Full Jet finder MCP matched to MCD", false); + + void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, JetTableMCDMatchedWeightedJoined const& mcdjets, JetTableMCPMatchedWeightedJoined const& mcpjets, aod::JMcCollisions const&, JetTracks const&, JetClusters const&, JetParticles const&) + { + float eventWeight = collision.mcCollision().weight(); + registry.fill(HIST("h_collisions_weighted"), 1.0, eventWeight); // total events + bool eventAccepted = false; + int fakemcdjet = 0; + int fakemcpjet = 0; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + const auto mcpJetsPerMcCollision = mcpjets.sliceBy(JetMCPPerMcCollision, collision.mcCollisionId()); + + for (auto mcpjet : mcpJetsPerMcCollision) { + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { // outlier rejection for MCP + return; + } + } + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_weighted"), 3.0, eventWeight); // JetsMCPMCDMatchedWeighted with kTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_weighted"), 3.0, eventWeight); // JetsMCPMCDMatchedWeighted with kTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("h_collisions_weighted"), 6.0, eventWeight); // JetsMCPMCDMatchedWeighted w/o kTVXinEMC + return; + } + + for (const auto& mcdjet : mcdjets) { + // Check if MCD jet is within the EMCAL fiducial region + if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax || mcdjet.eta() < jetEtaMin || mcdjet.eta() > jetEtaMax) { + fakemcdjet++; + registry.fill(HIST("h_collisions_weighted"), 8.0); // Fake Matched Weighted MCD Jets + registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakemcdjet, eventWeight); + continue; + } + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + // apply emcal fiducial cuts to the matched particle level jets + if (mcpjet.eta() > jetEtaMax || mcpjet.eta() < jetEtaMin || mcpjet.phi() > jetPhiMax || mcpjet.phi() < jetPhiMin) { + fakemcpjet++; + registry.fill(HIST("h_collisions_weighted"), 9.0); // Fake Matched Weighted MCP Jets + registry.fill(HIST("h2_full_fakemcpjets"), mcpjet.pt(), fakemcpjet, eventWeight); + continue; + } + // If both MCD-MCP matched jet pairs are within the EMCAL fiducial region, fill these histos + registry.fill(HIST("h_full_matchedmcpjet_eta"), mcpjet.eta(), eventWeight); + registry.fill(HIST("h_full_matchedmcpjet_phi"), mcpjet.phi(), eventWeight); + fillMatchedHistograms(mcdjet, eventWeight); + } // mcpjet + // Fill MCD jet histograms if a valid MCP jet match was found within the EMCAL region + registry.fill(HIST("h_full_matchedmcdjet_eta"), mcdjet.eta(), eventWeight); + registry.fill(HIST("h_full_matchedmcdjet_phi"), mcdjet.phi(), eventWeight); + } // mcdjet + } + PROCESS_SWITCH(FullJetSpectrapp, processJetsMCPMCDMatchedWeighted, "Full Jet finder MCP matched to MCD on weighted events", false); + + void processTracksWeighted(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, + soa::Filtered const& tracks, + soa::Filtered const& clusters) + { + bool eventAccepted = false; + float eventWeight = collision.mcCollision().weight(); + registry.fill(HIST("h_collisions_weighted"), 1.0, eventWeight); // total events + + // set "doMBGapTrigger" to true only if you are testing with MB Gap-triggers + if (doMBGapTrigger && eventWeight == 1) { + return; + } + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + fillTrackHistograms(tracks, clusters, eventWeight); + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collisions_weighted"), 4.0, eventWeight); // TracksWeighted with kTVXinEMC + } + } + } else { + // Check if EMCAL was readout with the MB trigger(kTVXinEMC) fired. If not then reject the event and exit the function. + // This is the default check for the simulations with proper trigger flags not requiring the above workaround. + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("h_collisions_weighted"), 4.0, eventWeight); // TracksWeighted with kTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("h_collisions_weighted"), 7.0, eventWeight); // TracksWeighted w/o kTVXinEMC + return; + } + // registry.fill(HIST("h_gaptrig_collisions"), 1.0, eventWeight); + fillTrackHistograms(tracks, clusters, eventWeight); + } + PROCESS_SWITCH(FullJetSpectrapp, processTracksWeighted, "Full Jet tracks weighted", false); + +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"full-jet-spectra-pp"})}; +} diff --git a/PWGJE/Tasks/gammajettreeproducer.cxx b/PWGJE/Tasks/gammajettreeproducer.cxx new file mode 100644 index 00000000000..d721ca725df --- /dev/null +++ b/PWGJE/Tasks/gammajettreeproducer.cxx @@ -0,0 +1,295 @@ +// Copyright 2019-2020 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. + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/GammaJetAnalysisTree.h" + +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/Constants.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "TVector2.h" + +#include "CommonDataFormat/InteractionRecord.h" + +#include "EventFiltering/filterTables.h" + +// \struct GammaJetTreeProducer +/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets +/// \author Florian Jonas , UC Berkeley/LBNL +/// \since 02.08.2024 +/// +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using selectedClusters = o2::soa::Filtered; + +#include "Framework/runDataProcessing.h" + +struct GammaJetTreeProducer { + // analysis tree + // charged jets + // photon candidates + Produces chargedJetsTable; + Produces eventsTable; + Produces gammasTable; + + HistogramRegistry mHistograms{"GammaJetTreeProducerHisto"}; + + // --------------- + // Configureables + // --------------- + + // event cuts + Configurable mVertexCut{"vertexCut", 10.0, "apply z-vertex cut with value in cm"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; + Configurable + trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable trackMinPt{"trackMinPt", 0.15, "minimum track pT cut"}; + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; + Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; + Configurable isoR{"isoR", 0.4, "isolation cone radius"}; + + // cluster cuts + Configurable mClusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; + // Preslice perClusterMatchedTracks = o2::aod::jcluster::clusterId; + + int mRunNumber = 0; + int eventSelection = -1; + int trackSelection = -1; + + std::unordered_map collisionMapping; + std::vector triggerMaskBits; + + void init(InitContext const&) + { + using o2HistType = HistType; + using o2Axis = AxisSpec; + + eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + + // create histograms + LOG(info) << "Creating histograms"; + + const o2Axis ptAxis{100, 0, 100, "p_{T} (GeV/c)"}; + const o2Axis energyAxis{100, 0, 100, "E (GeV)"}; + const o2Axis m02Axis{100, 0, 3, "m02"}; + + mHistograms.add("clusterE", "Energy of cluster", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("trackPt", "pT of track", o2HistType::kTH1F, {ptAxis}); + mHistograms.add("chjetPt", "pT of charged jet", o2HistType::kTH1F, {ptAxis}); + mHistograms.add("chjetpt_vs_constpt", "pT of charged jet vs pT of constituents", o2HistType::kTH2F, {ptAxis, ptAxis}); + } + + // --------------------- + // Helper functions + // --------------------- + bool isTrackSelected(const auto& track) + { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + return false; + } + if (track.pt() < trackMinPt) { + return false; + } + + return true; + } + + bool isEventAccepted(const auto& collision) + { + + if (collision.posZ() > mVertexCut) { + return false; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return false; + } + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return false; + } + if (!jetderiveddatautilities::eventEMCAL(collision)) { + return false; + } + return true; + } + + double ch_iso_in_cone(const auto& cluster, JetTracks const& tracks, float radius = 0.4) + { + double iso = 0; + for (auto track : tracks) { + if (!isTrackSelected(track)) { + continue; + } + // make dR function live somwhere else + float dR = jetutilities::deltaR(cluster, track); + if (dR < radius) { + iso += track.pt(); + } + } + return iso; + } + double ch_perp_cone_rho(const auto& cluster, JetTracks const& tracks, float radius = 0.4) + { + double ptSumLeft = 0; + double ptSumRight = 0; + + double cPhi = TVector2::Phi_0_2pi(cluster.phi()); + + // rotate cone left by 90 degrees + float cPhiLeft = cPhi - TMath::Pi() / 2; + float cPhiRight = cPhi + TMath::Pi() / 2; + + // loop over tracks + float dRLeft, dRRight; + for (auto track : tracks) { + if (!isTrackSelected(track)) { + continue; + } + dRLeft = jetutilities::deltaR(cluster.eta(), cPhiLeft, track.eta(), track.phi()); + dRRight = jetutilities::deltaR(cluster.eta(), cPhiRight, track.eta(), track.phi()); + + if (dRLeft < radius) { + ptSumLeft += track.pt(); + } + if (dRRight < radius) { + ptSumRight += track.pt(); + } + } + + float rho = (ptSumLeft + ptSumRight) / (2 * TMath::Pi() * radius * radius); + return rho; + } + + // --------------------- + // Processing functions + // --------------------- + void processClearMaps(JetCollisions const&) + { + collisionMapping.clear(); + } + PROCESS_SWITCH(GammaJetTreeProducer, processClearMaps, "process function that clears all the maps in each dataframe", true); + + // define cluster filter. It selects only those clusters which are of the type + // sadly passing of the string at runtime is not possible for technical region so cluster definition is + // an integer instead + Filter clusterDefinitionSelection = (o2::aod::jcluster::definition == mClusterDefinition); + // Process clusters + void processClusters(soa::Join::iterator const& collision, selectedClusters const& clusters, JetTracks const& tracks) + { + if (!isEventAccepted(collision)) { + return; + } + + eventsTable(collision.multiplicity(), collision.centrality(), collision.rho(), collision.eventSel(), collision.alias_raw()); + collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); + + // loop over clusters + for (auto cluster : clusters) { + + // fill histograms + mHistograms.fill(HIST("clusterE"), cluster.energy()); + + double isoraw = ch_iso_in_cone(cluster, tracks, isoR); + double perpconerho = ch_perp_cone_rho(cluster, tracks, isoR); + + // find closest matched track + double dEta = 0; + double dPhi = 0; + // double dRMin = 100; + double p = -1; + + // auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, cluster.globalIndex()); + // for (const auto& match : tracksofcluster) { + // // ask the jtracks table for track with ID trackID + // double dR = deltaR(cluster.eta(), cluster.phi(), match.tracks_as().Eta(), match.tracks_as().Phi()); + // if (dR < dRMin) { + // dRMin = dR; + // dEta = cluster.eta() - match.tracks_as().eta(); + // dPhi = TVector2::Phi_0_2pi(cluster.phi()) - TVector2::Phi_0_2pi(match.tracks_as().phi()); + // if (abs(dPhi) > M_PI) { + // dPhi = 2 * M_PI - abs(dPhi); + // } + // p = match.tracks_as().p(); + // } + // } + + // // for compression reasons make dPhi and dEta 0 if no match is found + // if (p == -1) { + // dPhi = 0; + // dEta = 0; + // } + + gammasTable(eventsTable.lastIndex(), cluster.energy(), cluster.eta(), cluster.phi(), cluster.m02(), cluster.m20(), cluster.nCells(), cluster.time(), cluster.isExotic(), cluster.distanceToBadChannel(), cluster.nlm(), isoraw, perpconerho, dPhi, dEta, p); + } + + // dummy loop over tracks + for (auto track : tracks) { + mHistograms.fill(HIST("trackPt"), track.pt()); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processClusters, "Process EMCal clusters", true); + + Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * 100.0f); + // Process charged jets + void processChargedJets(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, JetTracks const&) + { + // event selection + if (!isEventAccepted(collision)) { + return; + } + + // loop over charged jets + for (auto jet : chargedJets) { + if (jet.pt() < jetPtMin) + continue; + ushort nconst = 0; + // loop over constituents + for (auto& constituent : jet.template tracks_as()) { + mHistograms.fill(HIST("chjetpt_vs_constpt"), jet.pt(), constituent.pt()); + nconst++; + } + int32_t storedColIndex = -1; + if (auto foundCol = collisionMapping.find(collision.globalIndex()); foundCol != collisionMapping.end()) { + storedColIndex = foundCol->second; + } + chargedJetsTable(storedColIndex, jet.pt(), jet.eta(), jet.phi(), jet.energy(), jet.mass(), jet.area(), nconst); + // fill histograms + mHistograms.fill(HIST("chjetPt"), jet.pt()); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJets, "Process charged jets", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc, TaskName{"gamma-jet-tree-producer"})}; + return workflow; +} diff --git a/PWGJE/Tasks/hffragmentationfunction.cxx b/PWGJE/Tasks/hffragmentationfunction.cxx index 04277d8d001..b080485d2ea 100644 --- a/PWGJE/Tasks/hffragmentationfunction.cxx +++ b/PWGJE/Tasks/hffragmentationfunction.cxx @@ -195,7 +195,7 @@ struct HfFragmentationFunctionTask { // obtaining jet 3-vector TVector3 jetVector(jet.px(), jet.py(), jet.pz()); - for (auto& d0Candidate : jet.hfcandidates_as()) { + for (auto& d0Candidate : jet.candidates_as()) { // obtaining jet 3-vector TVector3 d0Vector(d0Candidate.px(), d0Candidate.py(), d0Candidate.pz()); @@ -246,7 +246,7 @@ struct HfFragmentationFunctionTask { for (const auto& mcdjet : d0mcdJetsPerCollision) { // obtain leading HF candidate in jet - auto mcdd0cand = mcdjet.hfcandidates_first_as(); + auto mcdd0cand = mcdjet.candidates_first_as(); // store data in MC detector level table mcddistJetTable(RecoDecay::sqrtSumOfSquares(mcdjet.eta() - mcdd0cand.eta(), deltaPhi(mcdjet.phi(), mcdd0cand.phi())), @@ -261,7 +261,7 @@ struct HfFragmentationFunctionTask { for (const auto& mcpjet : d0mcpJetsPerMCCollision) { // obtain leading HF particle in jet - auto mcpd0cand = mcpjet.hfcandidates_first_as(); + auto mcpd0cand = mcpjet.candidates_first_as(); // store data in MC detector level table (calculate angular distance in eta-phi plane on the fly) mcpdistJetTable(RecoDecay::sqrtSumOfSquares(mcpjet.eta() - mcpd0cand.eta(), deltaPhi(mcpjet.phi(), mcpd0cand.phi())), @@ -286,13 +286,13 @@ struct HfFragmentationFunctionTask { for (const auto& mcpjet : mcpjets) { // obtain leading HF particle in jet - auto mcpd0cand = mcpjet.hfcandidates_first_as(); + auto mcpd0cand = mcpjet.candidates_first_as(); // loop through detector level matched to current particle level for (auto& mcdjet : mcpjet.matchedJetCand_as()) { // obtain leading HF candidate in jet - auto mcdd0cand = mcdjet.hfcandidates_first_as(); + auto mcdd0cand = mcdjet.candidates_first_as(); // store matched particle and detector level data in one single table (calculate angular distance in eta-phi plane on the fly) matchJetTable(RecoDecay::sqrtSumOfSquares(mcpjet.eta() - mcpd0cand.eta(), deltaPhi(mcpjet.phi(), mcpd0cand.phi())), mcpjet.pt(), mcpjet.eta(), mcpjet.phi(), // particle level jet diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index e33aa89dd5a..493bb07b393 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -59,15 +59,21 @@ struct hJetAnalysis { Configurable pt_TTsig_max{"pt_TTsig_max", 50, "signal maximum trigger track pt"}; Configurable frac_sig{"frac_sig", 0.5, "fraction of events to use for signal"}; Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + + Preslice> PartJetsPerCollision = aod::jet::mcCollisionId; TRandom3* rand = new TRandom3(0); Filter jetCuts = aod::jet::r == nround(jetR.node() * 100.0f); Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); - Filter eventCuts = nabs(aod::jcollision::posZ) < vertexZCut; + Filter eventTrackLevelCuts = nabs(aod::jcollision::posZ) < vertexZCut; HistogramRegistry registry{"registry", {{"hNtrig", "number of triggers;trigger type;entries", {HistType::kTH1F, {{2, 0, 2}}}}, + {"hZvtxSelected", "Z vertex position;Z_{vtx};entries", {HistType::kTH1F, {{80, -20, 20}}}}, {"hPtTrack", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}}, {"hEtaTrack", "Track #eta;#eta;entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"hPhiTrack", "Track #phi;#phi;entries", {HistType::kTH1F, {{160, -1.0, 7.0}}}}, @@ -96,9 +102,9 @@ struct hJetAnalysis { {"hDeltaRpT", "jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, {"hDeltaRpTPart", "Particle jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, {"hDeltaRSignal", "#DeltaR;#DeltaR;#frac{dN_{jets}}{d#DeltaR}", {HistType::kTH1F, {{50, 0.0, 0.15}}}}, - {"hDeltaRPartSignal", "Particle #DeltaR;#DeltaR;#frac{1}{N_{jets}}#frac{dN_{jets}}{d#DeltaR}", {HistType::kTH1F, {{50, 0.0, 0.15}}}}, + {"hDeltaRSignalPart", "Particle #DeltaR;#DeltaR;#frac{1}{N_{jets}}#frac{dN_{jets}}{d#DeltaR}", {HistType::kTH1F, {{50, 0.0, 0.15}}}}, {"hDeltaRpTSignal", "jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, - {"hDeltaRpTPartSignal", "Particle jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, + {"hDeltaRpTSignalPart", "Particle jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, {"hDeltaRpTDPhiSignal", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{200, 0, 200}, {100, 0, 2 * o2::constants::math::PI}, {50, 0.0, 0.15}}}}, {"hDeltaRpTDPhiSignalPart", "Particle jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{200, 0, 200}, {100, 0, 2 * o2::constants::math::PI}, {50, 0.0, 0.15}}}}, {"hDeltaRReference", "#DeltaR;#DeltaR;#frac{dN_{jets}}{d#DeltaR}", {HistType::kTH1F, {{50, 0.0, 0.15}}}}, @@ -106,11 +112,20 @@ struct hJetAnalysis { {"hDeltaRpTReference", "jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, {"hDeltaRpTPartReference", "Particle jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{200, 0, 200}, {50, 0.0, 0.15}}}}, {"hDeltaRpTDPhiReference", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{200, 0, 200}, {100, 0, 2 * o2::constants::math::PI}, {50, 0.0, 0.15}}}}, - {"hDeltaRpTDPhiReferencePart", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{200, 0, 200}, {100, 0, 2 * o2::constants::math::PI}, {50, 0.0, 0.15}}}}}}; + {"hDeltaRpTDPhiReferencePart", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{200, 0, 200}, {100, 0, 2 * o2::constants::math::PI}, {50, 0.0, 0.15}}}}, + {"hPtMatched", "p_{T} matching;p_{T,det};p_{T,part}", {HistType::kTH2F, {{200, 0, 200}, {200, 0, 200}}}}, + {"hPhiMatched", "#phi matching;#phi_{det};#phi_{part}", {HistType::kTH2F, {{160, -1.0, 7.0}, {160, -1.0, 7.0}}}}, + {"hDeltaRMatched", "#DeltaR matching;#DeltaR_{det};#DeltaR_{part}", {HistType::kTH2F, {{50, 0.0, 0.15}, {50, 0.0, 0.15}}}}, + {"hPtResolution", "p_{T} resolution;p_{T,part};Relative Resolution", {HistType::kTH2F, {{200, 0, 200}, {1000, -5.0, 5.0}}}}, + {"hPhiResolution", "#phi resolution;#p{T,part};Resolution", {HistType::kTH2F, {{200, 0, 200}, {1000, -7.0, 7.0}}}}, + {"hDeltaRResolution", "#DeltaR Resolution;p_{T,part};Resolution", {HistType::kTH2F, {{200, 0, 200}, {1000, -0.15, 0.15}}}}, + {"hFullMatching", "Full 6D matching;p_{T,det};p_{T,part};#phi_{det};#phi_{part};#DeltaR_{det};#DeltaR_{part}", {HistType::kTHnSparseD, {{200, 0, 200}, {200, 0, 200}, {160, -1.0, 7.0}, {160, -1.0, 7.0}, {50, 0.0, 0.15}, {50, 0.0, 0.15}}}}}}; int eventSelection = -1; int trackSelection = -1; + Service pdg; + void init(InitContext const&) { eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); @@ -118,11 +133,11 @@ struct hJetAnalysis { Filter jetCuts = aod::jet::r == nround(jetR.node() * 100.0f); Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); - Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); + Filter eventTrackLevelCuts = nabs(aod::jcollision::posZ) < vertexZCut; } template - void fillHistograms(T const& jets, W const& /*jetsWTA*/, U const& tracks) + void fillHistograms(T const& jets, W const& /*jetsWTA*/, U const& tracks, float weight = 1.0) { bool is_sig_col; std::vector phi_TT_ar; @@ -130,6 +145,7 @@ struct hJetAnalysis { int trig_number = 0; int n_TT = 0; double leadingPT = 0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); float dice = rand->Rndm(); if (dice < frac_sig) @@ -149,36 +165,39 @@ struct hJetAnalysis { phi_TT_ar.push_back(track.phi()); n_TT++; } - registry.fill(HIST("hPtTrack"), track.pt()); - registry.fill(HIST("hEtaTrack"), track.eta()); - registry.fill(HIST("hPhiTrack"), track.phi()); + registry.fill(HIST("hPtTrack"), track.pt(), weight); + registry.fill(HIST("hEtaTrack"), track.eta(), weight); + registry.fill(HIST("hPhiTrack"), track.phi(), weight); } if (n_TT > 0) { trig_number = rand->Integer(n_TT); phi_TT = phi_TT_ar[trig_number]; if (is_sig_col) { - registry.fill(HIST("hNtrig"), 1.5); - registry.fill(HIST("hJetSignalMultiplicity"), jets.size()); - registry.fill(HIST("hSigEventTriggers"), n_TT); + registry.fill(HIST("hNtrig"), 1.5, weight); + registry.fill(HIST("hJetSignalMultiplicity"), jets.size(), weight); + registry.fill(HIST("hSigEventTriggers"), n_TT, weight); } if (!is_sig_col) { - registry.fill(HIST("hNtrig"), 0.5); - registry.fill(HIST("hJetReferenceMultiplicity"), jets.size()); - registry.fill(HIST("hRefEventTriggers"), n_TT); + registry.fill(HIST("hNtrig"), 0.5, weight); + registry.fill(HIST("hJetReferenceMultiplicity"), jets.size(), weight); + registry.fill(HIST("hRefEventTriggers"), n_TT, weight); } } for (auto& jet : jets) { - registry.fill(HIST("hJetPt"), jet.pt()); - registry.fill(HIST("hJetEta"), jet.eta()); - registry.fill(HIST("hJetPhi"), jet.phi()); + if (jet.pt() > pTHatMaxMCD * pTHat) { + continue; + } + registry.fill(HIST("hJetPt"), jet.pt(), weight); + registry.fill(HIST("hJetEta"), jet.eta(), weight); + registry.fill(HIST("hJetPhi"), jet.phi(), weight); for (auto& jetWTA : jet.template matchedJetGeo_as>()) { double deltaPhi = RecoDecay::constrainAngle(jetWTA.phi() - jet.phi(), -o2::constants::math::PI); double deltaEta = jetWTA.eta() - jet.eta(); double dR = RecoDecay::sqrtSumOfSquares(deltaPhi, deltaEta); - registry.fill(HIST("hDeltaR"), dR); - registry.fill(HIST("hDeltaRpT"), jet.pt(), dR); + registry.fill(HIST("hDeltaR"), dR, weight); + registry.fill(HIST("hDeltaRpT"), jet.pt(), dR, weight); } if (n_TT > 0) { float dphi = RecoDecay::constrainAngle(jet.phi() - phi_TT); @@ -187,51 +206,55 @@ struct hJetAnalysis { double deltaPhi = RecoDecay::constrainAngle(jetWTA.phi() - jet.phi(), -o2::constants::math::PI); double deltaEta = jetWTA.eta() - jet.eta(); double dR = RecoDecay::sqrtSumOfSquares(deltaPhi, deltaEta); - registry.fill(HIST("hDeltaRSignal"), dR); - registry.fill(HIST("hDeltaRpTSignal"), jet.pt(), dR); - registry.fill(HIST("hDeltaRpTDPhiSignal"), jet.pt(), dphi, dR); + if (std::abs(dphi - o2::constants::math::PI) < 0.6) { + registry.fill(HIST("hDeltaRpTSignal"), jet.pt(), dR, weight); + registry.fill(HIST("hDeltaRSignal"), dR, weight); + } + registry.fill(HIST("hDeltaRpTDPhiSignal"), jet.pt(), dphi, dR, weight); } - registry.fill(HIST("hSignalPtDPhi"), dphi, jet.pt()); + registry.fill(HIST("hSignalPtDPhi"), dphi, jet.pt(), weight); if (std::abs(dphi - o2::constants::math::PI) < 0.6) { - registry.fill(HIST("hSignalPt"), jet.pt()); + registry.fill(HIST("hSignalPt"), jet.pt(), weight); } - registry.fill(HIST("hJetSignalConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size()); + registry.fill(HIST("hJetSignalConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size(), weight); for (auto& constituent : jet.template tracks_as()) { if (constituent.pt() > leadingPT) { leadingPT = constituent.pt(); } - registry.fill(HIST("hJetSignalConstituentPt"), jet.pt(), dphi, constituent.pt()); + registry.fill(HIST("hJetSignalConstituentPt"), jet.pt(), dphi, constituent.pt(), weight); } - registry.fill(HIST("hSignalLeadingTrack"), jet.pt(), dphi, leadingPT); + registry.fill(HIST("hSignalLeadingTrack"), jet.pt(), dphi, leadingPT, weight); } if (!is_sig_col) { for (auto& jetWTA : jet.template matchedJetGeo_as>()) { double deltaPhi = RecoDecay::constrainAngle(jetWTA.phi() - jet.phi(), -o2::constants::math::PI); double deltaEta = jetWTA.eta() - jet.eta(); double dR = RecoDecay::sqrtSumOfSquares(deltaPhi, deltaEta); - registry.fill(HIST("hDeltaRReference"), dR); - registry.fill(HIST("hDeltaRpTReference"), jet.pt(), dR); - registry.fill(HIST("hDeltaRpTDPhiReference"), jet.pt(), dphi, dR); + if (std::abs(dphi - o2::constants::math::PI) < 0.6) { + registry.fill(HIST("hDeltaRpTReference"), jet.pt(), dR, weight); + registry.fill(HIST("hDeltaRReference"), dR, weight); + } + registry.fill(HIST("hDeltaRpTDPhiReference"), jet.pt(), dphi, dR, weight); } - registry.fill(HIST("hReferencePtDPhi"), dphi, jet.pt()); + registry.fill(HIST("hReferencePtDPhi"), dphi, jet.pt(), weight); if (std::abs(dphi - o2::constants::math::PI) < 0.6) { - registry.fill(HIST("hReferencePt"), jet.pt()); + registry.fill(HIST("hReferencePt"), jet.pt(), weight); } - registry.fill(HIST("hJetReferenceConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size()); + registry.fill(HIST("hJetReferenceConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size(), weight); for (auto& constituent : jet.template tracks_as()) { if (constituent.pt() > leadingPT) { leadingPT = constituent.pt(); } - registry.fill(HIST("hJetReferenceConstituentPt"), jet.pt(), dphi, constituent.pt()); + registry.fill(HIST("hJetReferenceConstituentPt"), jet.pt(), dphi, constituent.pt(), weight); } - registry.fill(HIST("hReferenceLeadingTrack"), jet.pt(), dphi, leadingPT); + registry.fill(HIST("hReferenceLeadingTrack"), jet.pt(), dphi, leadingPT, weight); } } } } - template - void fillMCPHistograms(T const& jets, U const& particles) + template + void fillMCPHistograms(T const& jets, W const& /*jetsWTA*/, U const& particles, float weight = 1.0) { bool is_sig_col; std::vector phi_TT_ar; @@ -239,6 +262,7 @@ struct hJetAnalysis { int trig_number = 0; int n_TT = 0; double leadingPT = 0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); float dice = rand->Rndm(); if (dice < frac_sig) @@ -247,6 +271,13 @@ struct hJetAnalysis { is_sig_col = false; for (auto& particle : particles) { + auto pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (!pdgParticle) { + continue; + } + if ((pdgParticle->Charge() == 0.0) || (!particle.isPhysicalPrimary())) { + continue; + } if (is_sig_col && particle.pt() < pt_TTsig_max && particle.pt() > pt_TTsig_min) { phi_TT_ar.push_back(particle.phi()); n_TT++; @@ -255,87 +286,305 @@ struct hJetAnalysis { phi_TT_ar.push_back(particle.phi()); n_TT++; } - registry.fill(HIST("hPtPart"), particle.pt()); - registry.fill(HIST("hEtaPart"), particle.eta()); - registry.fill(HIST("hPhiPart"), particle.phi()); + registry.fill(HIST("hPtPart"), particle.pt(), weight); + registry.fill(HIST("hEtaPart"), particle.eta(), weight); + registry.fill(HIST("hPhiPart"), particle.phi(), weight); } if (n_TT > 0) { trig_number = rand->Integer(n_TT); phi_TT = phi_TT_ar[trig_number]; if (is_sig_col) { - registry.fill(HIST("hNtrig"), 1.5); - registry.fill(HIST("hJetSignalMultiplicity"), jets.size()); - registry.fill(HIST("hSigEventTriggers"), n_TT); + registry.fill(HIST("hNtrig"), 1.5, weight); + registry.fill(HIST("hJetSignalMultiplicity"), jets.size(), weight); + registry.fill(HIST("hSigEventTriggers"), n_TT, weight); } if (!is_sig_col) { - registry.fill(HIST("hNtrig"), 0.5); - registry.fill(HIST("hJetReferenceMultiplicity"), jets.size()); - registry.fill(HIST("hRefEventTriggers"), n_TT); + registry.fill(HIST("hNtrig"), 0.5, weight); + registry.fill(HIST("hJetReferenceMultiplicity"), jets.size(), weight); + registry.fill(HIST("hRefEventTriggers"), n_TT, weight); } } for (auto& jet : jets) { - registry.fill(HIST("hJetPt"), jet.pt()); - registry.fill(HIST("hJetEta"), jet.eta()); - registry.fill(HIST("hJetPhi"), jet.phi()); + if (jet.pt() > pTHatMaxMCP * pTHat) { + continue; + } + registry.fill(HIST("hJetPt"), jet.pt(), weight); + registry.fill(HIST("hJetEta"), jet.eta(), weight); + registry.fill(HIST("hJetPhi"), jet.phi(), weight); + for (auto& jetWTA : jet.template matchedJetGeo_as>()) { + double deltaPhi = RecoDecay::constrainAngle(jetWTA.phi() - jet.phi(), -o2::constants::math::PI); + double deltaEta = jetWTA.eta() - jet.eta(); + double dR = RecoDecay::sqrtSumOfSquares(deltaPhi, deltaEta); + registry.fill(HIST("hDeltaRPart"), dR, weight); + registry.fill(HIST("hDeltaRpTPart"), jet.pt(), dR, weight); + } if (n_TT > 0) { float dphi = RecoDecay::constrainAngle(jet.phi() - phi_TT); if (is_sig_col) { - registry.fill(HIST("hSignalPtDPhi"), dphi, jet.pt()); + for (auto& jetWTA : jet.template matchedJetGeo_as>()) { + double deltaPhi = RecoDecay::constrainAngle(jetWTA.phi() - jet.phi(), -o2::constants::math::PI); + double deltaEta = jetWTA.eta() - jet.eta(); + double dR = RecoDecay::sqrtSumOfSquares(deltaPhi, deltaEta); + if (std::abs(dphi - o2::constants::math::PI) < 0.6) { + registry.fill(HIST("hDeltaRpTSignalPart"), jet.pt(), dR, weight); + registry.fill(HIST("hDeltaRSignalPart"), dR, weight); + } + registry.fill(HIST("hDeltaRpTDPhiSignalPart"), jet.pt(), dphi, dR, weight); + } + registry.fill(HIST("hSignalPtDPhi"), dphi, jet.pt(), weight); if (std::abs(dphi - o2::constants::math::PI) < 0.6) { - registry.fill(HIST("hSignalPt"), jet.pt()); + registry.fill(HIST("hSignalPt"), jet.pt(), weight); } - registry.fill(HIST("hJetSignalConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size()); + registry.fill(HIST("hJetSignalConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size(), weight); for (auto& constituent : jet.template tracks_as()) { if (constituent.pt() > leadingPT) { leadingPT = constituent.pt(); } - registry.fill(HIST("hJetSignalConstituentPt"), jet.pt(), dphi, constituent.pt()); + registry.fill(HIST("hJetSignalConstituentPt"), jet.pt(), dphi, constituent.pt(), weight); } - registry.fill(HIST("hSignalLeadingTrack"), jet.pt(), dphi, leadingPT); + registry.fill(HIST("hSignalLeadingTrack"), jet.pt(), dphi, leadingPT, weight); } if (!is_sig_col) { - registry.fill(HIST("hReferencePtDPhi"), dphi, jet.pt()); + for (auto& jetWTA : jet.template matchedJetGeo_as>()) { + double deltaPhi = RecoDecay::constrainAngle(jetWTA.phi() - jet.phi(), -o2::constants::math::PI); + double deltaEta = jetWTA.eta() - jet.eta(); + double dR = RecoDecay::sqrtSumOfSquares(deltaPhi, deltaEta); + if (std::abs(dphi - o2::constants::math::PI) < 0.6) { + registry.fill(HIST("hDeltaRpTPartReference"), jet.pt(), dR, weight); + registry.fill(HIST("hDeltaRPartReference"), dR, weight); + } + registry.fill(HIST("hDeltaRpTDPhiReferencePart"), jet.pt(), dphi, dR, weight); + } + registry.fill(HIST("hReferencePtDPhi"), dphi, jet.pt(), weight); if (std::abs(dphi - o2::constants::math::PI) < 0.6) { - registry.fill(HIST("hReferencePt"), jet.pt()); + registry.fill(HIST("hReferencePt"), jet.pt(), weight); } - registry.fill(HIST("hJetReferenceConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size()); + registry.fill(HIST("hJetReferenceConstituentMultiplicity"), jet.pt(), dphi, jet.tracksIds().size(), weight); for (auto& constituent : jet.template tracks_as()) { if (constituent.pt() > leadingPT) { leadingPT = constituent.pt(); } - registry.fill(HIST("hJetReferenceConstituentPt"), jet.pt(), dphi, constituent.pt()); + registry.fill(HIST("hJetReferenceConstituentPt"), jet.pt(), dphi, constituent.pt(), weight); + } + registry.fill(HIST("hReferenceLeadingTrack"), jet.pt(), dphi, leadingPT, weight); + } + } + } + } + + template + void fillMatchedHistograms(T const& jetBase, V const& mcdjetsWTA, W const& mcpjetsWTA, U const&, float weight = 1.0) + { + double dR = 0; + double dRp = 0; + + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + if (jetBase.pt() > pTHatMaxMCD * pTHat) { + return; + } + + for (const auto& mcdjetWTA : mcdjetsWTA) { + double djet = RecoDecay::sqrtSumOfSquares(RecoDecay::constrainAngle(jetBase.phi() - mcdjetWTA.phi(), -o2::constants::math::PI), jetBase.eta() - mcdjetWTA.eta()); + if (mcdjetWTA.pt() > pTHatMaxMCD * pTHat) { + continue; + } + if (djet < 0.6 * jetR) { + dR = djet; + break; + } + } + + if (jetBase.has_matchedJetGeo()) { + for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { + if (jetTag.pt() > pTHatMaxMCP * pTHat) { + continue; + } + for (const auto& mcpjetWTA : mcpjetsWTA) { + double djetp = RecoDecay::sqrtSumOfSquares(RecoDecay::constrainAngle(jetTag.phi() - mcpjetWTA.phi(), -o2::constants::math::PI), jetTag.eta() - mcpjetWTA.eta()); + if (mcpjetWTA.pt() > pTHatMaxMCP * pTHat) { + continue; + } + if (djetp < 0.6 * jetR) { + dRp = djetp; + break; } - registry.fill(HIST("hReferenceLeadingTrack"), jet.pt(), dphi, leadingPT); } + registry.fill(HIST("hPtMatched"), jetBase.pt(), jetTag.pt(), weight); + registry.fill(HIST("hPhiMatched"), jetBase.phi(), jetTag.phi(), weight); + registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - jetBase.pt()) / jetTag.pt(), weight); + registry.fill(HIST("hPhiResolution"), jetTag.pt(), jetTag.phi() - jetBase.phi(), weight); + registry.fill(HIST("hDeltaRMatched"), dR, dRp, weight); + registry.fill(HIST("hDeltaRResolution"), jetTag.pt(), dRp - dR, weight); + registry.fill(HIST("hFullMatching"), jetBase.pt(), jetTag.pt(), jetBase.phi(), jetTag.phi(), dR, dRp, weight); } } } - void processData(soa::Filtered::iterator const& collision, soa::Filtered> const& jets, soa::Filtered> const& jetsWTA, soa::Filtered const& tracks) + void processData(soa::Filtered::iterator const& collision, + soa::Filtered> const& jets, + soa::Filtered> const& jetsWTA, + soa::Filtered const& tracks) { if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { return; } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); fillHistograms(jets, jetsWTA, tracks); } PROCESS_SWITCH(hJetAnalysis, processData, "process data", true); - void processMCD(soa::Filtered::iterator const& collision, soa::Filtered> const& jets, soa::Filtered> const& jetsWTA, soa::Filtered const& tracks) + void processMCD(soa::Filtered::iterator const& collision, + soa::Filtered> const& jets, + soa::Filtered> const& jetsWTA, + soa::Filtered const& tracks) { if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { return; } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); fillHistograms(jets, jetsWTA, tracks); } PROCESS_SWITCH(hJetAnalysis, processMCD, "process MC detector level", false); - void processMCP(JetMcCollision const&, soa::Filtered> const& jets, JetParticles const& particles) + void processMCDWeighted(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, + soa::Filtered> const& jets, + soa::Filtered> const& jetsWTA, + soa::Filtered const& tracks) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); + fillHistograms(jets, jetsWTA, tracks, collision.mcCollision().weight()); + } + PROCESS_SWITCH(hJetAnalysis, processMCDWeighted, "process MC detector level with event weights", false); + + void processMCP(JetMcCollision const& collision, + soa::Filtered> const& jets, + soa::Filtered> const& jetsWTA, + JetParticles const& particles) { - fillMCPHistograms(jets, particles); + if (std::abs(collision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillMCPHistograms(jets, jetsWTA, particles); } PROCESS_SWITCH(hJetAnalysis, processMCP, "process MC particle level", false); + + void processMCPWeighted(JetMcCollision const& collision, + soa::Filtered> const& jets, + soa::Filtered> const& jetsWTA, + JetParticles const& particles) + { + if (std::abs(collision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.weight()); + fillMCPHistograms(jets, jetsWTA, particles, collision.weight()); + } + PROCESS_SWITCH(hJetAnalysis, processMCPWeighted, "process MC particle level with event weights", false); + + void processJetsMCPMCDMatched(soa::Filtered::iterator const& collision, + soa::Filtered> const& mcdjets, + soa::Filtered> const& mcdjetsWTA, + soa::Filtered> const& mcpjetsWTA, + JetTracks const&, + JetParticles const&, + JetMcCollisions const&, + soa::Filtered> const& mcpjets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(PartJetsPerCollision, collision.mcCollisionId()); + for (const auto& mcdjet : mcdjets) { + fillMatchedHistograms(mcdjet, mcdjetsWTA, mcpjetsWTACut, mcpjets); + } + } + PROCESS_SWITCH(hJetAnalysis, processJetsMCPMCDMatched, "process MC matched (inc jets)", false); + + void processJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, + soa::Filtered> const& mcdjets, + soa::Filtered> const& mcdjetsWTA, + soa::Filtered> const& mcpjetsWTA, + JetTracks const&, + JetParticles const&, + JetMcCollisions const&, + soa::Filtered> const& mcpjets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(PartJetsPerCollision, collision.mcCollisionId()); + for (const auto& mcdjet : mcdjets) { + fillMatchedHistograms(mcdjet, mcdjetsWTA, mcpjetsWTACut, mcpjets, mcdjet.eventWeight()); + } + } + PROCESS_SWITCH(hJetAnalysis, processJetsMCPMCDMatchedWeighted, "process MC matched with event weights (inc jets)", false); + + void processRecoilJetsMCPMCDMatched(soa::Filtered::iterator const& collision, + soa::Filtered> const& mcdjets, + soa::Filtered> const& mcdjetsWTA, + soa::Filtered> const& mcpjetsWTA, + JetTracks const& tracks, + JetParticles const&, + JetMcCollisions const&, + soa::Filtered> const& mcpjets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(PartJetsPerCollision, collision.mcCollisionId()); + bool ishJetEvent = false; + for (auto& track : tracks) { + if (track.pt() < pt_TTsig_max && track.pt() > pt_TTsig_min) { + ishJetEvent = true; + break; + } + } + if (ishJetEvent) { + for (const auto& mcdjet : mcdjets) { + fillMatchedHistograms(mcdjet, mcdjetsWTA, mcpjetsWTACut, mcpjets); + } + } + } + PROCESS_SWITCH(hJetAnalysis, processRecoilJetsMCPMCDMatched, "process MC matched (recoil jets)", false); + + void processRecoilJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, + soa::Filtered> const& mcdjets, + soa::Filtered> const& mcdjetsWTA, + soa::Filtered> const& mcpjetsWTA, + JetTracks const& tracks, + JetParticles const&, + JetMcCollisions const&, + soa::Filtered> const& mcpjets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(PartJetsPerCollision, collision.mcCollisionId()); + bool ishJetEvent = false; + for (auto& track : tracks) { + if (track.pt() < pt_TTsig_max && track.pt() > pt_TTsig_min) { + ishJetEvent = true; + break; + } + } + if (ishJetEvent) { + for (const auto& mcdjet : mcdjets) { + fillMatchedHistograms(mcdjet, mcdjetsWTA, mcpjetsWTACut, mcpjets, mcdjet.eventWeight()); + } + } + } + PROCESS_SWITCH(hJetAnalysis, processRecoilJetsMCPMCDMatchedWeighted, "process MC matched with event weights (recoil jets)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"hJetAnalysis"})}; } diff --git a/PWGJE/Tasks/jetfinderQA.cxx b/PWGJE/Tasks/jetfinderQA.cxx index fd29e0dbeb5..38c5b1cbab4 100644 --- a/PWGJE/Tasks/jetfinderQA.cxx +++ b/PWGJE/Tasks/jetfinderQA.cxx @@ -60,12 +60,18 @@ struct JetFinderQATask { Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable jetPtMax{"jetPtMax", 200., "set jet pT bin max"}; Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; + Configurable nBinsEta{"nBinsEta", 200, "number of bins for eta axes"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; Configurable leadingConstituentPtMin{"leadingConstituentPtMin", -99.0, "minimum pT selection on jet constituent"}; + Configurable leadingConstituentPtMax{"leadingConstituentPtMax", 9999.0, "maximum pT selection on jet constituent"}; Configurable randomConeR{"randomConeR", 0.4, "size of random Cone for estimating background fluctuations"}; + Configurable randomConeLeadJetDeltaR{"randomConeLeadJetDeltaR", -99.0, "min distance between leading jet axis and random cone (RC) axis; if negative, min distance is set to automatic value of R_leadJet+R_RC "}; Configurable checkMcCollisionIsMatched{"checkMcCollisionIsMatched", false, "0: count whole MCcollisions, 1: select MCcollisions which only have their correspond collisions"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions (data and mcd jets), not mc collisions (mcp jets)"}; + Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions (data and mcd jets), not mc collisions (mcp jets)"}; std::vector filledJetR_Both; std::vector filledJetR_Low; @@ -75,6 +81,9 @@ struct JetFinderQATask { int eventSelection = -1; int trackSelection = -1; + std::vector jetPtBins; + std::vector jetPtBinsRhoAreaSub; + void init(o2::framework::InitContext&) { eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); @@ -93,70 +102,101 @@ struct JetFinderQATask { jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); } + auto jetPtTemp = 0.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + while (jetPtTemp < jetPtMax) { + if (jetPtTemp < 100.0) { + jetPtTemp += 1.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(-jetPtTemp); + } else if (jetPtTemp < 200.0) { + jetPtTemp += 5.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(-jetPtTemp); + } else { + jetPtTemp += 10.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(-jetPtTemp); + } + } + std::sort(jetPtBinsRhoAreaSub.begin(), jetPtBinsRhoAreaSub.end()); + + AxisSpec jetPtAxis = {jetPtBins, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPtAxisRhoAreaSub = {jetPtBinsRhoAreaSub, "#it{p}_{T} (GeV/#it{c})"}; + + AxisSpec jetEtaAxis = {nBinsEta, jetEtaMin, jetEtaMax, "#eta"}; + AxisSpec trackEtaAxis = {nBinsEta, trackEtaMin, trackEtaMax, "#eta"}; + if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { - registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {jetEtaAxis}}); registry.add("h_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_jet_eta", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxis}}); + registry.add("h2_centrality_jet_eta", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetEtaAxis}}); registry.add("h2_centrality_jet_phi", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_area", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_leadingtrack_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,leading track} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + registry.add("h3_jet_r_jet_pt_centrality", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetEtaAxis}}); + registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_area", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_leadingtrack_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,leading track} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0.0, 200.0}}}); registry.add("h_jet_phat", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); registry.add("h_jet_ptcut", "p_{T} cut;p_{T,jet} (GeV/#it{c});N;entries", {HistType::kTH2F, {{200, 0, 200}, {20, 0, 5}}}); registry.add("h_jet_phat_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); + registry.add("h3_centrality_occupancy_jet_pt", "centrality; occupancy; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{120, -10.0, 110.0}, {60, 0, 30000}, jetPtAxis}}); } - if (doprocessJetsRhoAreaSubData) { + if (doprocessJetsRhoAreaSubData || doprocessJetsRhoAreaSubMCD) { - registry.add("h_jet_pt_rhoareasubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{400, -200., 200.}}}); - registry.add("h_jet_eta_rhoareasubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt_rhoareasubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_eta_rhoareasubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {jetEtaAxis}}); registry.add("h_jet_phi_rhoareasubtracted", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_rhoareasubtracted", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {400, -200., 200.}}}); - registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetEtaAxis}}); registry.add("h2_centrality_jet_phi_rhoareasubtracted", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks_rhoareasubtracted", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi_rhoareasubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_area_rhoareasubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {400, -200., 200.}}}); - } - - if (doprocessEvtWiseConstSubJetsData) { - registry.add("h_jet_pt_eventwiseconstituentsubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta_eventwiseconstituentsubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_centrality_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, jetEtaAxis}}); + registry.add("h3_jet_r_jet_pt_jet_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi_rhoareasubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_area_rhoareasubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxisRhoAreaSub}}); + registry.add("h3_centrality_occupancy_jet_pt_rhoareasubtracted", "centrality; occupancy; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{120, -10.0, 110.0}, {60, 0, 30000}, jetPtAxisRhoAreaSub}}); + } + + if (doprocessEvtWiseConstSubJetsData || doprocessEvtWiseConstSubJetsMCD) { + registry.add("h_jet_pt_eventwiseconstituentsubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta_eventwiseconstituentsubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {jetEtaAxis}}); registry.add("h_jet_phi_eventwiseconstituentsubtracted", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_eventwiseconstituentsubtracted", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt_eventwiseconstituentsubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_jet_eta_eventwiseconstituentsubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt_eventwiseconstituentsubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxis}}); + registry.add("h2_centrality_jet_eta_eventwiseconstituentsubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetEtaAxis}}); registry.add("h2_centrality_jet_phi_eventwiseconstituentsubtracted", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks_eventwiseconstituentsubtracted", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_area_eventwiseconstituentsubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_centrality_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetEtaAxis}}); + registry.add("h3_jet_r_jet_pt_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_area_eventwiseconstituentsubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_pt_track_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); } if (doprocessRho) { @@ -167,114 +207,115 @@ struct JetFinderQATask { registry.add("h2_centrality_rhom", ";centrality; #it{rho}_{m} (GeV/area)", {HistType::kTH2F, {{1100, 0., 110.}, {100, 0., 100.0}}}); } - if (doprocessRandomCone) { + if (doprocessRandomConeData || doprocessRandomConeMCD) { registry.add("h2_centrality_rhorandomcone", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); + registry.add("h2_centrality_rhorandomconerandomtrackdirection", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); registry.add("h2_centrality_rhorandomconewithoutleadingjet", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); + registry.add("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); + registry.add("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); } if (doprocessJetsMCP || doprocessJetsMCPWeighted) { - registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {jetEtaAxis}}); registry.add("h_jet_phi_part", "jet #varphi;#varphi_{jet}^{part};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetEtaAxis}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); registry.add("h_jet_phat_part", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); registry.add("h_jet_ptcut_part", "p_{T} cut;p_{T,jet}^{part} (GeV/#it{c});N;entries", {HistType::kTH2F, {{200, 0, 200}, {20, 0, 5}}}); registry.add("h_jet_phat_part_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); } if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted || doprocessJetsSubMatched) { - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {300, 0., 300.}, {300, 0., 300.}}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, jetEtaAxis}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeo", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 2.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, jetEtaAxis}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, jetEtaAxis}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpt", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, jetEtaAxis}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, jetEtaAxis}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, jetEtaAxis}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); } if (doprocessTriggeredData) { registry.add("h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{6, 0.0, 6.0}}}); registry.add("h_track_pt_MB", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {trackEtaAxis}}); registry.add("h_track_phi_MB", "track #varphi for MB events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_Triggered_Low", "track pT for low #it{p}_{T} Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_Triggered_Low", "track #eta for low #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_Triggered_Low", "track #eta for low #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {trackEtaAxis}}); registry.add("h_track_phi_Triggered_Low", "track #varphi for low #it{p}_{T} Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_Triggered_High", "track pT for high #it{p}_{T} Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_Triggered_High", "track #eta for high #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_Triggered_High", "track #eta for high #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {trackEtaAxis}}); registry.add("h_track_phi_Triggered_High", "track #varphi for high #it{p}_{T} Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_Triggered_Both", "track pT for both #it{p}_{T} Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_Triggered_Both", "track #eta for both #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_Triggered_Both", "track #eta for both #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {trackEtaAxis}}); registry.add("h_track_phi_Triggered_Both", "track #varphi for both #it{p}_{T} Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {4, -0.5, 3.5}}}); - registry.add("h3_jet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {4, -0.5, 3.5}}}); + registry.add("h3_jet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {4, -0.5, 3.5}}}); + registry.add("h3_jet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, jetEtaAxis, {4, -0.5, 3.5}}}); registry.add("h3_jet_r_jet_phi_collision", "#it{R}_{jet};#varphi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {4, -0.5, 3.5}}}); - registry.add("h2_jet_r_jet_pT_triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h2_jet_r_jet_pT_triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h3_jet_r_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, trackEtaAxis}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); } if (doprocessTracks || doprocessTracksWeighted) { registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {{1200, -10.0, 110.0}, {4, 0.0, 4.0}}}); - registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, 0.0, 100.0}}}); + registry.add("h3_centrality_track_pt_track_phi", "centrality vs track pT vs track #varphi; centrality; #it{p}_{T,track} (GeV/#it{c}); #varphi_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_centrality_track_pt_track_eta", "centrality vs track pT vs track #eta; centrality; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, trackEtaAxis}}); + registry.add("h3_centrality_track_pt_track_dcaxy", "centrality vs track pT vs track DCA_{xy}; centrality; #it{p}_{T,track} (GeV/#it{c}); track DCA_{xy}", {HistType::kTH3F, {{120, -10.0, 110.0}, {20, 0., 100.}, {200, -0.15, 0.15}}}); + registry.add("h3_track_pt_track_eta_track_phi", "track pT vs track #eta vs track #varphi; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}; #varphi_{track}", {HistType::kTH3F, {{200, 0., 200.}, trackEtaAxis, {160, -1.0, 7.}}}); if (doprocessTracksWeighted) { registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); } } if (doprocessTracksSub) { - - registry.add("h2_centrality_track_pt_eventwiseconstituentsubtracted", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta_eventwiseconstituentsubtracted", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi_eventwiseconstituentsubtracted", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy_eventwiseconstituentsubtracted", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, 0.0, 100.0}}}); + registry.add("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted", "centrality vs track pT vs track #varphi; centrality; #it{p}_{T,track} (GeV/#it{c}); #varphi_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted", "centrality vs track pT vs track #eta; centrality; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, trackEtaAxis}}); + registry.add("h3_track_pt_track_eta_track_phi_eventwiseconstituentsubtracted", "track pT vs track #eta vs track #varphi; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}; #varphi_{track}", {HistType::kTH3F, {{200, 0., 200.}, trackEtaAxis, {160, -1.0, 7.}}}); } if (doprocessMCCollisionsWeighted) { @@ -297,23 +338,46 @@ struct JetFinderQATask { return false; } } - if (leadingConstituentPtMin > -98.0) { - bool isMinleadingConstituent = false; - for (auto& constituent : jet.template tracks_as()) { - if (constituent.pt() >= leadingConstituentPtMin) { - isMinleadingConstituent = true; - break; + bool checkConstituentPt = true; + bool checkConstituentMinPt = (leadingConstituentPtMin > -98.0); + bool checkConstituentMaxPt = (leadingConstituentPtMax < 9998.0); + if (!checkConstituentMinPt && !checkConstituentMaxPt) { + checkConstituentPt = false; + } + + if (checkConstituentPt) { + bool isMinLeadingConstituent = !checkConstituentMinPt; + bool isMaxLeadingConstituent = true; + + for (const auto& constituent : jet.template tracks_as()) { + double pt = constituent.pt(); + + if (checkConstituentMinPt && pt >= leadingConstituentPtMin) { + isMinLeadingConstituent = true; + } + if (checkConstituentMaxPt && pt > leadingConstituentPtMax) { + isMaxLeadingConstituent = false; } } - if (!isMinleadingConstituent) { - return false; - } + return isMinLeadingConstituent && isMaxLeadingConstituent; } + return true; } + template + bool trackIsInJet(T const& track, U const& jet) + { + for (auto const& constituentId : jet.tracksIds()) { + if (constituentId == track.globalIndex()) { + return true; + } + } + return false; + } + template - void fillHistograms(T const& jet, float centrality, float weight = 1.0) + void fillHistograms(T const& jet, float centrality, float occupancy, float weight = 1.0) { float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); @@ -332,6 +396,7 @@ struct JetFinderQATask { registry.fill(HIST("h2_centrality_jet_eta"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi"), centrality, jet.phi(), weight); registry.fill(HIST("h2_centrality_jet_ntracks"), centrality, jet.tracksIds().size(), weight); + registry.fill(HIST("h3_centrality_occupancy_jet_pt"), centrality, occupancy, jet.pt(), weight); } registry.fill(HIST("h3_jet_r_jet_pt_centrality"), jet.r() / 100.0, jet.pt(), centrality, weight); @@ -350,7 +415,7 @@ struct JetFinderQATask { } template - void fillRhoAreaSubtractedHistograms(T const& jet, float centrality, float rho, float weight = 1.0) + void fillRhoAreaSubtractedHistograms(T const& jet, float centrality, float occupancy, float rho, float weight = 1.0) { if (jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (rho * jet.area()), weight); @@ -358,6 +423,7 @@ struct JetFinderQATask { registry.fill(HIST("h_jet_phi_rhoareasubtracted"), jet.phi(), weight); registry.fill(HIST("h_jet_ntracks_rhoareasubtracted"), jet.tracksIds().size(), weight); registry.fill(HIST("h2_centrality_jet_pt_rhoareasubtracted"), centrality, jet.pt() - (rho * jet.area()), weight); + registry.fill(HIST("h3_centrality_occupancy_jet_pt_rhoareasubtracted"), centrality, occupancy, jet.pt() - (rho * jet.area()), weight); if (jet.pt() - (rho * jet.area()) > 0) { registry.fill(HIST("h2_centrality_jet_eta_rhoareasubtracted"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi_rhoareasubtracted"), centrality, jet.phi(), weight); @@ -523,15 +589,105 @@ struct JetFinderQATask { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } - registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); - registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); - registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); - registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_phi"), collision.centrality(), track.pt(), track.phi(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_eta"), collision.centrality(), track.pt(), track.eta(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_dcaxy"), collision.centrality(), track.pt(), track.dcaXY(), weight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi"), track.pt(), track.eta(), track.phi(), weight); + } + } + + template + void randomCone(T const& collision, U const& jets, V const& tracks) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + TRandom3 randomNumber(0); + float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + float randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); + float randomConePt = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); + float dEta = track.eta() - randomConeEta; + if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } + } + registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + + // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles + randomConePt = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, 2 * M_PI) - randomConePhi, static_cast(-M_PI)); // ignores actual phi of track + float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track + if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } } + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + + // removing the leading jet from the random cone + if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet + float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); + float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + + bool jetWasInCone = false; + while ((randomConeLeadJetDeltaR <= 0 && (TMath::Sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR)) || (randomConeLeadJetDeltaR > 0 && (TMath::Sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < randomConeLeadJetDeltaR))) { + jetWasInCone = true; + randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); + dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); + dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + } + if (jetWasInCone) { + randomConePt = 0.0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { // if track selection is uniformTrack, dcaXY and dcaZ cuts need to be added as they aren't in the selection so that they can be studied here + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); + float dEta = track.eta() - randomConeEta; + if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } + } + } + } + + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + + // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles, removing tracks from 2 leading jets + double randomConePtWithoutOneLeadJet = 0; + double randomConePtWithoutTwoLeadJet = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, 2 * M_PI) - randomConePhi, static_cast(-M_PI)); // ignores actual phi of track + float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track + if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + if (!trackIsInJet(track, jets.iteratorAt(0))) { + randomConePtWithoutOneLeadJet += track.pt(); + if (!trackIsInJet(track, jets.iteratorAt(1))) { + randomConePtWithoutTwoLeadJet += track.pt(); + } + } + } + } + } + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), collision.centrality(), randomConePtWithoutOneLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centrality(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); } void processJetsData(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTracks const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -539,7 +695,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange()); } } PROCESS_SWITCH(JetFinderQATask, processJetsData, "jet finder QA data", false); @@ -548,6 +704,9 @@ struct JetFinderQATask { soa::Join const& jets, JetTracks const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -555,13 +714,35 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillRhoAreaSubtractedHistograms(jet, collision.centrality(), collision.rho()); + fillRhoAreaSubtractedHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.rho()); } } PROCESS_SWITCH(JetFinderQATask, processJetsRhoAreaSubData, "jet finder QA for rho-area subtracted jets", false); + void processJetsRhoAreaSubMCD(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + JetTracks const&) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillRhoAreaSubtractedHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.rho()); + } + } + PROCESS_SWITCH(JetFinderQATask, processJetsRhoAreaSubMCD, "jet finder QA for rho-area subtracted mcd jets", false); + void processEvtWiseConstSubJetsData(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTracksSub const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -574,11 +755,31 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processEvtWiseConstSubJetsData, "jet finder QA for eventwise constituent-subtracted jets data", false); - void processJetsSubMatched(soa::Filtered::iterator const&, + void processEvtWiseConstSubJetsMCD(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTracksSub const&) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillEventWiseConstituentSubtractedHistograms(jet, collision.centrality()); + } + } + PROCESS_SWITCH(JetFinderQATask, processEvtWiseConstSubJetsMCD, "jet finder QA for eventwise constituent-subtracted mcd jets", false); + + void processJetsSubMatched(soa::Filtered::iterator const& collision, soa::Join const& jets, soa::Join const&, JetTracks const&, JetTracksSub const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (const auto& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -593,6 +794,9 @@ struct JetFinderQATask { void processJetsMCD(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTracks const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -600,13 +804,16 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange()); } } PROCESS_SWITCH(JetFinderQATask, processJetsMCD, "jet finder QA mcd", false); void processJetsMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTracks const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -620,7 +827,7 @@ struct JetFinderQATask { registry.fill(HIST("h_jet_ptcut"), jet.pt(), N * 0.25, jet.eventWeight()); } } - fillHistograms(jet, collision.centrality(), jet.eventWeight()); + fillHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), jet.eventWeight()); } } PROCESS_SWITCH(JetFinderQATask, processJetsMCDWeighted, "jet finder QA mcd with weighted events", false); @@ -635,7 +842,7 @@ struct JetFinderQATask { } if (checkMcCollisionIsMatched) { auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, jet.mcCollisionId()); - if (collisionspermcpjet.size() >= 1) { + if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelection)) { fillMCPHistograms(jet); } } else { @@ -669,11 +876,14 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCPWeighted, "jet finder QA mcp with weighted events", false); - void processJetsMCPMCDMatched(soa::Filtered::iterator const&, + void processJetsMCPMCDMatched(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, soa::Join const&, JetTracks const&, JetParticles const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -686,11 +896,14 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCPMCDMatched, "jet finder QA matched mcp and mcd", false); - void processJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const&, + void processJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, soa::Join const&, JetTracks const&, JetParticles const&) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -722,13 +935,13 @@ struct JetFinderQATask { return; } registry.fill(HIST("h_collision_trigger_events"), 2.5); // events with sel8() - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h_collision_trigger_events"), 3.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_collision_trigger_events"), 4.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_collision_trigger_events"), 5.5); // events with high pT triggered jets } @@ -740,19 +953,19 @@ struct JetFinderQATask { for (auto& jet : jets) { for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f)) { - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && !filledJetR_Low[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && !filledJetR_Low[iJetRadius]) { filledJetR_Low[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_Low"), jet.r() / 100.0, pt); } } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh) && !filledJetR_High[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt) && !filledJetR_High[iJetRadius]) { filledJetR_High[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_High"), jet.r() / 100.0, pt); } } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh) && !filledJetR_Both[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt) && !filledJetR_Both[iJetRadius]) { filledJetR_Both[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_Both"), jet.r() / 100.0, pt); @@ -769,17 +982,17 @@ struct JetFinderQATask { registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 0.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 0.0); - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 1.0); registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 1.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 1.0); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 2.0); registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 2.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 2.0); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 3.0); registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 3.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 3.0); @@ -790,17 +1003,17 @@ struct JetFinderQATask { registry.fill(HIST("h3_jet_r_jet_pt_track_eta_MB"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_MB"), jet.r() / 100.0, jet.pt(), constituent.phi()); - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered_Low"), jet.r() / 100.0, jet.pt(), constituent.pt()); registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered_Low"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered_Low"), jet.r() / 100.0, jet.pt(), constituent.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered_High"), jet.r() / 100.0, jet.pt(), constituent.pt()); registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered_High"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered_High"), jet.r() / 100.0, jet.pt(), constituent.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered_Both"), jet.r() / 100.0, jet.pt(), constituent.pt()); registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered_Both"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered_Both"), jet.r() / 100.0, jet.pt(), constituent.phi()); @@ -816,17 +1029,17 @@ struct JetFinderQATask { registry.fill(HIST("h_track_eta_MB"), track.eta()); registry.fill(HIST("h_track_phi_MB"), track.phi()); - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h_track_pt_Triggered_Low"), track.pt()); registry.fill(HIST("h_track_eta_Triggered_Low"), track.eta()); registry.fill(HIST("h_track_phi_Triggered_Low"), track.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_track_pt_Triggered_High"), track.pt()); registry.fill(HIST("h_track_eta_Triggered_High"), track.eta()); registry.fill(HIST("h_track_phi_Triggered_High"), track.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_track_pt_Triggered_Both"), track.pt()); registry.fill(HIST("h_track_eta_Triggered_Both"), track.eta()); registry.fill(HIST("h_track_phi_Triggered_Both"), track.phi()); @@ -836,7 +1049,7 @@ struct JetFinderQATask { PROCESS_SWITCH(JetFinderQATask, processTriggeredData, "QA for charged jet trigger", false); void processTracks(soa::Filtered::iterator const& collision, - soa::Filtered const& tracks) + soa::Filtered> const& tracks) { registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 0.5); @@ -845,13 +1058,18 @@ struct JetFinderQATask { } registry.fill(HIST("h_collisions"), 1.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 1.5); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_collisions"), 2.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); fillTrackHistograms(collision, tracks); } PROCESS_SWITCH(JetFinderQATask, processTracks, "QA for charged tracks", false); void processTracksWeighted(soa::Join::iterator const& collision, JetMcCollisions const&, - soa::Filtered const& tracks) + soa::Filtered> const& tracks) { float eventWeight = collision.mcCollision().weight(); registry.fill(HIST("h_collisions"), 0.5); @@ -861,6 +1079,11 @@ struct JetFinderQATask { } registry.fill(HIST("h_collisions"), 1.5); registry.fill(HIST("h_collisions_weighted"), 1.5, eventWeight); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_collisions"), 2.5); + registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); fillTrackHistograms(collision, tracks, eventWeight); } PROCESS_SWITCH(JetFinderQATask, processTracksWeighted, "QA for charged tracks weighted", false); @@ -871,11 +1094,13 @@ struct JetFinderQATask { if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { return; } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto const& track : tracks) { - registry.fill(HIST("h2_centrality_track_pt_eventwiseconstituentsubtracted"), collision.centrality(), track.pt()); - registry.fill(HIST("h2_centrality_track_eta_eventwiseconstituentsubtracted"), collision.centrality(), track.eta()); - registry.fill(HIST("h2_centrality_track_phi_eventwiseconstituentsubtracted"), collision.centrality(), track.phi()); - registry.fill(HIST("h2_centrality_track_energy_eventwiseconstituentsubtracted"), collision.centrality(), track.energy()); + registry.fill(HIST("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.phi()); + registry.fill(HIST("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.eta()); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_eventwiseconstituentsubtracted"), track.pt(), track.eta(), track.phi()); } } PROCESS_SWITCH(JetFinderQATask, processTracksSub, "QA for charged event-wise embedded subtracted tracks", false); @@ -885,6 +1110,9 @@ struct JetFinderQATask { if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { return; } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } int nTracks = 0; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -899,56 +1127,17 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processRho, "QA for rho-area subtracted jets", false); - void processRandomCone(soa::Filtered>::iterator const& collision, soa::Join const& jets, soa::Filtered const& tracks) + void processRandomConeData(soa::Filtered>::iterator const& collision, soa::Join const& jets, soa::Filtered const& tracks) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { - return; - } - TRandom3 randomNumber(0); - float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - float randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); - float randomConePt = 0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); - float dEta = track.eta() - randomConeEta; - if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); - } - } - } - registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); - - // removing the leading jet from the random cone - if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet - float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); - float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; - - bool jetWasInCone = false; - while (TMath::Sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR) { - jetWasInCone = true; - randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); - dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); - dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; - } - if (jetWasInCone) { - randomConePt = 0.0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { // if track selection is uniformTrack, dcaXY and dcaZ cuts need to be added as they aren't in the selection so that they can be studied here - float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); - float dEta = track.eta() - randomConeEta; - if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); - } - } - } - } - } + randomCone(collision, jets, tracks); + } + PROCESS_SWITCH(JetFinderQATask, processRandomConeData, "QA for random cone estimation of background fluctuations in data", false); - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + void processRandomConeMCD(soa::Filtered>::iterator const& collision, soa::Join const& jets, soa::Filtered const& tracks) + { + randomCone(collision, jets, tracks); } - PROCESS_SWITCH(JetFinderQATask, processRandomCone, "QA for random cone estimation of background fluctuations", false); + PROCESS_SWITCH(JetFinderQATask, processRandomConeMCD, "QA for random cone estimation of background fluctuations in mcd", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-finder-charged-qa"})}; } diff --git a/PWGJE/Tasks/jetfinderfullQA.cxx b/PWGJE/Tasks/jetfinderfullQA.cxx index 13e42669e02..b5ea2f3d80f 100644 --- a/PWGJE/Tasks/jetfinderfullQA.cxx +++ b/PWGJE/Tasks/jetfinderfullQA.cxx @@ -54,6 +54,7 @@ struct JetFinderFullQATask { Configurable trackPtMax{"trackPtMax", 100.0, "maximum pT acceptance for tracks"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable jetPtMax{"jetPtMax", 200., "set jet pT bin max"}; Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; @@ -79,6 +80,8 @@ struct JetFinderFullQATask { int trackSelection = -1; + std::vector jetPtBins; + Service pdgDatabase; void init(o2::framework::InitContext&) @@ -97,107 +100,125 @@ struct JetFinderFullQATask { jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); } + auto jetPtTemp = 0.0; + jetPtBins.push_back(jetPtTemp); + while (jetPtTemp < jetPtMax) { + if (jetPtTemp < 100.0) { + jetPtTemp += 1.0; + jetPtBins.push_back(jetPtTemp); + } else if (jetPtTemp < 200.0) { + jetPtTemp += 5.0; + jetPtBins.push_back(jetPtTemp); + + } else { + jetPtTemp += 10.0; + jetPtBins.push_back(jetPtTemp); + } + } + + AxisSpec jetPtAxis = {jetPtBins, "#it{p}_{T} (GeV/#it{c})"}; + if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { - registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); registry.add("h_jet_nclusters", "jet N clusters;N_{jet clusters};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_jet_eta", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxis}}); + registry.add("h2_centrality_jet_eta", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {500, -5.0, 5.0}}}); registry.add("h2_centrality_jet_phi", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); registry.add("h2_centrality_jet_nclusters", "centrality vs N_{jet clusters}; centrality; N_{jet clusters}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_nclusters", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet clusters}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_neutralenergyfraction", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});E_{neutral}/E_{total}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {120, 0.0, 1.2}}}); - registry.add("h3_jet_r_jet_pt_jet_area", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_cluster_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,cluster} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_cluster_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{cluster}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_cluster_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{cluster}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_cluster_energy", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});E_{cluster} (GeV)", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.0}}}); + registry.add("h3_jet_r_jet_pt_centrality", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_nclusters", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet clusters}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_neutralenergyfraction", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});E_{neutral}/E_{total}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {120, 0.0, 1.2}}}); + registry.add("h3_jet_r_jet_pt_jet_area", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_cluster_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,cluster} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_cluster_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{cluster}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_cluster_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{cluster}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_cluster_energy", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});E_{cluster} (GeV)", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); registry.add("h_jet_phat_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); } if (doprocessJetsMCP || doprocessJetsMCPWeighted) { - registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_jet_phi_part", "jet #varphi;#varphi_{jet}^{part};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_neutralenergyfraction_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});E_{neutral}^{part}/E_{total}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {120, 0.0, 1.2}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_neutralenergyfraction_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});E_{neutral}^{part}/E_{total}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {120, 0.0, 1.2}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); registry.add("h_jet_phat_part_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); } if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted) { - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeo", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_cluster_pt_tag_cluster_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,cluster}^{tag} (GeV/#it{c});#it{p}_{T,cluster}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_cluster_eta_tag_cluster_eta_base_matchedgeo", "#it{R}_{jet};#eta_{cluster}^{tag};#eta_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_cluster_pt_tag_cluster_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,cluster}^{tag} (GeV/#it{c});#it{p}_{T,cluster}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_cluster_eta_tag_cluster_eta_base_matchedgeo", "#it{R}_{jet};#eta_{cluster}^{tag};#eta_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_cluster_phi_tag_cluster_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{cluster}^{tag};#varphi_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_cluster_energy_tag_cluster_energy_base_matchedgeo", "#it{R}_{jet};#E_{cluster}^{tag};#E_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_cluster_energy_tag_cluster_energy_base_matchedgeo", "#it{R}_{jet};#E_{cluster}^{tag};#E_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpt", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_cluster_pt_tag_cluster_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,cluster}^{tag} (GeV/#it{c});#it{p}_{T,cluster}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_cluster_eta_tag_cluster_eta_base_matchedpt", "#it{R}_{jet};#eta_{cluster}^{tag};#eta_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_cluster_eta_tag_cluster_eta_base_matchedpt", "#it{R}_{jet};#eta_{cluster}^{tag};#eta_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_cluster_phi_tag_cluster_phi_base_matchedpt", "#it{R}_{jet};#varphi_{cluster}^{tag};#varphi_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_cluster_energy_tag_cluster_energy_base_matchedpt", "#it{R}_{jet};#E_{cluster}^{tag};#E_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_cluster_energy_tag_cluster_energy_base_matchedpt", "#it{R}_{jet};#E_{cluster}^{tag};#E_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_cluster_pt_tag_cluster_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,cluster}^{tag} (GeV/#it{c});#it{p}_{T,cluster}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_cluster_eta_tag_cluster_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{cluster}^{tag};#eta_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_cluster_eta_tag_cluster_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{cluster}^{tag};#eta_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_cluster_phi_tag_cluster_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{cluster}^{tag};#varphi_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_cluster_energy_tag_cluster_energy_base_matchedgeopt", "#it{R}_{jet};#E_{cluster}^{tag};#E_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_cluster_energy_tag_cluster_energy_base_matchedgeopt", "#it{R}_{jet};#E_{cluster}^{tag};#E_{cluster}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); } if (doprocessTracks || doprocessTracksWeighted) { registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); registry.add("h_centrality_collisions", "centrality vs collisions; centrality, collisions", {HistType::kTH2F, {{1200, -10.0, 110.0}, {4, 0.0, 4.0}}}); registry.add("h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_energy", "track energy;Energy GeV ;entries", {HistType::kTH1F, {{100, 0.0, 100.0}}}); registry.add("h_cluster_pt", "cluster pT;#it{p}_{T,cluster} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_cluster_eta", "cluster #eta;#eta_{cluster};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_cluster_eta", "cluster #eta;#eta_{cluster};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_cluster_phi", "cluster #varphi;#varphi_{cluster};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_cluster_energy", "cluster E;E_{cluster} (GeV);entries", {HistType::kTH1F, {{200, 0., 200.}}}); if (doprocessTracksWeighted) { diff --git a/PWGJE/Tasks/jetfinderhfQA.cxx b/PWGJE/Tasks/jetfinderhfQA.cxx index 73e3e8276db..13a185ce36b 100644 --- a/PWGJE/Tasks/jetfinderhfQA.cxx +++ b/PWGJE/Tasks/jetfinderhfQA.cxx @@ -60,6 +60,7 @@ struct JetFinderHFQATask { Configurable trackPtMin{"trackPtMin", 0.15, "minimum pT acceptance for tracks"}; Configurable trackPtMax{"trackPtMax", 100.0, "maximum pT acceptance for tracks"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable jetPtMax{"jetPtMax", 200., "set jet pT bin max"}; Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; @@ -81,6 +82,9 @@ struct JetFinderHFQATask { int eventSelection = -1; int trackSelection = -1; + std::vector jetPtBins; + std::vector jetPtBinsRhoAreaSub; + void init(o2::framework::InitContext&) { eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); @@ -103,81 +107,108 @@ struct JetFinderHFQATask { jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); } + auto jetPtTemp = 0.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + while (jetPtTemp < jetPtMax) { + if (jetPtTemp < 100.0) { + jetPtTemp += 1.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(-jetPtTemp); + } else if (jetPtTemp < 200.0) { + jetPtTemp += 5.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(-jetPtTemp); + + } else { + jetPtTemp += 10.0; + jetPtBins.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(jetPtTemp); + jetPtBinsRhoAreaSub.push_back(-jetPtTemp); + } + } + std::sort(jetPtBinsRhoAreaSub.begin(), jetPtBinsRhoAreaSub.end()); + + AxisSpec jetPtAxis = {jetPtBins, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPtAxisRhoAreaSub = {jetPtBinsRhoAreaSub, "#it{p}_{T} (GeV/#it{c})"}; + if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { - registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_jet_eta", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxis}}); + registry.add("h2_centrality_jet_eta", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {500, -5.0, 5.0}}}); registry.add("h2_centrality_jet_phi", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_area", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_candidate_invmass_jet_pt_candidate_pt", ";#it{m}_{inv, candidate} (GeV/#it{c}^{2}); #it{p}_{T,jet} (GeV/#it{c}) ;#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{500, 0.0, 5.0}, {200, 0.0, 200.0}, {200, 0.0, 200.0}}}); - registry.add("h3_candidatebar_invmass_jet_pt_candidate_pt", ";#it{m}_{inv, candidate bar} (GeV/#it{c}^{2}); #it{p}_{T,jet} (GeV/#it{c}) ;#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{500, 0.0, 5.0}, {200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + registry.add("h3_jet_r_jet_pt_centrality", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_area", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_candidate_invmass_jet_pt_candidate_pt", ";#it{m}_{inv, candidate} (GeV/#it{c}^{2}); #it{p}_{T,jet} (GeV/#it{c}) ;#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{500, 0.0, 5.0}, jetPtAxis, {200, 0.0, 200.0}}}); + registry.add("h3_candidatebar_invmass_jet_pt_candidate_pt", ";#it{m}_{inv, candidate bar} (GeV/#it{c}^{2}); #it{p}_{T,jet} (GeV/#it{c}) ;#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{500, 0.0, 5.0}, jetPtAxis, {200, 0.0, 200.0}}}); registry.add("h_jet_phat_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); } - if (doprocessJetsRhoAreaSubData) { + if (doprocessJetsRhoAreaSubData || doprocessJetsRhoAreaSubMCD) { - registry.add("h_jet_pt_rhoareasubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{400, -200., 200.}}}); - registry.add("h_jet_eta_rhoareasubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt_rhoareasubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_eta_rhoareasubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_jet_phi_rhoareasubtracted", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_rhoareasubtracted", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {400, -200., 200.}}}); - registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {500, -5.0, 5.0}}}); registry.add("h2_centrality_jet_phi_rhoareasubtracted", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks_rhoareasubtracted", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi_rhoareasubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_area_rhoareasubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {400, -200., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {400, -200., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_centrality_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_jet_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi_rhoareasubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_area_rhoareasubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxisRhoAreaSub}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_rhoareasubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxisRhoAreaSub, {500, -5.0, 5.0}}}); } if (doprocessEvtWiseConstSubJetsData) { - registry.add("h_jet_pt_eventwiseconstituentsubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta_eventwiseconstituentsubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt_eventwiseconstituentsubtracted", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta_eventwiseconstituentsubtracted", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_jet_phi_eventwiseconstituentsubtracted", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_eventwiseconstituentsubtracted", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_centrality_jet_pt_eventwiseconstituentsubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_jet_eta_eventwiseconstituentsubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_jet_pt_eventwiseconstituentsubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxis}}); + registry.add("h2_centrality_jet_eta_eventwiseconstituentsubtracted", "centrality vs #eta_{jet}; centrality; #eta_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {500, -5.0, 5.0}}}); registry.add("h2_centrality_jet_phi_eventwiseconstituentsubtracted", "centrality vs #varphi_{jet}; centrality; #varphi_{jet}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); registry.add("h2_centrality_jet_ntracks_eventwiseconstituentsubtracted", "centrality vs N_{jet tracks}; centrality; N_{jet tracks}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_centrality_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {1200, -10.0, 110.0}}}); - registry.add("h3_jet_r_jet_pt_jet_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_eta_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_jet_ntracks_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_jet_pt_jet_area_eventwiseconstituentsubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {300, 0., 3.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_centrality_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});centrality", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1200, -10.0, 110.0}}}); + registry.add("h3_jet_r_jet_pt_jet_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_area_eventwiseconstituentsubtracted", "#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c}); #it{area}_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {300, 0., 3.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_eventwiseconstituentsubtracted", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); } if (doprocessRho) { @@ -188,239 +219,236 @@ struct JetFinderHFQATask { registry.add("h2_centrality_rhom", ";centrality; #it{rho}_{m} (GeV/area)", {HistType::kTH2F, {{1100, 0., 110.}, {100, 0., 100.0}}}); } - if (doprocessRandomCone) { + if (doprocessRandomConeData || doprocessRandomConeMCD) { registry.add("h2_centrality_rhorandomcone", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); registry.add("h2_centrality_rhorandomconewithoutleadingjet", "; centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho} (GeV/c);", {HistType::kTH2F, {{1100, 0., 110.}, {800, -400.0, 400.0}}}); } if (doprocessJetsMCP || doprocessJetsMCPWeighted) { - registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_jet_phi_part", "jet #varphi;#varphi_{jet}^{part};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, -0.5, 199.5}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_pt_part_candidate_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,candidate}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_part_jet_pt_part_candidate_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_part_jet_pt_part_candidate_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_part_jet_pt_part_candidate_y_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});y_{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,candidate}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_y_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});y_{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); registry.add("h_jet_phat_part_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0, 350}}}); } if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted || doprocessJetsSubMatched) { - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeo", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeo", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeo", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeo", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeo", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeo", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpt", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedpt", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedpt", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedpt", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedpt", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeopt", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeopt", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeopt", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedhf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedhf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopt", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedhf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedhf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedhf", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedhf", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedhf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedhf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedhf", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedhf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedhf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedhf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeohf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeohf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedhf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedhf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedhf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedhf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeohf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeohf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeohf", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeohf", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeohf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeohf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeohf", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeohf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeohf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeohf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpthf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpthf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeohf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeohf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeohf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeohf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpthf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpthf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpthf", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedpthf", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedpthf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedpthf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedpthf", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); - - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopthf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopthf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedpthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c});#it{p}_{T,jet}^{base} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, jetPtAxis}}); + registry.add("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopthf", "#it{R}_{jet};#eta_{jet}^{tag};#eta_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopthf", "#it{R}_{jet};#varphi_{jet}^{tag};#varphi_{jet}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); registry.add("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf", "#it{R}_{jet};N_{jet tracks}^{tag};N_{jet tracks}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); registry.add("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,candidate}^{tag} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeopthf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeopthf", "#it{R}_{jet};#eta_{candidate}^{tag};#eta_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); registry.add("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeopthf", "#it{R}_{jet};#varphi_{candidate}^{tag};#varphi_{candidate}^{base}", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); - registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {160, -1.0, 7.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {{200, 0.0, 200}, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_pt_base_diff_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#it{p}_{T,jet}^{tag} (GeV/#it{c}) - #it{p}_{T,jet}^{base} (GeV/#it{c})) / #it{p}_{T,jet}^{tag} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_eta_base_diff_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#eta_{jet}^{tag} - #eta_{jet}^{base}) / #eta_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_tag_jet_phi_base_diff_matchedgeopthf", "#it{R}_{jet};#it{p}_{T,jet}^{tag} (GeV/#it{c}); (#varphi_{jet}^{tag} - #varphi_{jet}^{base}) / #varphi_{jet}^{tag}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #eta_{jet}^{tag}; #eta_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {500, -5.0, 5.0}, {500, -5.0, 5.0}}}); + registry.add("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); #varphi_{jet}^{tag}; #varphi_{jet}^{base}", {HistType::kTH3F, {jetPtAxis, {160, -1.0, 7.}, {160, -1.0, 7.}}}); + registry.add("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf", ";#it{p}_{T,jet}^{tag} (GeV/#it{c}); N_{jet tracks}^{tag}; N_{jet tracks}^{base}", {HistType::kTH3F, {jetPtAxis, {200, -0.5, 199.5}, {200, -0.5, 199.5}}}); } if (doprocessTriggeredData) { registry.add("h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{6, 0.0, 6.0}}}); registry.add("h_track_pt_MB", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_MB", "track #varphi for MB events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_Triggered_Low", "track pT for low #it{p}_{T} Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_Triggered_Low", "track #eta for low #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_Triggered_Low", "track #eta for low #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_Triggered_Low", "track #varphi for low #it{p}_{T} Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_Triggered_High", "track pT for high #it{p}_{T} Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_Triggered_High", "track #eta for high #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_Triggered_High", "track #eta for high #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_Triggered_High", "track #varphi for high #it{p}_{T} Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_Triggered_Both", "track pT for both #it{p}_{T} Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_Triggered_Both", "track #eta for both #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_Triggered_Both", "track #eta for both #it{p}_{T} Triggered events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_Triggered_Both", "track #varphi for both #it{p}_{T} Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {4, -0.5, 3.5}}}); - registry.add("h3_jet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {4, -0.5, 3.5}}}); + registry.add("h3_jet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {4, -0.5, 3.5}}}); + registry.add("h3_jet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {4, -0.5, 3.5}}}); registry.add("h3_jet_r_jet_phi_collision", "#it{R}_{jet};#varphi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {4, -0.5, 3.5}}}); - registry.add("h2_jet_r_jet_pT_triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h2_jet_r_jet_pT_triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h3_jet_r_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_Triggered_Low", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_Triggered_High", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_Triggered_Both", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); } if (doprocessHFTriggeredData) { registry.add("h_collision_hftrigger_events", "event status;event status;entries", {HistType::kTH1F, {{115, 0.0, 15.0}}}); registry.add("h_track_pt_all", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_all", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_all", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_all", "track #varphi for MB events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_triggered_HFlow", "track pT for low #it{p}_{T} HF Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_triggered_HFlow", "track #eta for low #it{p}_{T} HF Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_triggered_HFlow", "track #eta for low #it{p}_{T} HF Triggered events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_triggered_HFlow", "track #varphi for low #it{p}_{T} HF Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); registry.add("h_track_pt_triggered_HFhigh", "track pT for high #it{p}_{T} HF Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_track_eta_triggered_HFhigh", "track #eta for high #it{p}_{T} HF Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_eta_triggered_HFhigh", "track #eta for high #it{p}_{T} HF Triggered events;#eta_{track};entries", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h_track_phi_triggered_HFhigh", "track #varphi for high #it{p}_{T} HF Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{160, -1.0, 7.}}}); - registry.add("h2_jet_r_jet_pT_triggered_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_Lcall", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_Lclow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_pT_triggered_Lchigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h2_jet_r_jet_eta_triggered_HFall", "#it{R}_{jet};#eta_{jet}", {HistType::kTH2F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}}}); - registry.add("h2_jet_r_jet_eta_triggered_HFlow", "#it{R}_{jet};#eta_{jet}", {HistType::kTH2F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}}}); - registry.add("h2_jet_r_jet_eta_triggered_HFhigh", "#it{R}_{jet};#eta_{jet}", {HistType::kTH2F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}}}); - - registry.add("h3_hfjet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {4, -0.5, 3.5}}}); - registry.add("h3_hfjet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {4, -0.5, 3.5}}}); + registry.add("h2_jet_r_jet_pT_triggered_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_Lcall", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_Lclow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_pT_triggered_Lchigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, jetPtAxis}}); + registry.add("h2_jet_r_jet_eta_triggered_HFall", "#it{R}_{jet};#eta_{jet}", {HistType::kTH2F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}}}); + registry.add("h2_jet_r_jet_eta_triggered_HFlow", "#it{R}_{jet};#eta_{jet}", {HistType::kTH2F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}}}); + registry.add("h2_jet_r_jet_eta_triggered_HFhigh", "#it{R}_{jet};#eta_{jet}", {HistType::kTH2F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}}}); + + registry.add("h3_hfjet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {4, -0.5, 3.5}}}); + registry.add("h3_hfjet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {500, -5.0, 5.0}, {4, -0.5, 3.5}}}); registry.add("h3_hfjet_r_jet_phi_collision", "#it{R}_{jet};#varphi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {160, -1.0, 7.}, {4, -0.5, 3.5}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_pt_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_r_jet_pt_candidate_eta_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_r_jet_pt_candidate_phi_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {160, -1.0, 7.}}}); - registry.add("h3_jet_r_jet_pt_candidate_y_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_all", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_triggered_HFlow", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {160, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_triggered_HFhigh", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, jetPtAxis, {500, -5.0, 5.0}}}); } if (doprocessTracks || doprocessTracksWeighted) { registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {{1200, -10.0, 110.0}, {4, 0.0, 4.0}}}); - registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, 0.0, 100.0}}}); + registry.add("h3_centrality_track_pt_track_phi", "centrality vs track pT vs track #varphi; centrality; #it{p}_{T,track} (GeV/#it{c}); #varphi_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_centrality_track_pt_track_eta", "centrality vs track pT vs track #eta; centrality; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, {500, -5.0, 5.0}}}); + registry.add("h3_track_pt_track_eta_track_phi", "track pT vs track #eta vs track #varphi; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}; #varphi_{track}", {HistType::kTH3F, {{200, 0., 200.}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); if (doprocessTracksWeighted) { registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); } } if (doprocessTracksSub) { - - registry.add("h2_centrality_track_pt_eventwiseconstituentsubtracted", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta_eventwiseconstituentsubtracted", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi_eventwiseconstituentsubtracted", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy_eventwiseconstituentsubtracted", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, 0.0, 100.0}}}); + registry.add("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted", "centrality vs track pT vs track #varphi; centrality; #it{p}_{T,track} (GeV/#it{c}); #varphi_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, {160, -1.0, 7.}}}); + registry.add("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted", "centrality vs track pT vs track #eta; centrality; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}", {HistType::kTH3F, {{1200, -10.0, 110.0}, {200, 0., 200.}, {500, -5.0, 5.0}}}); + registry.add("h3_track_pt_track_eta_track_phi_eventwiseconstituentsubtracted", "track pT vs track #eta vs track #varphi; #it{p}_{T,track} (GeV/#it{c}); #eta_{track}; #varphi_{track}", {HistType::kTH3F, {{200, 0., 200.}, {500, -5.0, 5.0}, {160, -1.0, 7.}}}); } if (doprocessMCCollisionsWeighted) { @@ -431,7 +459,7 @@ struct JetFinderHFQATask { if (doprocessCandidates) { registry.add("h_candidate_invmass", ";#it{m}_{inv, candidate} (GeV/#it{c}^{2});counts", {HistType::kTH1F, {{500, 0.0, 5.0}}}); registry.add("h_candidate_pt", ";#it{p}_{T,candidate} (GeV/#it{c});counts", {HistType::kTH1F, {{200, 0.0, 200.0}}}); - registry.add("h_candidate_y", ";y_{candidate};counts", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_candidate_y", ";y_{candidate};counts", {HistType::kTH1F, {{500, -5.0, 5.0}}}); registry.add("h2_centrality_ncandidates", "centrality vs N_{candidates};centrality;N_{candidates};", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, 0.0, 100.0}}}); } } @@ -462,10 +490,7 @@ struct JetFinderHFQATask { PresliceOptional> perD0CandidateTracks = aod::bkgd0::candidateId; PresliceOptional> perLcCandidateTracks = aod::bkglc::candidateId; PresliceOptional> perBplusCandidateTracks = aod::bkgbplus::candidateId; - - PresliceOptional perD0CandidateRhos = aod::bkgd0::candidateId; - PresliceOptional perLcCandidateRhos = aod::bkglc::candidateId; - PresliceOptional perBplusCandidateRhos = aod::bkgbplus::candidateId; + PresliceOptional> perDielectronCandidateTracks = aod::bkgdielectron::candidateId; template bool isAcceptedJet(V const& jet) @@ -484,7 +509,7 @@ struct JetFinderHFQATask { break; } } - for (auto& hfconstituent : jet.template hfcandidates_as()) { + for (auto& hfconstituent : jet.template candidates_as()) { if (hfconstituent.pt() >= leadingConstituentPtMin) { isMinleadingConstituent = true; break; @@ -511,18 +536,18 @@ struct JetFinderHFQATask { registry.fill(HIST("h_jet_pt"), jet.pt(), weight); registry.fill(HIST("h_jet_eta"), jet.eta(), weight); registry.fill(HIST("h_jet_phi"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h2_centrality_jet_pt"), centrality, jet.pt(), weight); registry.fill(HIST("h2_centrality_jet_eta"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi"), centrality, jet.phi(), weight); - registry.fill(HIST("h2_centrality_jet_ntracks"), centrality, jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h2_centrality_jet_ntracks"), centrality, jet.tracksIds().size() + jet.candidatesIds().size(), weight); } registry.fill(HIST("h3_jet_r_jet_pt_centrality"), jet.r() / 100.0, jet.pt(), centrality, weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); registry.fill(HIST("h3_jet_r_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_area"), jet.r() / 100.0, jet.pt(), jet.area(), weight); for (auto& constituent : jet.template tracks_as()) { @@ -532,20 +557,20 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - for (auto& hfcandidate : jet.template hfcandidates_as>()) { + for (auto& candidate : jet.template candidates_as>()) { - registry.fill(HIST("h3_jet_r_jet_pt_track_pt"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_track_eta"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt"), jet.r() / 100.0, jet.pt(), candidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta"), jet.r() / 100.0, jet.pt(), candidate.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), candidate.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y"), jet.r() / 100.0, jet.pt(), hfcandidate.y(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt"), jet.r() / 100.0, jet.pt(), candidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta"), jet.r() / 100.0, jet.pt(), candidate.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi"), jet.r() / 100.0, jet.pt(), candidate.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y"), jet.r() / 100.0, jet.pt(), candidate.y(), weight); if (jet.r() == round(selectedJetsRadius * 100.0f)) { - registry.fill(HIST("h3_candidate_invmass_jet_pt_candidate_pt"), hfcandidate.m(), jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h3_candidatebar_invmass_jet_pt_candidate_pt"), hfcandidate.m(), jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_candidate_invmass_jet_pt_candidate_pt"), jetcandidateutilities::getCandidateInvariantMass(candidate), jet.pt(), candidate.pt(), weight); + registry.fill(HIST("h3_candidatebar_invmass_jet_pt_candidate_pt"), jetcandidateutilities::getCandidateInvariantMass(candidate), jet.pt(), candidate.pt(), weight); } } } @@ -558,12 +583,12 @@ struct JetFinderHFQATask { registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (rho * jet.area()), weight); registry.fill(HIST("h_jet_eta_rhoareasubtracted"), jet.eta(), weight); registry.fill(HIST("h_jet_phi_rhoareasubtracted"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks_rhoareasubtracted"), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h_jet_ntracks_rhoareasubtracted"), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h2_centrality_jet_pt_rhoareasubtracted"), centrality, jet.pt() - (rho * jet.area()), weight); if (jet.pt() - (rho * jet.area()) > 0) { registry.fill(HIST("h2_centrality_jet_eta_rhoareasubtracted"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi_rhoareasubtracted"), centrality, jet.phi(), weight); - registry.fill(HIST("h2_centrality_jet_ntracks_rhoareasubtracted"), centrality, jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h2_centrality_jet_ntracks_rhoareasubtracted"), centrality, jet.tracksIds().size() + jet.candidatesIds().size(), weight); } } @@ -571,7 +596,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_jet_eta_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), jet.eta(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_phi_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), jet.phi(), weight); registry.fill(HIST("h3_jet_r_jet_eta_jet_phi_rhoareasubtracted"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_area_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), jet.area(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_pt_rhoareasubtracted"), jet.r() / 100.0, jet.pt(), jet.pt() - (rho * jet.area()), weight); @@ -582,11 +607,11 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_track_phi_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), constituent.phi(), weight); } - for (auto& hfcandidate : jet.template hfcandidates_as>()) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), hfcandidate.pt(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), hfcandidate.eta(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), hfcandidate.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), hfcandidate.y(), weight); + for (auto& candidate : jet.template candidates_as>()) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), candidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), candidate.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), candidate.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_rhoareasubtracted"), jet.r() / 100.0, jet.pt() - (rho * jet.area()), candidate.y(), weight); } } @@ -597,18 +622,18 @@ struct JetFinderHFQATask { registry.fill(HIST("h_jet_pt_eventwiseconstituentsubtracted"), jet.pt(), weight); registry.fill(HIST("h_jet_eta_eventwiseconstituentsubtracted"), jet.eta(), weight); registry.fill(HIST("h_jet_phi_eventwiseconstituentsubtracted"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks_eventwiseconstituentsubtracted"), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h_jet_ntracks_eventwiseconstituentsubtracted"), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h2_centrality_jet_pt_eventwiseconstituentsubtracted"), centrality, jet.pt(), weight); registry.fill(HIST("h2_centrality_jet_eta_eventwiseconstituentsubtracted"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi_eventwiseconstituentsubtracted"), centrality, jet.phi(), weight); - registry.fill(HIST("h2_centrality_jet_ntracks_eventwiseconstituentsubtracted"), centrality, jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h2_centrality_jet_ntracks_eventwiseconstituentsubtracted"), centrality, jet.tracksIds().size() + jet.candidatesIds().size(), weight); } registry.fill(HIST("h3_jet_r_jet_pt_centrality_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), centrality, weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_eta_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_phi_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); registry.fill(HIST("h3_jet_r_jet_eta_jet_phi_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_area_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), jet.area(), weight); for (auto& constituent : jet.template tracks_as()) { @@ -618,11 +643,11 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_track_phi_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - for (auto& hfcandidate : jet.template hfcandidates_as>()) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), hfcandidate.y(), weight); + for (auto& candidate : jet.template candidates_as>()) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), candidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), candidate.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), candidate.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_eventwiseconstituentsubtracted"), jet.r() / 100.0, jet.pt(), candidate.y(), weight); } } @@ -640,13 +665,13 @@ struct JetFinderHFQATask { registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks_part"), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h_jet_ntracks_part"), jet.tracksIds().size() + jet.candidatesIds().size(), weight); } registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_eta_part"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_phi_part"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); registry.fill(HIST("h3_jet_r_part_jet_eta_part_jet_phi_part"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_ntracks_part"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_ntracks_part"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.candidatesIds().size(), weight); for (auto& constituent : jet.template tracks_as>()) { @@ -655,16 +680,16 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - for (auto& hfcandidate : jet.template hfcandidates_as>()) { + for (auto& candidate : jet.template candidates_as>()) { - registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_pt_part"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_eta_part"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_pt_part"), jet.r() / 100.0, jet.pt(), candidate.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_eta_part"), jet.r() / 100.0, jet.pt(), candidate.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), candidate.phi(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_pt_part"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_eta_part"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_phi_part"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_y_part"), jet.r() / 100.0, jet.pt(), hfcandidate.y(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_pt_part"), jet.r() / 100.0, jet.pt(), candidate.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_eta_part"), jet.r() / 100.0, jet.pt(), candidate.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_phi_part"), jet.r() / 100.0, jet.pt(), candidate.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_y_part"), jet.r() / 100.0, jet.pt(), candidate.y(), weight); } } @@ -683,7 +708,7 @@ struct JetFinderHFQATask { auto candidateTagPhi = 0.0; auto candidateTagEta = 0.0; - auto candidateBase = jetBase.template hfcandidates_first_as>(); + auto candidateBase = jetBase.template candidates_first_as>(); candidateBasePt = candidateBase.pt(); candidateBasePhi = candidateBase.phi(); candidateBaseEta = candidateBase.eta(); @@ -693,7 +718,7 @@ struct JetFinderHFQATask { if (jetTag.pt() > pTHatMaxMCP * pTHat) { continue; } - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -701,7 +726,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeo"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeo"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeo"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeo"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeo"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeo"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeo"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeo"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -712,7 +737,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeo"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeo"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeo"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -722,7 +747,7 @@ struct JetFinderHFQATask { if (jetTag.pt() > pTHatMaxMCP * pTHat) { continue; } - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -730,7 +755,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpt"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpt"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpt"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpt"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpt"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedpt"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedpt"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedpt"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -741,7 +766,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpt"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpt"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpt"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -750,7 +775,7 @@ struct JetFinderHFQATask { if (jetTag.pt() > pTHatMaxMCP * pTHat) { continue; } - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -758,7 +783,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedhf"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedhf"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedhf"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedhf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedhf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedhf"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedhf"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedhf"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -769,7 +794,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedhf"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedhf"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedhf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedhf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -780,7 +805,7 @@ struct JetFinderHFQATask { } if (jetBase.template matchedJetGeo_first_as>().globalIndex() == jetBase.template matchedJetPt_first_as>().globalIndex()) { // not a good way to do this - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -788,7 +813,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopt"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopt"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopt"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopt"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopt"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeopt"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeopt"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeopt"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -799,7 +824,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopt"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopt"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopt"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -811,7 +836,7 @@ struct JetFinderHFQATask { } if (jetBase.template matchedJetGeo_first_as>().globalIndex() == jetBase.template matchedJetCand_first_as>().globalIndex()) { // not a good way to do this - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -819,7 +844,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeohf"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeohf"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeohf"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeohf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeohf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeohf"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeohf"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeohf"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -830,7 +855,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeohf"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeohf"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeohf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeohf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -842,7 +867,7 @@ struct JetFinderHFQATask { } if (jetBase.template matchedJetPt_first_as>().globalIndex() == jetBase.template matchedJetCand_first_as>().globalIndex()) { // not a good way to do this - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -850,7 +875,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedpthf"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedpthf"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedpthf"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpthf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedpthf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedpthf"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedpthf"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedpthf"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -861,7 +886,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedpthf"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedpthf"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpthf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedpthf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -875,7 +900,7 @@ struct JetFinderHFQATask { if (jetBase.template matchedJetGeo_first_as>().globalIndex() == jetBase.template matchedJetPt_first_as>().globalIndex()) { if (jetBase.template matchedJetGeo_first_as>().globalIndex() == jetBase.template matchedJetCand_first_as>().globalIndex()) { // not a good way to do this - auto candidateTag = jetTag.template hfcandidates_first_as>(); + auto candidateTag = jetTag.template candidates_first_as>(); candidateTagPt = candidateTag.pt(); candidateTagPhi = candidateTag.phi(); candidateTagEta = candidateTag.eta(); @@ -883,7 +908,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_tag_jet_pt_base_matchedgeopthf"), jetBase.r() / 100.0, jetTag.pt(), jetBase.pt(), weight); registry.fill(HIST("h3_jet_r_jet_eta_tag_jet_eta_base_matchedgeopthf"), jetBase.r() / 100.0, jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_r_jet_phi_tag_jet_phi_base_matchedgeopthf"), jetBase.r() / 100.0, jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf"), jetBase.r() / 100.0, jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_candidate_pt_tag_candidate_pt_base_matchedgeopthf"), jetBase.r() / 100.0, candidateTagPt, candidateBasePt, weight); registry.fill(HIST("h3_jet_r_candidate_eta_tag_candidate_eta_base_matchedgeopthf"), jetBase.r() / 100.0, candidateTagEta, candidateBaseEta, weight); registry.fill(HIST("h3_jet_r_candidate_phi_tag_candidate_phi_base_matchedgeopthf"), jetBase.r() / 100.0, candidateTagPhi, candidateBasePhi, weight); @@ -894,7 +919,7 @@ struct JetFinderHFQATask { if (jetBase.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h3_jet_pt_tag_jet_eta_tag_jet_eta_base_matchedgeopthf"), jetTag.pt(), jetTag.eta(), jetBase.eta(), weight); registry.fill(HIST("h3_jet_pt_tag_jet_phi_tag_jet_phi_base_matchedgeopthf"), jetTag.pt(), jetTag.phi(), jetBase.phi(), weight); - registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.hfcandidatesIds().size(), jetBase.tracksIds().size() + jetBase.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_pt_tag_jet_ntracks_tag_jet_ntracks_base_matchedgeopthf"), jetTag.pt(), jetTag.tracksIds().size() + jetTag.candidatesIds().size(), jetBase.tracksIds().size() + jetBase.candidatesIds().size(), weight); } } } @@ -909,10 +934,63 @@ struct JetFinderHFQATask { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } - registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); - registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); - registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); - registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_phi"), collision.centrality(), track.pt(), track.phi(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_eta"), collision.centrality(), track.pt(), track.eta(), weight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi"), track.pt(), track.eta(), track.phi(), weight); + } + } + + template + void randomCone(T const& collision, U const& jets, V const& candidates, M const& tracks) + { + + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto const& candidate : candidates) { + TRandom3 randomNumber(0); + float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + float randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); + float randomConePt = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); + float dEta = track.eta() - randomConeEta; + if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } + } + registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * candidate.rho()); + + // removing the leading jet from the random cone + if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet + float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); + float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + + bool jetWasInCone = false; + while (TMath::Sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR) { + jetWasInCone = true; + randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); + dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); + dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + } + if (jetWasInCone) { + randomConePt = 0.0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); + float dEta = track.eta() - randomConeEta; + if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } + } + } + } + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * candidate.rho()); + break; // currently only fills it for the first candidate in the event (not pT ordered). Jet is pT ordered so results for excluding leading jet might not be as expected } } @@ -936,9 +1014,8 @@ struct JetFinderHFQATask { PROCESS_SWITCH(JetFinderHFQATask, processJetsData, "jet finder HF QA data", false); void processJetsRhoAreaSubData(soa::Filtered::iterator const& collision, - BkgRhoTable const& bkgRhos, JetTableDataJoined const& jets, - CandidateTableData const&, + soa::Join const&, JetTracks const&) { for (auto const& jet : jets) { @@ -948,13 +1025,30 @@ struct JetFinderHFQATask { if (!isAcceptedJet(jet)) { continue; } - auto const jetCandidate = jet.template hfcandidates_first_as(); - auto bkgRho = jethfutilities::slicedPerCandidate(bkgRhos, jetCandidate, perD0CandidateRhos, perLcCandidateRhos, perBplusCandidateRhos).iteratorAt(0); - fillRhoAreaSubtractedHistograms(jet, collision.centrality(), bkgRho.rho()); + auto const candidate = jet.template candidates_first_as>(); + fillRhoAreaSubtractedHistograms(jet, collision.centrality(), candidate.rho()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsRhoAreaSubData, "jet finder HF QA for rho-area subtracted jets", false); + void processJetsRhoAreaSubMCD(soa::Filtered::iterator const& collision, + JetTableMCDJoined const& jets, + soa::Join const&, + JetTracks const&) + { + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + auto const candidate = jet.template candidates_first_as>(); + fillRhoAreaSubtractedHistograms(jet, collision.centrality(), candidate.rho()); + } + } + PROCESS_SWITCH(JetFinderHFQATask, processJetsRhoAreaSubMCD, "jet finder HF QA for rho-area subtracted mcd jets", false); + void processEvtWiseConstSubJetsData(soa::Filtered::iterator const& collision, JetTableDataSubJoined const& jets, CandidateTableData const&, JetTracksDataSub const&) { for (auto const& jet : jets) { @@ -1098,13 +1192,13 @@ struct JetFinderHFQATask { return; } registry.fill(HIST("h_collision_trigger_events"), 2.5); // events with sel8() - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h_collision_trigger_events"), 3.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_collision_trigger_events"), 4.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_collision_trigger_events"), 5.5); // events with high pT triggered jets } @@ -1116,19 +1210,19 @@ struct JetFinderHFQATask { for (auto& jet : jets) { for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f)) { - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && !filledJetR_Low[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && !filledJetR_Low[iJetRadius]) { filledJetR_Low[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_Low"), jet.r() / 100.0, pt); } } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh) && !filledJetR_High[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt) && !filledJetR_High[iJetRadius]) { filledJetR_High[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_High"), jet.r() / 100.0, pt); } } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh) && !filledJetR_Both[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt) && !filledJetR_Both[iJetRadius]) { filledJetR_Both[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_Both"), jet.r() / 100.0, pt); @@ -1145,17 +1239,17 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 0.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 0.0); - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 1.0); registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 1.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 1.0); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 2.0); registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 2.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 2.0); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 3.0); registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 3.0); registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 3.0); @@ -1166,46 +1260,46 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_jet_r_jet_pt_track_eta_MB"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_MB"), jet.r() / 100.0, jet.pt(), constituent.phi()); - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered_Low"), jet.r() / 100.0, jet.pt(), constituent.pt()); registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered_Low"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered_Low"), jet.r() / 100.0, jet.pt(), constituent.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered_High"), jet.r() / 100.0, jet.pt(), constituent.pt()); registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered_High"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered_High"), jet.r() / 100.0, jet.pt(), constituent.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered_Both"), jet.r() / 100.0, jet.pt(), constituent.pt()); registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered_Both"), jet.r() / 100.0, jet.pt(), constituent.eta()); registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered_Both"), jet.r() / 100.0, jet.pt(), constituent.phi()); } } - for (auto& hfcandidate : jet.template hfcandidates_as()) { - - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); - - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered_Low"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered_Low"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered_Low"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered_Low"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); + for (auto& candidate : jet.template candidates_as()) { + + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_MB"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_MB"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_MB"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_MB"), jet.r() / 100.0, jet.pt(), candidate.y()); + + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered_Low"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered_Low"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered_Low"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered_Low"), jet.r() / 100.0, jet.pt(), candidate.y()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered_High"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered_High"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered_High"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered_High"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered_High"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered_High"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered_High"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered_High"), jet.r() / 100.0, jet.pt(), candidate.y()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered_Both"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered_Both"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered_Both"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered_Both"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered_Both"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered_Both"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered_Both"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered_Both"), jet.r() / 100.0, jet.pt(), candidate.y()); } } } @@ -1218,17 +1312,17 @@ struct JetFinderHFQATask { registry.fill(HIST("h_track_eta_MB"), track.eta()); registry.fill(HIST("h_track_phi_MB"), track.phi()); - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { registry.fill(HIST("h_track_pt_Triggered_Low"), track.pt()); registry.fill(HIST("h_track_eta_Triggered_Low"), track.eta()); registry.fill(HIST("h_track_phi_Triggered_Low"), track.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_track_pt_Triggered_High"), track.pt()); registry.fill(HIST("h_track_eta_Triggered_High"), track.eta()); registry.fill(HIST("h_track_phi_Triggered_High"), track.phi()); } - if (jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow) && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { registry.fill(HIST("h_track_pt_Triggered_Both"), track.pt()); registry.fill(HIST("h_track_eta_Triggered_Both"), track.eta()); registry.fill(HIST("h_track_phi_Triggered_Both"), track.phi()); @@ -1247,12 +1341,12 @@ struct JetFinderHFQATask { int hfLowTrigger = -2; int hfHighTrigger = -2; if constexpr (jethfutilities::isD0Table()) { - hfLowTrigger = jetderiveddatautilities::JTrigSelChHF::chargedD0Low; - hfHighTrigger = jetderiveddatautilities::JTrigSelChHF::chargedD0High; + hfLowTrigger = jetderiveddatautilities::JTrigSel::JetD0ChLowPt; + hfHighTrigger = jetderiveddatautilities::JTrigSel::JetD0ChHighPt; } if constexpr (jethfutilities::isLcTable()) { - hfLowTrigger = jetderiveddatautilities::JTrigSelChHF::chargedLcLow; - hfHighTrigger = jetderiveddatautilities::JTrigSelChHF::chargedLcHigh; + hfLowTrigger = jetderiveddatautilities::JTrigSel::JetLcChLowPt; + hfHighTrigger = jetderiveddatautilities::JTrigSel::JetLcChHighPt; } registry.fill(HIST("h_collision_hftrigger_events"), 0.5); // all events @@ -1264,28 +1358,28 @@ struct JetFinderHFQATask { return; } registry.fill(HIST("h_collision_hftrigger_events"), 2.5); // events with sel8() - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedD0Low)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetD0ChLowPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 3.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedD0High)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetD0ChHighPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 4.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedD0Low) && jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedD0High)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetD0ChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetD0ChHighPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 5.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedLcLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetLcChLowPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 6.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedLcHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetLcChHighPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 7.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedLcLow) && jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedLcHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetLcChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetLcChHighPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 8.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedD0Low) && jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedLcLow)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetD0ChLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetLcChLowPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 9.5); // events with high pT triggered jets } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedD0High) && jetderiveddatautilities::selectChargedHFTrigger(collision, jetderiveddatautilities::JTrigSelChHF::chargedLcHigh)) { + if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetD0ChHighPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetLcChHighPt)) { registry.fill(HIST("h_collision_hftrigger_events"), 10.5); // events with high pT triggered jets } @@ -1297,13 +1391,13 @@ struct JetFinderHFQATask { for (auto& jet : jets) { for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f)) { - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfLowTrigger) && !filledJetHFR_Low[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, hfLowTrigger) && !filledJetHFR_Low[iJetRadius]) { filledJetHFR_Low[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_HFlow"), jet.r() / 100.0, pt); } } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfHighTrigger) && !filledJetHFR_High[iJetRadius]) { + if (jetderiveddatautilities::selectTrigger(collision, hfHighTrigger) && !filledJetHFR_High[iJetRadius]) { filledJetHFR_High[iJetRadius] = true; for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { registry.fill(HIST("h2_jet_r_jet_pT_triggered_HFhigh"), jet.r() / 100.0, pt); @@ -1326,40 +1420,40 @@ struct JetFinderHFQATask { registry.fill(HIST("h3_hfjet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 0.0); registry.fill(HIST("h3_hfjet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 0.0); - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfLowTrigger)) { + if (jetderiveddatautilities::selectTrigger(collision, hfLowTrigger)) { registry.fill(HIST("h3_hfjet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 1.0); registry.fill(HIST("h3_hfjet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 1.0); registry.fill(HIST("h3_hfjet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 1.0); } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfHighTrigger)) { + if (jetderiveddatautilities::selectTrigger(collision, hfHighTrigger)) { registry.fill(HIST("h3_hfjet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 2.0); registry.fill(HIST("h3_hfjet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 2.0); registry.fill(HIST("h3_hfjet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 2.0); } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfLowTrigger) && jetderiveddatautilities::selectChargedHFTrigger(collision, hfHighTrigger)) { + if (jetderiveddatautilities::selectTrigger(collision, hfLowTrigger) && jetderiveddatautilities::selectTrigger(collision, hfHighTrigger)) { registry.fill(HIST("h3_hfjet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), 3.0); registry.fill(HIST("h3_hfjet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), 3.0); registry.fill(HIST("h3_hfjet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), 3.0); } - for (auto& hfcandidate : jet.template hfcandidates_as()) { + for (auto& candidate : jet.template candidates_as()) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_all"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_all"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_all"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_all"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_all"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_all"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_all"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_all"), jet.r() / 100.0, jet.pt(), candidate.y()); - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfLowTrigger)) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_triggered_HFlow"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_triggered_HFlow"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_triggered_HFlow"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_triggered_HFlow"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); + if (jetderiveddatautilities::selectTrigger(collision, hfLowTrigger)) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_triggered_HFlow"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_triggered_HFlow"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_triggered_HFlow"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_triggered_HFlow"), jet.r() / 100.0, jet.pt(), candidate.y()); } - if (jetderiveddatautilities::selectChargedHFTrigger(collision, hfHighTrigger)) { - registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), hfcandidate.y()); + if (jetderiveddatautilities::selectTrigger(collision, hfHighTrigger)) { + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), candidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), candidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), candidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_triggered_HFhigh"), jet.r() / 100.0, jet.pt(), candidate.y()); } } } @@ -1406,24 +1500,22 @@ struct JetFinderHFQATask { } for (auto const& candidate : candidates) { - for (auto const& track : jethfutilities::slicedPerCandidate(tracks, candidate, perD0CandidateTracks, perLcCandidateTracks, perBplusCandidateTracks)) { - registry.fill(HIST("h2_centrality_track_pt_eventwiseconstituentsubtracted"), collision.centrality(), track.pt()); - registry.fill(HIST("h2_centrality_track_eta_eventwiseconstituentsubtracted"), collision.centrality(), track.eta()); - registry.fill(HIST("h2_centrality_track_phi_eventwiseconstituentsubtracted"), collision.centrality(), track.phi()); - registry.fill(HIST("h2_centrality_track_energy_eventwiseconstituentsubtracted"), collision.centrality(), track.energy()); + for (auto const& track : jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0CandidateTracks, perLcCandidateTracks, perBplusCandidateTracks, perDielectronCandidateTracks)) { + registry.fill(HIST("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.phi()); + registry.fill(HIST("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.eta()); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_eventwiseconstituentsubtracted"), track.pt(), track.eta(), track.phi()); } break; // currently only fills it for the first candidate in the event (not pT ordered) } } PROCESS_SWITCH(JetFinderHFQATask, processTracksSub, "QA for charged event-wise embedded subtracted tracks", false); - void processRho(JetCollision const& collision, CandidateTableData const& candidates, BkgRhoTable const& bkgRhos, soa::Filtered const& tracks) + void processRho(JetCollision const& collision, soa::Join const& candidates, soa::Filtered const& tracks) { if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { return; } for (auto const& candidate : candidates) { - auto bkgRho = jethfutilities::slicedPerCandidate(bkgRhos, candidate, perD0CandidateRhos, perLcCandidateRhos, perBplusCandidateRhos).iteratorAt(0); int nTracks = 0; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -1431,74 +1523,32 @@ struct JetFinderHFQATask { } } registry.fill(HIST("h2_centrality_ntracks"), collision.centrality(), nTracks); - registry.fill(HIST("h2_ntracks_rho"), nTracks, bkgRho.rho()); - registry.fill(HIST("h2_ntracks_rhom"), nTracks, bkgRho.rhoM()); - registry.fill(HIST("h2_centrality_rho"), collision.centrality(), bkgRho.rho()); - registry.fill(HIST("h2_centrality_rhom"), collision.centrality(), bkgRho.rhoM()); + registry.fill(HIST("h2_ntracks_rho"), nTracks, candidate.rho()); + registry.fill(HIST("h2_ntracks_rhom"), nTracks, candidate.rhoM()); + registry.fill(HIST("h2_centrality_rho"), collision.centrality(), candidate.rho()); + registry.fill(HIST("h2_centrality_rhom"), collision.centrality(), candidate.rhoM()); break; // currently only fills it for the first candidate in the event (not pT ordered) } } PROCESS_SWITCH(JetFinderHFQATask, processRho, "QA for rho-area subtracted jets", false); - void processRandomCone(soa::Filtered::iterator const& collision, JetTableDataSubJoined const& jets, CandidateTableData const& candidates, BkgRhoTable const& bkgRhos, soa::Filtered const& tracks) + void processRandomConeData(soa::Filtered::iterator const& collision, JetTableDataJoined const& jets, soa::Join const& candidates, soa::Filtered const& tracks) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { - return; - } - for (auto const& candidate : candidates) { - auto bkgRho = jethfutilities::slicedPerCandidate(bkgRhos, candidate, perD0CandidateRhos, perLcCandidateRhos, perBplusCandidateRhos).iteratorAt(0); - TRandom3 randomNumber(0); - float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - float randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); - float randomConePt = 0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); - float dEta = track.eta() - randomConeEta; - if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); - } - } - } - registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * bkgRho.rho()); - - // removing the leading jet from the random cone - if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet - float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); - float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + randomCone(collision, jets, candidates, tracks); + } + PROCESS_SWITCH(JetFinderHFQATask, processRandomConeData, "QA for random cone estimation of background fluctuations in data", false); - bool jetWasInCone = false; - while (TMath::Sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR) { - jetWasInCone = true; - randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - randomConePhi = randomNumber.Uniform(0.0, 2 * M_PI); - dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-M_PI)); - dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; - } - if (jetWasInCone) { - randomConePt = 0.0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-M_PI)); - float dEta = track.eta() - randomConeEta; - if (TMath::Sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); - } - } - } - } - } - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * bkgRho.rho()); - break; // currently only fills it for the first candidate in the event (not pT ordered). Jet is pT ordered so results for excluding leading jet might not be as expected - } + void processRandomConeMCD(soa::Filtered::iterator const& collision, JetTableMCDJoined const& jets, soa::Join const& candidates, soa::Filtered const& tracks) + { + randomCone(collision, jets, candidates, tracks); } - PROCESS_SWITCH(JetFinderHFQATask, processRandomCone, "QA for random cone estimation of background fluctuations", false); + PROCESS_SWITCH(JetFinderHFQATask, processRandomConeMCD, "QA for random cone estimation of background fluctuations in mcd", false); void processCandidates(soa::Filtered::iterator const& collision, CandidateTableData const& candidates) { for (auto const& candidate : candidates) { - registry.fill(HIST("h_candidate_invmass"), candidate.m()); + registry.fill(HIST("h_candidate_invmass"), jetcandidateutilities::getCandidateInvariantMass(candidate)); registry.fill(HIST("h_candidate_pt"), candidate.pt()); registry.fill(HIST("h_candidate_y"), candidate.y()); } @@ -1510,6 +1560,7 @@ struct JetFinderHFQATask { using JetFinderD0QATask = JetFinderHFQATask; using JetFinderLcQATask = JetFinderHFQATask; // using JetFinderBplusQATask = JetFinderHFQATask; +using JetFinderDielectronQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { @@ -1523,6 +1574,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) SetDefaultProcesses{}, TaskName{"jet-finder-charged-lc-qa"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-charged-dielectron-qa"})); + // tasks.emplace_back(adaptAnalysisTask(cfgc, // SetDefaultProcesses{}, // TaskName{"jet-finder-charged-bplus-qa"})); diff --git a/PWGJE/Tasks/jetfinderv0QA.cxx b/PWGJE/Tasks/jetfinderv0QA.cxx index 7286d6bef9e..8f0152db0ee 100644 --- a/PWGJE/Tasks/jetfinderv0QA.cxx +++ b/PWGJE/Tasks/jetfinderv0QA.cxx @@ -184,7 +184,7 @@ struct JetFinderV0QATask { break; } } - for (auto& hfconstituent : jet.template hfcandidates_as()) { + for (auto& hfconstituent : jet.template candidates_as()) { if (hfconstituent.pt() >= leadingConstituentPtMin) { isMinleadingConstituent = true; break; @@ -210,18 +210,18 @@ struct JetFinderV0QATask { registry.fill(HIST("h_jet_pt"), jet.pt(), weight); registry.fill(HIST("h_jet_eta"), jet.eta(), weight); registry.fill(HIST("h_jet_phi"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h2_centrality_jet_pt"), centrality, jet.pt(), weight); registry.fill(HIST("h2_centrality_jet_eta"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi"), centrality, jet.phi(), weight); - registry.fill(HIST("h2_centrality_jet_ntracks"), centrality, jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h2_centrality_jet_ntracks"), centrality, jet.tracksIds().size() + jet.candidatesIds().size(), weight); } registry.fill(HIST("h3_jet_r_jet_pt_centrality"), jet.r() / 100.0, jet.pt(), centrality, weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); registry.fill(HIST("h3_jet_r_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.candidatesIds().size(), weight); registry.fill(HIST("h3_jet_r_jet_pt_jet_area"), jet.r() / 100.0, jet.pt(), jet.area(), weight); for (auto& constituent : jet.template tracks_as()) { @@ -231,7 +231,7 @@ struct JetFinderV0QATask { registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - for (auto& v0candidate : jet.template hfcandidates_as>()) { + for (auto& v0candidate : jet.template candidates_as>()) { registry.fill(HIST("h3_jet_r_jet_pt_track_pt"), jet.r() / 100.0, jet.pt(), v0candidate.pt(), weight); registry.fill(HIST("h3_jet_r_jet_pt_track_eta"), jet.r() / 100.0, jet.pt(), v0candidate.eta(), weight); @@ -263,13 +263,13 @@ struct JetFinderV0QATask { registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks_part"), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h_jet_ntracks_part"), jet.tracksIds().size() + jet.candidatesIds().size(), weight); } registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_eta_part"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_phi_part"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); registry.fill(HIST("h3_jet_r_part_jet_eta_part_jet_phi_part"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_ntracks_part"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.hfcandidatesIds().size(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_ntracks_part"), jet.r() / 100.0, jet.pt(), jet.tracksIds().size() + jet.candidatesIds().size(), weight); for (auto& constituent : jet.template tracks_as>()) { @@ -278,7 +278,7 @@ struct JetFinderV0QATask { registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - for (auto& v0candidate : jet.template hfcandidates_as>()) { + for (auto& v0candidate : jet.template candidates_as>()) { registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_pt_part"), jet.r() / 100.0, jet.pt(), v0candidate.pt(), weight); registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_eta_part"), jet.r() / 100.0, jet.pt(), v0candidate.eta(), weight); diff --git a/PWGJE/Tasks/jetfragmentation.cxx b/PWGJE/Tasks/jetfragmentation.cxx index 710c9220267..cbabebc5c38 100644 --- a/PWGJE/Tasks/jetfragmentation.cxx +++ b/PWGJE/Tasks/jetfragmentation.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// jet V0 fragmentation +/// \brief Task for jet fragmentation into V0s // /// \author Gijs van Weelden // @@ -63,7 +63,7 @@ using MatchedMCPV0Jets = soa::Join; struct JetFragmentation { - HistogramRegistry registry{"registry"}; + HistogramRegistry registry{"registry"}; // CallSumw2 = false? Configurable evSel{"evSel", "sel8WithoutTimeFrameBorderCut", "choose event selection"}; Configurable vertexZCut{"vertexZCut", 10.f, "vertex z cut"}; @@ -115,6 +115,7 @@ struct JetFragmentation { ConfigurableAxis jetCount{"jetCount", {20, -.5f, 19.5f}, ""}; ConfigurableAxis trackCount{"trackCount", {1000, -.5f, 999.5f}, ""}; ConfigurableAxis v0Count{"v0Count", {50, -.5f, 49.5f}, ""}; + ConfigurableAxis v0Weight{"v0Weight", {50, 0.f, 10.0f}, ""}; ConfigurableAxis binV0Pt{"binV0Pt", {120, 0.0f, 60.0f}, ""}; ConfigurableAxis binV0Eta{"binV0Eta", {20, -1.f, 1.f}, ""}; @@ -239,7 +240,7 @@ struct JetFragmentation { registry.add("data/collision/collisionVtxZ", "Collision vertex z (cm)", HistType::kTH1D, {binVtxZ}); registry.add("data/tracks/trackPtEtaPhi", "trackPtEtaPhi", HistType::kTH3D, {trackPtAxis, etaAxis, phiAxis}); } - if (doprocessDataRun3 || doprocessDataV0Frag || doprocessDataV0JetsFrag) { + if (doprocessDataRun3 || doprocessDataV0Frag || doprocessDataV0JetsFrag || doprocessDataV0JetsFragWithWeights) { registry.add("data/jets/jetPtEtaPhi", "Jet #it{p}_{T}, #eta, #phi", HistType::kTH3D, {jetPtAxis, etaAxis, phiAxis}); } if (doprocessDataRun3 || doprocessDataV0Frag) { @@ -253,8 +254,11 @@ struct JetFragmentation { registry.add("data/jets/jetPtZTheta", "Jet #it{p}_{T}, z, #theta", HistType::kTH3D, {jetPtAxis, zAxis, thetaAxis}); } // doprocessDataRun3 || doprocessDataV0Frag - if (doprocessDataV0 || doprocessDataV0Frag || doprocessDataV0JetsFrag) { + if (doprocessDataV0 || doprocessDataV0Frag || doprocessDataV0JetsFrag || doprocessDataV0JetsFragWithWeights || doprocessDataV0PerpCone) { registry.add("data/V0/nV0sEvent", "nV0sEvent", HistType::kTH1D, {v0Count}); + // TODO: Does this make sense? + registry.add("data/V0/nV0sEventWeighted", "nV0s per event (weighted)", HistType::kTH1D, {v0Count}); + registry.get(HIST("data/V0/nV0sEventWeighted"))->Sumw2(); // Unidentified registry.add("data/V0/V0PtEtaPhi", "V0PtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); @@ -295,7 +299,7 @@ struct JetFragmentation { registry.add("data/jets/V0/jetCorrectedPtV0TrackProj", "jetCorrectedPtV0TrackProj", HistType::kTH2D, {jetPtAxis, zAxis}); } - if (doprocessDataV0Frag || doprocessDataV0JetsFrag) { + if (doprocessDataV0Frag || doprocessDataV0JetsFrag || doprocessDataV0JetsFragWithWeights) { registry.add("data/jets/V0/jetPtV0TrackProj", "jetPtV0TrackProj", HistType::kTH2D, {jetPtAxis, zAxis}); registry.add("data/jets/V0/jetPtnV0nK0SnLambdanAntiLambda", "jetPtnV0nK0SnLambdanAntiLambda", HistType::kTHnSparseD, {jetPtAxis, v0Count, v0Count, v0Count, v0Count}); @@ -371,6 +375,83 @@ struct JetFragmentation { registry.add("data/jets/V0/jetPtK0STrackProjDCAposneg", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, DCA#pm", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0DCApAxis, V0DCAnAxis}); } // doprocessDataV0Frag || doprocessDataV0JetsFrag + if (doprocessDataV0JetsFragWithWeights) { + // FIXME: These hists need Sumw2 + registry.add("data/jets/weighted/jetPtEtaPhi", "Jet #it{p}_{T}, #eta, #phi", HistType::kTH3D, {jetPtAxis, etaAxis, phiAxis}); + registry.add("data/jets/weighted/V0/jetPtnV0nK0SnLambdanAntiLambda", "jetPtnV0nK0SnLambdanAntiLambda", HistType::kTHnSparseD, {jetPtAxis, v0Weight, v0Weight, v0Weight, v0Weight}); + + registry.add("data/jets/weighted/V0/jetPtV0TrackProjCtau", "jetPtV0TrackProjCtau", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0CtauAxis, V0CtauAxis, V0CtauAxis}); + registry.add("data/jets/weighted/V0/jetPtV0TrackProjMass", "jetPtV0TrackProjMass", HistType::kTHnSparseD, {jetPtAxis, zAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtV0TrackProjLambdaMasses", "jetPtV0TrackProjLambdaMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, LambdaMassDiffAxis, LambdaMassRatioAxis, LambdaMassRelDiffAxis}); + registry.add("data/jets/weighted/V0/jetPtV0TrackProjRadiusCosPA", "jetPtV0TrackProjRadiusCosPA", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/jets/weighted/V0/jetPtV0TrackProjDCAposneg", "jetPtV0TrackProjDCAposneg", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/jets/weighted/V0/jetPtV0TrackProjDCAd", "jetPtV0TrackProjDCAd", HistType::kTH3D, {jetPtAxis, zAxis, V0DCAdAxis}); + // K0S + registry.add("data/jets/weighted/V0/jetPtK0STrackProjCtau", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, c#tau", HistType::kTH3D, {jetPtAxis, zAxis, V0CtauAxis}); + registry.add("data/jets/weighted/V0/jetPtK0STrackProjMass", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, mass", HistType::kTH3D, {jetPtAxis, zAxis, K0SMassAxis}); + registry.add("data/jets/weighted/V0/jetPtK0STrackProjAllMasses", "jetPtK0STrackProjAllMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtK0STrackProjRadius", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, radius", HistType::kTH3D, {jetPtAxis, zAxis, V0RadiusAxis}); + registry.add("data/jets/weighted/V0/jetPtK0STrackProjCosPA", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, cosPA", HistType::kTH3D, {jetPtAxis, zAxis, V0CosPAAxis}); + registry.add("data/jets/weighted/V0/jetPtK0STrackProjDCAd", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, DCA daughters", HistType::kTH3D, {jetPtAxis, zAxis, V0DCAdAxis}); + registry.add("data/jets/weighted/V0/jetPtK0STrackProjDCAposneg", "Jet #it{p}_{T}, #it{z}_{K^{0}_{S}}, DCA#pm", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0DCApAxis, V0DCAnAxis}); + // Lambda + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjCtau", "Jet #it{p}_{T}, #it{z}_{#Lambda^{0}}, c#tau", HistType::kTH3D, {jetPtAxis, zAxis, V0CtauAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjMass", "Jet #it{p}_{T}, #it{z}_{#Lambda^{0}}, mass", HistType::kTH3D, {jetPtAxis, zAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjAllMasses", "jetPtLambdaTrackProjAllMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjLambdaMasses", "jetPtLambdaTrackProjLambdaMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, LambdaMassDiffAxis, LambdaMassRatioAxis, LambdaMassRelDiffAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjRadius", "Jet #it{p}_{T}, #it{z}_{#Lambda^{0}}, radius", HistType::kTH3D, {jetPtAxis, zAxis, V0RadiusAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjCosPA", "Jet #it{p}_{T}, #it{z}_{#Lambda^{0}}, cosPA", HistType::kTH3D, {jetPtAxis, zAxis, V0CosPAAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjDCAd", "Jet #it{p}_{T}, #it{z}_{#Lambda^{0}}, DCA daughters", HistType::kTH3D, {jetPtAxis, zAxis, V0DCAdAxis}); + registry.add("data/jets/weighted/V0/jetPtLambdaTrackProjDCAposneg", "Jet #it{p}_{T}, #it{z}_{#Lambda^{0}}, DCA#pm", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0DCApAxis, V0DCAnAxis}); + // AntiLambda + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjCtau", "Jet #it{p}_{T}, #it{z}_{#bar{#Lambda}^{0}}, c#tau", HistType::kTH3D, {jetPtAxis, zAxis, V0CtauAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjMass", "Jet #it{p}_{T}, #it{z}_{#bar{#Lambda}^{0}}, mass", HistType::kTH3D, {jetPtAxis, zAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjAllMasses", "jetPtAntiLambdaTrackProjAllMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjLambdaMasses", "jetPtAntiLambdaTrackProjLambdaMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, LambdaMassDiffAxis, LambdaMassRatioAxis, LambdaMassRelDiffAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjRadius", "Jet #it{p}_{T}, #it{z}_{#bar{#Lambda}^{0}}, radius", HistType::kTH3D, {jetPtAxis, zAxis, V0RadiusAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjCosPA", "Jet #it{p}_{T}, #it{z}_{#bar{#Lambda}^{0}}, cosPA", HistType::kTH3D, {jetPtAxis, zAxis, V0CosPAAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjDCAd", "Jet #it{p}_{T}, #it{z}_{#bar{#Lambda}^{0}}, DCA daughters", HistType::kTH3D, {jetPtAxis, zAxis, V0DCAdAxis}); + registry.add("data/jets/weighted/V0/jetPtAntiLambdaTrackProjDCAposneg", "Jet #it{p}_{T}, #it{z}_{#bar{#Lambda}^{0}}, DCA#pm", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0DCApAxis, V0DCAnAxis}); + // Background + registry.add("data/jets/weighted/V0/jetPtBkgTrackProjCtau", "jetPtBkgTrackProjCtau", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0CtauAxis, V0CtauAxis, V0CtauAxis}); + registry.add("data/jets/weighted/V0/jetPtBkgTrackProjMass", "jetPtBkgTrackProjMass", HistType::kTHnSparseD, {jetPtAxis, zAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/jets/weighted/V0/jetPtBkgTrackProjLambdaMasses", "jetPtBkgTrackProjLambdaMasses", HistType::kTHnSparseD, {jetPtAxis, zAxis, LambdaMassDiffAxis, LambdaMassRatioAxis, LambdaMassRelDiffAxis}); + registry.add("data/jets/weighted/V0/jetPtBkgTrackProjRadiusCosPA", "jetPtBkgTrackProjRadiusCosPA", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/jets/weighted/V0/jetPtBkgTrackProjDCAposneg", "jetPtBkgTrackProjDCAposneg", HistType::kTHnSparseD, {jetPtAxis, zAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/jets/weighted/V0/jetPtBkgTrackProjDCAd", "jetPtBkgTrackProjDCAd", HistType::kTH3D, {jetPtAxis, zAxis, V0DCAdAxis}); + } + + if (doprocessDataV0PerpCone) { + registry.add("data/PC/V0PtEtaPhi", "V0 #it{p}_{T}, #eta, #phi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/V0PtCtau", "V0PtCtau", HistType::kTHnSparseD, {V0PtAxis, V0CtauAxis, V0CtauAxis, V0CtauAxis}); + registry.add("data/PC/V0PtMass", "V0PtMass", HistType::kTHnSparseD, {V0PtAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/PC/V0PtRadiusCosPA", "V0PtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/V0PtDCAposneg", "V0PtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/V0PtDCAd", "V0PtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/LambdaPtEtaPhi", "LambdaPtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/LambdaPtCtauMass", "LambdaPtCtauMass", HistType::kTH3D, {V0PtAxis, V0CtauAxis, LambdaMassAxis}); + registry.add("data/PC/LambdaPtRadiusCosPA", "LambdaPtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/LambdaPtDCAposneg", "LambdaPtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/LambdaPtDCAd", "LambdaPtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/antiLambdaPtEtaPhi", "antiLambdaPtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/antiLambdaPtCtauMass", "antiLambdaPtCtauMass", HistType::kTH3D, {V0PtAxis, V0CtauAxis, LambdaMassAxis}); + registry.add("data/PC/antiLambdaPtRadiusCosPA", "antiLambdaPtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/antiLambdaPtDCAposneg", "antiLambdaPtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/antiLambdaPtDCAd", "antiLambdaPtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/K0SPtEtaPhi", "K0SPtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/K0SPtCtauMass", "K0SPtCtauMass", HistType::kTH3D, {V0PtAxis, V0CtauAxis, K0SMassAxis}); + registry.add("data/PC/K0SPtRadiusCosPA", "K0SPtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/K0SPtDCAposneg", "K0SPtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/K0SPtDCAd", "K0SPtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/nV0sConePtEta", "nV0sConePtEta", HistType::kTH3D, {v0Count, jetPtAxis, etaAxis}); + registry.add("data/PC/ConePtEtaPhi", "ConePtEtaPhi", HistType::kTH3D, {jetPtAxis, etaAxis, phiAxis}); + registry.add("data/PC/JetPtEtaConePt", "JetPtEtaConePt", HistType::kTH3D, {jetPtAxis, etaAxis, jetPtAxis}); + } + if (doprocessMcP || doprocessMcMatchedV0JetsFrag) { registry.add("particle-level/jets/partJetPtEtaPhi", "Particle level jet #it{p}_{T}, #eta, #phi", HistType::kTH3D, {partJetPtAxis, partEtaAxis, partPhiAxis}); } @@ -486,8 +567,10 @@ struct JetFragmentation { registry.add("matching/jets/missPartJetPtZTheta", "Misses", HistType::kTH3D, {partJetPtAxis, partZAxis, partThetaAxis}); } // doprocessMcMatched - if (doprocessMcMatchedV0 || doprocessMcMatchedV0Frag || doprocessMcMatchedV0JetsFrag) { + if (doprocessMcMatchedV0 || doprocessMcMatchedV0Frag || doprocessMcMatchedV0JetsFrag || doprocessMcV0PerpCone) { registry.add("matching/V0/nV0sEvent", "nV0sDet per event", HistType::kTH1D, {v0Count}); + registry.add("matching/V0/nV0sEventWeighted", "nV0sDet per event (weighted)", HistType::kTH1D, {v0Count}); + registry.get(HIST("matching/V0/nV0sEventWeighted"))->Sumw2(); } // doprocessMcMatchedV0 || doprocessMcMatchedV0Frag if (doprocessMcMatchedV0 || doprocessMcMatchedV0JetsFrag) { @@ -729,18 +812,199 @@ struct JetFragmentation { } // doprocessMcMatchedV0Frag if (doprocessMcMatchedV0JetsFrag) { + registry.add("matching/V0/fakeV0PosTrackPtEtaPhi", "fakeV0PosTrackPtEtaPhi", HistType::kTH3D, {trackPtAxis, etaAxis, phiAxis}); + registry.add("matching/V0/fakeV0NegTrackPtEtaPhi", "fakeV0NegTrackPtEtaPhi", HistType::kTH3D, {trackPtAxis, etaAxis, phiAxis}); + registry.add("matching/V0/V0PosPartPtRatioPtRelDiffPt", "V0PosPartPtRatioRelDiffPt", HistType::kTH3D, {trackPtAxis, ptRatioAxis, ptTrackRelDiffAxis}); registry.add("matching/V0/V0NegPartPtRatioPtRelDiffPt", "V0NegPartPtRatioRelDiffPt", HistType::kTH3D, {trackPtAxis, ptRatioAxis, ptTrackRelDiffAxis}); registry.add("matching/jets/V0/partJetPtDetJetPtPartV0PtPosPtRatioPtRelDiffPt", "V0PtPosPartPtRatioRelDiffPt", HistType::kTHnSparseD, {partJetPtAxis, detJetPtAxis, V0PtAxis, trackPtAxis, ptRatioAxis, ptTrackRelDiffAxis}); registry.add("matching/jets/V0/partJetPtDetJetPtPartV0PtNegPtRatioPtRelDiffPt", "V0PtNegPartPtRatioRelDiffPt", HistType::kTHnSparseD, {partJetPtAxis, detJetPtAxis, V0PtAxis, trackPtAxis, ptRatioAxis, ptTrackRelDiffAxis}); - } + } // doprocessMcMatchedV0JetsFrag + + if (doprocessDataV0PerpCone) { + registry.add("data/PC/JetPtEtaV0Pt", "JetPtEtaV0Pt", HistType::kTH3D, {jetPtAxis, etaAxis, V0PtAxis}); + registry.add("data/PC/V0PtEtaPhi", "V0PtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/V0PtCtau", "V0PtCtau", HistType::kTHnSparseD, {V0PtAxis, V0CtauAxis, V0CtauAxis, V0CtauAxis}); + registry.add("data/PC/V0PtMass", "V0PtMass", HistType::kTHnSparseD, {V0PtAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("data/PC/V0PtRadiusCosPA", "V0PtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/V0PtDCAposneg", "V0PtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/V0PtDCAd", "V0PtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/JetPtEtaLambda0Pt", "JetPtEtaLambda0Pt", HistType::kTH3D, {jetPtAxis, etaAxis, V0PtAxis}); + registry.add("data/PC/JetPtLambda0PtMass", "JetPtLambda0PtMass", HistType::kTH3D, {jetPtAxis, V0PtAxis, LambdaMassAxis}); + registry.add("data/PC/LambdaPtEtaPhi", "LambdaPtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/LambdaPtCtauMass", "LambdaPtCtauMass", HistType::kTH3D, {V0PtAxis, V0CtauAxis, LambdaMassAxis}); + registry.add("data/PC/LambdaPtRadiusCosPA", "LambdaPtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/LambdaPtDCAposneg", "LambdaPtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/LambdaPtDCAd", "LambdaPtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/JetPtEtaAntiLambda0Pt", "JetPtEtaAntiLambda0Pt", HistType::kTH3D, {jetPtAxis, etaAxis, V0PtAxis}); + registry.add("data/PC/JetPtAntiLambda0PtMass", "JetPtAntiLambda0PtMass", HistType::kTH3D, {jetPtAxis, V0PtAxis, LambdaMassAxis}); + registry.add("data/PC/antiLambdaPtEtaPhi", "antiLambdaPtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/antiLambdaPtCtauMass", "antiLambdaPtCtauMass", HistType::kTH3D, {V0PtAxis, V0CtauAxis, LambdaMassAxis}); + registry.add("data/PC/antiLambdaPtRadiusCosPA", "antiLambdaPtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/antiLambdaPtDCAposneg", "antiLambdaPtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/antiLambdaPtDCAd", "antiLambdaPtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/JetPtEtaK0SPt", "JetPtEtaK0SPt", HistType::kTH3D, {jetPtAxis, etaAxis, V0PtAxis}); + registry.add("data/PC/JetPtK0SPtMass", "JetPtK0SPtMass", HistType::kTH3D, {jetPtAxis, V0PtAxis, K0SMassAxis}); + registry.add("data/PC/K0SPtEtaPhi", "K0SPtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("data/PC/K0SPtCtauMass", "K0SPtCtauMass", HistType::kTH3D, {V0PtAxis, V0CtauAxis, K0SMassAxis}); + registry.add("data/PC/K0SPtRadiusCosPA", "K0SPtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("data/PC/K0SPtDCAposneg", "K0SPtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("data/PC/K0SPtDCAd", "K0SPtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("data/PC/nV0sConePtEta", "nV0sConePtEta", HistType::kTH3D, {v0Count, jetPtAxis, etaAxis}); + registry.add("data/PC/ConePtEtaPhi", "ConePtEtaPhi", HistType::kTH3D, {jetPtAxis, etaAxis, phiAxis}); + registry.add("data/PC/JetPtEtaConePt", "JetPtEtaConePt", HistType::kTH3D, {jetPtAxis, etaAxis, jetPtAxis}); + } // doprocessDataV0PerpCone + + if (doprocessMcV0PerpCone) { + registry.add("matching/PC/jetPtEtaFakeV0Pt", "JetPtEtaFakeV0Pt", HistType::kTH3D, {jetPtAxis, etaAxis, V0PtAxis}); + registry.add("matching/PC/fakeV0PtEtaPhi", "fakeV0PtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("matching/PC/fakeV0PtCtau", "fakeV0PtCtau", HistType::kTHnSparseD, {V0PtAxis, V0CtauAxis, V0CtauAxis, V0CtauAxis}); + registry.add("matching/PC/fakeV0PtMass", "fakeV0PtMass", HistType::kTHnSparseD, {V0PtAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("matching/PC/fakeV0PtRadiusCosPA", "fakeV0PtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("matching/PC/fakeV0PtDCAposneg", "fakeV0PtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("matching/PC/fakeV0PtDCAd", "fakeV0PtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("matching/PC/jetPtEtaMatchedV0Pt", "jetPtEtaMatchedV0Pt", HistType::kTH3D, {jetPtAxis, etaAxis, V0PtAxis}); + registry.add("matching/PC/matchedV0PtEtaPhi", "matchedV0PtEtaPhi", HistType::kTH3D, {V0PtAxis, V0EtaAxis, V0PhiAxis}); + registry.add("matching/PC/matchedV0PtCtau", "matchedV0PtCtau", HistType::kTHnSparseD, {V0PtAxis, V0CtauAxis, V0CtauAxis, V0CtauAxis}); + registry.add("matching/PC/matchedV0PtMass", "matchedV0PtMass", HistType::kTHnSparseD, {V0PtAxis, K0SMassAxis, LambdaMassAxis, LambdaMassAxis}); + registry.add("matching/PC/matchedV0PtRadiusCosPA", "matchedV0PtRadiusCosPA", HistType::kTH3D, {V0PtAxis, V0RadiusAxis, V0CosPAAxis}); + registry.add("matching/PC/matchedV0PtDCAposneg", "matchedV0PtDCAposneg", HistType::kTH3D, {V0PtAxis, V0DCApAxis, V0DCAnAxis}); + registry.add("matching/PC/matchedV0PtDCAd", "matchedV0PtDCAd", HistType::kTH2D, {V0PtAxis, V0DCAdAxis}); + + registry.add("matching/PC/matchedJetPtK0SPtMass", "matchedJetPtK0SPtMass", HistType::kTH3D, {jetPtAxis, V0PtAxis, K0SMassAxis}); + registry.add("matching/PC/matchedJetPtLambda0PtMass", "matchedJetPtLambda0PtMass", HistType::kTH3D, {jetPtAxis, V0PtAxis, LambdaMassAxis}); + registry.add("matching/PC/matchedJetPtAntiLambda0PtMass", "matchedJetPtAntiLambda0PtMass", HistType::kTH3D, {jetPtAxis, V0PtAxis, LambdaMassAxis}); + + registry.add("matching/PC/matchednV0sConePtEta", "matchednV0sConePtEta", HistType::kTH3D, {v0Count, jetPtAxis, etaAxis}); + registry.add("matching/PC/matchedConePtEtaPhi", "matchedConePtEtaPhi", HistType::kTH3D, {jetPtAxis, etaAxis, phiAxis}); + registry.add("matching/PC/matchedJetPtEtaConePt", "matchedJetPtEtaConePt", HistType::kTH3D, {jetPtAxis, etaAxis, jetPtAxis}); + + registry.add("matching/PC/fakenV0sConePtEta", "fakenV0sConePtEta", HistType::kTH3D, {v0Count, jetPtAxis, etaAxis}); + registry.add("matching/PC/fakeConePtEtaPhi", "fakeConePtEtaPhi", HistType::kTH3D, {jetPtAxis, etaAxis, phiAxis}); + registry.add("matching/PC/fakeJetPtEtaConePt", "fakeJetPtEtaConePt", HistType::kTH3D, {jetPtAxis, etaAxis, jetPtAxis}); + } // doprocessMcV0PerpCone } // init + // TODO: This should contain a lookup table or function containing the various V0 weights + // Returns a std::vector of weights for a particle + template + std::vector getV0SignalWeight(C const& coll, V const& v0) + { + // 0: bkg, 1: K0S, 2: Lambda, 3: AntiLambda + std::vector w(4, 0.); + double purity = 0.8; // TODO: need getter to set this + + bool isK = IsK0SCandidate(coll, v0); + bool isL = IsLambdaCandidate(coll, v0); + bool isAL = IsAntiLambdaCandidate(coll, v0); + + // FIXME: Competing Mass Cut will change this approach. Only one signal type per particle + // Candidate for a single particle + switch (isK + isL + isAL) { + case 0: + break; + case 1: + w[1] = static_cast(isK) * purity; + w[2] = static_cast(isL) * purity; + w[3] = static_cast(isAL) * purity; + break; + case 2: + w[1] = static_cast(isK) * (2. / 3.) * purity; + w[2] = (isK ? 2. / 3. : 0.5) * purity; + w[3] = (isK ? 2. / 3. : 0.5) * purity; + break; + case 3: + w[1] = 0.5 * purity; + w[2] = 0.25 * purity; + w[3] = 0.25 * purity; + break; + } + w[0] = 1. - (w[1] + w[2] + w[3]); + return w; + } // getV0SignalWeight + // Converts state from uint32_t to std::vector containing the particle classes for that weight + std::vector convertState(uint32_t state, int nParticles, int nClasses = 4) + { + std::vector v(nParticles, nClasses); + int nStates = pow(nClasses, nParticles); + int nBitsPerParticle = round(log2(nClasses)); + int nBitsPerInt = sizeof(uint32_t) * 8; + + // Check if the input configuration is parseable + if ((nClasses & (nClasses - 1)) != 0) { + // It's likely possible to make this work for non-power of 2 classes, but it's not needed and therefore not implemented + LOGF(warning, "Number of classes (%d) must be a power of 2", nClasses); + return v; + } + if (nStates <= 0) { + LOGF(warning, "Illegal number of states (%d)! %s", nStates, (nStates == 0) ? "" : "Max = 2^31"); + return v; + } + if (nParticles * nBitsPerParticle > nBitsPerInt) { + LOGF(warning, "Number of bits required to parse the state (%d * %d = %d) is too large for %d bits per int!", nParticles, nBitsPerParticle, nParticles * nBitsPerParticle, nBitsPerInt); + return v; + } + if (state >= (uint32_t)nStates) { + LOGF(warning, "Illegal state! State %d >= %d", state, nStates); + return v; + } + + for (int ip = 0; ip < nParticles; ip++) { + double value = 0; + int startBit = ip * nBitsPerParticle; + for (int ib = 0; ib < nBitsPerParticle; ib++) { + int bit = startBit + ib; + int bitVal = ((state & (1 << bit)) > 0); + value += bitVal * TMath::Power(2, ib); + } + v[ip] = value; + } + return v; + } // convertState + // Returns the corrected values for z and ptjet for a given state + std::vector correctedValues(std::vector state, std::vector values) + { + // Assumes values = (z1, z2, ..., zn, ptjet) + std::vector v(values); + double r = 0; + int nParticles = state.size(); + + if (values.size() != (uint32_t)(nParticles + 1)) { + LOGF(warning, "Number of values (%d) must be equal to the number of particles (%d) + 1!", values.size(), nParticles); + return v; + } + for (int ip = 0; ip < nParticles; ip++) { + if (state[ip] == 0) { + r += values[ip]; + } + } + for (int ip = 0; ip < nParticles; ip++) { + if (state[ip] == 0) { + v[ip] = values[ip] / (1 - r); + } + } + v[nParticles] = values[nParticles] * (1 - r); + return v; + } + double stateWeight(std::vector state, std::vector> weights) + { + double w = 1.; + for (int ip = 0; (uint32_t)ip < state.size(); ip++) { + w *= weights[ip][state[ip]]; + } + return w; + } + template bool JetContainsV0s(JetType const& jet) { - return (jet.hfcandidatesIds().size() > 0); + return (jet.candidatesIds().size() > 0); } template bool V0sAreMatched(T const& v0, U const& particle, V const& /*tracks*/) @@ -877,7 +1141,7 @@ struct JetFragmentation { } // TODO: Can probably be made simpler/shorter by using V0MCLabels - template + template // Not used for V0 jets void fillMcMatchedV0Histograms(CollisionType const& collision, V0Type const& v0, trackType const&, particleType const&, double weight = 1.) { auto negTrack = v0.template negTrack_as(); @@ -902,7 +1166,7 @@ struct JetFragmentation { registry.fill(HIST("matching/V0/V0PartPtDetPt"), ptPartV0, v0.pt()); registry.fill(HIST("matching/V0/V0PartPtRatioPtRelDiffPt"), ptPartV0, v0.pt() / ptPartV0, (v0.pt() - ptPartV0) / ptPartV0); - if (pdg == 310) { // K0S + if (TMath::Abs(pdg) == 310) { // K0S registry.fill(HIST("matching/V0/K0SPtEtaPhi"), ptPartV0, v0.pt(), v0.eta(), v0.phi()); registry.fill(HIST("matching/V0/K0SPtCtauMass"), ptPartV0, v0.pt(), ctauK0s, v0.mK0Short(), weight); registry.fill(HIST("matching/V0/K0SPtRadiusCosPA"), ptPartV0, v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); @@ -933,17 +1197,21 @@ struct JetFragmentation { registry.fill(HIST("matching/V0/antiLambda0Reflection"), ptPartV0, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), reflectedMass, weight); } } // if mothers match - } // for mothers of pos - } // for mothers of neg + } // for mothers of pos + } // for mothers of neg } template - void fillDataJetHistograms(T const& jet) + void fillDataJetHistograms(T const& jet, double weight = 1.) { - registry.fill(HIST("data/jets/jetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + registry.fill(HIST("data/jets/jetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi(), weight); } - template - void fillDataFragHistograms(T const& jet) + void fillDataJetHistogramsWithWeights(double jetpt, double jeteta, double jetphi, double weight = 1.) + { + registry.fill(HIST("data/jets/weighted/jetPtEtaPhi"), jetpt, jeteta, jetphi, weight); + } + template // Not used for V0 jets + void fillDataFragHistograms(T const& jet, double weight = 1.) { for (const auto& track : jet.template tracks_as()) { double chargeFrag = -1., trackProj = -1., xi = -1., theta = -1.; @@ -952,19 +1220,19 @@ struct JetFragmentation { theta = Theta(jet, track); xi = Xi(jet, track); - registry.fill(HIST("data/jets/jetPtTrackPt"), jet.pt(), track.pt()); - registry.fill(HIST("data/jets/jetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); - registry.fill(HIST("data/jets/jetPtFrag"), jet.pt(), chargeFrag); - registry.fill(HIST("data/jets/jetPtTrackProj"), jet.pt(), trackProj); - registry.fill(HIST("data/jets/jetPtXi"), jet.pt(), xi); - registry.fill(HIST("data/jets/jetPtTheta"), jet.pt(), theta); - registry.fill(HIST("data/jets/jetPtXiTheta"), jet.pt(), xi, theta); - registry.fill(HIST("data/jets/jetPtZTheta"), jet.pt(), trackProj, theta); + registry.fill(HIST("data/jets/jetPtTrackPt"), jet.pt(), track.pt(), weight); + registry.fill(HIST("data/jets/jetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi(), weight); + registry.fill(HIST("data/jets/jetPtFrag"), jet.pt(), chargeFrag, weight); + registry.fill(HIST("data/jets/jetPtTrackProj"), jet.pt(), trackProj, weight); + registry.fill(HIST("data/jets/jetPtXi"), jet.pt(), xi, weight); + registry.fill(HIST("data/jets/jetPtTheta"), jet.pt(), theta, weight); + registry.fill(HIST("data/jets/jetPtXiTheta"), jet.pt(), xi, theta, weight); + registry.fill(HIST("data/jets/jetPtZTheta"), jet.pt(), trackProj, theta, weight); } } template - void fillDataV0Histograms(CollisionType const& collision, V0Type const& V0s) + void fillDataV0Histograms(CollisionType const& collision, V0Type const& V0s, double weight = 1.) { for (const auto& v0 : V0s) { double ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; @@ -975,44 +1243,44 @@ struct JetFragmentation { double massRatio = v0.mAntiLambda() / v0.mLambda(); double massRelDiff = (v0.mLambda() - v0.mAntiLambda()) / v0.mLambda(); - registry.fill(HIST("data/V0/V0PtEtaPhi"), v0.pt(), v0.eta(), v0.phi()); - registry.fill(HIST("data/V0/V0PtCtau"), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda); - registry.fill(HIST("data/V0/V0PtMass"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/V0/V0PtLambdaMasses"), v0.pt(), massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/V0/V0PtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA()); - registry.fill(HIST("data/V0/V0PtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - registry.fill(HIST("data/V0/V0PtDCAd"), v0.pt(), v0.dcaV0daughters()); + registry.fill(HIST("data/V0/V0PtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/V0/V0PtCtau"), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/V0/V0PtMass"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/V0/V0PtLambdaMasses"), v0.pt(), massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/V0/V0PtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/V0/V0PtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/V0/V0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); - registry.fill(HIST("data/V0/V0CutVariation"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), v0.v0radius(), ctauK0s, v0.v0cosPA(), TMath::Abs(v0.dcapostopv()), TMath::Abs(v0.dcanegtopv()), v0.dcaV0daughters()); + registry.fill(HIST("data/V0/V0CutVariation"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), v0.v0radius(), ctauK0s, v0.v0cosPA(), TMath::Abs(v0.dcapostopv()), TMath::Abs(v0.dcanegtopv()), v0.dcaV0daughters(), weight); if (IsLambdaCandidate(collision, v0)) { - registry.fill(HIST("data/V0/LambdaPtEtaPhi"), v0.pt(), v0.eta(), v0.phi()); - registry.fill(HIST("data/V0/LambdaPtCtauMass"), v0.pt(), ctauLambda, v0.mLambda()); - registry.fill(HIST("data/V0/LambdaPtLambdaMasses"), v0.pt(), massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/V0/LambdaPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA()); - registry.fill(HIST("data/V0/LambdaPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - registry.fill(HIST("data/V0/LambdaPtDCAd"), v0.pt(), v0.dcaV0daughters()); + registry.fill(HIST("data/V0/LambdaPtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/V0/LambdaPtCtauMass"), v0.pt(), ctauLambda, v0.mLambda(), weight); + registry.fill(HIST("data/V0/LambdaPtLambdaMasses"), v0.pt(), massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/V0/LambdaPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/V0/LambdaPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/V0/LambdaPtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); } if (IsAntiLambdaCandidate(collision, v0)) { - registry.fill(HIST("data/V0/antiLambdaPtEtaPhi"), v0.pt(), v0.eta(), v0.phi()); - registry.fill(HIST("data/V0/antiLambdaPtCtauMass"), v0.pt(), ctauAntiLambda, v0.mAntiLambda()); - registry.fill(HIST("data/V0/antiLambdaPtLambdaMasses"), v0.pt(), massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/V0/antiLambdaPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA()); - registry.fill(HIST("data/V0/antiLambdaPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - registry.fill(HIST("data/V0/antiLambdaPtDCAd"), v0.pt(), v0.dcaV0daughters()); + registry.fill(HIST("data/V0/antiLambdaPtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/V0/antiLambdaPtCtauMass"), v0.pt(), ctauAntiLambda, v0.mAntiLambda(), weight); + registry.fill(HIST("data/V0/antiLambdaPtLambdaMasses"), v0.pt(), massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/V0/antiLambdaPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/V0/antiLambdaPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/V0/antiLambdaPtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); } if (IsK0SCandidate(collision, v0)) { - registry.fill(HIST("data/V0/K0SPtEtaPhi"), v0.pt(), v0.eta(), v0.phi()); - registry.fill(HIST("data/V0/K0SPtCtauMass"), v0.pt(), ctauK0s, v0.mK0Short()); - registry.fill(HIST("data/V0/K0SPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA()); - registry.fill(HIST("data/V0/K0SPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - registry.fill(HIST("data/V0/K0SPtDCAd"), v0.pt(), v0.dcaV0daughters()); + registry.fill(HIST("data/V0/K0SPtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/V0/K0SPtCtauMass"), v0.pt(), ctauK0s, v0.mK0Short(), weight); + registry.fill(HIST("data/V0/K0SPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/V0/K0SPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/V0/K0SPtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); } } // for v0 } template - void fillDataV0FragHistograms(CollisionType const& collision, JetType const& jet, V0Type const& v0) + void fillDataV0FragHistograms(CollisionType const& collision, JetType const& jet, V0Type const& v0, double weight = 1.) { double trackProj = TrackProj(jet, v0); double ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; @@ -1023,76 +1291,130 @@ struct JetFragmentation { double massRatio = v0.mAntiLambda() / v0.mLambda(); double massRelDiff = (v0.mLambda() - v0.mAntiLambda()) / v0.mLambda(); - registry.fill(HIST("data/jets/V0/jetPtV0PtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi()); - registry.fill(HIST("data/jets/V0/jetPtV0PtCtau"), jet.pt(), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda); - registry.fill(HIST("data/jets/V0/jetPtV0PtMass"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtV0PtLambdaMasses"), jet.pt(), v0.pt(), massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/jets/V0/jetPtV0PtRadiusCosPA"), jet.pt(), v0.pt(), v0.v0radius(), v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtV0PtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - registry.fill(HIST("data/jets/V0/jetPtV0PtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters()); - - registry.fill(HIST("data/jets/V0/jetPtV0TrackProj"), jet.pt(), trackProj); - registry.fill(HIST("data/jets/V0/jetPtV0TrackProjCtau"), jet.pt(), trackProj, ctauK0s, ctauLambda, ctauAntiLambda); - registry.fill(HIST("data/jets/V0/jetPtV0TrackProjMass"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtV0TrackProjLambdaMasses"), jet.pt(), trackProj, massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/jets/V0/jetPtV0TrackProjRadiusCosPA"), jet.pt(), trackProj, v0.v0radius(), v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtV0TrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv()); - registry.fill(HIST("data/jets/V0/jetPtV0TrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters()); + registry.fill(HIST("data/jets/V0/jetPtV0PtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0PtCtau"), jet.pt(), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/V0/jetPtV0PtMass"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0PtLambdaMasses"), jet.pt(), v0.pt(), massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/jets/V0/jetPtV0PtRadiusCosPA"), jet.pt(), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0PtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0PtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters(), weight); + + registry.fill(HIST("data/jets/V0/jetPtV0TrackProj"), jet.pt(), trackProj, weight); + registry.fill(HIST("data/jets/V0/jetPtV0TrackProjCtau"), jet.pt(), trackProj, ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/V0/jetPtV0TrackProjMass"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0TrackProjLambdaMasses"), jet.pt(), trackProj, massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/jets/V0/jetPtV0TrackProjRadiusCosPA"), jet.pt(), trackProj, v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0TrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/jets/V0/jetPtV0TrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters(), weight); if (IsK0SCandidate(collision, v0)) { - registry.fill(HIST("data/jets/V0/jetPtK0SPtCtau"), jet.pt(), v0.pt(), ctauK0s); - registry.fill(HIST("data/jets/V0/jetPtK0SPtMass"), jet.pt(), v0.pt(), v0.mK0Short()); - registry.fill(HIST("data/jets/V0/jetPtK0SPtAllMasses"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtK0SPtRadius"), jet.pt(), v0.pt(), v0.v0radius()); - registry.fill(HIST("data/jets/V0/jetPtK0SPtCosPA"), jet.pt(), v0.pt(), v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtK0SPtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters()); - registry.fill(HIST("data/jets/V0/jetPtK0SPtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjCtau"), jet.pt(), trackProj, ctauK0s); - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjMass"), jet.pt(), trackProj, v0.mK0Short()); - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjAllMasses"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjRadius"), jet.pt(), trackProj, v0.v0radius()); - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjCosPA"), jet.pt(), trackProj, v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters()); - registry.fill(HIST("data/jets/V0/jetPtK0STrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv()); + registry.fill(HIST("data/jets/V0/jetPtK0SPtCtau"), jet.pt(), v0.pt(), ctauK0s, weight); + registry.fill(HIST("data/jets/V0/jetPtK0SPtMass"), jet.pt(), v0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0SPtAllMasses"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0SPtRadius"), jet.pt(), v0.pt(), v0.v0radius(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0SPtCosPA"), jet.pt(), v0.pt(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0SPtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0SPtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjCtau"), jet.pt(), trackProj, ctauK0s, weight); + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjMass"), jet.pt(), trackProj, v0.mK0Short(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjAllMasses"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjRadius"), jet.pt(), trackProj, v0.v0radius(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjCosPA"), jet.pt(), trackProj, v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/V0/jetPtK0STrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); } if (IsLambdaCandidate(collision, v0)) { - registry.fill(HIST("data/jets/V0/jetPtLambdaPtCtau"), jet.pt(), v0.pt(), ctauLambda); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtMass"), jet.pt(), v0.pt(), v0.mLambda()); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtAllMasses"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtLambdaMasses"), jet.pt(), v0.pt(), massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtRadius"), jet.pt(), v0.pt(), v0.v0radius()); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtCosPA"), jet.pt(), v0.pt(), v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters()); - registry.fill(HIST("data/jets/V0/jetPtLambdaPtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjCtau"), jet.pt(), trackProj, ctauLambda); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjMass"), jet.pt(), trackProj, v0.mLambda()); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjAllMasses"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjLambdaMasses"), jet.pt(), trackProj, massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjRadius"), jet.pt(), trackProj, v0.v0radius()); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjCosPA"), jet.pt(), trackProj, v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters()); - registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv()); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtCtau"), jet.pt(), v0.pt(), ctauLambda, weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtMass"), jet.pt(), v0.pt(), v0.mLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtAllMasses"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtLambdaMasses"), jet.pt(), v0.pt(), massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtRadius"), jet.pt(), v0.pt(), v0.v0radius(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtCosPA"), jet.pt(), v0.pt(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaPtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjCtau"), jet.pt(), trackProj, ctauLambda, weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjMass"), jet.pt(), trackProj, v0.mLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjAllMasses"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjLambdaMasses"), jet.pt(), trackProj, massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjRadius"), jet.pt(), trackProj, v0.v0radius(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjCosPA"), jet.pt(), trackProj, v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/V0/jetPtLambdaTrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); } if (IsAntiLambdaCandidate(collision, v0)) { - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtCtau"), jet.pt(), v0.pt(), ctauAntiLambda); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtMass"), jet.pt(), v0.pt(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtAllMasses"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtLambdaMasses"), jet.pt(), v0.pt(), massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtRadius"), jet.pt(), v0.pt(), v0.v0radius()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtCosPA"), jet.pt(), v0.pt(), v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv()); - - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjCtau"), jet.pt(), trackProj, ctauAntiLambda); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjMass"), jet.pt(), trackProj, v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjAllMasses"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjLambdaMasses"), jet.pt(), trackProj, massDiff, massRatio, massRelDiff); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjRadius"), jet.pt(), trackProj, v0.v0radius()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjCosPA"), jet.pt(), trackProj, v0.v0cosPA()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters()); - registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv()); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtCtau"), jet.pt(), v0.pt(), ctauAntiLambda, weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtMass"), jet.pt(), v0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtAllMasses"), jet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtLambdaMasses"), jet.pt(), v0.pt(), massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtRadius"), jet.pt(), v0.pt(), v0.v0radius(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtCosPA"), jet.pt(), v0.pt(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtDCAd"), jet.pt(), v0.pt(), v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaPtDCAposneg"), jet.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjCtau"), jet.pt(), trackProj, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjMass"), jet.pt(), trackProj, v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjAllMasses"), jet.pt(), trackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjLambdaMasses"), jet.pt(), trackProj, massDiff, massRatio, massRelDiff, weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjRadius"), jet.pt(), trackProj, v0.v0radius(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjCosPA"), jet.pt(), trackProj, v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjDCAd"), jet.pt(), trackProj, v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/V0/jetPtAntiLambdaTrackProjDCAposneg"), jet.pt(), trackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); + } + } + template + void fillDataV0FragHistogramsWithWeights(C const& collision, J const& jet, std::vector state, std::vector values, double weight) + { + // TODO: Add other histograms + double jetpt = values[values.size() - 1]; + int ip = 0; + for (const auto& v0 : jet.template candidates_as()) { + double z = values[ip]; + ip++; + + double ctauK0s = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; + double ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + double ctauAntiLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar; + + switch (state[ip]) { + case 0: // Background + registry.fill(HIST("data/jets/weighted/V0/jetPtBkgTrackProjCtau"), jetpt, z, ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtBkgTrackProjMass"), jetpt, z, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtBkgTrackProjRadiusCosPA"), jetpt, z, v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtBkgTrackProjDCAposneg"), jetpt, z, v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtBkgTrackProjDCAd"), jetpt, z, v0.dcaV0daughters(), weight); + break; + case 1: // K0S + registry.fill(HIST("data/jets/weighted/V0/jetPtK0STrackProjCtau"), jetpt, z, ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtK0STrackProjAllMasses"), jetpt, z, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtK0STrackProjRadius"), jetpt, z, v0.v0radius(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtK0STrackProjCosPA"), jetpt, z, v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtK0STrackProjDCAd"), jetpt, z, v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtK0STrackProjDCAposneg"), jetpt, z, v0.dcapostopv(), v0.dcanegtopv(), weight); + break; + case 2: // Lambda + registry.fill(HIST("data/jets/weighted/V0/jetPtLambdaTrackProjCtau"), jetpt, z, ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtLambdaTrackProjAllMasses"), jetpt, z, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtLambdaTrackProjRadius"), jetpt, z, v0.v0radius(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtLambdaTrackProjCosPA"), jetpt, z, v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtLambdaTrackProjDCAd"), jetpt, z, v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtLambdaTrackProjDCAposneg"), jetpt, z, v0.dcapostopv(), v0.dcanegtopv(), weight); + break; + case 3: // AntiLambda + registry.fill(HIST("data/jets/weighted/V0/jetPtAntiLambdaTrackProjCtau"), jetpt, z, ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtAntiLambdaTrackProjAllMasses"), jetpt, z, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtAntiLambdaTrackProjRadius"), jetpt, z, v0.v0radius(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtAntiLambdaTrackProjCosPA"), jetpt, z, v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtAntiLambdaTrackProjDCAd"), jetpt, z, v0.dcaV0daughters(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtAntiLambdaTrackProjDCAposneg"), jetpt, z, v0.dcapostopv(), v0.dcanegtopv(), weight); + break; + } + registry.fill(HIST("data/jets/weighted/V0/jetPtV0TrackProjCtau"), jetpt, z, ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtV0TrackProjMass"), jetpt, z, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtV0TrackProjRadiusCosPA"), jetpt, z, v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtV0TrackProjDCAposneg"), jetpt, z, v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/jets/weighted/V0/jetPtV0TrackProjDCAd"), jetpt, z, v0.dcaV0daughters(), weight); } } @@ -1116,7 +1438,7 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/matchPartJetPtRelDiffPt"), partJet.pt(), (detJet.pt() - partJet.pt()) / partJet.pt(), weight); } - template + template // Not used for V0 jets void fillMatchingHistogramsConstituent(DetJet const& detJet, PartJet const& partJet, Track const& track, Particle const& particle, double weight = 1.) { double detChargeFrag = -1., detTrackProj = -1., detTheta = -1., detXi = -1.; @@ -1174,7 +1496,7 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/matchDetJetPtZThetaPartJetPtZTheta"), detJet.pt(), detTrackProj, detTheta, partJet.pt(), partTrackProj, partTheta, weight); } - template + template // Not used for V0 jets void fillMatchingFakeOrMiss(Jet const& jet, Constituent const& constituent, bool isFake, double weight = 1.) { double chargeFrag = -1., trackProj = -1., theta = -1., xi = -1.; @@ -1207,7 +1529,7 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/V0/missJetPtV0TrackProj"), jet.pt(), trackProj, weight); registry.fill(HIST("matching/jets/V0/missJetPtV0PtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); - if (v0.pdgCode() == 310) { // K0S + if (TMath::Abs(v0.pdgCode()) == 310) { // K0S registry.fill(HIST("matching/jets/V0/missJetPtK0SPtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/jets/V0/missJetPtK0STrackProj"), jet.pt(), trackProj, weight); } else if (v0.pdgCode() == 3122) { // Lambda @@ -1303,6 +1625,31 @@ struct JetFragmentation { } } + // Combinatorial background for inclusive V0s + template + void fillMatchingV0FakeHistograms(T const& coll, U const& v0, double weight = 1.) + { + double ctauLambda = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassLambda0; + double ctauAntiLambda = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassLambda0Bar; + double ctauK0s = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassK0Short; + + registry.fill(HIST("matching/V0/fakeV0PtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("matching/V0/fakeV0PtCtau"), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("matching/V0/fakeV0PtMass"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("matching/V0/fakeV0PtLambdaMasses"), v0.pt(), v0.mLambda() - v0.mAntiLambda(), v0.mAntiLambda() / v0.mLambda(), (v0.mLambda() - v0.mAntiLambda()) / v0.mLambda(), weight); + registry.fill(HIST("matching/V0/fakeV0PtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("matching/V0/fakeV0PtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("matching/V0/fakeV0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + } + template + void fillMatchingFakeV0DauHistograms(U const& v0, double weight = 1.) + { + auto negTrack = v0.template negTrack_as(); + auto posTrack = v0.template posTrack_as(); + registry.fill(HIST("matching/V0/fakeV0PosTrackPtEtaPhi"), posTrack.pt(), posTrack.eta(), posTrack.phi(), weight); + registry.fill(HIST("matching/V0/fakeV0NegTrackPtEtaPhi"), negTrack.pt(), negTrack.eta(), negTrack.phi(), weight); + } + // Reconstructed signal for inclusive V0s template void fillMatchingV0Histograms(CollisionType const& collision, V0Type const& v0, particleType const& particle, double weight = 1.) { @@ -1344,7 +1691,7 @@ struct JetFragmentation { registry.fill(HIST("matching/V0/antiLambda0Reflection"), particle.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), reflectedMass, weight); } } - + // Reconstructed signal for inclusive V0s: daughters template void fillMatchingV0DauHistograms(V0Type const& v0, ParticleType const& /*particle*/, double weight = 1.) { @@ -1355,6 +1702,7 @@ struct JetFragmentation { registry.fill(HIST("matching/V0/V0PosPartPtRatioPtRelDiffPt"), posPart.pt(), posTrack.pt() / posPart.pt(), (posTrack.pt() - posPart.pt()) / posPart.pt(), weight); registry.fill(HIST("matching/V0/V0NegPartPtRatioPtRelDiffPt"), negPart.pt(), negTrack.pt() / negPart.pt(), (negTrack.pt() - negPart.pt()) / negPart.pt(), weight); } + // Reconstructed signal for in-jet V0s: daughters template void fillMatchingV0DauJetHistograms(DetJetType const& detJet, PartJetType const& partJet, V0Type const& v0, ParticleType const& particle, double weight = 1.) { @@ -1365,7 +1713,7 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/V0/partJetPtDetJetPtPartV0PtPosPtRatioPtRelDiffPt"), partJet.pt(), detJet.pt(), particle.pt(), posTrack.pt(), posTrack.pt() / posPart.pt(), (posTrack.pt() - posPart.pt()) / posPart.pt(), weight); registry.fill(HIST("matching/jets/V0/partJetPtDetJetPtPartV0PtNegPtRatioPtRelDiffPt"), partJet.pt(), detJet.pt(), particle.pt(), negTrack.pt(), negTrack.pt() / negPart.pt(), (negTrack.pt() - negPart.pt()) / negPart.pt(), weight); } - + // Reconstructed signal for in-jet V0s template void fillMatchingV0FragHistograms(CollisionType const& collision, DetJetType const& detJet, PartJetType const& partJet, V0Type const& v0, ParticleType const& particle, double weight = 1.) { @@ -1403,7 +1751,7 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/V0/partJetPtV0TrackProjDetJetPtV0TrackProjDCAposneg"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); registry.fill(HIST("matching/jets/V0/partJetPtV0TrackProjDetJetPtV0TrackProjDCAd"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.dcaV0daughters(), weight); - if (particle.pdgCode() == 310) { // K0S + if (TMath::Abs(particle.pdgCode()) == 310) { // K0S registry.fill(HIST("matching/jets/V0/matchDetJetPtK0STrackProjPartJetPtK0STrackProj"), detJet.pt(), detTrackProj, partJet.pt(), partTrackProj, weight); registry.fill(HIST("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPt"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); @@ -1502,7 +1850,7 @@ struct JetFragmentation { { registry.fill(HIST("detector-level/jets/detJetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi(), weight); } - template + template // Not used for V0 jets void fillMCDFragHistograms(Jet const& jet, double weight = 1.) { for (const auto& track : jet.template tracks_as()) { @@ -1528,7 +1876,7 @@ struct JetFragmentation { { registry.fill(HIST("particle-level/jets/partJetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi(), weight); } - template + template // Not used for V0 jets void fillMCPFragHistograms(Jet const& jet, double weight = 1.) { for (const auto& track : jet.template tracks_as()) { @@ -1549,6 +1897,151 @@ struct JetFragmentation { } } + template + void fillDataPerpConeHists(T const& coll, U const& jet, V const& v0s, double weight = 1.) + { + double perpConeR = jet.r() * 1e-2; + double conePhi[2] = {RecoDecay::constrainAngle(jet.phi() - M_PI / 2, -M_PI), + RecoDecay::constrainAngle(jet.phi() + M_PI / 2, -M_PI)}; + double conePt[2] = {0., 0.}; + int nV0sinCone[2] = {0, 0}; + for (const auto& v0 : v0s) { + // Need to check if v0 passed jet finder selection/preselector cuts + bool v0InCones = false; + double dEta = v0.eta() - jet.eta(); + double dPhi[2] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -M_PI), + RecoDecay::constrainAngle(v0.phi() - conePhi[1], -M_PI)}; + for (int i = 0; i < 2; i++) { + if (TMath::Sqrt(dEta * dEta + dPhi[i] * dPhi[i]) < perpConeR) { + conePt[i] += v0.pt(); + nV0sinCone[i]++; + v0InCones = true; + } + } + if (!v0InCones) { + continue; + } + + double ctauLambda = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassLambda0; + double ctauAntiLambda = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassLambda0Bar; + double ctauK0s = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassK0Short; + + registry.fill(HIST("data/PC/JetPtEtaV0Pt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("data/PC/V0PtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/PC/V0PtCtau"), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("data/PC/V0PtMass"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("data/PC/V0PtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/PC/V0PtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/PC/V0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + + if (IsLambdaCandidate(coll, v0)) { + registry.fill(HIST("data/PC/JetPtLambda0PtMass"), jet.pt(), v0.pt(), v0.mLambda(), weight); + + registry.fill(HIST("data/PC/JetPtEtaLambda0Pt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("data/PC/LambdaPtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/PC/LambdaPtCtauMass"), v0.pt(), ctauLambda, v0.mLambda(), weight); + registry.fill(HIST("data/PC/LambdaPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/PC/LambdaPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/PC/LambdaPtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + } + if (IsAntiLambdaCandidate(coll, v0)) { + registry.fill(HIST("data/PC/JetPtAntiLambda0PtMass"), jet.pt(), v0.pt(), v0.mAntiLambda(), weight); + + registry.fill(HIST("data/PC/JetPtEtaAntiLambda0Pt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("data/PC/antiLambdaPtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/PC/antiLambdaPtCtauMass"), v0.pt(), ctauAntiLambda, v0.mAntiLambda(), weight); + registry.fill(HIST("data/PC/antiLambdaPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/PC/antiLambdaPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/PC/antiLambdaPtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + } + if (IsK0SCandidate(coll, v0)) { + registry.fill(HIST("data/PC/JetPtK0SPtMass"), jet.pt(), v0.pt(), v0.mK0Short(), weight); + + registry.fill(HIST("data/PC/JetPtEtaK0SPt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("data/PC/K0SPtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("data/PC/K0SPtCtauMass"), v0.pt(), ctauK0s, v0.mK0Short(), weight); + registry.fill(HIST("data/PC/K0SPtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("data/PC/K0SPtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("data/PC/K0SPtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + } + } + // Fill hist for Ncones: nv0s, conePt, coneEta, conePhi + for (int i = 0; i < 2; i++) { + registry.fill(HIST("data/PC/nV0sConePtEta"), nV0sinCone[i], conePt[i], jet.eta(), weight); + registry.fill(HIST("data/PC/ConePtEtaPhi"), conePt[i], jet.eta(), conePhi[i], weight); + registry.fill(HIST("data/PC/JetPtEtaConePt"), jet.pt(), jet.eta(), conePt[i], weight); + } + } + + template + void fillMcPerpConeHists(T const& coll, U const& jet, V const& v0s, W const& /* V0 particles */, double weight = 1.) + { + double perpConeR = jet.r() * 1e-2; + double conePhi[2] = {RecoDecay::constrainAngle(jet.phi() - M_PI / 2, -M_PI), + RecoDecay::constrainAngle(jet.phi() + M_PI / 2, -M_PI)}; + double coneMatchedPt[2] = {0., 0.}; + double coneFakePt[2] = {0., 0.}; + int nMatchedV0sinCone[2] = {0, 0}; + int nFakeV0sinCone[2] = {0, 0}; + + for (const auto& v0 : v0s) { + double dEta = v0.eta() - jet.eta(); + double dPhi[2] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -M_PI), + RecoDecay::constrainAngle(v0.phi() - conePhi[1], -M_PI)}; + for (int i = 0; i < 2; i++) { + if (TMath::Sqrt(dEta * dEta + dPhi[i] * dPhi[i]) > perpConeR) { + continue; + } + + double ctauLambda = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassLambda0; + double ctauAntiLambda = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassLambda0Bar; + double ctauK0s = v0.distovertotmom(coll.posX(), coll.posY(), coll.posZ()) * o2::constants::physics::MassK0Short; + + if (!v0.has_mcParticle()) { // The V0 is combinatorial background + coneFakePt[i] += v0.pt(); + nFakeV0sinCone[i]++; + registry.fill(HIST("matching/PC/jetPtEtaFakeV0Pt"), jet.pt(), jet.eta(), v0.pt(), weight); + + registry.fill(HIST("matching/PC/fakeV0PtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("matching/PC/fakeV0PtCtau"), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("matching/PC/fakeV0PtMass"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("matching/PC/fakeV0PtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("matching/PC/fakeV0PtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("matching/PC/fakeV0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + } else { + coneMatchedPt[i] += v0.pt(); + nMatchedV0sinCone[i]++; + registry.fill(HIST("matching/PC/jetPtEtaMatchedV0Pt"), jet.pt(), jet.eta(), v0.pt(), weight); + + registry.fill(HIST("matching/PC/matchedV0PtEtaPhi"), v0.pt(), v0.eta(), v0.phi(), weight); + registry.fill(HIST("matching/PC/matchedV0PtCtau"), v0.pt(), ctauK0s, ctauLambda, ctauAntiLambda, weight); + registry.fill(HIST("matching/PC/matchedV0PtMass"), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); + registry.fill(HIST("matching/PC/matchedV0PtRadiusCosPA"), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); + registry.fill(HIST("matching/PC/matchedV0PtDCAposneg"), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); + registry.fill(HIST("matching/PC/matchedV0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); + + auto particle = v0.template mcParticle_as(); + if (TMath::Abs(particle.pdgCode()) == 310) { // K0S + registry.fill(HIST("matching/PC/matchedJetPtK0SPtMass"), jet.pt(), v0.pt(), v0.mK0Short(), weight); + } else if (particle.pdgCode() == 3122) { // Lambda + registry.fill(HIST("matching/PC/matchedJetPtLambda0PtMass"), jet.pt(), v0.pt(), v0.mLambda(), weight); + } else if (particle.pdgCode() == -3122) { + registry.fill(HIST("matching/PC/matchedJetPtAntiLambda0PtMass"), jet.pt(), v0.pt(), v0.mAntiLambda(), weight); + } + } // if v0 has mcParticle + } // for cone + } // for v0s + for (int i = 0; i < 2; i++) { + registry.fill(HIST("matching/PC/matchednV0sConePtEta"), nMatchedV0sinCone[i], coneMatchedPt[i], jet.eta(), weight); + registry.fill(HIST("matching/PC/matchedConePtEtaPhi"), coneMatchedPt[i], jet.eta(), conePhi[i], weight); + registry.fill(HIST("matching/PC/matchedJetPtEtaConePt"), jet.pt(), jet.eta(), coneMatchedPt[i], weight); + + registry.fill(HIST("matching/PC/fakenV0sConePtEta"), nFakeV0sinCone[i], coneFakePt[i], jet.eta(), weight); + registry.fill(HIST("matching/PC/fakeConePtEtaPhi"), coneFakePt[i], jet.eta(), conePhi[i], weight); + registry.fill(HIST("matching/PC/fakeJetPtEtaConePt"), jet.pt(), jet.eta(), coneFakePt[i], weight); + } + } + void processDummy(JetTracks const&) {} PROCESS_SWITCH(JetFragmentation, processDummy, "Dummy process function turned on by default", true); @@ -1660,13 +2153,13 @@ struct JetFragmentation { isTrackMatched = true; fillMatchingHistogramsConstituent(detJet, partJet, track, particle, weight); break; // No need to inspect other particles - } // if track has mcParticle and particle is in matched jet - } // for particle in matched partJet + } // if track has mcParticle and particle is in matched jet + } // for particle in matched partJet if (!isTrackMatched) { isFake = true; fillMatchingFakeOrMiss(detJet, track, isFake, weight); } // if track is not matched - } // for detJet tracks + } // for detJet tracks } if (!detJet.has_matchedJetGeo()) { isFake = true; @@ -1675,7 +2168,7 @@ struct JetFragmentation { fillMatchingFakeOrMiss(detJet, track, isFake, weight); } } // if detJet does not have a match - } // for det jet + } // for det jet for (const auto& partJet : mcPartJets) { for (const auto& detJet : partJet.template matchedJetGeo_as()) { // Check if the matched detector level jet is outside the allowed eta range @@ -1703,7 +2196,7 @@ struct JetFragmentation { fillMatchingFakeOrMiss(partJet, particle, isFake, weight); } } // for particle - } // for matched det jet + } // for matched det jet if (!partJet.has_matchedJetGeo()) { isFake = false; registry.fill(HIST("matching/jets/missPartJetPtEtaPhi"), partJet.pt(), partJet.eta(), partJet.phi(), weight); @@ -1711,7 +2204,7 @@ struct JetFragmentation { fillMatchingFakeOrMiss(partJet, particle, isFake, weight); } } // if no matched jet - } // for part jet + } // for part jet } PROCESS_SWITCH(JetFragmentation, processMcMatched, "Monte Carlo particle and detector level", false); @@ -1768,6 +2261,7 @@ struct JetFragmentation { isV0Used[i] = false; } registry.fill(HIST("matching/V0/nV0sEvent"), kNV0s); + registry.fill(HIST("matching/V0/nV0sEventWeighted"), kNV0s, weight); int kNParticles = mcParticles.size(); bool isParticleUsed[kNParticles]; @@ -1829,8 +2323,8 @@ struct JetFragmentation { isV0Used[iv0] = true; fillMatchingV0Fake(collision, detJet, v0, weight); } // v0 loop - } // if no matched jet - } // det jet loop + } // if no matched jet + } // det jet loop for (const auto& partJet : mcPartJets) { int iparticle = -1; for (const auto& particle : mcParticles) { @@ -1877,13 +2371,13 @@ struct JetFragmentation { } } } // v0 loop - } // detJet loop + } // detJet loop if (!isParticleUsed[iparticle]) { isParticleUsed[iparticle] = true; fillMatchingV0Miss(partJet, particle, weight); } } // particle loop - } // part jet loop + } // part jet loop } PROCESS_SWITCH(JetFragmentation, processMcMatchedV0Frag, "Monte Carlo V0 fragmentation", false); @@ -1978,6 +2472,8 @@ struct JetFragmentation { } PROCESS_SWITCH(JetFragmentation, processDataV0Frag, "Data V0 fragmentation", false); + // + // // ---------------- V0 jets ---------------- void processDataV0JetsFrag(soa::Filtered::iterator const& jcoll, soa::Join const& v0jets, CandidatesV0Data const& v0s) { @@ -1998,7 +2494,7 @@ struct JetFragmentation { fillDataJetHistograms(jet); int nV0inJet = 0, nLambdainJet = 0, nAntiLambdainJet = 0, nK0SinJet = 0; - for (const auto& v0 : jet.hfcandidates_as()) { + for (const auto& v0 : jet.candidates_as()) { nV0inJet++; fillDataV0FragHistograms(jcoll, jet, v0); if (IsK0SCandidate(jcoll, v0)) { @@ -2016,6 +2512,70 @@ struct JetFragmentation { } PROCESS_SWITCH(JetFragmentation, processDataV0JetsFrag, "Data V0 jets fragmentation", false); + void processDataV0JetsFragWithWeights(soa::Filtered::iterator const& jcoll, soa::Join const& v0jets, CandidatesV0Data const& v0s) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelection)) { + return; + } + registry.fill(HIST("data/V0/nV0sEvent"), v0s.size()); + fillDataV0Histograms(jcoll, v0s); + + for (const auto& jet : v0jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, -99., -99., v0EtaMin, v0EtaMax)) { + continue; + } + // Double check if the jet contains V0s + if (!JetContainsV0s(jet)) { + continue; + } + fillDataJetHistograms(jet); + + std::vector values; + std::vector> weights; + int nParticles = 0; + int nClasses = 4; // Should be set globally? Maybe just a global constant? + for (const auto& v0 : jet.candidates_as()) { + nParticles++; + fillDataV0FragHistograms(jcoll, jet, v0); + double z = TrackProj(jet, v0); + std::vector w = getV0SignalWeight(jcoll, v0); + values.push_back(z); + weights.push_back(w); + } + values.push_back(jet.pt()); + + int nStates = TMath::Power(nClasses, nParticles); + for (int M = 0; M < nStates; M++) { + std::vector state = convertState(M, nParticles, nClasses); + std::vector corrected = correctedValues(state, values); + double ws = stateWeight(state, weights); + double jetpt = corrected[nParticles]; + fillDataJetHistogramsWithWeights(jetpt, jet.eta(), jet.phi(), ws); + fillDataV0FragHistogramsWithWeights(jcoll, jet, state, corrected, ws); + } + // TODO: Fill nV0 hist + // TODO: Fill weighted nV0 hist? + } + } + PROCESS_SWITCH(JetFragmentation, processDataV0JetsFragWithWeights, "Data V0 jets fragmentation with weights", false); + + void processDataV0PerpCone(soa::Filtered::iterator const& jcoll, soa::Join const& v0jets, CandidatesV0Data const& v0s) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelection)) { + return; + } + registry.fill(HIST("data/V0/nV0sEvent"), v0s.size()); + fillDataV0Histograms(jcoll, v0s); + + for (const auto& jet : v0jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, -99., -99., v0EtaMin, v0EtaMax)) { + continue; + } + fillDataPerpConeHists(jcoll, jet, v0s); + } + } + PROCESS_SWITCH(JetFragmentation, processDataV0PerpCone, "Perpendicular cone V0s in data", false); + void processMcMatchedV0JetsFrag(soa::Filtered::iterator const& jcoll, JetMcCollisions const&, MatchedMCDV0JetsWithConstituents const& v0jetsMCD, MatchedMCPV0JetsWithConstituents const& v0jetsMCP, soa::Join const& v0s, CandidatesV0MCP const& pv0s, JetTracksMCD const& jTracks, JetParticles const&) { if (!jcoll.has_mcCollision()) { @@ -2026,9 +2586,15 @@ struct JetFragmentation { } double weight = jcoll.mcCollision().weight(); registry.fill(HIST("matching/V0/nV0sEvent"), v0s.size()); + registry.fill(HIST("matching/V0/nV0sEventWeighted"), v0s.size(), weight); // TODO: This is not very efficient for (const auto& v0 : v0s) { + if (!v0.has_mcParticle()) { + fillMatchingV0FakeHistograms(jcoll, v0, weight); + fillMatchingFakeV0DauHistograms(v0, weight); + continue; + } for (const auto& pv0 : pv0s) { if (V0sAreMatched(v0, pv0, jTracks)) { fillMatchingV0Histograms(jcoll, v0, pv0, weight); @@ -2049,7 +2615,7 @@ struct JetFragmentation { int nV0inJet = 0, nLambdainJet = 0, nAntiLambdainJet = 0, nK0SinJet = 0; if (!detJet.has_matchedJetGeo()) { - for (const auto& detV0 : detJet.hfcandidates_as>()) { + for (const auto& detV0 : detJet.candidates_as>()) { fillMatchingV0Fake(jcoll, detJet, detV0, weight); } continue; @@ -2057,13 +2623,13 @@ struct JetFragmentation { for (const auto& partJet : detJet.template matchedJetGeo_as()) { fillMatchingHistogramsJet(detJet, partJet, weight); - for (const auto& detV0 : detJet.hfcandidates_as>()) { + for (const auto& detV0 : detJet.candidates_as>()) { if (!detV0.has_mcParticle()) { fillMatchingV0Fake(jcoll, detJet, detV0, weight); continue; } bool isV0Matched = false; - for (const auto& partV0 : partJet.template hfcandidates_as()) { + for (const auto& partV0 : partJet.template candidates_as()) { if (V0sAreMatched(detV0, partV0, jTracks)) { isV0Matched = true; nV0inJet++; @@ -2079,7 +2645,7 @@ struct JetFragmentation { } break; } // if matched - } // partV0 loop + } // partV0 loop if (!isV0Matched) { fillMatchingV0Fake(jcoll, detJet, detV0, weight); @@ -2087,7 +2653,7 @@ struct JetFragmentation { } // detV0 loop registry.fill(HIST("matching/jets/V0/jetPtnV0MatchednK0SnLambdanAntiLambda"), partJet.pt(), nV0inJet, nK0SinJet, nLambdainJet, nAntiLambdainJet, weight); } // Matched partJet loop - } // detJet loop + } // detJet loop for (const auto& partJet : v0jetsMCP) { if (!JetContainsV0s(partJet)) { @@ -2096,7 +2662,7 @@ struct JetFragmentation { fillMCPJetHistograms(partJet, weight); if (!partJet.has_matchedJetGeo()) { - for (const auto& partV0 : partJet.hfcandidates_as()) { + for (const auto& partV0 : partJet.candidates_as()) { fillMatchingV0Miss(partJet, partV0, weight); } continue; @@ -2108,9 +2674,9 @@ struct JetFragmentation { continue; } isJetMatched = true; - for (const auto& partV0 : partJet.hfcandidates_as()) { + for (const auto& partV0 : partJet.candidates_as()) { bool isV0Matched = false; - for (const auto& detV0 : detJet.hfcandidates_as>()) { + for (const auto& detV0 : detJet.candidates_as>()) { if (V0sAreMatched(detV0, partV0, jTracks)) { isV0Matched = true; break; @@ -2120,17 +2686,36 @@ struct JetFragmentation { fillMatchingV0Miss(partJet, partV0, weight); } } // partV0 loop - } // detJet loop + } // detJet loop // To account for matched jets where the detector level jet is outside of the eta range (cut applied within this task) if (!isJetMatched) { - for (const auto& partV0 : partJet.hfcandidates_as()) { + for (const auto& partV0 : partJet.candidates_as()) { fillMatchingV0Miss(partJet, partV0, weight); } } } // partJet loop } PROCESS_SWITCH(JetFragmentation, processMcMatchedV0JetsFrag, "Matched V0 jets fragmentation", false); + + void processMcV0PerpCone(soa::Filtered::iterator const& jcoll, JetMcCollisions const&, MatchedMCDV0JetsWithConstituents const& jets, soa::Join const& v0s, aod::McParticles const& particles) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelection)) { + return; + } + double weight = jcoll.mcCollision().weight(); + registry.fill(HIST("matching/V0/nV0sEvent"), v0s.size()); + registry.fill(HIST("matching/V0/nV0sEventWeighted"), v0s.size(), weight); + // Inclusive spectrum fill + + for (const auto& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, -99., -99., v0EtaMin, v0EtaMax)) { + continue; + } + fillMcPerpConeHists(jcoll, jet, v0s, particles, weight); + } + } + PROCESS_SWITCH(JetFragmentation, processMcV0PerpCone, "Perpendicular cone V0s in MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetmatchingqa.cxx b/PWGJE/Tasks/jetmatchingqa.cxx index 5dc89b8536b..e4ec72d1e44 100644 --- a/PWGJE/Tasks/jetmatchingqa.cxx +++ b/PWGJE/Tasks/jetmatchingqa.cxx @@ -42,6 +42,7 @@ struct JetMatchingQA { {"h_jet_match_geo_pt_zoom", "geo-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, {"h_jet_match_geo_dpt", "geo-matched jets", {HistType::kTH1F, {{100, -10.0f, 10.0f, "#Delta#it{p}_{T} (particle level vs detector level, GeV/#it{c})"}}}}, + {"h2_jet_pt_jet_match_geo_dptoverpt", "geo-matched jets", {HistType::kTH2F, {{2000, 0.0f, 200.0f, "#it{p}_{T} (detector level, GeV/#it{c})"}, {700, -5.0f, 2.0f, "(#it{p}_{T, part}-#it{p}_{T, det})/#it{p}_{T,part} (particle level vs detector level, GeV/#it{c})"}}}}, {"h_jet_match_geo_PtLeadingPart", "geo-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (detector level, GeV/#it{c})"}}}}, {"h_jet_match_geo_phi", "geo-matched jets", {HistType::kTH2F, {{80, -1.0f, 7.0f, "#phi_{jet} (particle level, rad)"}, {80, -1.0f, 7.0f, "#phi_{jet} (detector level, rad)"}}}}, {"h_jet_match_geo_eta", "geo-matched jets", {HistType::kTH2F, {{70, -0.7f, 0.7f, "#it{p}_{T}^{particle level} (GeV/#it{c})"}, {70, -0.7f, 0.7f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, @@ -127,6 +128,7 @@ struct JetMatchingQA { registry.fill(HIST("h_jet_match_geo_pt_zoom"), pjet.pt(), djet.pt()); registry.fill(HIST("h_jet_match_geo_dpt"), pjet.pt() - djet.pt()); + registry.fill(HIST("h2_jet_pt_jet_match_geo_dptoverpt"), pjet.pt(), (pjet.pt() - djet.pt()) * 1. / pjet.pt()); registry.fill(HIST("h_jet_match_geo_phi"), pjet.phi(), djet.phi()); registry.fill(HIST("h_jet_match_geo_eta"), pjet.eta(), djet.eta()); registry.fill(HIST("h_jet_match_geo_Nconst"), pjet.tracksIds().size(), djet.tracksIds().size()); @@ -174,7 +176,7 @@ struct JetMatchingQA { } } } - PROCESS_SWITCH(JetMatchingQA, processMCD, "QA on detector-level jets", true); + PROCESS_SWITCH(JetMatchingQA, processMCD, "QA on detector-level jets", false); void processMCP(JetMcCollision const&, TagJetCollection const& pjets, BaseJetCollection const&) @@ -188,7 +190,7 @@ struct JetMatchingQA { } } } - PROCESS_SWITCH(JetMatchingQA, processMCP, "QA on generator-level jets", true); + PROCESS_SWITCH(JetMatchingQA, processMCP, "QA on generator-level jets", false); }; using ChargedDetectorLevelJets = soa::Join; @@ -207,6 +209,10 @@ using BplusChargedDetectorLevelJets = soa::Join; using BplusChargedJetMatchingQA = JetMatchingQA; +using DielectronChargedDetectorLevelJets = soa::Join; +using DielectronChargedParticleLevelJets = soa::Join; +using DielectronChargedJetMatchingQA = JetMatchingQA; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::vector tasks; @@ -214,7 +220,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-matching-qa-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-d0-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-lc-ch"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-bplus-ch"})); + // tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-bplus-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-dielectron-ch"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/Tasks/jetplanarflow.cxx b/PWGJE/Tasks/jetplanarflow.cxx index a4c5527ac64..03ba20f5031 100644 --- a/PWGJE/Tasks/jetplanarflow.cxx +++ b/PWGJE/Tasks/jetplanarflow.cxx @@ -228,7 +228,7 @@ struct JetPlanarFlowTask { if (particleSelection == "PhysicalPrimary" && !track.isPhysicalPrimary()) { continue; } - if (isinf(track.eta())) { + if (std::isinf(track.eta())) { continue; } } else { diff --git a/PWGJE/Tasks/jetsubstructure.cxx b/PWGJE/Tasks/jetsubstructure.cxx index c706352f5f7..ebf9d4c34f2 100644 --- a/PWGJE/Tasks/jetsubstructure.cxx +++ b/PWGJE/Tasks/jetsubstructure.cxx @@ -32,6 +32,7 @@ #include "PWGJE/DataModel/JetSubstructure.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetSubstructureUtilities.h" using namespace o2; @@ -48,13 +49,24 @@ struct JetSubstructureTask { Configurable zCut{"zCut", 0.1, "soft drop z cut"}; Configurable beta{"beta", 0.0, "soft drop beta"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + Configurable pairConstituentPtMin{"pairConstituentPtMin", 1.0, "pt cut off for constituents going into pairs"}; Service pdg; std::vector jetConstituents; std::vector jetReclustered; JetFinder jetReclusterer; + std::vector energyMotherVec; + std::vector ptLeadingVec; + std::vector ptSubLeadingVec; + std::vector thetaVec; std::vector nSub; + std::vector pairPtVec; + std::vector pairEnergyVec; + std::vector pairThetaVec; + float angularity; HistogramRegistry registry; @@ -76,9 +88,13 @@ struct JetSubstructureTask { jetReclusterer.algorithm = fastjet::JetAlgorithm::cambridge_algorithm; } - template - void jetReclustering(T const& jet, U& outputTable) + template + void jetReclustering(T const& jet) { + energyMotherVec.clear(); + ptLeadingVec.clear(); + ptSubLeadingVec.clear(); + thetaVec.clear(); jetReclustered.clear(); fastjet::ClusterSequenceArea clusterSeq(jetReclusterer.findJets(jetConstituents, jetReclustered)); jetReclustered = sorted_by_pt(jetReclustered); @@ -89,10 +105,6 @@ struct JetSubstructureTask { auto nsd = 0.0; auto zg = -1.0; auto rg = -1.0; - std::vector energyMotherVec; - std::vector ptLeadingVec; - std::vector ptSubLeadingVec; - std::vector thetaVec; while (daughterSubJet.has_parents(parentSubJet1, parentSubJet2)) { if (parentSubJet1.perp() < parentSubJet2.perp()) { @@ -136,7 +148,39 @@ struct JetSubstructureTask { if constexpr (isSubtracted && !isMCP) { registry.fill(HIST("h2_jet_pt_jet_nsd_eventwiseconstituentsubtracted"), jet.pt(), nsd); } - outputTable(energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, nSub[0], nSub[1], nSub[2]); + } + + template + void jetPairing(T const& jet, U const& /*tracks*/) + { + pairPtVec.clear(); + pairEnergyVec.clear(); + pairThetaVec.clear(); + std::vector tracksVec; + for (auto const& constituent : jet.template tracks_as()) { + if (constituent.pt() >= pairConstituentPtMin) { + tracksVec.push_back(constituent); + } + } + if (tracksVec.size() >= 1) { + for (typename std::vector::size_type track1Index = 0; track1Index < tracksVec.size(); track1Index++) { + for (typename std::vector::size_type track2Index = 0; track2Index < tracksVec.size(); track2Index++) { + pairPtVec.push_back(tracksVec.at(track1Index).pt() * tracksVec.at(track2Index).pt()); + pairEnergyVec.push_back(tracksVec.at(track1Index).energy() * tracksVec.at(track2Index).energy()); + pairThetaVec.push_back(jetutilities::deltaR(tracksVec.at(track1Index), tracksVec.at(track2Index))); + } + } + } + } + + template + void jetSubstructureSimple(T const& jet, U const& /*tracks*/) + { + angularity = 0.0; + for (auto& constituent : jet.template tracks_as()) { + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); + } + angularity /= (jet.pt() * (jet.r() / 100.f)); } template @@ -147,8 +191,10 @@ struct JetSubstructureTask { fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); } nSub = jetsubstructureutilities::getNSubjettiness(jet, tracks, tracks, tracks, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); - - jetReclustering(jet, outputTable); + jetReclustering(jet); + jetPairing(jet, tracks); + jetSubstructureSimple(jet, tracks); + outputTable(energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, nSub[0], nSub[1], nSub[2], pairPtVec, pairEnergyVec, pairThetaVec, angularity); } void processDummy(JetTracks const&) @@ -185,7 +231,10 @@ struct JetSubstructureTask { fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), pdg->Mass(jetConstituent.pdgCode())); } nSub = jetsubstructureutilities::getNSubjettiness(jet, particles, particles, particles, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); - jetReclustering(jet, jetSubstructureMCPTable); + jetReclustering(jet); + jetPairing(jet, particles); + jetSubstructureSimple(jet, particles); + jetSubstructureMCPTable(energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, nSub[0], nSub[1], nSub[2], pairPtVec, pairEnergyVec, pairThetaVec, angularity); } PROCESS_SWITCH(JetSubstructureTask, processChargedJetsMCP, "charged jet substructure on MC particle level", false); }; diff --git a/PWGJE/Tasks/jetsubstructurehf.cxx b/PWGJE/Tasks/jetsubstructurehf.cxx index 969ddcfb44e..47bda670c42 100644 --- a/PWGJE/Tasks/jetsubstructurehf.cxx +++ b/PWGJE/Tasks/jetsubstructurehf.cxx @@ -29,15 +29,12 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetSubstructure.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetSubstructureUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" using namespace o2; using namespace o2::framework; @@ -56,15 +53,26 @@ struct JetSubstructureHFTask { // Jet level configurables Configurable zCut{"zCut", 0.1, "soft drop z cut"}; Configurable beta{"beta", 0.0, "soft drop beta"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + Configurable pairConstituentPtMin{"pairConstituentPtMin", 1.0, "pt cut off for constituents going into pairs"}; Service pdg; - int candMass; + float candMass; std::vector jetConstituents; std::vector jetReclustered; JetFinder jetReclusterer; + std::vector energyMotherVec; + std::vector ptLeadingVec; + std::vector ptSubLeadingVec; + std::vector thetaVec; std::vector nSub; + std::vector pairPtVec; + std::vector pairEnergyVec; + std::vector pairThetaVec; + float angularity; HistogramRegistry registry; void init(InitContext const&) @@ -84,12 +92,16 @@ struct JetSubstructureHFTask { jetReclusterer.isReclustering = true; jetReclusterer.algorithm = fastjet::JetAlgorithm::cambridge_algorithm; - candMass = jethfutilities::getTablePDGMass(); + candMass = jetcandidateutilities::getTablePDGMass(); } - template - void jetReclustering(T const& jet, U& outputTable) + template + void jetReclustering(T const& jet) { + energyMotherVec.clear(); + ptLeadingVec.clear(); + ptSubLeadingVec.clear(); + thetaVec.clear(); jetReclustered.clear(); fastjet::ClusterSequenceArea clusterSeq(jetReclusterer.findJets(jetConstituents, jetReclustered)); jetReclustered = sorted_by_pt(jetReclustered); @@ -100,15 +112,11 @@ struct JetSubstructureHFTask { auto nsd = 0.0; auto zg = -1.0; auto rg = -1.0; - std::vector energyMotherVec; - std::vector ptLeadingVec; - std::vector ptSubLeadingVec; - std::vector thetaVec; while (daughterSubJet.has_parents(parentSubJet1, parentSubJet2)) { bool isHFInSubjet1 = false; for (auto& subjet1Constituent : parentSubJet1.constituents()) { - if (subjet1Constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidateHF)) { + if (subjet1Constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidate)) { isHFInSubjet1 = true; break; } @@ -153,22 +161,84 @@ struct JetSubstructureHFTask { if constexpr (isSubtracted && !isMCP) { registry.fill(HIST("h2_jet_pt_jet_nsd_eventwiseconstituentsubtracted"), jet.pt(), nsd); } - outputTable(energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, nSub[0], nSub[1], nSub[2]); + } + + template + void jetPairing(T const& jet, U const& /*tracks*/, V const& /*candidates*/) + { + pairPtVec.clear(); + pairEnergyVec.clear(); + pairThetaVec.clear(); + std::vector> tracksVec; + std::vector> candidatesVec; + for (auto& constituent : jet.template tracks_as()) { + if (constituent.pt() >= pairConstituentPtMin) { + tracksVec.push_back(constituent); + } + } + for (auto& candidate : jet.template candidates_as()) { + candidatesVec.push_back(candidate); + } + if (tracksVec.size() >= 1) { + for (typename std::vector>::size_type track1Index = 0; track1Index < tracksVec.size(); track1Index++) { + for (typename std::vector>::size_type track2Index = 0; track2Index < tracksVec.size(); track2Index++) { + pairPtVec.push_back(tracksVec.at(track1Index).pt() * tracksVec.at(track2Index).pt()); + pairEnergyVec.push_back(tracksVec.at(track1Index).energy() * tracksVec.at(track2Index).energy()); + pairThetaVec.push_back(jetutilities::deltaR(tracksVec.at(track1Index), tracksVec.at(track2Index))); + } + } + } + if (candidatesVec.size() >= 1) { + for (typename std::vector>::size_type candidate1Index = 0; candidate1Index < candidatesVec.size(); candidate1Index++) { + for (typename std::vector>::size_type candidate2Index = 0; candidate2Index < candidatesVec.size(); candidate2Index++) { + pairPtVec.push_back(candidatesVec.at(candidate1Index).pt() * candidatesVec.at(candidate2Index).pt()); + auto candidate1Energy = std::sqrt((candidatesVec.at(candidate1Index).p() * candidatesVec.at(candidate1Index).p()) + (candMass * candMass)); + auto candidate2Energy = std::sqrt((candidatesVec.at(candidate2Index).p() * candidatesVec.at(candidate2Index).p()) + (candMass * candMass)); + pairEnergyVec.push_back(candidate1Energy * candidate2Energy); + pairThetaVec.push_back(jetutilities::deltaR(candidatesVec.at(candidate1Index), candidatesVec.at(candidate2Index))); + } + } + } + if (candidatesVec.size() >= 1 && tracksVec.size() >= 1) { + for (typename std::vector>::size_type candidateIndex = 0; candidateIndex < candidatesVec.size(); candidateIndex++) { // could just directly get the candidate and tracks here but keeping it consistent with above + for (typename std::vector>::size_type trackIndex = 0; trackIndex < tracksVec.size(); trackIndex++) { + pairPtVec.push_back(candidatesVec.at(candidateIndex).pt() * tracksVec.at(trackIndex).pt()); + auto candidateEnergy = std::sqrt((candidatesVec.at(candidateIndex).p() * candidatesVec.at(candidateIndex).p()) + (candMass * candMass)); + pairEnergyVec.push_back(candidateEnergy * tracksVec.at(trackIndex).energy()); + pairThetaVec.push_back(jetutilities::deltaR(candidatesVec.at(candidateIndex), tracksVec.at(trackIndex))); + } + } + } + } + + template + void jetSubstructureSimple(T const& jet, U const& /*tracks*/, V const& /*candidates*/) + { + angularity = 0.0; + for (auto& candidate : jet.template candidates_as()) { + angularity += std::pow(candidate.pt(), kappa) * std::pow(jetutilities::deltaR(jet, candidate), alpha); + } + for (auto& constituent : jet.template tracks_as()) { + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); + } + angularity /= (jet.pt() * (jet.r() / 100.f)); } template void analyseCharged(T const& jet, U const& tracks, V const& candidates, M& outputTable) { - jetConstituents.clear(); for (auto& jetConstituent : jet.template tracks_as()) { fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); } - for (auto& jetHFCandidate : jet.template hfcandidates_as()) { // should only be one at the moment - fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), candMass); + for (auto& jetHFCandidate : jet.template candidates_as()) { // should only be one at the moment + fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidate), candMass); } nSub = jetsubstructureutilities::getNSubjettiness(jet, tracks, tracks, candidates, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); - jetReclustering(jet, outputTable); + jetReclustering(jet); + jetPairing(jet, tracks, candidates); + jetSubstructureSimple(jet, tracks, candidates); + outputTable(energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, nSub[0], nSub[1], nSub[2], pairPtVec, pairEnergyVec, pairThetaVec, angularity); } void processDummy(JetTracks const&) @@ -208,17 +278,21 @@ struct JetSubstructureHFTask { for (auto& jetConstituent : jet.template tracks_as()) { fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), pdg->Mass(jetConstituent.pdgCode())); } - for (auto& jetHFCandidate : jet.template hfcandidates_as()) { - fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), candMass); + for (auto& jetHFCandidate : jet.template candidates_as()) { + fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidate), candMass); } nSub = jetsubstructureutilities::getNSubjettiness(jet, particles, particles, candidates, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); - jetReclustering(jet, jetSubstructureMCPTable); + jetReclustering(jet); + jetPairing(jet, particles, candidates); + jetSubstructureSimple(jet, particles, candidates); + jetSubstructureMCPTable(energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, nSub[0], nSub[1], nSub[2], pairPtVec, pairEnergyVec, pairThetaVec, angularity); } PROCESS_SWITCH(JetSubstructureHFTask, processChargedJetsMCP, "HF jet substructure on MC particle level", false); }; using JetSubstructureD0 = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, CandidatesD0Data, CandidatesD0MCP, aod::D0CJetSSs, aod::D0CMCDJetSSs, aod::D0CMCPJetSSs, aod::D0CEWSJetSSs, aod::JTrackD0Subs>; using JetSubstructureLc = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, CandidatesLcData, CandidatesLcMCP, aod::LcCJetSSs, aod::LcCMCDJetSSs, aod::LcCMCPJetSSs, aod::LcCEWSJetSSs, aod::JTrackLcSubs>; // using JetSubstructureBplus = JetSubstructureHFTask,soa::Join,soa::Join,soa::Join, CandidatesBplusData, CandidatesBplusMCP, aod::BplusCJetSSs,aod::BplusCMCDJetSSs,aod::BplusCMCPJetSSs, aod::BplusCEWSJetSSs, aod::JTrackBplusSubs>; +using JetSubstructureDielectron = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, CandidatesDielectronData, CandidatesDielectronMCP, aod::DielectronCJetSSs, aod::DielectronCMCDJetSSs, aod::DielectronCMCPJetSSs, aod::DielectronCEWSJetSSs, aod::JTrackDielectronSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { @@ -231,6 +305,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-lc"})); + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-dielectron"})); /* tasks.emplace_back(adaptAnalysisTask(cfgc, diff --git a/PWGJE/Tasks/jetsubstructurehfoutput.cxx b/PWGJE/Tasks/jetsubstructurehfoutput.cxx index ead87e38e72..291d123d9d8 100644 --- a/PWGJE/Tasks/jetsubstructurehfoutput.cxx +++ b/PWGJE/Tasks/jetsubstructurehfoutput.cxx @@ -22,7 +22,6 @@ #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -41,9 +40,9 @@ using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! #include "Framework/runDataProcessing.h" -template +template struct JetSubstructureHFOutputTask { - Produces storedCollisionCountsTable; + Produces collisionOutputTableData; Produces jetOutputTableData; Produces jetSubstructureOutputTableData; @@ -82,19 +81,14 @@ struct JetSubstructureHFOutputTask { Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track pseudorapidity"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track pseudorapidity"}; - Configurable eventSelectionForCounting{"eventSelectionForCounting", "sel8", "choose event selection for collision counter"}; - - std::map candidateMapping; - std::map candidateCollisionMapping; - - std::map candidateMappingMCP; - std::map jetMappingData; std::map jetMappingDataSub; std::map jetMappingMCD; std::map jetMappingMCP; - std::map hfCollisionMapping; - std::map hfMcCollisionMapping; + std::map candidateMapping; + std::map candidateMappingMCP; + std::map candidateCollisionMapping; + std::map candidateMcCollisionMapping; std::vector jetRadiiValues; @@ -104,33 +98,42 @@ struct JetSubstructureHFOutputTask { PresliceUnsorted> CollisionsPerMcCollision = aod::jmccollisionlb::mcCollisionId; PresliceOptional D0CollisionsPerCollision = aod::jd0indices::collisionId; PresliceOptional LcCollisionsPerCollision = aod::jlcindices::collisionId; + PresliceOptional DielectronCollisionsPerCollision = aod::jdielectronindices::collisionId; PresliceOptional> D0McCollisionsPerMcCollision = aod::jd0indices::mcCollisionId; PresliceOptional> LcMcCollisionsPerMcCollision = aod::jlcindices::mcCollisionId; + PresliceOptional DielectronMcCollisionsPerMcCollision = aod::jdielectronindices::mcCollisionId; - int eventSelection = -1; void init(InitContext const&) { jetRadiiValues = (std::vector)jetRadii; - eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelectionForCounting)); } template - void fillTables(T const& jet, U const& /*cand*/, int32_t collisionIndex, int32_t candidateIndex, V& jetOutputTable, M& jetSubstructureOutputTable, std::map& jetMap) + void fillJetTables(T const& jet, U const& /*cand*/, int32_t collisionIndex, int32_t candidateIndex, V& jetOutputTable, M& jetSubstructureOutputTable, std::map& jetMap) { std::vector energyMotherVec; std::vector ptLeadingVec; std::vector ptSubLeadingVec; std::vector thetaVec; + std::vector pairPtVec; + std::vector pairEnergyVec; + std::vector pairThetaVec; auto energyMotherSpan = jet.energyMother(); auto ptLeadingSpan = jet.ptLeading(); auto ptSubLeadingSpan = jet.ptSubLeading(); auto thetaSpan = jet.theta(); + auto pairPtSpan = jet.pairPt(); + auto pairEnergySpan = jet.pairEnergy(); + auto pairThetaSpan = jet.pairTheta(); std::copy(energyMotherSpan.begin(), energyMotherSpan.end(), std::back_inserter(energyMotherVec)); std::copy(ptLeadingSpan.begin(), ptLeadingSpan.end(), std::back_inserter(ptLeadingVec)); std::copy(ptSubLeadingSpan.begin(), ptSubLeadingSpan.end(), std::back_inserter(ptSubLeadingVec)); std::copy(thetaSpan.begin(), thetaSpan.end(), std::back_inserter(thetaVec)); - jetOutputTable(collisionIndex, candidateIndex, jet.pt(), jet.phi(), jet.eta(), jet.y(), jet.r(), jet.tracksIds().size() + jet.hfcandidatesIds().size()); // here we take the decision to keep the collision index consistent with the JE framework in case it is later needed to join to other tables. The candidate Index however can be linked to the HF tables - jetSubstructureOutputTable(jetOutputTable.lastIndex(), energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, jet.nSub2DR(), jet.nSub1(), jet.nSub2()); + std::copy(pairPtSpan.begin(), pairPtSpan.end(), std::back_inserter(pairPtVec)); + std::copy(pairEnergySpan.begin(), pairEnergySpan.end(), std::back_inserter(pairEnergyVec)); + std::copy(pairThetaSpan.begin(), pairThetaSpan.end(), std::back_inserter(pairThetaVec)); + jetOutputTable(collisionIndex, candidateIndex, jet.pt(), jet.phi(), jet.eta(), jet.y(), jet.r(), jet.tracksIds().size() + jet.candidatesIds().size()); // here we take the decision to keep the collision index consistent with the JE framework in case it is later needed to join to other tables. The candidate Index however can be linked to the HF tables + jetSubstructureOutputTable(jetOutputTable.lastIndex(), energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, jet.nSub2DR(), jet.nSub1(), jet.nSub2(), pairPtVec, pairEnergyVec, pairThetaVec, jet.angularity()); jetMap.insert(std::make_pair(jet.globalIndex(), jetOutputTable.lastIndex())); } @@ -149,7 +152,7 @@ struct JetSubstructureHFOutputTask { } for (const auto& jetRadiiValue : jetRadiiValues) { if (jet.r() == round(jetRadiiValue * 100.0f)) { - auto candidate = jet.template hfcandidates_first_as(); + auto candidate = jet.template candidates_first_as(); int32_t candidateIndex = -1; auto candidateTableIndex = candidateMap.find(candidate.globalIndex()); if (candidateTableIndex != candidateMap.end()) { @@ -162,7 +165,7 @@ struct JetSubstructureHFOutputTask { } nJetInCollision++; } - fillTables(jet, candidate, collisionIndex, candidateIndex, jetOutputTable, jetSubstructureOutputTable, jetMap); + fillJetTables(jet, candidate, collisionIndex, candidateIndex, jetOutputTable, jetSubstructureOutputTable, jetMap); } } } @@ -181,7 +184,7 @@ struct JetSubstructureHFOutputTask { for (const auto& jetRadiiValue : jetRadiiValues) { if (jet.r() == round(jetRadiiValue * 100.0f)) { - auto candidate = jet.template hfcandidates_first_as(); + auto candidate = jet.template candidates_first_as(); auto candidateTableIndex = candidateMap.find(candidate.globalIndex()); if (candidateTableIndex != candidateMap.end()) { @@ -190,17 +193,17 @@ struct JetSubstructureHFOutputTask { int32_t candidateCollisionIndex = -1; int32_t candidateIndex = -1; if constexpr (isMCP) { - auto hfMcCollisionIndex = hfMcCollisionMapping.find(candidate.hfMcCollBaseId()); - if (hfMcCollisionIndex != hfMcCollisionMapping.end()) { + auto hfMcCollisionIndex = candidateMcCollisionMapping.find(jetcandidateutilities::getMcCandidateCollisionId(candidate)); + if (hfMcCollisionIndex != candidateMcCollisionMapping.end()) { candidateCollisionIndex = hfMcCollisionIndex->second; } - jethfutilities::fillCandidateMcTable(candidate, candidateCollisionIndex, hfParticlesTable, candidateIndex); + jetcandidateutilities::fillCandidateMcTable(candidate, candidateCollisionIndex, hfParticlesTable, candidateIndex); } else { - auto hfCollisionIndex = hfCollisionMapping.find(candidate.hfCollBaseId()); - if (hfCollisionIndex != hfCollisionMapping.end()) { + auto hfCollisionIndex = candidateCollisionMapping.find(jetcandidateutilities::getCandidateCollisionId(candidate)); + if (hfCollisionIndex != candidateCollisionMapping.end()) { candidateCollisionIndex = hfCollisionIndex->second; } - jethfutilities::fillCandidateTable(candidate, candidateCollisionIndex, candidateTable, candidateParsTable, candidateParExtrasTable, candidateSelsTable, candidateMlsTable, candidateMcsTable, candidateIndex); + jetcandidateutilities::fillCandidateTable(candidate, candidateCollisionIndex, candidateTable, candidateParsTable, candidateParExtrasTable, candidateSelsTable, candidateMlsTable, candidateMcsTable, candidateIndex); } candidateMap.insert(std::make_pair(candidate.globalIndex(), candidateIndex)); } @@ -315,15 +318,15 @@ struct JetSubstructureHFOutputTask { if constexpr (!isMCPOnly) { for (const auto& collision : collisions) { if (collisionFlag[collision.globalIndex()]) { - const auto hfCollisionsPerCollision = jethfutilities::slicedPerCollision(hfCollisions, candidates, collision, D0CollisionsPerCollision, LcCollisionsPerCollision, D0CollisionsPerCollision); // add Bplus later + const auto hfCollisionsPerCollision = jetcandidateutilities::slicedPerCandidateCollision(hfCollisions, candidates, collision, D0CollisionsPerCollision, LcCollisionsPerCollision, D0CollisionsPerCollision, DielectronCollisionsPerCollision); // add Bplus later int32_t candidateCollisionIndex = -1; for (const auto& hfCollisionPerCollision : hfCollisionsPerCollision) { // should only ever be one - auto hfCollisionTableIndex = hfCollisionMapping.find(hfCollisionPerCollision.globalIndex()); - if (hfCollisionTableIndex != hfCollisionMapping.end()) { + auto hfCollisionTableIndex = candidateCollisionMapping.find(hfCollisionPerCollision.globalIndex()); + if (hfCollisionTableIndex != candidateCollisionMapping.end()) { continue; } - jethfutilities::fillHFCollisionTable(hfCollisionPerCollision, candidates, hfCollisionsTable, candidateCollisionIndex); - hfCollisionMapping.insert(std::make_pair(hfCollisionPerCollision.globalIndex(), hfCollisionsTable.lastIndex())); + jetcandidateutilities::fillCandidateCollisionTable(hfCollisionPerCollision, candidates, hfCollisionsTable, candidateCollisionIndex); + candidateCollisionMapping.insert(std::make_pair(hfCollisionPerCollision.globalIndex(), hfCollisionsTable.lastIndex())); } } } @@ -331,24 +334,24 @@ struct JetSubstructureHFOutputTask { if constexpr (isMC) { for (const auto& mcCollision : mcCollisions) { if (mcCollisionFlag[mcCollision.globalIndex()]) { - const auto hfMcCollisionsPerMcCollision = jethfutilities::slicedPerCollision(hfMcCollisions, candidatesMCP, mcCollision, D0McCollisionsPerMcCollision, LcMcCollisionsPerMcCollision, D0McCollisionsPerMcCollision); // add Bplus later + const auto hfMcCollisionsPerMcCollision = jetcandidateutilities::slicedPerCandidateCollision(hfMcCollisions, candidatesMCP, mcCollision, D0McCollisionsPerMcCollision, LcMcCollisionsPerMcCollision, D0McCollisionsPerMcCollision, DielectronMcCollisionsPerMcCollision); // add Bplus later int32_t candidateMcCollisionIndex = -1; for (const auto& hfMcCollisionPerMcCollision : hfMcCollisionsPerMcCollision) { // should only ever be one - auto hfMcCollisionTableIndex = hfMcCollisionMapping.find(hfMcCollisionPerMcCollision.globalIndex()); - if (hfMcCollisionTableIndex != hfMcCollisionMapping.end()) { + auto hfMcCollisionTableIndex = candidateMcCollisionMapping.find(hfMcCollisionPerMcCollision.globalIndex()); + if (hfMcCollisionTableIndex != candidateMcCollisionMapping.end()) { continue; } - jethfutilities::fillHFMcCollisionTable(hfMcCollisionPerMcCollision, candidatesMCP, hfMcCollisionsTable, candidateMcCollisionIndex); - hfMcCollisionMapping.insert(std::make_pair(hfMcCollisionPerMcCollision.globalIndex(), hfMcCollisionsTable.lastIndex())); - if constexpr (!isMCPOnly) { + jetcandidateutilities::fillCandidateMcCollisionTable(hfMcCollisionPerMcCollision, candidatesMCP, hfMcCollisionsTable, candidateMcCollisionIndex); + candidateMcCollisionMapping.insert(std::make_pair(hfMcCollisionPerMcCollision.globalIndex(), hfMcCollisionsTable.lastIndex())); + if constexpr (!isMCPOnly && (jethfutilities::isHFTable

() || jethfutilities::isHFMcTable())) { // the matching of mcCollision to Collision is only done for HF tables std::vector hfCollisionIDs; - for (auto const& hfCollisionPerMcCollision : hfMcCollisionPerMcCollision.template hfCollBases_as()) { - auto hfCollisionIndex = hfCollisionMapping.find(hfCollisionPerMcCollision.globalIndex()); - if (hfCollisionIndex != hfCollisionMapping.end()) { + for (auto const& hfCollisionPerMcCollision : hfMcCollisionPerMcCollision.template hfCollBases_as()) { // if added for others this line needs to be templated per type + auto hfCollisionIndex = candidateCollisionMapping.find(hfCollisionPerMcCollision.globalIndex()); + if (hfCollisionIndex != candidateCollisionMapping.end()) { hfCollisionIDs.push_back(hfCollisionIndex->second); } } - hfMcCollisionsMatchingTable(hfCollisionIDs); // make matching table a template + hfMcCollisionsMatchingTable(hfCollisionIDs); } } } @@ -365,50 +368,11 @@ struct JetSubstructureHFOutputTask { jetMappingDataSub.clear(); jetMappingMCD.clear(); jetMappingMCP.clear(); - hfCollisionMapping.clear(); - hfMcCollisionMapping.clear(); + candidateCollisionMapping.clear(); + candidateMcCollisionMapping.clear(); } PROCESS_SWITCH(JetSubstructureHFOutputTask, processClearMaps, "process function that clears all the maps in each dataframe", true); - void processCountCollisions(JetCollisions const& collisions, aod::CollisionCounts const& collisionCounts) - { - int readCollisionCounter = 0; - int readSelectedCollisionCounter = 0; - int writtenCollisionCounter = -1; - for (auto const& collision : collisions) { - readCollisionCounter++; - if (jetderiveddatautilities::selectCollision(collision, eventSelection)) { - readSelectedCollisionCounter++; - } - } - std::vector previousReadCounts; - std::vector previousReadSelectedCounts; - std::vector previousWrittenCounts; - int iPreviousDataFrame = 0; - for (const auto& collisionCount : collisionCounts) { - auto readCollisionCounterSpan = collisionCount.readCounts(); - auto readSelectedCollisionCounterSpan = collisionCount.readSelectedCounts(); - auto writtenCollisionCounterSpan = collisionCount.writtenCounts(); - if (iPreviousDataFrame == 0) { - std::copy(readCollisionCounterSpan.begin(), readCollisionCounterSpan.end(), std::back_inserter(previousReadCounts)); - std::copy(readSelectedCollisionCounterSpan.begin(), readSelectedCollisionCounterSpan.end(), std::back_inserter(previousReadSelectedCounts)); - std::copy(writtenCollisionCounterSpan.begin(), writtenCollisionCounterSpan.end(), std::back_inserter(previousWrittenCounts)); - } else { - for (unsigned int i = 0; i < previousReadCounts.size(); i++) { - previousReadCounts[i] += readCollisionCounterSpan[i]; - previousReadSelectedCounts[i] += readSelectedCollisionCounterSpan[i]; - previousWrittenCounts[i] += writtenCollisionCounterSpan[i]; - } - } - iPreviousDataFrame++; - } - previousReadCounts.push_back(readCollisionCounter); - previousReadSelectedCounts.push_back(readSelectedCollisionCounter); - previousWrittenCounts.push_back(writtenCollisionCounter); - storedCollisionCountsTable(previousReadCounts, previousReadSelectedCounts, previousWrittenCounts); - } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processCountCollisions, "process function that counts read in collisions", false); - void processOutputCollisionsData(JetCollisions const& collisions, JetTableData const& jets, CandidateCollisionTable const& canidateCollisions, @@ -530,9 +494,10 @@ struct JetSubstructureHFOutputTask { } PROCESS_SWITCH(JetSubstructureHFOutputTask, processOutputMatchingMC, "jet matching output MC", false); }; -using JetSubstructureOutputD0 = JetSubstructureHFOutputTask, CandidatesD0Data, CandidatesD0MCD, CandidatesD0MCP, aod::JTrackD0Subs, soa::Join, soa::Join, aod::D0CJetCOs, aod::D0CJetOs, aod::D0CJetSSOs, aod::D0CJetMOs, soa::Join, aod::D0CMCDJetCOs, aod::D0CMCDJetOs, aod::D0CMCDJetSSOs, aod::D0CMCDJetMOs, soa::Join, aod::D0CMCPJetCOs, aod::D0CMCPJetOs, aod::D0CMCPJetSSOs, aod::D0CMCPJetMOs, soa::Join, aod::D0CEWSJetCOs, aod::D0CEWSJetOs, aod::D0CEWSJetSSOs, aod::D0CEWSJetMOs, aod::StoredHfD0CollBase, aod::StoredHfD0Bases, aod::StoredHfD0Pars, aod::StoredHfD0ParEs, aod::StoredHfD0Sels, aod::StoredHfD0Mls, aod::StoredHfD0Mcs, aod::StoredHfD0McCollBases, aod::StoredHfD0McRCollIds, aod::StoredHfD0PBases, aod::D0CollisionCounts>; -using JetSubstructureOutputLc = JetSubstructureHFOutputTask, CandidatesLcData, CandidatesLcMCD, CandidatesLcMCP, aod::JTrackLcSubs, soa::Join, soa::Join, aod::LcCJetCOs, aod::LcCJetOs, aod::LcCJetSSOs, aod::LcCJetMOs, soa::Join, aod::LcCMCDJetCOs, aod::LcCMCDJetOs, aod::LcCMCDJetSSOs, aod::LcCMCDJetMOs, soa::Join, aod::LcCMCPJetCOs, aod::LcCMCPJetOs, aod::LcCMCPJetSSOs, aod::LcCMCPJetMOs, soa::Join, aod::LcCEWSJetCOs, aod::LcCEWSJetOs, aod::LcCEWSJetSSOs, aod::LcCEWSJetMOs, aod::StoredHf3PCollBase, aod::StoredHf3PBases, aod::StoredHf3PPars, aod::StoredHf3PParEs, aod::StoredHf3PSels, aod::StoredHf3PMls, aod::StoredHf3PMcs, aod::StoredHf3PMcCollBases, aod::StoredHf3PMcRCollIds, aod::StoredHf3PPBases, aod::LcCollisionCounts>; -// using JetSubstructureOutputBplus = JetSubstructureHFOutputTask, CandidatesBplusData, CandidatesBplusMCD, CandidatesBplusMCP, aod::JTrackBplusSubs, soa::Join, soa::Join, aod::BplusCJetCOs, aod::BplusCJetOs, aod::BplusCJetSSOs, aod::BplusCJetMOs, soa::Join, aod::BplusCMCDJetCOs, aod::BplusCMCDJetOs, aod::BplusCMCDJetSSOs, aod::BplusCMCDJetMOs, soa::Join, aod::BplusCMCPJetCOs, aod::BplusCMCPJetOs, aod::BplusCMCPJetSSOs, aod::BplusCMCPJetMOs, soa::Join, aod::BplusCEWSJetCOs, aod::BplusCEWSJetOs, aod::BplusCEWSJetSSOs, aod::BplusCEWSJetMOs, aod::StoredHfBplusCollBase, aod::StoredHfBplusBases, aod::StoredHfBplusPars, aod::StoredHfBplusParEs, aod::StoredHfBplusSels, aod::StoredHfBplusMls, aod::StoredHfBplusMcs, aod::StoredHfBplusPBases, aod::BplusCollisionCounts>; +using JetSubstructureOutputD0 = JetSubstructureHFOutputTask, CandidatesD0Data, CandidatesD0MCD, CandidatesD0MCP, aod::JTrackD0Subs, soa::Join, soa::Join, aod::D0CJetCOs, aod::D0CJetOs, aod::D0CJetSSOs, aod::D0CJetMOs, soa::Join, aod::D0CMCDJetCOs, aod::D0CMCDJetOs, aod::D0CMCDJetSSOs, aod::D0CMCDJetMOs, soa::Join, aod::D0CMCPJetCOs, aod::D0CMCPJetOs, aod::D0CMCPJetSSOs, aod::D0CMCPJetMOs, soa::Join, aod::D0CEWSJetCOs, aod::D0CEWSJetOs, aod::D0CEWSJetSSOs, aod::D0CEWSJetMOs, aod::StoredHfD0CollBase, aod::StoredHfD0Bases, aod::StoredHfD0Pars, aod::StoredHfD0ParEs, aod::StoredHfD0Sels, aod::StoredHfD0Mls, aod::StoredHfD0Mcs, aod::StoredHfD0McCollBases, aod::StoredHfD0McRCollIds, aod::StoredHfD0PBases>; +using JetSubstructureOutputLc = JetSubstructureHFOutputTask, CandidatesLcData, CandidatesLcMCD, CandidatesLcMCP, aod::JTrackLcSubs, soa::Join, soa::Join, aod::LcCJetCOs, aod::LcCJetOs, aod::LcCJetSSOs, aod::LcCJetMOs, soa::Join, aod::LcCMCDJetCOs, aod::LcCMCDJetOs, aod::LcCMCDJetSSOs, aod::LcCMCDJetMOs, soa::Join, aod::LcCMCPJetCOs, aod::LcCMCPJetOs, aod::LcCMCPJetSSOs, aod::LcCMCPJetMOs, soa::Join, aod::LcCEWSJetCOs, aod::LcCEWSJetOs, aod::LcCEWSJetSSOs, aod::LcCEWSJetMOs, aod::StoredHf3PCollBase, aod::StoredHf3PBases, aod::StoredHf3PPars, aod::StoredHf3PParEs, aod::StoredHf3PSels, aod::StoredHf3PMls, aod::StoredHf3PMcs, aod::StoredHf3PMcCollBases, aod::StoredHf3PMcRCollIds, aod::StoredHf3PPBases>; +// using JetSubstructureOutputBplus = JetSubstructureHFOutputTask, CandidatesBplusData, CandidatesBplusMCD, CandidatesBplusMCP, aod::JTrackBplusSubs, soa::Join, soa::Join, aod::BplusCJetCOs, aod::BplusCJetOs, aod::BplusCJetSSOs, aod::BplusCJetMOs, soa::Join, aod::BplusCMCDJetCOs, aod::BplusCMCDJetOs, aod::BplusCMCDJetSSOs, aod::BplusCMCDJetMOs, soa::Join, aod::BplusCMCPJetCOs, aod::BplusCMCPJetOs, aod::BplusCMCPJetSSOs, aod::BplusCMCPJetMOs, soa::Join, aod::BplusCEWSJetCOs, aod::BplusCEWSJetOs, aod::BplusCEWSJetSSOs, aod::BplusCEWSJetMOs, aod::StoredHfBplusCollBase, aod::StoredHfBplusBases, aod::StoredHfBplusPars, aod::StoredHfBplusParEs, aod::StoredHfBplusSels, aod::StoredHfBplusMls, aod::StoredHfBplusMcs, aod::StoredHfBplusPBases>; +using JetSubstructureOutputDielectron = JetSubstructureHFOutputTask, soa::Join, aod::DielectronCJetCOs, aod::DielectronCJetOs, aod::DielectronCJetSSOs, aod::DielectronCJetMOs, soa::Join, aod::DielectronCMCDJetCOs, aod::DielectronCMCDJetOs, aod::DielectronCMCDJetSSOs, aod::DielectronCMCDJetMOs, soa::Join, aod::DielectronCMCPJetCOs, aod::DielectronCMCPJetOs, aod::DielectronCMCPJetSSOs, aod::DielectronCMCPJetMOs, soa::Join, aod::DielectronCEWSJetCOs, aod::DielectronCEWSJetOs, aod::DielectronCEWSJetSSOs, aod::DielectronCEWSJetMOs, aod::StoredReducedEvents, aod::StoredDielectrons, aod::JDielectron1Dummys, aod::JDielectron2Dummys, aod::JDielectron3Dummys, aod::JDielectron4Dummys, aod::JDielectron5Dummys, aod::StoredJDielectronMcCollisions, aod::JDielectron6Dummys, aod::StoredJDielectronMcs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { @@ -541,5 +506,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-d0-output"})); tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-lc-output"})); // tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-bplus-output"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-dielectron-output"})); + return WorkflowSpec{tasks}; } diff --git a/PWGJE/Tasks/jetsubstructureoutput.cxx b/PWGJE/Tasks/jetsubstructureoutput.cxx index dd7e6b49fb6..a5ce1525c31 100644 --- a/PWGJE/Tasks/jetsubstructureoutput.cxx +++ b/PWGJE/Tasks/jetsubstructureoutput.cxx @@ -23,6 +23,7 @@ #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/EventSelection.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/TrackSelectionTables.h" #include "PWGJE/Core/JetFinder.h" @@ -40,7 +41,6 @@ using namespace o2::framework::expressions; struct JetSubstructureOutputTask { - Produces storedCollisionCountsTable; Produces collisionOutputTableData; Produces jetOutputTableData; Produces jetSubstructureOutputTableData; @@ -69,8 +69,6 @@ struct JetSubstructureOutputTask { Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track pseudorapidity"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track pseudorapidity"}; - Configurable eventSelectionForCounting{"eventSelectionForCounting", "sel8", "choose event selection for collision counter"}; - std::map jetMappingData; std::map jetMappingDataSub; std::map jetMappingMCD; @@ -78,30 +76,37 @@ struct JetSubstructureOutputTask { std::vector jetRadiiValues; - int eventSelection = -1; void init(InitContext const&) { jetRadiiValues = (std::vector)jetRadii; - eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelectionForCounting)); } template - void fillTables(T const& jet, int32_t collisionIndex, U& jetOutputTable, V& jetSubstructureOutputTable, std::map& jetMapping) + void fillJetTables(T const& jet, int32_t collisionIndex, U& jetOutputTable, V& jetSubstructureOutputTable, std::map& jetMapping) { std::vector energyMotherVec; std::vector ptLeadingVec; std::vector ptSubLeadingVec; std::vector thetaVec; + std::vector pairPtVec; + std::vector pairEnergyVec; + std::vector pairThetaVec; auto energyMotherSpan = jet.energyMother(); auto ptLeadingSpan = jet.ptLeading(); auto ptSubLeadingSpan = jet.ptSubLeading(); auto thetaSpan = jet.theta(); + auto pairPtSpan = jet.pairPt(); + auto pairEnergySpan = jet.pairEnergy(); + auto pairThetaSpan = jet.pairTheta(); std::copy(energyMotherSpan.begin(), energyMotherSpan.end(), std::back_inserter(energyMotherVec)); std::copy(ptLeadingSpan.begin(), ptLeadingSpan.end(), std::back_inserter(ptLeadingVec)); std::copy(ptSubLeadingSpan.begin(), ptSubLeadingSpan.end(), std::back_inserter(ptSubLeadingVec)); std::copy(thetaSpan.begin(), thetaSpan.end(), std::back_inserter(thetaVec)); + std::copy(pairPtSpan.begin(), pairPtSpan.end(), std::back_inserter(pairPtVec)); + std::copy(pairEnergySpan.begin(), pairEnergySpan.end(), std::back_inserter(pairEnergyVec)); + std::copy(pairThetaSpan.begin(), pairThetaSpan.end(), std::back_inserter(pairThetaVec)); jetOutputTable(collisionIndex, collisionIndex, jet.pt(), jet.phi(), jet.eta(), jet.y(), jet.r(), jet.tracksIds().size()); // second collision index is a dummy coloumn mirroring the hf candidate - jetSubstructureOutputTable(jetOutputTable.lastIndex(), energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, jet.nSub2DR(), jet.nSub1(), jet.nSub2()); + jetSubstructureOutputTable(jetOutputTable.lastIndex(), energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, jet.nSub2DR(), jet.nSub1(), jet.nSub2(), pairPtVec, pairEnergyVec, pairThetaVec, jet.angularity()); jetMapping.insert(std::make_pair(jet.globalIndex(), jetOutputTable.lastIndex())); } @@ -126,7 +131,7 @@ struct JetSubstructureOutputTask { } nJetInCollision++; } - fillTables(jet, collisionIndex, jetOutputTable, jetSubstructureOutputTable, jetMapping); + fillJetTables(jet, collisionIndex, jetOutputTable, jetSubstructureOutputTable, jetMapping); } } } @@ -183,45 +188,6 @@ struct JetSubstructureOutputTask { } PROCESS_SWITCH(JetSubstructureOutputTask, processClearMaps, "process function that clears all the maps in each dataframe", true); - void processCountCollisions(JetCollisions const& collisions, aod::CollisionCounts const& collisionCounts) - { - int readCollisionCounter = 0; - int readSelectedCollisionCounter = 0; - int writtenCollisionCounter = -1; - for (auto const& collision : collisions) { - readCollisionCounter++; - if (jetderiveddatautilities::selectCollision(collision, eventSelection)) { - readSelectedCollisionCounter++; - } - } - std::vector previousReadCounts; - std::vector previousReadSelectedCounts; - std::vector previousWrittenCounts; - int iPreviousDataFrame = 0; - for (const auto& collisionCount : collisionCounts) { - auto readCollisionCounterSpan = collisionCount.readCounts(); - auto readSelectedCollisionCounterSpan = collisionCount.readSelectedCounts(); - auto writtenCollisionCounterSpan = collisionCount.writtenCounts(); - if (iPreviousDataFrame == 0) { - std::copy(readCollisionCounterSpan.begin(), readCollisionCounterSpan.end(), std::back_inserter(previousReadCounts)); - std::copy(readSelectedCollisionCounterSpan.begin(), readSelectedCollisionCounterSpan.end(), std::back_inserter(previousReadSelectedCounts)); - std::copy(writtenCollisionCounterSpan.begin(), writtenCollisionCounterSpan.end(), std::back_inserter(previousWrittenCounts)); - } else { - for (unsigned int i = 0; i < previousReadCounts.size(); i++) { - previousReadCounts[i] += readCollisionCounterSpan[i]; - previousReadSelectedCounts[i] += readSelectedCollisionCounterSpan[i]; - previousWrittenCounts[i] += writtenCollisionCounterSpan[i]; - } - } - iPreviousDataFrame++; - } - previousReadCounts.push_back(readCollisionCounter); - previousReadSelectedCounts.push_back(readSelectedCollisionCounter); - previousWrittenCounts.push_back(writtenCollisionCounter); - storedCollisionCountsTable(previousReadCounts, previousReadSelectedCounts, previousWrittenCounts); - } - PROCESS_SWITCH(JetSubstructureOutputTask, processCountCollisions, "process function that counts read in collisions", false); - void processOutputData(JetCollision const& collision, soa::Join const& jets) { diff --git a/PWGJE/Tasks/jettaggerhfQA.cxx b/PWGJE/Tasks/jettaggerhfQA.cxx index 745f463ec87..c6ba49277be 100644 --- a/PWGJE/Tasks/jettaggerhfQA.cxx +++ b/PWGJE/Tasks/jettaggerhfQA.cxx @@ -36,7 +36,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -template +template struct JetTaggerHFQA { // task on/off configuration @@ -51,19 +51,28 @@ struct JetTaggerHFQA { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum eta acceptance for tracks"}; Configurable trackPtMin{"trackPtMin", 0.15, "minimum pT acceptance for tracks"}; Configurable trackPtMax{"trackPtMax", 100.0, "maximum pT acceptance for tracks"}; + Configurable trackDcaXYMax{"trackDcaXYMax", 1, "minimum DCA xy acceptance for tracks [cm]"}; + Configurable trackDcaZMax{"trackDcaZMax", 2, "minimum DCA z acceptance for tracks [cm]"}; Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; - Configurable prong2LxySigmaMax{"prong2LxySigmaMax", 0.03, "maximum sigma of decay length of 2-prong on xy plane"}; - Configurable prong2SxyMin{"prong2SxyMin", 7, "minimum decay length significance of 2-prong on xy plane"}; - Configurable prong2LxyzSigmaMax{"prong2LxyzSigmazMax", 0.03, "maximum sigma of decay length of 2-prong on xyz plane"}; - Configurable prong2SxyzMin{"prong2SxyzMin", 7, "minimum decay length significance of 2-prong on xyz plane"}; - Configurable prong3LxySigmaMax{"prong3LxySigmaMax", 0.03, "maximum sigma of decay length of 3-prong on xy plane"}; - Configurable prong3SxyMin{"prong3SxyMin", 7, "minimum decay length significance of 3-prong on xy plane"}; - Configurable prong3LxyzSigmaMax{"prong3LxyzSigmazMax", 0.03, "maximum sigma of decay length of 3-prong on xyz plane"}; - Configurable prong3SxyzMin{"prong3SxyzMin", 7, "minimum decay length significance of 3-prong on xyz plane"}; + Configurable prongChi2PCAMin{"prongChi2PCAMin", 1, "minimum Chi2 PCA of decay length of prongs"}; + Configurable prongChi2PCAMax{"prongChi2PCAMax", 100, "maximum Chi2 PCA of decay length of prongs"}; + Configurable prongsigmaLxyMax{"prongsigmaLxyMax", 100, "maximum sigma of decay length of prongs on xy plane"}; + Configurable prongsigmaLxyzMax{"prongsigmaLxyzMax", 100, "maximum sigma of decay length of prongs on xyz plane"}; + Configurable prongIPxyMin{"prongIPxyMin", 0.008, "maximum impact paramter of prongs on xy plane"}; + Configurable prongIPxyMax{"prongIpxyMax", 1, "minimum impact parmeter of prongs on xy plane"}; Configurable numFlavourSpecies{"numFlavourSpecies", 6, "number of jet flavour species"}; Configurable numOrder{"numOrder", 6, "number of ordering"}; + Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; + Configurable leadingConstituentPtMin{"leadingConstituentPtMin", -99.0, "minimum pT selection on jet constituent"}; + Configurable checkMcCollisionIsMatched{"checkMcCollisionIsMatched", false, "0: count whole MCcollisions, 1: select MCcollisions which only have their correspond collisions"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions (data and mcd jets), not mc collisions (mcp jets)"}; + Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions (data and mcd jets), not mc collisions (mcp jets)"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; // Binning ConfigurableAxis binJetFlavour{"binJetFlavour", {6, -0.5, 5.5}, ""}; @@ -72,30 +81,37 @@ struct JetTaggerHFQA { ConfigurableAxis binPhi{"binPhi", {18 * 8, 0.f, 2. * TMath::Pi()}, ""}; ConfigurableAxis binNtracks{"binNtracks", {100, 0., 100.}, ""}; ConfigurableAxis binTrackPt{"binTrackPt", {200, 0.f, 100.f}, ""}; - ConfigurableAxis binImpactParameterXY{"binImpactParameterXY", {800, -400.5f, 400.5f}, ""}; - ConfigurableAxis binImpactParameterXYSignificance{"binImpactParameterXYSignificance", {800, -40.5f, 40.5f}, ""}; - ConfigurableAxis binImpactParameterZ{"binImpactParameterZ", {800, -400.5f, 400.5f}, ""}; - ConfigurableAxis binImpactParameterZSignificance{"binImpactParameterZSignificance", {800, -40.5f, 40.5f}, ""}; - ConfigurableAxis binImpactParameterXYZ{"binImpactParameterXYZ", {2000, -1000.5f, 1000.5f}, ""}; - ConfigurableAxis binImpactParameterXYZSignificance{"binImpactParameterXYZSignificance", {2000, -100.5f, 100.5f}, ""}; + ConfigurableAxis binImpactParameterXY{"binImpactParameterXY", {801, -400.5f, 400.5f}, ""}; + ConfigurableAxis binSigmaImpactParameterXY{"binImpactSigmaParameterXY", {800, 0.f, 100.f}, ""}; + ConfigurableAxis binImpactParameterXYSignificance{"binImpactParameterXYSignificance", {801, -40.5f, 40.5f}, ""}; + ConfigurableAxis binImpactParameterZ{"binImpactParameterZ", {801, -400.5f, 400.5f}, ""}; + ConfigurableAxis binImpactParameterZSignificance{"binImpactParameterZSignificance", {801, -40.5f, 40.5f}, ""}; + ConfigurableAxis binImpactParameterXYZ{"binImpactParameterXYZ", {2001, -1000.5f, 1000.5f}, ""}; + ConfigurableAxis binImpactParameterXYZSignificance{"binImpactParameterXYZSignificance", {2001, -100.5f, 100.5f}, ""}; ConfigurableAxis binNumOrder{"binNumOrder", {6, 0.5, 6.5}, ""}; ConfigurableAxis binJetProbability{"binJetProbability", {100, 0.f, 1.f}, ""}; ConfigurableAxis binJetProbabilityLog{"binJetProbabilityLog", {100, 0.f, 10.f}, ""}; ConfigurableAxis binNprongs{"binNprongs", {100, 0., 100.}, ""}; ConfigurableAxis binLxy{"binLxy", {200, 0, 20.f}, ""}; - ConfigurableAxis binSxy{"binSxy", {200, 0, 200.f}, ""}; + ConfigurableAxis binSxy{"binSxy", {1000, 0, 1000.f}, ""}; ConfigurableAxis binLxyz{"binLxyz", {200, 0, 20.f}, ""}; - ConfigurableAxis binSxyz{"binSxyz", {200, 0, 200.f}, ""}; + ConfigurableAxis binSxyz{"binSxyz", {1000, 0, 1000.f}, ""}; + ConfigurableAxis binMass{"binMass", {50, 0, 10.f}, ""}; ConfigurableAxis binSigmaLxy{"binSigmaLxy", {100, 0., 0.1}, ""}; ConfigurableAxis binSigmaLxyz{"binSigmaLxyz", {100, 0., 0.1}, ""}; int numberOfJetFlavourSpecies = 6; + int eventSelection = -1; int trackSelection = -1; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext const&) { + numberOfJetFlavourSpecies = static_cast(numFlavourSpecies); + + eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); // Axis AxisSpec jetFlavourAxis = {binJetFlavour, "Jet flavour"}; AxisSpec jetPtAxis = {binJetPt, "#it{p}_{T, jet}"}; @@ -104,6 +120,8 @@ struct JetTaggerHFQA { AxisSpec ntracksAxis = {binNtracks, "#it{N}_{tracks}"}; AxisSpec trackPtAxis = {binTrackPt, "#it{p}_{T}^{track}"}; AxisSpec impactParameterXYAxis = {binImpactParameterXY, "IP_{XY} [#mum]"}; + AxisSpec sigmaImpactParameterXYAxis = {binSigmaImpactParameterXY, "#sigma_{XY} [#mum]"}; + AxisSpec sigmaImpactParameterXYZAxis = {binSigmaImpactParameterXY, "#sigma_{XYZ} [#mum]"}; AxisSpec impactParameterXYSignificanceAxis = {binImpactParameterXYSignificance, "IPs_{XY}"}; AxisSpec impactParameterZAxis = {binImpactParameterZ, "IP_{Z} [#mum]"}; AxisSpec impactParameterZSignificanceAxis = {binImpactParameterZSignificance, "IPs_{Z}"}; @@ -117,12 +135,10 @@ struct JetTaggerHFQA { AxisSpec SxyAxis = {binSxy, "S_{XY}"}; AxisSpec LxyzAxis = {binLxyz, "L_{XYZ} [cm]"}; AxisSpec SxyzAxis = {binSxyz, "S_{XYZ}"}; + AxisSpec massAxis = {binMass, "#it{m}_{SV}"}; AxisSpec sigmaLxyAxis = {binSigmaLxy, "#sigma_{L_{XY}} [cm]"}; AxisSpec sigmaLxyzAxis = {binSigmaLxyz, "#sigma_{L_{XYZ}} [cm]"}; - numberOfJetFlavourSpecies = static_cast(numFlavourSpecies); - - trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); if (doprocessTracksDca) { registry.add("h_impact_parameter_xy", "", {HistType::kTH1F, {{impactParameterXYAxis}}}); registry.add("h_impact_parameter_xy_significance", "", {HistType::kTH1F, {{impactParameterXYSignificanceAxis}}}); @@ -161,7 +177,7 @@ struct JetTaggerHFQA { registry.add("h3_track_pt_sign_impact_parameter_xyz_significance_tc", "", {HistType::kTH3F, {{trackPtAxis}, {impactParameterXYZSignificanceAxis}, {numOrderAxis}}}); } } - if (doprocessIPsMCD) { + if (doprocessIPsMCD || doprocessIPsMCDWeighted) { registry.add("h2_jet_pt_flavour", "", {HistType::kTH2F, {{jetPtAxis}, {jetFlavourAxis}}}); registry.add("h2_jet_eta_flavour", "", {HistType::kTH2F, {{etaAxis}, {jetFlavourAxis}}}); registry.add("h2_jet_phi_flavour", "", {HistType::kTH2F, {{phiAxis}, {jetFlavourAxis}}}); @@ -170,6 +186,7 @@ struct JetTaggerHFQA { registry.add("h3_jet_pt_track_phi_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {phiAxis}, {jetFlavourAxis}}}); if (fillIPxy) { registry.add("h3_jet_pt_impact_parameter_xy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_sigma_impact_parameter_xy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaImpactParameterXYAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_sign_impact_parameter_xy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_impact_parameter_xy_significance_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_sign_impact_parameter_xy_significance_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); @@ -213,6 +230,37 @@ struct JetTaggerHFQA { registry.add("h3_sign_impact_parameter_xyz_significance_tc_flavour", "", {HistType::kTH3F, {{impactParameterXYZSignificanceAxis}, {numOrderAxis}, {jetFlavourAxis}}}); } } + if (doprocessIPsMCP || doprocessIPsMCPWeighted) { + registry.add("h2_jet_pt_part_flavour", "", {HistType::kTH2F, {{jetPtAxis}, {jetFlavourAxis}}}); + registry.add("h2_jet_eta_part_flavour", "", {HistType::kTH2F, {{etaAxis}, {jetFlavourAxis}}}); + registry.add("h2_jet_phi_part_flavour", "", {HistType::kTH2F, {{phiAxis}, {jetFlavourAxis}}}); + } + + if (doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) { + registry.add("h3_jet_pt_jet_pt_part_matchedgeo_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {jetPtAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_jet_pt_part_matchedgeo_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {jetPtAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_flavour_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {jetFlavourAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_eta_flavour_flavour_run2", "", {HistType::kTH3F, {{etaAxis}, {jetFlavourAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_phi_flavour_flavour_run2", "", {HistType::kTH3F, {{phiAxis}, {jetFlavourAxis}, {jetFlavourAxis}}}); + registry.add("h_compare_flavour_flavour_run2", "", {HistType::kTH1F, {{2, 0, 2}}}); + if (fillIPxy) { + registry.add("h3_jet_pt_impact_parameter_xy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_sigma_impact_parameter_xy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaImpactParameterXYAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_sign_impact_parameter_xy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_impact_parameter_xy_significance_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + registry.add("h3_track_pt_impact_parameter_xy_flavour_run2", "", {HistType::kTH3F, {{trackPtAxis}, {impactParameterXYAxis}, {jetFlavourAxis}}}); + registry.add("h3_track_pt_sign_impact_parameter_xy_flavour_run2", "", {HistType::kTH3F, {{trackPtAxis}, {impactParameterXYAxis}, {jetFlavourAxis}}}); + registry.add("h3_track_pt_impact_parameter_xy_significance_flavour_run2", "", {HistType::kTH3F, {{trackPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + registry.add("h3_track_pt_sign_impact_parameter_xy_significance_flavour_run2", "", {HistType::kTH3F, {{trackPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + } + if (fillTrackCounting) { + registry.add("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2_N1", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2_N2", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2_N3", "", {HistType::kTH3F, {{jetPtAxis}, {impactParameterXYSignificanceAxis}, {jetFlavourAxis}}}); + } + } + if (doprocessJPData) { registry.add("h2_jet_pt_JP", "jet pt jet probability untagged", {HistType::kTH2F, {{jetPtAxis}, {JetProbabilityAxis}}}); registry.add("h2_jet_pt_neg_log_JP", "jet pt jet probabilityun tagged", {HistType::kTH2F, {{jetPtAxis}, {JetProbabilityLogAxis}}}); @@ -223,7 +271,7 @@ struct JetTaggerHFQA { registry.add("h2_jet_pt_JP_N3", "jet pt jet probability N3", {HistType::kTH2F, {{jetPtAxis}, {JetProbabilityAxis}}}); registry.add("h2_jet_pt_neg_log_JP_N3", "jet pt jet probabilityun N3", {HistType::kTH2F, {{jetPtAxis}, {JetProbabilityLogAxis}}}); } - if (doprocessJPMCD) { + if (doprocessJPMCD || doprocessJPMCDWeighted) { registry.add("h3_jet_pt_JP_flavour", "jet pt jet probability flavour untagged", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_neg_log_JP_flavour", "jet pt log jet probability flavour untagged", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityLogAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_JP_N1_flavour", "jet pt jet probability flavour N1", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); @@ -236,604 +284,1121 @@ struct JetTaggerHFQA { if (doprocessSV2ProngData) { registry.add("h_2prong_nprongs", "", {HistType::kTH1F, {{nprongsAxis}}}); registry.add("h2_jet_pt_2prong_Lxy", "", {HistType::kTH2F, {{jetPtAxis}, {LxyAxis}}}); + registry.add("h2_jet_pt_2prong_sigmaLxy", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyAxis}}}); registry.add("h2_jet_pt_2prong_Sxy", "", {HistType::kTH2F, {{jetPtAxis}, {SxyAxis}}}); registry.add("h2_jet_pt_2prong_Lxyz", "", {HistType::kTH2F, {{jetPtAxis}, {LxyzAxis}}}); + registry.add("h2_jet_pt_2prong_sigmaLxyz", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyzAxis}}}); registry.add("h2_jet_pt_2prong_Sxyz", "", {HistType::kTH2F, {{jetPtAxis}, {SxyzAxis}}}); registry.add("h2_jet_pt_2prong_Sxy_N1", "", {HistType::kTH2F, {{jetPtAxis}, {SxyAxis}}}); registry.add("h2_jet_pt_2prong_Sxyz_N1", "", {HistType::kTH2F, {{jetPtAxis}, {SxyzAxis}}}); - registry.add("h2_2prong_Sxy_sigmaLxy", "", {HistType::kTH2F, {{SxyAxis}, {sigmaLxyAxis}}}); - registry.add("h2_2prong_Sxyz_sigmaLxyz", "", {HistType::kTH2F, {{SxyzAxis}, {sigmaLxyzAxis}}}); - registry.add("h2_jet_pt_2prong_sigmaLxy", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyAxis}}}); - registry.add("h2_jet_pt_2prong_sigmaLxyz", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyzAxis}}}); + registry.add("h2_jet_pt_2prong_mass_N1", "", {HistType::kTH2F, {{jetPtAxis}, {massAxis}}}); } if (doprocessSV3ProngData) { registry.add("h_3prong_nprongs", "", {HistType::kTH1F, {{nprongsAxis}}}); registry.add("h2_jet_pt_3prong_Lxy", "", {HistType::kTH2F, {{jetPtAxis}, {LxyAxis}}}); + registry.add("h2_jet_pt_3prong_sigmaLxy", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyAxis}}}); registry.add("h2_jet_pt_3prong_Sxy", "", {HistType::kTH2F, {{jetPtAxis}, {SxyAxis}}}); registry.add("h2_jet_pt_3prong_Lxyz", "", {HistType::kTH2F, {{jetPtAxis}, {LxyzAxis}}}); + registry.add("h2_jet_pt_3prong_sigmaLxyz", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyzAxis}}}); registry.add("h2_jet_pt_3prong_Sxyz", "", {HistType::kTH2F, {{jetPtAxis}, {SxyzAxis}}}); registry.add("h2_jet_pt_3prong_Sxy_N1", "", {HistType::kTH2F, {{jetPtAxis}, {SxyAxis}}}); registry.add("h2_jet_pt_3prong_Sxyz_N1", "", {HistType::kTH2F, {{jetPtAxis}, {SxyzAxis}}}); - registry.add("h2_3prong_Sxy_sigmaLxy", "", {HistType::kTH2F, {{SxyAxis}, {sigmaLxyAxis}}}); - registry.add("h2_3prong_Sxyz_sigmaLxyz", "", {HistType::kTH2F, {{SxyzAxis}, {sigmaLxyzAxis}}}); - registry.add("h2_jet_pt_3prong_sigmaLxy", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyAxis}}}); - registry.add("h2_jet_pt_3prong_sigmaLxyz", "", {HistType::kTH2F, {{jetPtAxis}, {sigmaLxyzAxis}}}); + registry.add("h2_jet_pt_3prong_mass_N1", "", {HistType::kTH2F, {{jetPtAxis}, {massAxis}}}); } - if (doprocessSV2ProngMCD) { + if (doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted) { registry.add("h2_2prong_nprongs_flavour", "", {HistType::kTH2F, {{nprongsAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_2prong_Lxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {LxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_sigmaLxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_2prong_Sxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_2prong_Lxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {LxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_sigmaLxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_2prong_Sxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_2prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_2prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); - registry.add("h3_2prong_Sxy_sigmaLxy_flavour", "", {HistType::kTH3F, {{SxyAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); - registry.add("h3_2prong_Sxyz_sigmaLxyz_flavour", "", {HistType::kTH3F, {{SxyzAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); - registry.add("h3_jet_pt_2prong_sigmaLxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); - registry.add("h3_jet_pt_2prong_sigmaLxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_mass_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_2prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_2prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_2prong_mass_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); } - if (doprocessSV3ProngMCD) { + if (doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted) { registry.add("h2_3prong_nprongs_flavour", "", {HistType::kTH2F, {{nprongsAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_3prong_Lxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {LxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_sigmaLxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_3prong_Sxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_3prong_Lxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {LxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_sigmaLxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_3prong_Sxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_3prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_3prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); - registry.add("h3_3prong_Sxy_sigmaLxy_flavour", "", {HistType::kTH3F, {{SxyAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); - registry.add("h3_3prong_Sxyz_sigmaLxyz_flavour", "", {HistType::kTH3F, {{SxyzAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); - registry.add("h3_jet_pt_3prong_sigmaLxy_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); - registry.add("h3_jet_pt_3prong_sigmaLxyz_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_mass_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_3prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_3prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_3prong_mass_N1_flavour", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); + } + if (doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted) { + registry.add("h3_jet_pt_2prong_Lxy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {LxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_sigmaLxy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_Sxy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_Lxyz_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {LxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_sigmaLxyz_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_Sxyz_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_Sxy_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_Sxyz_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_2prong_mass_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); + } + if (doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted) { + registry.add("h3_jet_pt_3prong_Lxy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {LxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_sigmaLxy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_Sxy_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_Lxyz_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {LxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_sigmaLxyz_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {sigmaLxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_Sxyz_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_Sxy_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_Sxyz_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_3prong_mass_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_3prong_Sxy_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_3prong_Sxyz_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {SxyzAxis}, {jetFlavourAxis}}}); + registry.add("h3_taggedjet_pt_3prong_mass_N1_flavour_run2", "", {HistType::kTH3F, {{jetPtAxis}, {massAxis}, {jetFlavourAxis}}}); } } // Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); + PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; + Preslice particlesPerCollision = aod::jmcparticle::mcCollisionId; - using JetTagTracksData = soa::Join; - using JetTagTracksMCD = soa::Join; - using OriTracksData = soa::Join; - using OriTracksMCD = soa::Join; + using JetTagTracksData = soa::Join; + using JetTagTracksMCD = soa::Join; std::function&, const std::vector&)> sortImp = [](const std::vector& a, const std::vector& b) { return a[0] > b[0]; }; + template + bool isAcceptedJet(U const& jet) + { + if (jetAreaFractionMin > -98.0) { + if (jet.area() < jetAreaFractionMin * M_PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + return false; + } + } + if (leadingConstituentPtMin > -98.0) { + bool isMinleadingConstituent = false; + for (auto& constituent : jet.template tracks_as()) { + if (constituent.pt() >= leadingConstituentPtMin) { + isMinleadingConstituent = true; + break; + } + } + if (!isMinleadingConstituent) { + return false; + } + } + return true; + } + template bool trackAcceptance(T const& track) { if (track.pt() < trackPtMin || track.pt() > trackPtMax) - return 0; + return false; - return 1; + return true; } - template - bool prongAcceptance(T const& prong, U const& maxDecayLengthSigma, V const& minDecayLengthSig) + template + void fillHistogramIPsData(T const& jet, U const& /*jtracks*/) { - auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - if (prong.errorDecayLengthXY() < maxDecayLengthSigma || Sxy > minDecayLengthSig) - return 0; + float eventWeight = 1.0; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (jet.pt() > pTHatMaxMCD * pTHat) { + return; + } + std::vector> vecSignImpXYSig, vecSignImpZSig, vecSignImpXYZSig; + for (auto& track : jet.template tracks_as()) { + if (!trackAcceptance(track)) + continue; + if (!jettaggingutilities::trackAcceptanceWithDca(track, trackDcaXYMax, trackDcaZMax)) + continue; + // General parameters + registry.fill(HIST("h3_jet_pt_track_pt_track_eta"), jet.pt(), track.pt(), track.eta()); + registry.fill(HIST("h3_jet_pt_track_pt_track_phi"), jet.pt(), track.pt(), track.phi()); + int geoSign = jettaggingutilities::getGeoSign(jet, track); + if (fillIPxy) { + float varImpXY, varSignImpXY, varImpXYSig, varSignImpXYSig; + varImpXY = track.dcaXY() * jettaggingutilities::cmTomum; + varSignImpXY = geoSign * std::abs(track.dcaXY()) * jettaggingutilities::cmTomum; + varImpXYSig = track.dcaXY() / track.sigmadcaXY(); + varSignImpXYSig = geoSign * std::abs(track.dcaXY()) / track.sigmadcaXY(); + registry.fill(HIST("h2_jet_pt_impact_parameter_xy"), jet.pt(), varImpXY); + registry.fill(HIST("h2_jet_pt_sign_impact_parameter_xy"), jet.pt(), varSignImpXY); + registry.fill(HIST("h2_jet_pt_impact_parameter_xy_significance"), jet.pt(), varImpXYSig); + registry.fill(HIST("h3_jet_pt_track_pt_sign_impact_parameter_xy_significance"), jet.pt(), track.pt(), varSignImpXYSig); + vecSignImpXYSig.push_back({varSignImpXYSig, track.pt()}); + } + if (fillIPz) { + float varImpZ, varSignImpZ, varImpZSig, varSignImpZSig; + varImpZ = track.dcaZ() * jettaggingutilities::cmTomum; + varSignImpZ = geoSign * std::abs(track.dcaZ()) * jettaggingutilities::cmTomum; + varImpZSig = track.dcaZ() / track.sigmadcaZ(); + varSignImpZSig = geoSign * std::abs(track.dcaZ()) / track.sigmadcaZ(); + registry.fill(HIST("h2_jet_pt_impact_parameter_z"), jet.pt(), varImpZ); + registry.fill(HIST("h2_jet_pt_sign_impact_parameter_z"), jet.pt(), varSignImpZ); + registry.fill(HIST("h2_jet_pt_impact_parameter_z_significance"), jet.pt(), varImpZSig); + registry.fill(HIST("h3_jet_pt_track_pt_sign_impact_parameter_z_significance"), jet.pt(), track.pt(), varSignImpZSig); + vecSignImpZSig.push_back({varSignImpZSig, track.pt()}); + } + if (fillIPxyz) { + float varImpXYZ, varSignImpXYZ, varImpXYZSig, varSignImpXYZSig; + varImpXYZ = track.dcaXYZ() * jettaggingutilities::cmTomum; + varSignImpXYZ = geoSign * std::abs(track.dcaXYZ()) * jettaggingutilities::cmTomum; + varImpXYZSig = track.dcaXYZ() / track.sigmadcaXYZ(); + varSignImpXYZSig = geoSign * std::abs(track.dcaXYZ()) / track.sigmadcaXYZ(); + registry.fill(HIST("h2_jet_pt_impact_parameter_xyz"), jet.pt(), varImpXYZ); + registry.fill(HIST("h2_jet_pt_sign_impact_parameter_xyz"), jet.pt(), varSignImpXYZ); + registry.fill(HIST("h2_jet_pt_impact_parameter_xyz_significance"), jet.pt(), varImpXYZSig); + registry.fill(HIST("h3_jet_pt_track_pt_sign_impact_parameter_xyz_significance"), jet.pt(), track.pt(), varSignImpXYZSig); + vecSignImpXYZSig.push_back({varSignImpXYZSig, track.pt()}); + } + } - return 1; + if (!fillTrackCounting) + return; + if (fillIPxy) + std::sort(vecSignImpXYSig.begin(), vecSignImpXYSig.end(), sortImp); + if (fillIPz) + std::sort(vecSignImpZSig.begin(), vecSignImpZSig.end(), sortImp); + if (fillIPxyz) + std::sort(vecSignImpXYZSig.begin(), vecSignImpXYZSig.end(), sortImp); + if (fillIPxy && vecSignImpXYSig.empty()) + return; + if (fillIPz && vecSignImpZSig.empty()) + return; + if (fillIPxyz && vecSignImpXYZSig.empty()) + return; + for (int order = 1; order <= numOrder; order++) { + if (fillIPxy && static_cast>::size_type>(order) < vecSignImpXYSig.size()) { + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_tc"), jet.pt(), vecSignImpXYSig[order - 1][0], order); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_significance_tc"), vecSignImpXYSig[order - 1][1], vecSignImpXYSig[order - 1][0], order); + } + if (fillIPz && static_cast>::size_type>(order) < vecSignImpZSig.size()) { + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_tc"), jet.pt(), vecSignImpZSig[order - 1][0], order); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_z_significance_tc"), vecSignImpZSig[order - 1][1], vecSignImpZSig[order - 1][0], order); + } + if (fillIPxyz && static_cast>::size_type>(order) < vecSignImpXYZSig.size()) { + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_tc"), jet.pt(), vecSignImpXYZSig[order - 1][0], order); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xyz_significance_tc"), vecSignImpXYZSig[order - 1][1], vecSignImpXYZSig[order - 1][0], order); + } + } } - template - double getMaxSxyForJet(const JetType& mcdjet) + template + void fillHistogramIPsMCD(T const& mcdjet, U const& /*jtracks*/, float eventWeight = 1.0) { - double maxSxy = 0; - for (const auto& prong : mcdjet.template secondaryVertices_as()) { - int Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - if (maxSxy < Sxy) { - maxSxy = Sxy; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + std::vector vecImpXY[numberOfJetFlavourSpecies], vecSignImpXY[numberOfJetFlavourSpecies], vecImpXYSig[numberOfJetFlavourSpecies], vecSignImpXYSig[numberOfJetFlavourSpecies]; + std::vector vecImpZ[numberOfJetFlavourSpecies], vecSignImpZ[numberOfJetFlavourSpecies], vecImpZSig[numberOfJetFlavourSpecies], vecSignImpZSig[numberOfJetFlavourSpecies]; + std::vector vecImpXYZ[numberOfJetFlavourSpecies], vecSignImpXYZ[numberOfJetFlavourSpecies], vecImpXYZSig[numberOfJetFlavourSpecies], vecSignImpXYZSig[numberOfJetFlavourSpecies]; + std::vector> vecSignImpXYSigTC, vecSignImpZSigTC, vecSignImpXYZSigTC; + int jetflavour = mcdjet.origin(); + if (jetflavour == JetTaggingSpecies::none) { + LOGF(debug, "NOT DEFINE JET FLAVOR"); + } + registry.fill(HIST("h2_jet_pt_flavour"), mcdjet.pt(), jetflavour, eventWeight); + registry.fill(HIST("h2_jet_eta_flavour"), mcdjet.eta(), jetflavour, eventWeight); + registry.fill(HIST("h2_jet_phi_flavour"), mcdjet.phi(), jetflavour, eventWeight); + for (auto& track : mcdjet.template tracks_as()) { + if (!trackAcceptance(track)) + continue; + if (!jettaggingutilities::trackAcceptanceWithDca(track, trackDcaXYMax, trackDcaZMax)) + continue; + + // General parameters + registry.fill(HIST("h3_jet_pt_track_pt_flavour"), mcdjet.pt(), track.pt(), jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_track_eta_flavour"), mcdjet.pt(), track.eta(), jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_track_phi_flavour"), mcdjet.pt(), track.phi(), jetflavour, eventWeight); + int geoSign = jettaggingutilities::getGeoSign(mcdjet, track); + if (fillIPxy) { + float varImpXY, varSignImpXY, varImpXYSig, varSignImpXYSig; + varImpXY = track.dcaXY() * jettaggingutilities::cmTomum; + float varSigmaImpXY = track.dcaXY() * jettaggingutilities::cmTomum; + varSignImpXY = geoSign * std::abs(track.dcaXY()) * jettaggingutilities::cmTomum; + varImpXYSig = track.dcaXY() / track.sigmadcaXY(); + varSignImpXYSig = geoSign * std::abs(track.dcaXY()) / track.sigmadcaXY(); + registry.fill(HIST("h3_jet_pt_impact_parameter_xy_flavour"), mcdjet.pt(), varImpXY, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sigma_impact_parameter_xy_flavour"), mcdjet.pt(), varSigmaImpXY, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_flavour"), mcdjet.pt(), varSignImpXY, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_impact_parameter_xy_significance_flavour"), mcdjet.pt(), varImpXYSig, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour"), mcdjet.pt(), varSignImpXYSig, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_xy_flavour"), track.pt(), varImpXY, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_flavour"), track.pt(), varSignImpXY, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_xy_significance_flavour"), track.pt(), varImpXYSig, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_significance_flavour"), track.pt(), varSignImpXYSig, jetflavour, eventWeight); + vecImpXY[jetflavour].push_back(varImpXY); + vecSignImpXY[jetflavour].push_back(varSignImpXY); + vecImpXYSig[jetflavour].push_back(varImpXYSig); + vecSignImpXYSig[jetflavour].push_back(varSignImpXYSig); + vecSignImpXYSigTC.push_back({varSignImpXYSig, track.pt()}); + } + if (fillIPz) { + float varImpZ, varSignImpZ, varImpZSig, varSignImpZSig; + varImpZ = track.dcaZ() * jettaggingutilities::cmTomum; + varSignImpZ = geoSign * std::abs(track.dcaZ()) * jettaggingutilities::cmTomum; + varImpZSig = track.dcaZ() / track.sigmadcaZ(); + varSignImpZSig = geoSign * std::abs(track.dcaZ()) / track.sigmadcaZ(); + registry.fill(HIST("h3_jet_pt_impact_parameter_z_flavour"), mcdjet.pt(), varImpZ, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_flavour"), mcdjet.pt(), varSignImpZ, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_impact_parameter_z_significance_flavour"), mcdjet.pt(), varImpZSig, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour"), mcdjet.pt(), varSignImpZSig, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_z_flavour"), track.pt(), varImpZ, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_z_flavour"), track.pt(), varSignImpZ, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_z_significance_flavour"), track.pt(), varImpZSig, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_z_significance_flavour"), track.pt(), varSignImpZSig, jetflavour, eventWeight); + vecImpZ[jetflavour].push_back(varImpZ); + vecSignImpZ[jetflavour].push_back(varSignImpZ); + vecImpZSig[jetflavour].push_back(varImpZSig); + vecSignImpZSig[jetflavour].push_back(varSignImpZSig); + vecSignImpZSigTC.push_back({varSignImpZSig, track.pt()}); + } + if (fillIPxyz) { + float varImpXYZ, varSignImpXYZ, varImpXYZSig, varSignImpXYZSig; + float dcaXYZ = track.dcaXYZ(); + float sigmadcaXYZ2 = track.sigmadcaXYZ(); + varImpXYZ = dcaXYZ * jettaggingutilities::cmTomum; + varSignImpXYZ = geoSign * std::abs(dcaXYZ) * jettaggingutilities::cmTomum; + varImpXYZSig = dcaXYZ / std::sqrt(sigmadcaXYZ2); + varSignImpXYZSig = geoSign * std::abs(dcaXYZ) / std::sqrt(sigmadcaXYZ2); + registry.fill(HIST("h3_jet_pt_impact_parameter_xyz_flavour"), mcdjet.pt(), varImpXYZ, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_flavour"), mcdjet.pt(), varSignImpXYZ, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_impact_parameter_xyz_significance_flavour"), mcdjet.pt(), varImpXYZSig, jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour"), mcdjet.pt(), varSignImpXYZSig, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_xyz_flavour"), track.pt(), varImpXYZ, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xyz_flavour"), track.pt(), varSignImpXYZ, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_xyz_significance_flavour"), track.pt(), varImpXYZSig, jetflavour, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xyz_significance_flavour"), track.pt(), varSignImpXYZSig, jetflavour, eventWeight); + vecImpXYZ[jetflavour].push_back(varImpXYZ); + vecSignImpXYZ[jetflavour].push_back(varSignImpXYZ); + vecImpXYZSig[jetflavour].push_back(varImpXYZSig); + vecSignImpXYZSig[jetflavour].push_back(varSignImpXYZSig); + vecSignImpXYZSigTC.push_back({varSignImpXYZSig, track.pt()}); + } + } + + if (!fillTrackCounting) + return; + sort(vecImpXY[jetflavour].begin(), vecImpXY[jetflavour].end(), std::greater()); + sort(vecSignImpXY[jetflavour].begin(), vecSignImpXY[jetflavour].end(), std::greater()); + sort(vecImpXYSig[jetflavour].begin(), vecImpXYSig[jetflavour].end(), std::greater()); + sort(vecSignImpXYSig[jetflavour].begin(), vecSignImpXYSig[jetflavour].end(), std::greater()); + sort(vecImpZ[jetflavour].begin(), vecImpZ[jetflavour].end(), std::greater()); + sort(vecSignImpZ[jetflavour].begin(), vecSignImpZ[jetflavour].end(), std::greater()); + sort(vecImpZSig[jetflavour].begin(), vecImpZSig[jetflavour].end(), std::greater()); + sort(vecSignImpZSig[jetflavour].begin(), vecSignImpZSig[jetflavour].end(), std::greater()); + sort(vecImpXYZ[jetflavour].begin(), vecImpXYZ[jetflavour].end(), std::greater()); + sort(vecSignImpXYZ[jetflavour].begin(), vecSignImpXYZ[jetflavour].end(), std::greater()); + sort(vecImpXYZSig[jetflavour].begin(), vecImpXYZSig[jetflavour].end(), std::greater()); + sort(vecSignImpXYZSig[jetflavour].begin(), vecSignImpXYZSig[jetflavour].end(), std::greater()); + + if (vecImpXY[jetflavour].size() > 0) { // N1 + if (fillIPxy) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_N1"), mcdjet.pt(), vecSignImpXYSig[jetflavour][0], jetflavour, eventWeight); + if (fillIPz) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour_N1"), mcdjet.pt(), vecSignImpZSig[jetflavour][0], jetflavour, eventWeight); + if (fillIPxyz) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour_N1"), mcdjet.pt(), vecSignImpXYZSig[jetflavour][0], jetflavour, eventWeight); + } + if (vecImpXY[jetflavour].size() > 1) { // N2 + if (fillIPxy) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_N2"), mcdjet.pt(), vecSignImpXYSig[jetflavour][1], jetflavour, eventWeight); + if (fillIPz) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour_N2"), mcdjet.pt(), vecSignImpZSig[jetflavour][1], jetflavour, eventWeight); + if (fillIPxyz) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour_N2"), mcdjet.pt(), vecSignImpXYZSig[jetflavour][1], jetflavour, eventWeight); + } + if (vecImpXY[jetflavour].size() > 2) { // N3 + if (fillIPxy) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_N3"), mcdjet.pt(), vecSignImpXYSig[jetflavour][2], jetflavour, eventWeight); + if (fillIPz) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour_N3"), mcdjet.pt(), vecSignImpZSig[jetflavour][2], jetflavour, eventWeight); + if (fillIPxyz) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour_N3"), mcdjet.pt(), vecSignImpXYZSig[jetflavour][2], jetflavour, eventWeight); + } + + std::sort(vecSignImpXYSigTC.begin(), vecSignImpXYSigTC.end(), sortImp); + std::sort(vecSignImpZSigTC.begin(), vecSignImpZSigTC.end(), sortImp); + std::sort(vecSignImpXYZSigTC.begin(), vecSignImpXYZSigTC.end(), sortImp); + + if (vecSignImpXYSigTC.empty()) + return; + for (int order = 1; order <= numOrder; order++) { + if (fillIPxy && static_cast>::size_type>(order) < vecSignImpXYSigTC.size()) { + registry.fill(HIST("h3_sign_impact_parameter_xy_significance_tc_flavour"), vecSignImpXYSigTC[order - 1][0], order, jetflavour, eventWeight); + } + } + if (vecSignImpZSigTC.empty()) + return; + for (int order = 1; order <= numOrder; order++) { + if (fillIPxy && static_cast>::size_type>(order) < vecSignImpZSigTC.size()) { + registry.fill(HIST("h3_sign_impact_parameter_z_significance_tc_flavour"), vecSignImpZSigTC[order - 1][0], order, jetflavour, eventWeight); + } + } + + if (vecSignImpXYZSigTC.empty()) + return; + for (int order = 1; order <= numOrder; order++) { + if (fillIPxy && static_cast>::size_type>(order) < vecSignImpXYZSigTC.size()) { + registry.fill(HIST("h3_sign_impact_parameter_xyz_significance_tc_flavour"), vecSignImpXYZSigTC[order - 1][0], order, jetflavour, eventWeight); } } - return maxSxy; } - template - double getMaxSxyzForJet(const JetType& mcdjet) + template + void fillHistogramIPsMCP(T const& mcpjet, float eventWeight = 1.0) { - double maxSxyz = 0; - for (const auto& prong : mcdjet.template secondaryVertices_as()) { - int Sxyz = prong.decayLength() / prong.errorDecayLength(); - if (maxSxyz < Sxyz) { - maxSxyz = Sxyz; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcpjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + int jetflavour = mcpjet.origin(); + if (jetflavour == JetTaggingSpecies::none) { + LOGF(debug, "NOT DEFINE JET FLAVOR"); + } + registry.fill(HIST("h2_jet_pt_part_flavour"), mcpjet.pt(), jetflavour, eventWeight); + registry.fill(HIST("h2_jet_eta_part_flavour"), mcpjet.eta(), jetflavour, eventWeight); + registry.fill(HIST("h2_jet_phi_part_flavour"), mcpjet.phi(), jetflavour, eventWeight); + } + + template + void fillHistogramIPsMatched(T const& mcdjet, U const&, V const&, W const& particlesPerColl, float eventWeight = 1.0) + { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + std::vector vecImpXY[numberOfJetFlavourSpecies], vecSignImpXY[numberOfJetFlavourSpecies], vecImpXYSig[numberOfJetFlavourSpecies], vecSignImpXYSig[numberOfJetFlavourSpecies]; + int jetflavour = mcdjet.origin(); + if (jetflavour == JetTaggingSpecies::none) + jetflavour = JetTaggingSpecies::lightflavour; + int jetflavourRun2Def = -1; + // if (!mcdjet.has_matchedJetGeo()) continue; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + jetflavourRun2Def = jettaggingutilities::getJetFlavor(mcpjet, particlesPerColl); + registry.fill(HIST("h3_jet_pt_jet_pt_part_matchedgeo_flavour"), mcpjet.pt(), mcdjet.pt(), jetflavour, eventWeight); + registry.fill(HIST("h3_jet_pt_jet_pt_part_matchedgeo_flavour_run2"), mcpjet.pt(), mcdjet.pt(), jetflavourRun2Def, eventWeight); + } + if (jetflavourRun2Def < 0) + return; + if (jetflavour == jetflavourRun2Def) + registry.fill(HIST("h_compare_flavour_flavour_run2"), 0.5); + else + registry.fill(HIST("h_compare_flavour_flavour_run2"), 1.5); + registry.fill(HIST("h3_jet_pt_flavour_flavour_run2"), mcdjet.pt(), jetflavour, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_eta_flavour_flavour_run2"), mcdjet.eta(), jetflavour, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_phi_flavour_flavour_run2"), mcdjet.phi(), jetflavour, jetflavourRun2Def, eventWeight); + for (auto& track : mcdjet.template tracks_as()) { + int geoSign = jettaggingutilities::getGeoSign(mcdjet, track); + if (fillIPxy) { + float varImpXY, varSignImpXY, varImpXYSig, varSignImpXYSig; + varImpXY = track.dcaXY() * jettaggingutilities::cmTomum; + float varSigmaImpXY = track.dcaXY() * jettaggingutilities::cmTomum; + varSignImpXY = geoSign * std::abs(track.dcaXY()) * jettaggingutilities::cmTomum; + varImpXYSig = track.dcaXY() / track.sigmadcaXY(); + varSignImpXYSig = geoSign * std::abs(track.dcaXY()) / track.sigmadcaXY(); + registry.fill(HIST("h3_jet_pt_impact_parameter_xy_flavour_run2"), mcdjet.pt(), varImpXY, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_sigma_impact_parameter_xy_flavour_run2"), mcdjet.pt(), varSigmaImpXY, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_flavour_run2"), mcdjet.pt(), varSignImpXY, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_impact_parameter_xy_significance_flavour_run2"), mcdjet.pt(), varImpXYSig, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2"), mcdjet.pt(), varSignImpXYSig, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_xy_flavour_run2"), track.pt(), varImpXY, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_flavour_run2"), track.pt(), varSignImpXY, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_track_pt_impact_parameter_xy_significance_flavour_run2"), track.pt(), varImpXYSig, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_significance_flavour_run2"), track.pt(), varSignImpXYSig, jetflavourRun2Def, eventWeight); + vecImpXY[jetflavour].push_back(varImpXY); + vecSignImpXY[jetflavour].push_back(varSignImpXY); + vecImpXYSig[jetflavour].push_back(varImpXYSig); + vecSignImpXYSig[jetflavour].push_back(varSignImpXYSig); } } - return maxSxyz; + if (!fillTrackCounting) + return; + sort(vecImpXY[jetflavour].begin(), vecImpXY[jetflavour].end(), std::greater()); + sort(vecSignImpXY[jetflavour].begin(), vecSignImpXY[jetflavour].end(), std::greater()); + sort(vecImpXYSig[jetflavour].begin(), vecImpXYSig[jetflavour].end(), std::greater()); + sort(vecSignImpXYSig[jetflavour].begin(), vecSignImpXYSig[jetflavour].end(), std::greater()); + if (vecImpXY[jetflavour].size() > 0) { // N1 + if (fillIPxy) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2_N1"), mcdjet.pt(), vecSignImpXYSig[jetflavour][0], jetflavourRun2Def, eventWeight); + } + if (vecImpXY[jetflavour].size() > 1) { // N2 + if (fillIPxy) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2_N2"), mcdjet.pt(), vecSignImpXYSig[jetflavour][1], jetflavourRun2Def, eventWeight); + } + if (vecImpXY[jetflavour].size() > 2) { // N3 + if (fillIPxy) + registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_run2_N3"), mcdjet.pt(), vecSignImpXYSig[jetflavour][2], jetflavourRun2Def, eventWeight); + } + } + + template + void fillHistogramJPData(T const& jet) + { + float eventWeight = 1.0; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (jet.pt() > pTHatMaxMCD * pTHat) { + return; + } + registry.fill(HIST("h2_jet_pt_JP"), jet.pt(), jet.jetProb()[0]); + registry.fill(HIST("h2_jet_pt_neg_log_JP"), jet.pt(), -1 * std::log(jet.jetProb()[0])); + registry.fill(HIST("h2_jet_pt_JP_N1"), jet.pt(), jet.jetProb()[1]); + registry.fill(HIST("h2_jet_pt_neg_log_JP_N1"), jet.pt(), -1 * TMath::Log(jet.jetProb()[1])); + registry.fill(HIST("h2_jet_pt_JP_N2"), jet.pt(), jet.jetProb()[2]); + registry.fill(HIST("h2_jet_pt_neg_log_JP_N2"), jet.pt(), -1 * TMath::Log(jet.jetProb()[2])); + registry.fill(HIST("h2_jet_pt_JP_N3"), jet.pt(), jet.jetProb()[3]); + registry.fill(HIST("h2_jet_pt_neg_log_JP_N3"), jet.pt(), -1 * TMath::Log(jet.jetProb()[3])); + } + + template + void fillHistogramJPMCD(T const& mcdjet, float eventWeight = 1.0) + { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + registry.fill(HIST("h3_jet_pt_JP_flavour"), mcdjet.pt(), mcdjet.jetProb()[0], mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[0]), mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_JP_N1_flavour"), mcdjet.pt(), mcdjet.jetProb()[1], mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_N1_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[1]), mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_JP_N2_flavour"), mcdjet.pt(), mcdjet.jetProb()[2], mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_N2_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[2]), mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_JP_N3_flavour"), mcdjet.pt(), mcdjet.jetProb()[3], mcdjet.origin(), eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_N3_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[3]), mcdjet.origin(), eventWeight); + } + + template + void fillHistogramSV2ProngData(T const& jet, U const& /*prongs*/) + { + float eventWeight = 1.0; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (jet.pt() > pTHatMaxMCD * pTHat) { + return; + } + registry.fill(HIST("h_2prong_nprongs"), jet.template secondaryVertices_as().size()); + for (const auto& prong : jet.template secondaryVertices_as()) { + auto Lxy = prong.decayLengthXY(); + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + auto Lxyz = prong.decayLength(); + auto Sxyz = prong.decayLength() / prong.errorDecayLength(); + registry.fill(HIST("h2_jet_pt_2prong_Lxy"), jet.pt(), Lxy); + registry.fill(HIST("h2_jet_pt_2prong_Sxy"), jet.pt(), Sxy); + registry.fill(HIST("h2_jet_pt_2prong_Lxyz"), jet.pt(), Lxyz); + registry.fill(HIST("h2_jet_pt_2prong_Sxyz"), jet.pt(), Sxyz); + registry.fill(HIST("h2_jet_pt_2prong_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); + registry.fill(HIST("h2_jet_pt_2prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); + } + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); + if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, false)) { + return; + } + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); + auto maxSxyz = bjetCandForXYZ.decayLength() / bjetCandForXYZ.errorDecayLength(); + registry.fill(HIST("h2_jet_pt_2prong_Sxy_N1"), jet.pt(), maxSxy); + registry.fill(HIST("h2_jet_pt_2prong_Sxyz_N1"), jet.pt(), maxSxyz); + } + + template + void fillHistogramSV3ProngData(T const& jet, U const& /*prongs*/) + { + float eventWeight = 1.0; + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (jet.pt() > pTHatMaxMCD * pTHat) { + return; + } + registry.fill(HIST("h_3prong_nprongs"), jet.template secondaryVertices_as().size()); + for (const auto& prong : jet.template secondaryVertices_as()) { + auto Lxy = prong.decayLengthXY(); + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + auto Lxyz = prong.decayLength(); + auto Sxyz = prong.decayLength() / prong.errorDecayLength(); + registry.fill(HIST("h2_jet_pt_3prong_Lxy"), jet.pt(), Lxy); + registry.fill(HIST("h2_jet_pt_3prong_Sxy"), jet.pt(), Sxy); + registry.fill(HIST("h2_jet_pt_3prong_Lxyz"), jet.pt(), Lxyz); + registry.fill(HIST("h2_jet_pt_3prong_Sxyz"), jet.pt(), Sxyz); + registry.fill(HIST("h2_jet_pt_3prong_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); + registry.fill(HIST("h2_jet_pt_3prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); + } + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); + if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, false)) { + return; + } + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); + auto maxSxyz = bjetCandForXYZ.decayLength() / bjetCandForXYZ.errorDecayLength(); + registry.fill(HIST("h2_jet_pt_3prong_Sxy_N1"), jet.pt(), maxSxy); + registry.fill(HIST("h2_jet_pt_3prong_Sxyz_N1"), jet.pt(), maxSxyz); + } + + template + void fillHistogramSV2ProngMCD(T const& mcdjet, U const& /*prongs*/, float eventWeight = 1.0) + { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + auto origin = mcdjet.origin(); + registry.fill(HIST("h2_2prong_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin, eventWeight); + if (mcdjet.template secondaryVertices_as().size() < 1) + return; + for (const auto& prong : mcdjet.template secondaryVertices_as()) { + auto Lxy = prong.decayLengthXY(); + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + auto Lxyz = prong.decayLength(); + auto Sxyz = prong.decayLength() / prong.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_2prong_Lxy_flavour"), mcdjet.pt(), Lxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Sxy_flavour"), mcdjet.pt(), Sxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Lxyz_flavour"), mcdjet.pt(), Lxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Sxyz_flavour"), mcdjet.pt(), Sxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); + } + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); + if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, false)) { + return; + } + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); + auto maxSxyz = bjetCandForXYZ.decayLength() / bjetCandForXYZ.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_2prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + if (!mcdjet.flagtaggedjetSV()) + return; + registry.fill(HIST("h3_taggedjet_pt_2prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_2prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_2prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); } template - void fillHistogramIPsData(T const& collision, U const& jets, V const& /*jtracks*/, W const& /*tracks*/) + void fillHistogramSV2ProngMCPMCDMatched(T const& mcdjet, U const& /*mcpjets*/, V const& /*prongs*/, W const& particlesPerColl, float eventWeight = 1.0) { - for (auto& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + int jetflavourRun2Def = -1; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + jetflavourRun2Def = jettaggingutilities::getJetFlavor(mcpjet, particlesPerColl); + } + if (jetflavourRun2Def < 0) + return; + if (mcdjet.template secondaryVertices_as().size() < 1) + return; + for (const auto& prong : mcdjet.template secondaryVertices_as()) { + auto Lxy = prong.decayLengthXY(); + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + auto Lxyz = prong.decayLength(); + auto Sxyz = prong.decayLength() / prong.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_2prong_Lxy_flavour_run2"), mcdjet.pt(), Lxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Sxy_flavour_run2"), mcdjet.pt(), Sxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Lxyz_flavour_run2"), mcdjet.pt(), Lxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Sxyz_flavour_run2"), mcdjet.pt(), Sxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_sigmaLxy_flavour_run2"), mcdjet.pt(), prong.errorDecayLengthXY(), jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_sigmaLxyz_flavour_run2"), mcdjet.pt(), prong.errorDecayLength(), jetflavourRun2Def, eventWeight); + } + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); + if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, false)) { + return; + } + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); + auto maxSxyz = bjetCandForXYZ.decayLength() / bjetCandForXYZ.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_2prong_Sxy_N1_flavour_run2"), mcdjet.pt(), maxSxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_Sxyz_N1_flavour_run2"), mcdjet.pt(), maxSxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_2prong_mass_N1_flavour_run2"), mcdjet.pt(), massSV, jetflavourRun2Def, eventWeight); + } + + template + void fillHistogramSV3ProngMCD(T const& mcdjet, U const& /*prongs*/, float eventWeight = 1.0) + { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + auto origin = mcdjet.origin(); + registry.fill(HIST("h2_3prong_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin); + if (mcdjet.template secondaryVertices_as().size() < 1) + return; + for (const auto& prong : mcdjet.template secondaryVertices_as()) { + auto Lxy = prong.decayLengthXY(); + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + auto Lxyz = prong.decayLength(); + auto Sxyz = prong.decayLength() / prong.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_3prong_Lxy_flavour"), mcdjet.pt(), Lxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Sxy_flavour"), mcdjet.pt(), Sxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Lxyz_flavour"), mcdjet.pt(), Lxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Sxyz_flavour"), mcdjet.pt(), Sxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); + } + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); + if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, false)) { + return; + } + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); + auto maxSxyz = bjetCandForXYZ.decayLength() / bjetCandForXYZ.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_3prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + if (!mcdjet.flagtaggedjetSV()) + return; + registry.fill(HIST("h3_taggedjet_pt_3prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_3prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_3prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + } + + template + void fillHistogramSV3ProngMCPMCDMatched(T const& mcdjet, U const& /*mcpjets*/, V const& /*prongs*/, W const& particlesPerColl, float eventWeight = 1.0) + { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + int jetflavourRun2Def = -1; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + jetflavourRun2Def = jettaggingutilities::getJetFlavor(mcpjet, particlesPerColl); + } + if (jetflavourRun2Def < 0) + return; + if (mcdjet.template secondaryVertices_as().size() < 1) + return; + for (const auto& prong : mcdjet.template secondaryVertices_as()) { + auto Lxy = prong.decayLengthXY(); + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); + auto Lxyz = prong.decayLength(); + auto Sxyz = prong.decayLength() / prong.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_3prong_Lxy_flavour_run2"), mcdjet.pt(), Lxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Sxy_flavour_run2"), mcdjet.pt(), Sxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Lxyz_flavour_run2"), mcdjet.pt(), Lxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Sxyz_flavour_run2"), mcdjet.pt(), Sxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_sigmaLxy_flavour_run2"), mcdjet.pt(), prong.errorDecayLengthXY(), jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_sigmaLxyz_flavour_run2"), mcdjet.pt(), prong.errorDecayLength(), jetflavourRun2Def, eventWeight); + } + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); + if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, false)) { + return; + } + + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); + auto maxSxyz = bjetCandForXYZ.decayLength() / bjetCandForXYZ.errorDecayLength(); + registry.fill(HIST("h3_jet_pt_3prong_Sxy_N1_flavour_run2"), mcdjet.pt(), maxSxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_Sxyz_N1_flavour_run2"), mcdjet.pt(), maxSxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_3prong_mass_N1_flavour_run2"), mcdjet.pt(), massSV, jetflavourRun2Def, eventWeight); + if (!mcdjet.flagtaggedjetSV()) + return; + registry.fill(HIST("h3_taggedjet_pt_3prong_Sxy_N1_flavour_run2"), mcdjet.pt(), maxSxy, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_3prong_Sxyz_N1_flavour_run2"), mcdjet.pt(), maxSxyz, jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_3prong_mass_N1_flavour_run2"), mcdjet.pt(), massSV, jetflavourRun2Def, eventWeight); + } + + void processDummy(aod::Collision const&, aod::Tracks const&) + { + } + PROCESS_SWITCH(JetTaggerHFQA, processDummy, "Dummy process", true); + + void processTracksDca(JetTagTracksData& jtracks) + { + for (auto const& jtrack : jtracks) { + if (!jetderiveddatautilities::selectTrack(jtrack, trackSelection)) { continue; } - std::vector> vecSignImpXYSig, vecSignImpZSig, vecSignImpXYZSig; - for (auto& jtrack : jet.template tracks_as()) { - auto track = jtrack.template track_as(); - if (!trackAcceptance(track)) - continue; - - // General parameters - registry.fill(HIST("h3_jet_pt_track_pt_track_eta"), jet.pt(), track.pt(), track.eta()); - registry.fill(HIST("h3_jet_pt_track_pt_track_phi"), jet.pt(), track.pt(), track.phi()); - int geoSign = jettaggingutilities::getGeoSign(collision, jet, track); - if (fillIPxy) { - float varImpXY, varSignImpXY, varImpXYSig, varSignImpXYSig; - varImpXY = track.dcaXY() * jettaggingutilities::cmTomum; - varSignImpXY = geoSign * TMath::Abs(track.dcaXY()) * jettaggingutilities::cmTomum; - varImpXYSig = track.dcaXY() / TMath::Sqrt(track.sigmaDcaXY2()); - varSignImpXYSig = geoSign * TMath::Abs(track.dcaXY()) / TMath::Sqrt(track.sigmaDcaXY2()); - registry.fill(HIST("h2_jet_pt_impact_parameter_xy"), jet.pt(), varImpXY); - registry.fill(HIST("h2_jet_pt_sign_impact_parameter_xy"), jet.pt(), varSignImpXY); - registry.fill(HIST("h2_jet_pt_impact_parameter_xy_significance"), jet.pt(), varImpXYSig); - registry.fill(HIST("h3_jet_pt_track_pt_sign_impact_parameter_xy_significance"), jet.pt(), track.pt(), varSignImpXYSig); - vecSignImpXYSig.push_back({varSignImpXYSig, track.pt()}); - } - if (fillIPz) { - float varImpZ, varSignImpZ, varImpZSig, varSignImpZSig; - varImpZ = track.dcaZ() * jettaggingutilities::cmTomum; - varSignImpZ = geoSign * TMath::Abs(track.dcaZ()) * jettaggingutilities::cmTomum; - varImpZSig = track.dcaZ() / TMath::Sqrt(track.sigmaDcaZ2()); - varSignImpZSig = geoSign * TMath::Abs(track.dcaZ()) / TMath::Sqrt(track.sigmaDcaZ2()); - registry.fill(HIST("h2_jet_pt_impact_parameter_z"), jet.pt(), varImpZ); - registry.fill(HIST("h2_jet_pt_sign_impact_parameter_z"), jet.pt(), varSignImpZ); - registry.fill(HIST("h2_jet_pt_impact_parameter_z_significance"), jet.pt(), varImpZSig); - registry.fill(HIST("h3_jet_pt_track_pt_sign_impact_parameter_z_significance"), jet.pt(), track.pt(), varSignImpZSig); - vecSignImpZSig.push_back({varSignImpZSig, track.pt()}); - } - if (fillIPxyz) { - float varImpXYZ, varSignImpXYZ, varImpXYZSig, varSignImpXYZSig; - float dcaXYZ = jtrack.dcaXYZ(); - float sigmaDcaXYZ2 = jtrack.sigmaDcaXYZ2(); - varImpXYZ = dcaXYZ * jettaggingutilities::cmTomum; - varSignImpXYZ = geoSign * TMath::Abs(dcaXYZ) * jettaggingutilities::cmTomum; - varImpXYZSig = dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2); - varSignImpXYZSig = geoSign * TMath::Abs(dcaXYZ) / TMath::Sqrt(sigmaDcaXYZ2); - registry.fill(HIST("h2_jet_pt_impact_parameter_xyz"), jet.pt(), varImpXYZ); - registry.fill(HIST("h2_jet_pt_sign_impact_parameter_xyz"), jet.pt(), varSignImpXYZ); - registry.fill(HIST("h2_jet_pt_impact_parameter_xyz_significance"), jet.pt(), varImpXYZSig); - registry.fill(HIST("h3_jet_pt_track_pt_sign_impact_parameter_xyz_significance"), jet.pt(), track.pt(), varSignImpXYZSig); - vecSignImpXYZSig.push_back({varSignImpXYZSig, track.pt()}); - } - } - if (!fillTrackCounting) - continue; - if (fillIPxy) - std::sort(vecSignImpXYSig.begin(), vecSignImpXYSig.end(), sortImp); - if (fillIPz) - std::sort(vecSignImpZSig.begin(), vecSignImpZSig.end(), sortImp); - if (fillIPxyz) - std::sort(vecSignImpXYZSig.begin(), vecSignImpXYZSig.end(), sortImp); - if (fillIPxy && vecSignImpXYSig.empty()) - continue; - if (fillIPz && vecSignImpZSig.empty()) + float varImpXY, varImpXYSig, varImpZ, varImpZSig, varImpXYZ, varImpXYZSig; + varImpXY = jtrack.dcaXY() * jettaggingutilities::cmTomum; + varImpXYSig = jtrack.dcaXY() / jtrack.sigmadcaXY(); + varImpZ = jtrack.dcaZ() * jettaggingutilities::cmTomum; + varImpZSig = jtrack.dcaZ() / jtrack.sigmadcaZ(); + float dcaXYZ = jtrack.dcaXYZ(); + float sigmadcaXYZ2 = jtrack.sigmadcaXYZ(); + varImpXYZ = dcaXYZ * jettaggingutilities::cmTomum; + varImpXYZSig = dcaXYZ / std::sqrt(sigmadcaXYZ2); + + registry.fill(HIST("h_impact_parameter_xy"), varImpXY); + registry.fill(HIST("h_impact_parameter_xy_significance"), varImpXYSig); + registry.fill(HIST("h_impact_parameter_z"), varImpZ); + registry.fill(HIST("h_impact_parameter_z_significance"), varImpZSig); + registry.fill(HIST("h_impact_parameter_xyz"), varImpXYZ); + registry.fill(HIST("h_impact_parameter_xyz_significance"), varImpXYZSig); + } + } + PROCESS_SWITCH(JetTaggerHFQA, processTracksDca, "Fill inclusive tracks' imformation for data", false); + + void processIPsData(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTagTracksData const& jtracks) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; - if (fillIPxyz && vecSignImpXYZSig.empty()) + } + if (!isAcceptedJet(jet)) { continue; - for (int order = 1; order <= numOrder; order++) { - if (fillIPxy && order < vecSignImpXYSig.size()) { - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_tc"), jet.pt(), vecSignImpXYSig[order - 1][0], order); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_significance_tc"), vecSignImpXYSig[order - 1][1], vecSignImpXYSig[order - 1][0], order); - } - if (fillIPz && order < vecSignImpZSig.size()) { - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_tc"), jet.pt(), vecSignImpZSig[order - 1][0], order); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_z_significance_tc"), vecSignImpZSig[order - 1][1], vecSignImpZSig[order - 1][0], order); - } - if (fillIPxyz && order < vecSignImpXYZSig.size()) { - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_tc"), jet.pt(), vecSignImpXYZSig[order - 1][0], order); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_xyz_significance_tc"), vecSignImpXYZSig[order - 1][1], vecSignImpXYZSig[order - 1][0], order); - } } + fillHistogramIPsData(jet, jtracks); } } + PROCESS_SWITCH(JetTaggerHFQA, processIPsData, "Fill impact parameter imformation for data jets", false); - template - void fillHistogramIPsMCD(T const& collision, U const& mcdjets, V const& /*jtracks*/, W const& /*tracks*/) + void processIPsMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, JetTagTracksMCD const& jtracks, JetParticles&) { - for (auto& mcdjet : mcdjets) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - std::vector vecImpXY[numberOfJetFlavourSpecies], vecSignImpXY[numberOfJetFlavourSpecies], vecImpXYSig[numberOfJetFlavourSpecies], vecSignImpXYSig[numberOfJetFlavourSpecies]; - std::vector vecImpZ[numberOfJetFlavourSpecies], vecSignImpZ[numberOfJetFlavourSpecies], vecImpZSig[numberOfJetFlavourSpecies], vecSignImpZSig[numberOfJetFlavourSpecies]; - std::vector vecImpXYZ[numberOfJetFlavourSpecies], vecSignImpXYZ[numberOfJetFlavourSpecies], vecImpXYZSig[numberOfJetFlavourSpecies], vecSignImpXYZSig[numberOfJetFlavourSpecies]; - std::vector> vecSignImpXYSigTC, vecSignImpZSigTC, vecSignImpXYZSigTC; - int jetflavour = mcdjet.origin(); - if (jetflavour == JetTaggingSpecies::none) { - LOGF(debug, "NOT DEFINE JET FLAVOR"); - } - registry.fill(HIST("h2_jet_pt_flavour"), mcdjet.pt(), jetflavour); - registry.fill(HIST("h2_jet_eta_flavour"), mcdjet.eta(), jetflavour); - registry.fill(HIST("h2_jet_phi_flavour"), mcdjet.phi(), jetflavour); - for (auto& jtrack : mcdjet.template tracks_as()) { - auto track = jtrack.template track_as(); - if (!trackAcceptance(track)) - continue; - // General parameters - registry.fill(HIST("h3_jet_pt_track_pt_flavour"), mcdjet.pt(), track.pt(), jetflavour); - registry.fill(HIST("h3_jet_pt_track_eta_flavour"), mcdjet.pt(), track.eta(), jetflavour); - registry.fill(HIST("h3_jet_pt_track_phi_flavour"), mcdjet.pt(), track.phi(), jetflavour); - int geoSign = jettaggingutilities::getGeoSign(collision, mcdjet, track); - if (fillIPxy) { - float varImpXY, varSignImpXY, varImpXYSig, varSignImpXYSig; - varImpXY = track.dcaXY() * jettaggingutilities::cmTomum; - varSignImpXY = geoSign * TMath::Abs(track.dcaXY()) * jettaggingutilities::cmTomum; - varImpXYSig = track.dcaXY() / TMath::Sqrt(track.sigmaDcaXY2()); - varSignImpXYSig = geoSign * TMath::Abs(track.dcaXY()) / TMath::Sqrt(track.sigmaDcaXY2()); - registry.fill(HIST("h3_jet_pt_impact_parameter_xy_flavour"), mcdjet.pt(), varImpXY, jetflavour); - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_flavour"), mcdjet.pt(), varSignImpXY, jetflavour); - registry.fill(HIST("h3_jet_pt_impact_parameter_xy_significance_flavour"), mcdjet.pt(), varImpXYSig, jetflavour); - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour"), mcdjet.pt(), varSignImpXYSig, jetflavour); - registry.fill(HIST("h3_track_pt_impact_parameter_xy_flavour"), jtrack.pt(), varImpXY, jetflavour); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_flavour"), jtrack.pt(), varSignImpXY, jetflavour); - registry.fill(HIST("h3_track_pt_impact_parameter_xy_significance_flavour"), jtrack.pt(), varImpXYSig, jetflavour); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_xy_significance_flavour"), jtrack.pt(), varSignImpXYSig, jetflavour); - vecImpXY[jetflavour].push_back(varImpXY); - vecSignImpXY[jetflavour].push_back(varSignImpXY); - vecImpXYSig[jetflavour].push_back(varImpXYSig); - vecSignImpXYSig[jetflavour].push_back(varSignImpXYSig); - vecSignImpXYSigTC.push_back({varSignImpXYSig, jtrack.pt()}); - } - if (fillIPz) { - float varImpZ, varSignImpZ, varImpZSig, varSignImpZSig; - varImpZ = track.dcaZ() * jettaggingutilities::cmTomum; - varSignImpZ = geoSign * TMath::Abs(track.dcaZ()) * jettaggingutilities::cmTomum; - varImpZSig = track.dcaZ() / TMath::Sqrt(track.sigmaDcaZ2()); - varSignImpZSig = geoSign * TMath::Abs(track.dcaZ()) / TMath::Sqrt(track.sigmaDcaZ2()); - registry.fill(HIST("h3_jet_pt_impact_parameter_z_flavour"), mcdjet.pt(), varImpZ, jetflavour); - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_flavour"), mcdjet.pt(), varSignImpZ, jetflavour); - registry.fill(HIST("h3_jet_pt_impact_parameter_z_significance_flavour"), mcdjet.pt(), varImpZSig, jetflavour); - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour"), mcdjet.pt(), varSignImpZSig, jetflavour); - registry.fill(HIST("h3_track_pt_impact_parameter_z_flavour"), jtrack.pt(), varImpZ, jetflavour); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_z_flavour"), jtrack.pt(), varSignImpZ, jetflavour); - registry.fill(HIST("h3_track_pt_impact_parameter_z_significance_flavour"), jtrack.pt(), varImpZSig, jetflavour); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_z_significance_flavour"), jtrack.pt(), varSignImpZSig, jetflavour); - vecImpZ[jetflavour].push_back(varImpZ); - vecSignImpZ[jetflavour].push_back(varSignImpZ); - vecImpZSig[jetflavour].push_back(varImpZSig); - vecSignImpZSig[jetflavour].push_back(varSignImpZSig); - vecSignImpZSigTC.push_back({varSignImpZSig, jtrack.pt()}); - } - if (fillIPxyz) { - float varImpXYZ, varSignImpXYZ, varImpXYZSig, varSignImpXYZSig; - float dcaXYZ = jtrack.dcaXYZ(); - float sigmaDcaXYZ2 = jtrack.sigmaDcaXYZ2(); - varImpXYZ = dcaXYZ * jettaggingutilities::cmTomum; - varSignImpXYZ = geoSign * TMath::Abs(dcaXYZ) * jettaggingutilities::cmTomum; - varImpXYZSig = dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2); - varSignImpXYZSig = geoSign * TMath::Abs(dcaXYZ) / TMath::Sqrt(sigmaDcaXYZ2); - registry.fill(HIST("h3_jet_pt_impact_parameter_xyz_flavour"), mcdjet.pt(), varImpXYZ, jetflavour); - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_flavour"), mcdjet.pt(), varSignImpXYZ, jetflavour); - registry.fill(HIST("h3_jet_pt_impact_parameter_xyz_significance_flavour"), mcdjet.pt(), varImpXYZSig, jetflavour); - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour"), mcdjet.pt(), varSignImpXYZSig, jetflavour); - registry.fill(HIST("h3_track_pt_impact_parameter_xyz_flavour"), jtrack.pt(), varImpXYZ, jetflavour); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_xyz_flavour"), jtrack.pt(), varSignImpXYZ, jetflavour); - registry.fill(HIST("h3_track_pt_impact_parameter_xyz_significance_flavour"), jtrack.pt(), varImpXYZSig, jetflavour); - registry.fill(HIST("h3_track_pt_sign_impact_parameter_xyz_significance_flavour"), jtrack.pt(), varSignImpXYZSig, jetflavour); - vecImpXYZ[jetflavour].push_back(varImpXYZ); - vecSignImpXYZ[jetflavour].push_back(varSignImpXYZ); - vecImpXYZSig[jetflavour].push_back(varImpXYZSig); - vecSignImpXYZSig[jetflavour].push_back(varSignImpXYZSig); - vecSignImpXYZSigTC.push_back({varSignImpXYZSig, jtrack.pt()}); - } + if (!isAcceptedJet(mcdjet)) { + continue; } + fillHistogramIPsMCD(mcdjet, jtracks); + } + } + PROCESS_SWITCH(JetTaggerHFQA, processIPsMCD, "Fill impact parameter imformation for mcd jets", false); - if (!fillTrackCounting) - continue; - sort(vecImpXY[jetflavour].begin(), vecImpXY[jetflavour].end(), std::greater()); - sort(vecSignImpXY[jetflavour].begin(), vecSignImpXY[jetflavour].end(), std::greater()); - sort(vecImpXYSig[jetflavour].begin(), vecImpXYSig[jetflavour].end(), std::greater()); - sort(vecSignImpXYSig[jetflavour].begin(), vecSignImpXYSig[jetflavour].end(), std::greater()); - sort(vecImpZ[jetflavour].begin(), vecImpZ[jetflavour].end(), std::greater()); - sort(vecSignImpZ[jetflavour].begin(), vecSignImpZ[jetflavour].end(), std::greater()); - sort(vecImpZSig[jetflavour].begin(), vecImpZSig[jetflavour].end(), std::greater()); - sort(vecSignImpZSig[jetflavour].begin(), vecSignImpZSig[jetflavour].end(), std::greater()); - sort(vecImpXYZ[jetflavour].begin(), vecImpXYZ[jetflavour].end(), std::greater()); - sort(vecSignImpXYZ[jetflavour].begin(), vecSignImpXYZ[jetflavour].end(), std::greater()); - sort(vecImpXYZSig[jetflavour].begin(), vecImpXYZSig[jetflavour].end(), std::greater()); - sort(vecSignImpXYZSig[jetflavour].begin(), vecSignImpXYZSig[jetflavour].end(), std::greater()); - - if (vecImpXY[jetflavour].size() > 0) { // N1 - if (fillIPxy) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_N1"), mcdjet.pt(), vecSignImpXYSig[jetflavour][0], jetflavour); - if (fillIPz) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour_N1"), mcdjet.pt(), vecSignImpZSig[jetflavour][0], jetflavour); - if (fillIPxyz) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour_N1"), mcdjet.pt(), vecSignImpXYZSig[jetflavour][0], jetflavour); - } - if (vecImpXY[jetflavour].size() > 1) { // N2 - if (fillIPxy) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_N2"), mcdjet.pt(), vecSignImpXYSig[jetflavour][1], jetflavour); - if (fillIPz) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour_N2"), mcdjet.pt(), vecSignImpZSig[jetflavour][1], jetflavour); - if (fillIPxyz) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour_N2"), mcdjet.pt(), vecSignImpXYZSig[jetflavour][1], jetflavour); - } - if (vecImpXY[jetflavour].size() > 2) { // N3 - if (fillIPxy) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xy_significance_flavour_N3"), mcdjet.pt(), vecSignImpXYSig[jetflavour][2], jetflavour); - if (fillIPz) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_z_significance_flavour_N3"), mcdjet.pt(), vecSignImpZSig[jetflavour][2], jetflavour); - if (fillIPxyz) - registry.fill(HIST("h3_jet_pt_sign_impact_parameter_xyz_significance_flavour_N3"), mcdjet.pt(), vecSignImpXYZSig[jetflavour][2], jetflavour); - } - - std::sort(vecSignImpXYSigTC.begin(), vecSignImpXYSigTC.end(), sortImp); - std::sort(vecSignImpZSigTC.begin(), vecSignImpZSigTC.end(), sortImp); - std::sort(vecSignImpXYZSigTC.begin(), vecSignImpXYZSigTC.end(), sortImp); - - if (vecSignImpXYSigTC.empty()) - continue; - for (int order = 1; order <= numOrder; order++) { - if (fillIPxy && order < vecSignImpXYSigTC.size()) { - registry.fill(HIST("h3_sign_impact_parameter_xy_significance_tc_flavour"), vecSignImpXYSigTC[order - 1][0], order, jetflavour); - } - } - if (vecSignImpZSigTC.empty()) + void processIPsMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, JetTagTracksMCD const& jtracks, JetParticles&) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; - for (int order = 1; order <= numOrder; order++) { - if (fillIPxy && order < vecSignImpZSigTC.size()) { - registry.fill(HIST("h3_sign_impact_parameter_z_significance_tc_flavour"), vecSignImpZSigTC[order - 1][0], order, jetflavour); - } } + fillHistogramIPsMCD(mcdjet, jtracks, mcdjet.eventWeight()); + } + } + PROCESS_SWITCH(JetTaggerHFQA, processIPsMCDWeighted, "Fill impact parameter imformation for mcd jets", false); - if (vecSignImpXYZSigTC.empty()) + void processIPsMCP(soa::Join const& mcpjets, JetParticles&, JetMcCollisions const&, soa::Filtered const& collisions) + { + for (auto mcpjet : mcpjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcpjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; - for (int order = 1; order <= numOrder; order++) { - if (fillIPxy && order < vecSignImpXYZSigTC.size()) { - registry.fill(HIST("h3_sign_impact_parameter_xyz_significance_tc_flavour"), vecSignImpXYZSigTC[order - 1][0], order, jetflavour); + } + if (!isAcceptedJet(mcpjet)) { + return; + } + if (checkMcCollisionIsMatched) { + auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, mcpjet.mcCollisionId()); + if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelection)) { + fillHistogramIPsMCP(mcpjet); } + } else { + fillHistogramIPsMCP(mcpjet); } } } + PROCESS_SWITCH(JetTaggerHFQA, processIPsMCP, "Fill impact parameter imformation for mcp jets", false); - template - void fillHistogramJPData(T const& /*collision*/, U const& jets) + void processIPsMCPWeighted(soa::Filtered const& collisions, soa::Join const& mcpjets, JetParticles&) { - for (auto& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + for (auto mcpjet : mcpjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcpjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - registry.fill(HIST("h2_jet_pt_JP"), jet.pt(), jet.jetProb()[0]); - registry.fill(HIST("h2_jet_pt_neg_log_JP"), jet.pt(), -1 * TMath::Log(jet.jetProb()[0])); - registry.fill(HIST("h2_jet_pt_JP_N1"), jet.pt(), jet.jetProb()[1]); - registry.fill(HIST("h2_jet_pt_neg_log_JP_N1"), jet.pt(), -1 * TMath::Log(jet.jetProb()[1])); - registry.fill(HIST("h2_jet_pt_JP_N2"), jet.pt(), jet.jetProb()[2]); - registry.fill(HIST("h2_jet_pt_neg_log_JP_N2"), jet.pt(), -1 * TMath::Log(jet.jetProb()[2])); - registry.fill(HIST("h2_jet_pt_JP_N3"), jet.pt(), jet.jetProb()[3]); - registry.fill(HIST("h2_jet_pt_neg_log_JP_N3"), jet.pt(), -1 * TMath::Log(jet.jetProb()[3])); + if (!isAcceptedJet(mcpjet)) { + return; + } + if (checkMcCollisionIsMatched) { + auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, mcpjet.mcCollisionId()); + if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelection)) { + fillHistogramIPsMCP(mcpjet, mcpjet.eventWeight()); + } else { + fillHistogramIPsMCP(mcpjet, mcpjet.eventWeight()); + } + } } } + PROCESS_SWITCH(JetTaggerHFQA, processIPsMCPWeighted, "Fill impact parameter imformation for mcp jets weighted", false); - template - void fillHistogramJPMCD(T const& /*collision*/, U const& mcdjets) + void processIPsMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, JetTagTracksMCD const& jtracks, JetParticles& particles) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } for (auto& mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - registry.fill(HIST("h3_jet_pt_JP_flavour"), mcdjet.pt(), mcdjet.jetProb()[0], mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_neg_log_JP_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[0]), mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_JP_N1_flavour"), mcdjet.pt(), mcdjet.jetProb()[1], mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_neg_log_JP_N1_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[1]), mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_JP_N2_flavour"), mcdjet.pt(), mcdjet.jetProb()[2], mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_neg_log_JP_N2_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[2]), mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_JP_N3_flavour"), mcdjet.pt(), mcdjet.jetProb()[3], mcdjet.origin()); - registry.fill(HIST("h3_jet_pt_neg_log_JP_N3_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[3]), mcdjet.origin()); + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramIPsMatched(mcdjet, mcpjets, jtracks, particlesPerColl); } } + PROCESS_SWITCH(JetTaggerHFQA, processIPsMCPMCDMatched, "Fill impact parameter imformation for mcp mcd matched jets", false); - template - void fillHistogramSV2ProngData(T const& collision, U const& jets, V const& prongs) + void processIPsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, JetTagTracksMCD const& jtracks, JetParticles& particles) { - for (const auto& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto& mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - auto maxSxy = getMaxSxyForJet(jet); - auto maxSxyz = getMaxSxyzForJet(jet); - registry.fill(HIST("h_2prong_nprongs"), jet.template secondaryVertices_as().size()); - for (const auto& prong : jet.template secondaryVertices_as()) { - auto Lxy = prong.decayLengthXY(); - auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - auto Lxyz = prong.decayLength(); - auto Sxyz = prong.decayLength() / prong.errorDecayLength(); - registry.fill(HIST("h2_jet_pt_2prong_Lxy"), jet.pt(), Lxy); - registry.fill(HIST("h2_jet_pt_2prong_Sxy"), jet.pt(), Sxy); - registry.fill(HIST("h2_jet_pt_2prong_Lxyz"), jet.pt(), Lxyz); - registry.fill(HIST("h2_jet_pt_2prong_Sxyz"), jet.pt(), Sxyz); - registry.fill(HIST("h2_2prong_Sxy_sigmaLxy"), Sxy, prong.errorDecayLengthXY()); - registry.fill(HIST("h2_2prong_Sxyz_sigmaLxyz"), Sxyz, prong.errorDecayLength()); - registry.fill(HIST("h2_jet_pt_2prong_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); - registry.fill(HIST("h2_jet_pt_2prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); + if (!isAcceptedJet(mcdjet)) { + continue; } - registry.fill(HIST("h2_jet_pt_2prong_Sxy_N1"), jet.pt(), maxSxy); - registry.fill(HIST("h2_jet_pt_2prong_Sxyz_N1"), jet.pt(), maxSxyz); + fillHistogramIPsMatched(mcdjet, mcpjets, jtracks, particlesPerColl, mcdjet.eventWeight()); } } + PROCESS_SWITCH(JetTaggerHFQA, processIPsMCPMCDMatchedWeighted, "Fill impact parameter imformation for mcp mcd matched jets", false); - template - void fillHistogramSV3ProngData(T const& collision, U const& jets, V const& prongs) + void processJPData(soa::Filtered::iterator const& collision, soa::Join const& jets, JetTagTracksData const&) { - for (const auto& jet : jets) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - auto maxSxy = getMaxSxyForJet(jet); - auto maxSxyz = getMaxSxyzForJet(jet); - registry.fill(HIST("h_3prong_nprongs"), jet.template secondaryVertices_as().size()); - for (const auto& prong : jet.template secondaryVertices_as()) { - auto Lxy = prong.decayLengthXY(); - auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - auto Lxyz = prong.decayLength(); - auto Sxyz = prong.decayLength() / prong.errorDecayLength(); - registry.fill(HIST("h2_jet_pt_3prong_Lxy"), jet.pt(), Lxy); - registry.fill(HIST("h2_jet_pt_3prong_Sxy"), jet.pt(), Sxy); - registry.fill(HIST("h2_jet_pt_3prong_Lxyz"), jet.pt(), Lxyz); - registry.fill(HIST("h2_jet_pt_3prong_Sxyz"), jet.pt(), Sxyz); - registry.fill(HIST("h2_3prong_Sxy_sigmaLxy"), Sxy, prong.errorDecayLengthXY()); - registry.fill(HIST("h2_3prong_Sxyz_sigmaLxyz"), Sxyz, prong.errorDecayLength()); - registry.fill(HIST("h2_jet_pt_3prong_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); - registry.fill(HIST("h2_jet_pt_3prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); + if (!isAcceptedJet(jet)) { + continue; } - registry.fill(HIST("h2_jet_pt_3prong_Sxy_N1"), jet.pt(), maxSxy); - registry.fill(HIST("h2_jet_pt_3prong_Sxyz_N1"), jet.pt(), maxSxyz); + fillHistogramJPData(jet); } } + PROCESS_SWITCH(JetTaggerHFQA, processJPData, "Fill jet probability imformation for data jets", false); - template - void fillHistogramSV2ProngMCD(T const& collision, U const& mcdjets, V const& prongs) + void processJPMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, JetTagTracksMCD const&) { - for (const auto& mcdjet : mcdjets) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - auto origin = mcdjet.origin(); - auto maxSxy = getMaxSxyForJet(mcdjet); - auto maxSxyz = getMaxSxyzForJet(mcdjet); - registry.fill(HIST("h2_2prong_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin); - for (const auto& prong : mcdjet.template secondaryVertices_as()) { - auto Lxy = prong.decayLengthXY(); - auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - auto Lxyz = prong.decayLength(); - auto Sxyz = prong.decayLength() / prong.errorDecayLength(); - registry.fill(HIST("h3_jet_pt_2prong_Lxy_flavour"), mcdjet.pt(), Lxy, origin); - registry.fill(HIST("h3_jet_pt_2prong_Sxy_flavour"), mcdjet.pt(), Sxy, origin); - registry.fill(HIST("h3_jet_pt_2prong_Lxyz_flavour"), mcdjet.pt(), Lxyz, origin); - registry.fill(HIST("h3_jet_pt_2prong_Sxyz_flavour"), mcdjet.pt(), Sxyz, origin); - registry.fill(HIST("h3_2prong_Sxy_sigmaLxy_flavour"), Sxy, prong.errorDecayLengthXY(), origin); - registry.fill(HIST("h3_2prong_Sxyz_sigmaLxyz_flavour"), Sxyz, prong.errorDecayLength(), origin); - registry.fill(HIST("h3_jet_pt_2prong_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin); - registry.fill(HIST("h3_jet_pt_2prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin); + if (!isAcceptedJet(mcdjet)) { + continue; } - registry.fill(HIST("h3_jet_pt_2prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin); - registry.fill(HIST("h3_jet_pt_2prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin); + fillHistogramJPMCD(mcdjet); } } + PROCESS_SWITCH(JetTaggerHFQA, processJPMCD, "Fill jet probability imformation for mcd jets", false); - template - void fillHistogramSV3ProngMCD(T const& collision, U const& mcdjets, V const& prongs) + void processJPMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, JetTagTracksMCD const&) { - for (const auto& mcdjet : mcdjets) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - auto origin = mcdjet.origin(); - auto maxSxy = getMaxSxyForJet(mcdjet); - auto maxSxyz = getMaxSxyzForJet(mcdjet); - registry.fill(HIST("h2_3prong_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin); - for (const auto& prong : mcdjet.template secondaryVertices_as()) { - auto Lxy = prong.decayLengthXY(); - auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - auto Lxyz = prong.decayLength(); - auto Sxyz = prong.decayLength() / prong.errorDecayLength(); - registry.fill(HIST("h3_jet_pt_3prong_Lxy_flavour"), mcdjet.pt(), Lxy, origin); - registry.fill(HIST("h3_jet_pt_3prong_Sxy_flavour"), mcdjet.pt(), Sxy, origin); - registry.fill(HIST("h3_jet_pt_3prong_Lxyz_flavour"), mcdjet.pt(), Lxyz, origin); - registry.fill(HIST("h3_jet_pt_3prong_Sxyz_flavour"), mcdjet.pt(), Sxyz, origin); - registry.fill(HIST("h3_3prong_Sxy_sigmaLxy_flavour"), Sxy, prong.errorDecayLengthXY(), origin); - registry.fill(HIST("h3_3prong_Sxyz_sigmaLxyz_flavour"), Sxyz, prong.errorDecayLength(), origin); - registry.fill(HIST("h3_jet_pt_3prong_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin); - registry.fill(HIST("h3_jet_pt_3prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin); + if (!isAcceptedJet(mcdjet)) { + continue; } - registry.fill(HIST("h3_jet_pt_3prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin); - registry.fill(HIST("h3_jet_pt_3prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin); + fillHistogramJPMCD(mcdjet, mcdjet.eventWeight()); } } + PROCESS_SWITCH(JetTaggerHFQA, processJPMCDWeighted, "Fill jet probability imformation for mcd jets", false); - void processDummy(aod::Collision const&, aod::Tracks const&) + void processSV2ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex2Prongs const& prongs) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillHistogramSV2ProngData(jet, prongs); + } } - PROCESS_SWITCH(JetTaggerHFQA, processDummy, "Dummy process", true); + PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngData, "Fill 2prong imformation for data jets", false); - void processTracksDca(JetTagTracksData& jtracks, OriTracksData const&) + void processSV3ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) { - for (auto const& jtrack : jtracks) { - if (!jetderiveddatautilities::selectTrack(jtrack, trackSelection)) { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - auto track = jtrack.track_as(); - - float varImpXY, varImpXYSig, varImpZ, varImpZSig, varImpXYZ, varImpXYZSig; - varImpXY = track.dcaXY() * jettaggingutilities::cmTomum; - varImpXYSig = track.dcaXY() / TMath::Sqrt(track.sigmaDcaXY2()); - varImpZ = track.dcaZ() * jettaggingutilities::cmTomum; - varImpZSig = track.dcaZ() / TMath::Sqrt(track.sigmaDcaZ2()); - float dcaXYZ = jtrack.dcaXYZ(); - float sigmaDcaXYZ2 = jtrack.sigmaDcaXYZ2(); - varImpXYZ = dcaXYZ * jettaggingutilities::cmTomum; - varImpXYZSig = dcaXYZ / TMath::Sqrt(sigmaDcaXYZ2); - - registry.fill(HIST("h_impact_parameter_xy"), varImpXY); - registry.fill(HIST("h_impact_parameter_xy_significance"), varImpXYSig); - registry.fill(HIST("h_impact_parameter_z"), varImpZ); - registry.fill(HIST("h_impact_parameter_z_significance"), varImpZSig); - registry.fill(HIST("h_impact_parameter_xyz"), varImpXYZ); - registry.fill(HIST("h_impact_parameter_xyz_significance"), varImpXYZSig); + if (!isAcceptedJet(jet)) { + continue; + } + fillHistogramSV3ProngData(jet, prongs); } } - PROCESS_SWITCH(JetTaggerHFQA, processTracksDca, "Fill inclusive tracks' imformation for data", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngData, "Fill 2prong imformation for data jets", false); - void processIPsData(soa::Filtered::iterator const& jcollision, JetTagTableData const& jets, JetTagTracksData const& jtracks, OriTracksData const& tracks) + void processSV2ProngMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex2Prongs const& prongs) { - fillHistogramIPsData(jcollision, jets, jtracks, tracks); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV2ProngMCD(mcdjet, prongs); + } } - PROCESS_SWITCH(JetTaggerHFQA, processIPsData, "Fill impact parameter imformation for data jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCD, "Fill 2prong imformation for mcd jets", false); - void processIPsMCD(soa::Filtered::iterator const& jcollision, JetTagTableMCD const& mcdjets, JetTagTracksMCD const& jtracks, OriTracksMCD const& tracks, JetParticles&) + void processSV2ProngMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex2Prongs const& prongs) { - fillHistogramIPsMCD(jcollision, mcdjets, jtracks, tracks); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV2ProngMCD(mcdjet, prongs, mcdjet.eventWeight()); + } } - PROCESS_SWITCH(JetTaggerHFQA, processIPsMCD, "Fill impact parameter imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCDWeighted, "Fill 2prong imformation for mcd jets", false); - void processJPData(soa::Filtered::iterator const& jcollision, JetTagTableData const& jets, JetTagTracksData const&) + void processSV2ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, aod::MCDSecondaryVertex2Prongs const& prongs, JetParticles& particles) { - fillHistogramJPData(jcollision, jets); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV2ProngMCPMCDMatched(mcdjet, mcpjets, prongs, particlesPerColl); + } } - PROCESS_SWITCH(JetTaggerHFQA, processJPData, "Fill jet probability imformation for data jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCPMCDMatched, "Fill 2prong imformation for mcd jets", false); - void processJPMCD(soa::Filtered::iterator const& jcollision, JetTagTableMCD const& mcdjets, JetTagTracksMCD const&) + void processSV2ProngMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, aod::MCDSecondaryVertex2Prongs const& prongs, JetParticles& particles) { - fillHistogramJPMCD(jcollision, mcdjets); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV2ProngMCPMCDMatched(mcdjet, mcpjets, prongs, particlesPerColl, mcdjet.eventWeight()); + } } - PROCESS_SWITCH(JetTaggerHFQA, processJPMCD, "Fill jet probability imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCPMCDMatchedWeighted, "Fill 2prong imformation for mcd jets", false); - void processSV2ProngData(soa::Filtered::iterator const& jcollision, soa::Join const& jets, aod::DataSecondaryVertex2Prongs const& prongs) + void processSV3ProngMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) { - fillHistogramSV2ProngData(jcollision, jets, prongs); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV3ProngMCD(mcdjet, prongs); + } } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngData, "Fill 2prong imformation for data jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCD, "Fill 3prong imformation for mcd jets", false); - void processSV3ProngData(soa::Filtered::iterator const& jcollision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) + void processSV3ProngMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) { - fillHistogramSV3ProngData(jcollision, jets, prongs); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV3ProngMCD(mcdjet, prongs, mcdjet.eventWeight()); + } } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngData, "Fill 2prong imformation for data jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCDWeighted, "Fill 3prong imformation for mcd jets", false); - void processSV2ProngMCD(soa::Filtered::iterator const& jcollision, soa::Join const& mcdjets, aod::MCDSecondaryVertex2Prongs const& prongs) + void processSV3ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, aod::MCDSecondaryVertex3Prongs const& prongs, JetParticles& particles) { - fillHistogramSV2ProngMCD(jcollision, mcdjets, prongs); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV3ProngMCPMCDMatched(mcdjet, mcpjets, prongs, particlesPerColl); + } } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCD, "Fill 2prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatched, "Fill 3prong imformation for mcd jets", false); - void processSV3ProngMCD(soa::Filtered::iterator const& jcollision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSV3ProngMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, aod::MCDSecondaryVertex3Prongs const& prongs, JetParticles& particles) { - fillHistogramSV3ProngMCD(jcollision, mcdjets, prongs); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV3ProngMCPMCDMatched(mcdjet, mcpjets, prongs, particlesPerColl, mcdjet.eventWeight()); + } } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCD, "Fill 3prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatchedWeighted, "Fill 3prong imformation for mcd jets", false); }; -using JetTaggerQAChargedDataJets = soa::Join; -using JetTaggerQAChargedMCDJets = soa::Join; +using JetTaggerQAChargedDataJets = soa::Join; +using JetTaggerQAChargedMCDJets = soa::Join; using JetTaggerQAChargedMCPJets = soa::Join; -using JetTaggerQACharged = JetTaggerHFQA; +using JetTaggerQACharged = JetTaggerHFQA; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGJE/Tasks/mcgeneratorstudies.cxx b/PWGJE/Tasks/mcgeneratorstudies.cxx index 4df20c893ce..1362ed572a5 100644 --- a/PWGJE/Tasks/mcgeneratorstudies.cxx +++ b/PWGJE/Tasks/mcgeneratorstudies.cxx @@ -21,6 +21,9 @@ #include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "DetectorsBase/GeometryManager.h" +#include "EMCALBase/Geometry.h" + #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" @@ -28,57 +31,184 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using MyMCCollisions = soa::Join; +using MyMCCollisions = soa::Join; struct MCGeneratorStudies { HistogramRegistry mHistManager{"MCGeneratorStudyHistograms"}; Configurable mVertexCut{"vertexCut", 10.f, "apply z-vertex cut with value in cm"}; Configurable mRapidityCut{"rapidityCut", 0.9f, "Maximum absolute rapidity of counted generated particles"}; - Configurable mSelectedParticleCode{"particlePDGCode", 111, "PDG code of the particle to be investigated"}; - - Filter collisionFilter = (aod::collision::posZ > -mVertexCut) && (aod::collision::posZ < mVertexCut); - Filter mcParticleFilter = (aod::mcparticle::pdgCode == mSelectedParticleCode) && (aod::mcparticle::y > -mRapidityCut) && (aod::mcparticle::y < mRapidityCut); + Configurable mSelectedParticleCode{"particlePDGCode", 111, "PDG code of the particle to be investigated"}; + Configurable mRequireGammaGammaDecay{"requireGammaGammaDecay", false, "Only count generated particles that decayed into two photons"}; + Configurable mRequireEMCCellContent{"requireEMCCellContent", false, "Ask forEMCal cell content instead of the kTVXinEMC trigger"}; void init(InitContext const&) { AxisSpec pTAxis{250, 0., 25., "#it{p}_{T} (GeV/#it{c})"}; - mHistManager.add("hCollisionCounter", "Number of collisions after event cuts", HistType::kTH1F, {{5, 0.5, 5.5}}); - mHistManager.add("hpT_all", "All collisions", HistType::kTH1F, {pTAxis}); - mHistManager.add("hpT_T0Triggered", "T0 triggered collisions", HistType::kTH1F, {pTAxis}); - mHistManager.add("hpT_T0Triggered_EMCReadout", "T0 triggered and EMC readout collisions", HistType::kTH1F, {pTAxis}); - mHistManager.add("hpT_T0Triggered_EMCReadout_Unique", "Unique T0 triggered and EMC readout collisions", HistType::kTH1F, {pTAxis}); + auto hCollisionCounter = mHistManager.add("hCollisionCounter", "Number of collisions after event cuts", HistType::kTH1F, {{7, 0.5, 7.5}}); + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "TVX"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "T zSmall"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "Tz zGood"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "Tzz EMCal"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "TzzE Sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "TzzES Unique"); + TString mesonLatexString = (TString)mSelectedParticleCode; + switch (mSelectedParticleCode) { + case 111: + mesonLatexString = "#pi^{0}"; + break; + case 221: + mesonLatexString = "#eta"; + break; + } + mHistManager.add("hpT_all", Form("Generated %s in all collisions", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpT_TVX", Form("Generated %s in TVX triggered collisions", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpT_T_zsmall", Form("Generated %s in TVX collisions with z < 10cm", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpT_T_z_zGood", Form("Generated %s in TVX collisions with good z < 10cm", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpTAccepted_T_z_z", Form("Accepted (EMCal) %s in TVX collisions with good z < 10cm", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpT_T_z_z_EMCal", Form("Generated %s in TVXinEMC collisions with good z < 10cm", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpT_T_z_z_E_Sel8", Form("Generated %s in TVXinEMC collisions with good z < 10cm and Sel8", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpT_T_z_z_E_S_Unique", Form("Generated %s in unique TVXinEMC collisions with good z < 10cm and Sel8", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + mHistManager.add("hpTAccepted_T_z_z_E_S_U", Form("Accepted %s in unique TVXinEMC collisions with good z < 10cm and Sel8", mesonLatexString.Data()), HistType::kTH1F, {pTAxis}); + + auto hEMCollisionCounter = mHistManager.add("hEMCollisionCounter", "collision counter;;Number of events", kTH1F, {{13, 0.5, 13.5}}, false); + hEMCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(10, "EMC MB Readout"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(11, "EMC L0 Triggered"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(12, "EMC Cell Content"); + hEMCollisionCounter->GetXaxis()->SetBinLabel(13, "accepted"); + + o2::emcal::Geometry::GetInstanceFromRunNumber(300000); } PresliceUnsorted perMcCollision = aod::mcparticle::mcCollisionId; - void process(soa::Filtered::iterator const& collision, soa::Filtered const& mcParticles) + void process(MyMCCollisions::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { - bool isT0Triggered = collision.sel8(); - bool isEMCReadout = collision.isemcreadout(); - bool isUniqueCollision = !collision.ambiguous(); - - mHistManager.fill(HIST("hCollisionCounter"), 1); - if (isT0Triggered) { - mHistManager.fill(HIST("hCollisionCounter"), 2); - // mHistManager.fill(HIST("hpT_T0Triggered"), mcParticles, aod::evsel::sel8 == true); - if (isEMCReadout) { - mHistManager.fill(HIST("hCollisionCounter"), 3); - if (isUniqueCollision) { - mHistManager.fill(HIST("hCollisionCounter"), 4); + fillEventHistogram(&mHistManager, collision); + + auto mcCollision = collision.mcCollision(); + auto mcParticles_inColl = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); + + for (auto& mcParticle : mcParticles_inColl) { + if (mcParticle.pdgCode() != mSelectedParticleCode || fabs(mcParticle.y()) > mRapidityCut) + continue; + if (!mcParticle.isPhysicalPrimary() && !mcParticle.producedByGenerator()) + continue; + if (mRequireGammaGammaDecay && !isGammaGammaDecay(mcParticle, mcParticles)) + continue; + + mHistManager.fill(HIST("hpT_all"), mcParticle.pt()); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + mHistManager.fill(HIST("hpT_TVX"), mcParticle.pt()); + if (abs(collision.posZ()) < mVertexCut) { + mHistManager.fill(HIST("hpT_T_zsmall"), mcParticle.pt()); + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + mHistManager.fill(HIST("hpT_T_z_zGood"), mcParticle.pt()); + if (isAccepted(mcParticle, mcParticles)) + mHistManager.fill(HIST("hpTAccepted_T_z_z"), mcParticle.pt()); + if (mRequireEMCCellContent ? collision.isemcreadout() : collision.alias_bit(kTVXinEMC)) { + mHistManager.fill(HIST("hpT_T_z_z_EMCal"), mcParticle.pt()); + if (collision.sel8()) { + mHistManager.fill(HIST("hpT_T_z_z_E_Sel8"), mcParticle.pt()); + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + mHistManager.fill(HIST("hpT_T_z_z_E_S_Unique"), mcParticle.pt()); + if (isAccepted(mcParticle, mcParticles)) + mHistManager.fill(HIST("hpTAccepted_T_z_z_E_S_U"), mcParticle.pt()); + } + } + } + } } } } - auto mcParticles_inColl = mcParticles.sliceBy(perMcCollision, collision.globalIndex()); - for (auto& mcParticle : mcParticles_inColl) { - mHistManager.fill(HIST("hpT_all"), mcParticle.pt()); - if (isT0Triggered) { - mHistManager.fill(HIST("hpT_T0Triggered"), mcParticle.pt()); - if (isEMCReadout) { - mHistManager.fill(HIST("hpT_T0Triggered_EMCReadout"), mcParticle.pt()); - if (isUniqueCollision) { - mHistManager.fill(HIST("hpT_T0Triggered_EMCReadout_Unique"), mcParticle.pt()); + } + + template + bool isGammaGammaDecay(TMCParticle mcParticle, TMCParticles mcParticles) + { + auto daughtersIds = mcParticle.daughtersIds(); + if (daughtersIds.size() != 2) + return false; + for (auto& daughterId : daughtersIds) { + if (mcParticles.iteratorAt(daughterId).pdgCode() != 22) + return false; + } + return true; + } + + template + bool isAccepted(TMCParticle mcParticle, TMCParticles mcParticles) + { + auto daughtersIds = mcParticle.daughtersIds(); + if (daughtersIds.size() != 2) + return false; + for (auto& daughterId : daughtersIds) { + if (mcParticles.iteratorAt(daughterId).pdgCode() != 22) + return false; + int iCellID = -1; + try { + iCellID = emcal::Geometry::GetInstance()->GetAbsCellIdFromEtaPhi(mcParticles.iteratorAt(daughterId).eta(), mcParticles.iteratorAt(daughterId).phi()); + } catch (emcal::InvalidPositionException& e) { + iCellID = -1; + } + if (iCellID == -1) + return false; + } + return true; + } + + void fillEventHistogram(HistogramRegistry* fRegistry, MyMCCollisions::iterator const& collision) + { + fRegistry->fill(HIST("hEMCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + fRegistry->fill(HIST("hEMCollisionCounter"), 2.0); + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + fRegistry->fill(HIST("hEMCollisionCounter"), 3.0); + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + fRegistry->fill(HIST("hEMCollisionCounter"), 4.0); + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + fRegistry->fill(HIST("hEMCollisionCounter"), 5.0); + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + fRegistry->fill(HIST("hEMCollisionCounter"), 6.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) + fRegistry->fill(HIST("hEMCollisionCounter"), 7.0); + if (collision.sel8()) + fRegistry->fill(HIST("hEMCollisionCounter"), 8.0); + if (abs(collision.posZ()) < 10.0) + fRegistry->fill(HIST("hEMCollisionCounter"), 9.0); + if (collision.alias_bit(kTVXinEMC)) + fRegistry->fill(HIST("hEMCollisionCounter"), 10.0); + if (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7)) + fRegistry->fill(HIST("hEMCollisionCounter"), 11.0); + if (collision.isemcreadout()) + fRegistry->fill(HIST("hEMCollisionCounter"), 12.0); + fRegistry->fill(HIST("hEMCollisionCounter"), 13.0); + + fRegistry->fill(HIST("hCollisionCounter"), 1); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry->fill(HIST("hCollisionCounter"), 2); + if (abs(collision.posZ()) < mVertexCut) { + fRegistry->fill(HIST("hCollisionCounter"), 3); + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + fRegistry->fill(HIST("hCollisionCounter"), 4); + if (mRequireEMCCellContent ? collision.isemcreadout() : collision.alias_bit(kTVXinEMC)) { + fRegistry->fill(HIST("hCollisionCounter"), 5); + if (collision.sel8()) { + fRegistry->fill(HIST("hCollisionCounter"), 6); + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry->fill(HIST("hCollisionCounter"), 7); + } } } } diff --git a/PWGJE/Tasks/nucleiInJets.cxx b/PWGJE/Tasks/nucleiInJets.cxx new file mode 100644 index 00000000000..897774b8874 --- /dev/null +++ b/PWGJE/Tasks/nucleiInJets.cxx @@ -0,0 +1,1172 @@ +// Copyright 2019-2020 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. + +// author: Arvind Khuntia (arvind.khuntia@cern.ch) INFN Bologna, Italy + +#include +#include + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "CommonConstants/PhysicsConstants.h" +#include "ReconstructionDataFormats/Track.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +struct nucleiInJets { + + enum Particle { + kPion = 1, // π+ + kKaon = 2, // K+ + kProton = 3, // p + kDeuteron = 4, // d + kTriton = 5, // Tr + kHelium = 6 // He + }; + + int mapPDGToValue(int pdgCode) + { + switch (pdgCode) { + case 211: // π+ + return Particle::kPion; + case -211: // π- + return -Particle::kPion; + + case 321: // k+ + return Particle::kKaon; + case -321: // k- + return -Particle::kKaon; + + case 2212: // p + return Particle::kProton; + case -2212: // antip + return -Particle::kProton; + + case 1000010020: // Deuteron + return Particle::kDeuteron; + case -1000010020: // AntiDeuteron + return -Particle::kDeuteron; + + case 1000010030: // Triton + return Particle::kTriton; + case -1000010030: // AntiTriton + return -Particle::kTriton; + + case 1000020030: // Helium + return Particle::kHelium; + case -1000020030: // AntiHelium + return -Particle::kHelium; + default: + return 0; // Default case for unknown or unmapped PDG codes + } + } + + Configurable cfgeventSelections{"cfgeventSelections", "sel8", "choose event selection"}; + Configurable cfgtrackSelections{"cfgtrackSelections", "globalTracks", "set track selections"}; + + Configurable isMC{"isMC", false, "flag for the MC"}; + Configurable cfgtrkMinPt{"cfgtrkMinPt", 0.15, "set track min pT"}; + Configurable cfgtrkMaxEta{"cfgtrkMaxEta", 0.8, "set track max Eta"}; + Configurable cfgtrkMaxRap{"cfgtrkMaxRap", 0.5, "set track max y"}; + Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.12, "Track DCAr cut to PV Maximum"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 1.0, "Track DCAz cut to PV Maximum"}; + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; + Configurable cfgConnectedToPV{"cfgConnectedToPV", true, "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgnFindableTPCClusters{"cfgnFindableTPCClusters", 120, "nFindable TPC Clusters"}; + Configurable cfgnTPCCrossedRows{"cfgnTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfgnTPCChi2{"cfgnTPChi2", 4.0, "nTPC Chi2 per Cluster"}; + Configurable cfgnITSChi2{"cfgnITShi2", 36.0, "nITS Chi2 per Cluster"}; + + Configurable cfgjetPtMin{"cfgjetPtMin", 5.0, "minimum jet pT cut"}; + Configurable cfgjetR{"cfgjetR", 0.4, "jet resolution parameter"}; + Configurable cDebugLevel{"cDebugLevel", 0, "print debug msg"}; + Configurable cMaxPt{"cMaxPt", 10, "max pt for Hist"}; + + Configurable cfgnTPCPIDPr{"cfgnTPCPIDPr", 3, "nTPC PID Pr"}; + Configurable cfgnTPCPIDDe{"cfgnTPCPIDDe", 3, "nTPC PID De"}; + Configurable cfgnTPCPIDHe{"cfgnTPCPIDHe", 3, "nTPC PID He"}; + Configurable cfgnTPCPIDTr{"cfgnTPCPIDTr", 3, "nTPC PID Tr"}; + + Configurable cEnableProtonQA{"cEnableProtonQA", true, "nTPC PID Pr"}; + Configurable cEnableDeuteronQA{"cEnableDeuteronQA", true, "nTPC PID De"}; + Configurable cEnableHeliumQA{"cEnableHeliumQA", true, "nTPC PID He"}; + Configurable cEnableTritonQA{"cEnableTritonQA", true, "nTPC PID Tr"}; + Configurable addTOFplots{"addTOFplots", true, "add TOF plots"}; + Configurable useTPCpreSel{"useTPCpreSel", 3, "add TPC nsgma preselection for TOF: (0) no selection (!0) selction on TPC"}; + + Configurable addpik{"addpik", true, "add pion and kaon hist"}; + + ConfigurableAxis binsDCA{"binsDCA", {400, -1.f, 1.f}, ""}; + ConfigurableAxis binsdEdx{"binsdEdx", {1000, 0.f, 1000.f}, ""}; + ConfigurableAxis binsBeta{"binsBeta", {120, 0.0, 1.2}, ""}; + + ConfigurableAxis binsMassPr{"binsMassPr", {100, -1., 1.f}, ""}; + ConfigurableAxis binsMassDe{"binsMassDe", {180, -1.8, 1.8f}, ""}; + ConfigurableAxis binsMassTr{"binsMassTr", {250, -2.5, 2.5f}, ""}; + ConfigurableAxis binsMassHe{"binsMassHe", {300, -3., 3.f}, ""}; + + ConfigurableAxis binsPtZHe{"binsPtZHe", {VARIABLE_WIDTH, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.375, 1.5, 1.625, 1.75, 1.875, 2.0, 2.25, 2.5, 3.0, 3.5, 4.0}, ""}; + + static constexpr float gMassProton = 0.93827208f; + static constexpr float gMassDeuteron = 1.87561f; + static constexpr float gMassTriton = 2.80892f; + static constexpr float gMassHelium = 2.80839f; + static constexpr int PDGProton = 2212; + static constexpr int PDGDeuteron = 1000010020; + static constexpr int PDGTriton = 1000010030; + static constexpr int PDGHelium = 1000020030; + + using EventCandidates = soa::Join; // , aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs + using TrackCandidates = soa::Join; + + using TrackCandidatesMC = soa::Join; + + Filter jetCuts = aod::jet::pt > cfgjetPtMin&& aod::jet::r == nround(cfgjetR.node() * 100.0f); + + using chargedJetstrack = soa::Filtered>; + using JetMCPartTable = soa::Filtered>; + using JetMCDetTable = soa::Filtered>; + + SliceCache cache; + HistogramRegistry jetHist{"jetHist", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + const AxisSpec PtAxis = {100, 0, 10.0}; + const AxisSpec PtJetAxis = {300, 0, 30.0}; + const AxisSpec MultAxis = {100, 0, 100}; + const AxisSpec dRAxis = {100, 0, 3.6}; + const AxisSpec dcaxyAxis{binsDCA, "DCAxy (cm)"}; + const AxisSpec dcazAxis{binsDCA, "DCAz (cm)"}; + const AxisSpec dedxAxis{binsdEdx, "d#it{E}/d#it{x} A.U."}; + + const AxisSpec betaAxis{binsBeta, "TOF #beta"}; + const AxisSpec ptZHeAxis{binsPtZHe, "#it{p}_{T}"}; + + const AxisSpec massPrAxis{binsMassPr, ""}; + const AxisSpec massDeAxis{binsMassDe, ""}; + const AxisSpec massTrAxis{binsMassTr, ""}; + const AxisSpec massHeAxis{binsMassHe, ""}; + + // jet property + jetHist.add("jet/h1JetPt", "jet_{p_{T}}", kTH1F, {PtJetAxis}); + jetHist.add("jet/h1JetEta", "jet_{#eta}", kTH1F, {{100, -1.0, 1.0}}); + jetHist.add("jet/h1JetPhi", "jet_{#phi}", kTH1F, {{80, -1.0, 7.}}); + jetHist.add("jet/nJetsPerEvent", "nJetsPerEvent", kTH1F, {{15, .0, 15.}}); + jetHist.add("mcpJet/nJetsPerEvent", "nJetsPerEvent", kTH1F, {{15, .0, 15.}}); + jetHist.add("mcdJet/nJetsPerEvent", "nJetsPerEvent", kTH1F, {{15, .0, 15.}}); + jetHist.add("jet/vertexZ", "vertexZ (Jet flag)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("vertexZ", "vertexZ (all)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("jetOut/vertexZ", "vertexZ (without z-flag)", kTH1F, {{100, -15.0, 15.0}}); + //////////////////////////// + // MC + //////////////////////////// + jetHist.add("mcpJet/eventStat", "vertexZ (All)", kTH1F, {{5, .0, 5.0}}); + auto h = jetHist.get(HIST("mcpJet/eventStat")); + h->GetXaxis()->SetBinLabel(1, "All"); + h->GetXaxis()->SetBinLabel(2, "Sel8-goodRecJet"); + h->GetXaxis()->SetBinLabel(3, "vz< 10"); + h->GetXaxis()->SetBinLabel(4, "ingt0"); + + jetHist.add("mcpJet/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("mcdJet/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("mcdJet/eventStat", "vertexZ (All)", kTH1F, {{5, .0, 5.0}}); + auto h1 = jetHist.get(HIST("mcdJet/eventStat")); + h1->GetXaxis()->SetBinLabel(1, "All"); + h1->GetXaxis()->SetBinLabel(2, "Sel8-goodRecJet"); + h1->GetXaxis()->SetBinLabel(3, "vz< 10"); + h1->GetXaxis()->SetBinLabel(4, "ingt0"); + + jetHist.add("recmatched/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("genmatched/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); + + ////////////////////////////////////////////// + // inside jet + ////////////////////////////////////////////// + if (addpik) { + jetHist.add("tracks/pion/h3PtVsPionNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/antiPion/h3PtVsPionNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/kaon/h3PtVsKaonNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/antiKaon/h3PtVsKaonNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + } + jetHist.add("tracks/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet", "pT(#bar{p}) vs NSigmaTPC (#bar{p}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet_jet", "pT(d) vs NSigmaTPC (d) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet_jet", "pT(#bar{d}) vs NSigmaTPC (#bar{d}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet", "pT(He) vs NSigmaTPC (He) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet", "pT(#bar{He}) vs NSigmaTPC (#bar{He}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet", "pT(Tr) vs NSigmaTPC (Tr) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet", "pT(#bar{Tr}) vs NSigmaTPC (#bar{Tr}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + + if (cEnableProtonQA) { + jetHist.add("tracks/proton/dca/after/hDCAxyVsPtProton_jet", "DCAxy vs Pt (p)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/after/hDCAxyVsPtantiProton_jet", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/proton/dca/after/hDCAzVsPtProton_jet", "DCAz vs Pt (p)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/after/hDCAzVsPtantiProton_jet", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableDeuteronQA) { + jetHist.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteron_jet", "DCAxy vs Pt (d)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/after/hDCAxyVsPtantiDeuteron_jet", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteron_jet", "DCAz vs Pt (d)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/after/hDCAzVsPtantiDeuteron_jet", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableTritonQA) { + jetHist.add("tracks/triton/dca/after/hDCAxyVsPtTriton_jet", "DCAxy vs Pt (t)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/after/hDCAxyVsPtantiTriton_jet", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/triton/dca/after/hDCAzVsPtTriton_jet", "DCAz vs Pt (t)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/after/hDCAzVsPtantiTriton_jet", "DCAz vs Pt (#bar{t})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + if (cEnableHeliumQA) { + jetHist.add("tracks/helium/dca/after/hDCAxyVsPtHelium_jet", "DCAxy vs Pt (He)", HistType::kTH2F, {{dcaxyAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/after/hDCAxyVsPtantiHelium_jet", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{dcaxyAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/helium/dca/after/hDCAzVsPtHelium_jet", "DCAz vs Pt (He)", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/after/hDCAzVsPtantiHelium_jet", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + } + + jetHist.add("tracks/h2TPCsignVsTPCmomentum", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, -5.f, 5.f}, {dedxAxis}}); + jetHist.add("tracks/h2TPCsignVsTPCmomentum_Jet", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, -5.f, 5.f}, {dedxAxis}}); + jetHist.add("tracks/h2TPCsignVsTPCmomentum_OutJet", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, -5.f, 5.f}, {dedxAxis}}); + + jetHist.add("tracks/h2TOFbetaVsP_Jet", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); + jetHist.add("tracks/h2TOFbetaVsP_OutJet", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); + jetHist.add("tracks/h2TOFbetaVsP", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); + + // TOF hist + jetHist.add("tracks/proton/h2TOFmassProtonVsPt_jet", "h2TOFmassProtonVsPt_jet; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/antiProton/h2TOFmassantiProtonVsPt_jet", "h2TOFmassantiProtonVsPt_jet; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/proton/h2TOFmass2ProtonVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); + jetHist.add("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); + + jetHist.add("tracks/deuteron/h2TOFmassDeuteronVsPt_jet", "h2TOFmassDeuteronVsPt_jet; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt_jet", "h2TOFmassantiDeuteronVsPt_jet; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + jetHist.add("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + + jetHist.add("tracks/triton/h2TOFmassTritonVsPt_jet", "h2TOFmassTritonVsPt_jet; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/antiTriton/h2TOFmassantiTritonVsPt_jet", "h2TOFmassantiTritonVsPt_jet; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/triton/h2TOFmass2TritonVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); + jetHist.add("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); + + jetHist.add("tracks/helium/h2TOFmassHeliumVsPt_jet", "h2TOFmassHeliumVsPt_jet; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); + jetHist.add("tracks/antiHelium/h2TOFmassantiHeliumVsPt_jet", "h2TOFmassantiHeliumVsPt_jet; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); + jetHist.add("tracks/helium/h2TOFmass2HeliumVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}t; TOFmass2; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); + jetHist.add("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); + + // TOF hist nSigma + if (addpik) { + jetHist.add("tracks/pion/h2TofNsigmaPionVsPt_jet", "h2TofNsigmaPionVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiPion/h2TofNsigmaantiPionVsPt_jet", "h2TofNsigmaantiPionVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/kaon/h2TofNsigmaKaonVsPt_jet", "h2TofNsigmaKaonVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiKaon/h2TofNsigmaantiKaonVsPt_jet", "h2TofNsigmaantiKaonVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + } + jetHist.add("tracks/proton/h2TofNsigmaProtonVsPt_jet", "h2TofNsigmaProtonVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiProton/h2TofNsigmaantiProtonVsPt_jet", "h2TofNsigmaantiProtonVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/deuteron/h2TofNsigmaDeuteronVsPt_jet", "h2TofNsigmaDeuteronVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt_jet", "h2TofNsigmaantiDeuteronVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/triton/h2TofNsigmaTritonVsPt_jet", "h2TofNsigmaTritonVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiTriton/h2TofNsigmaantiTritonVsPt_jet", "h2TofNsigmaantiTritonVsPt_jet; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/helium/h2TofNsigmaHeliumVsPt_jet", "h2TofNsigmaHeliumVsPt_jet; TofNsigma; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt_jet", "h2TofNsigmaantiHeliumVsPt_jet; TofNsigma; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + ////////////////////////////////////////////// + // outside jet + ////////////////////////////////////////////// + jetHist.add("tracks/proton/h3PtVsProtonNSigmaTPC", "pT(p) vs NSigmaTPC (p); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/antiProton/h3PtVsantiProtonNSigmaTPC", "pT(#bar{p}) vs NSigmaTPC (#bar{p}); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/deuteron/h3PtVsDeuteronNSigmaTPC", "pT(d) vs NSigmaTPC (d); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPC", "pT(#bar{d}) vs NSigmaTPC (#bar{d}); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/helium/h3PtVsHeliumNSigmaTPC", "pT(He) vs NSigmaTPC (He); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPC", "pT(#bar{He}) vs NSigmaTPC (#bar{He}); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/triton/h3PtVsTritonNSigmaTPC", "pT(Tr) vs NSigmaTPC(Tr); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + jetHist.add("tracks/antiTriton/h3PtVsantiTritonNSigmaTPC", "pT(#barTr}) vs NSigmaTPC (#bar{Tr}); #it{p}_{T} (GeV/#it{c}; NSigmaTPC;", HistType::kTH2F, {{PtAxis}, {200, -10, 10}}); + + if (cEnableProtonQA) { + jetHist.add("tracks/proton/dca/after/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/after/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/proton/dca/after/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/after/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + if (cEnableDeuteronQA) { + jetHist.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/after/hDCAxyVsPtantiDeuteron", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/after/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + if (cEnableTritonQA) { + jetHist.add("tracks/triton/dca/after/hDCAxyVsPtTriton", "DCAxy vs Pt (t)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/after/hDCAxyVsPtantiTriton", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/triton/dca/after/hDCAzVsPtTriton", "DCAz vs Pt (t)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/after/hDCAzVsPtantiTriton", "DCAz vs Pt (#bar{t})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + if (cEnableHeliumQA) { + jetHist.add("tracks/helium/dca/after/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{dcaxyAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/after/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{dcaxyAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/helium/dca/after/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/after/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + } + + // TOF hist #DeltaMass2 + jetHist.add("tracks/proton/h2TOFmassProtonVsPt", "h2TOFmassProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/antiProton/h2TOFmassantiProtonVsPt", "h2TOFmassantiProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/proton/h2TOFmass2ProtonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); + jetHist.add("tracks/antiProton/h2TOFmass2antiProtonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); + + jetHist.add("tracks/deuteron/h2TOFmassDeuteronVsPt", "h2TOFmassDeuteronVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt", "h2TOFmassantiDeuteronVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/deuteron/h2TOFmass2DeuteronVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + jetHist.add("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + + jetHist.add("tracks/triton/h2TOFmassTritonVsPt", "h2TOFmassTritonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/antiTriton/h2TOFmassantiTritonVsPt", "h2TOFmassantiTritonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{80, 0.4, 4.}, {50, 0., 5.}}); + jetHist.add("tracks/triton/h2TOFmass2TritonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); + jetHist.add("tracks/antiTriton/h2TOFmass2antiTritonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); + + jetHist.add("tracks/helium/h2TOFmassHeliumVsPt", "h2TOFmassHeliumVsPt; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); + jetHist.add("tracks/antiHelium/h2TOFmassantiHeliumVsPt", "h2TOFmassantiHeliumVsPt; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); + jetHist.add("tracks/helium/h2TOFmass2HeliumVsPt", "#Delta M^{2} (t) vs #it{p}_{T}t; TOFmass2; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); + jetHist.add("tracks/antiHelium/h2TOFmass2antiHeliumVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); + + // TOF hist nSigma + jetHist.add("tracks/proton/h2TofNsigmaProtonVsPt", "h2TofNsigmaProtonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiProton/h2TofNsigmaantiProtonVsPt", "h2TofNsigmaantiProtonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/deuteron/h2TofNsigmaDeuteronVsPt", "h2TofNsigmaDeuteronVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt", "h2TofNsigmaantiDeuteronVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/triton/h2TofNsigmaTritonVsPt", "h2TofNsigmaTritonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiTriton/h2TofNsigmaantiTritonVsPt", "h2TofNsigmaantiTritonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/helium/h2TofNsigmaHeliumVsPt", "h2TofNsigmaHeliumVsPt; TofNsigma; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + jetHist.add("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt", "h2TofNsigmaantiHeliumVsPt; TofNsigma; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); + + if (isMC) { + // inside jet + jetHist.add("tracks/mc/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet", "pT(#bar{p}) vs NSigmaTPC (#bar{p}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet_jet", "pT(d) vs NSigmaTPC (d) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet_jet", "pT(#bar{d}) vs NSigmaTPC (#bar{d}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet", "pT(He) vs NSigmaTPC (He) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet", "pT(#bar{He}) vs NSigmaTPC (#bar{He}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet", "pT(Tr) vs NSigmaTPC (Tr) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + jetHist.add("tracks/mc/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet", "pT(#bar{Tr}) vs NSigmaTPC (#bar{Tr}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); + + if (cEnableProtonQA) { + jetHist.add("tracks/proton/dca/before/hDCAxyVsPtProton_jet", "DCAxy vs Pt (p)", HistType::kTH2F, {{PtAxis}, {dcaxyAxis}}); + jetHist.add("tracks/antiProton/dca/before/hDCAxyVsPtantiProton_jet", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{PtAxis}, {dcaxyAxis}}); + jetHist.add("tracks/proton/dca/before/hDCAzVsPtProton_jet", "DCAz vs Pt (p)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/before/hDCAzVsPtantiProton_jet", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableDeuteronQA) { + jetHist.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron_jet", "DCAxy vs Pt (d)", HistType::kTH2F, {{PtAxis}, {dcaxyAxis}}); + jetHist.add("tracks/antiDeuteron/dca/before/hDCAxyVsPtantiDeuteron_jet", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{PtAxis}, {dcaxyAxis}}); + jetHist.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteron_jet", "DCAz vs Pt (d)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/before/hDCAzVsPtantiDeuteron_jet", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableTritonQA) { + jetHist.add("tracks/triton/dca/before/hDCAxyVsPtTriton_jet", "DCAxy vs Pt (t)", HistType::kTH2F, {{PtAxis}, {dcaxyAxis}}); + jetHist.add("tracks/antiTriton/dca/before/hDCAxyVsPtantiTriton_jet", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{PtAxis}, {dcaxyAxis}}); + jetHist.add("tracks/triton/dca/before/hDCAzVsPtTriton_jet", "DCAz vs Pt (t)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/before/hDCAzVsPtantiTriton_jet", "DCAz vs Pt (#bar{t})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableHeliumQA) { + jetHist.add("tracks/helium/dca/before/hDCAxyVsPtHelium_jet", "DCAxy vs Pt (He)", HistType::kTH2F, {{dcaxyAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/before/hDCAxyVsPtantiHelium_jet", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{dcaxyAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/helium/dca/before/hDCAzVsPtHelium_jet", "DCAz vs Pt (He)", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/before/hDCAzVsPtantiHelium_jet", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + } + + // outside jet + if (cEnableProtonQA) { + jetHist.add("tracks/proton/dca/before/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/before/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/proton/dca/before/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiProton/dca/before/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableDeuteronQA) { + jetHist.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/before/hDCAxyVsPtantiDeuteron", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiDeuteron/dca/before/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableTritonQA) { + jetHist.add("tracks/triton/dca/before/hDCAxyVsPtTriton", "DCAxy vs Pt (t)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/before/hDCAxyVsPtantiTriton", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracks/triton/dca/before/hDCAzVsPtTriton", "DCAz vs Pt (t)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracks/antiTriton/dca/before/hDCAzVsPtantiTriton", "DCAz vs Pt (#bar{t})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + } + + if (cEnableHeliumQA) { + jetHist.add("tracks/helium/dca/before/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{450, 0.5f, 5.f}, {dcaxyAxis}}); + jetHist.add("tracks/antiHelium/dca/before/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{450, 0.5f, 5.f}, {dcaxyAxis}}); + jetHist.add("tracks/helium/dca/before/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + jetHist.add("tracks/antiHelium/dca/before/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{dcazAxis}, {450, 0.5f, 5.f}}); + } + + // PartilceJet-constituents + jetHist.add("mcpJet/pt/PtParticleType", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); + // detectorJet-constituents + jetHist.add("mcdJet/pt/PtParticleType", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); + + jetHist.add("mcpJet/hJetPt", "Pt (jet)", HistType::kTH1F, {{100, 0.f, 50.f}}); + jetHist.add("mcpJet/hJetEta", "Eta (jet)", HistType::kTH1F, {{100, 1.5, 1.5}}); + jetHist.add("mcpJet/hJetPhi", "Phi (jet)", HistType::kTH1F, {{70, 0.f, 7.f}}); + + jetHist.add("mcdJet/hJetPt", "Pt (jet)", HistType::kTH1F, {{100, 0.f, 50.f}}); + jetHist.add("mcdJet/hJetEta", "Eta (jet)", HistType::kTH1F, {{100, 1.5, 1.5}}); + jetHist.add("mcdJet/hJetPhi", "Phi (jet)", HistType::kTH1F, {{70, 0.f, 7.f}}); + + // rec matched + jetHist.add("recmatched/hRecMatchedJetPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH2F, {{100, 0., 100.}, {400, -20., 20.}}); + jetHist.add("recmatched/hRecMatchedJetPhi", "matched jet #varphi (Rec level);#varphi_{T,jet part}; #varphi_{jet part}-#varphi_{jet det}", HistType::kTH2F, {{700, 0., 7.}, {200, -5., 5.}}); + jetHist.add("recmatched/hRecMatchedJetEta", "matched jet #eta (Rec level);#eta_{T,jet part}; #eta_{jet part}-#eta_{jet det} ", HistType::kTH2F, {{200, -1., 1.}, {500, -2.5, 2.5}}); + + jetHist.add("recmatched/h2ResponseMatrix", "matched jet pT;#it{p}_{T} (true); #it{p}_{T} (measured)", HistType::kTH2F, {{40, 0., 100.}, {40, 0., 100.}}); + ///////// + jetHist.add("recmatched/hRecJetPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH1F, {{100, 0., 100.}}); + jetHist.add("recmatched/hGenJetPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH1F, {{100, 0., 100.}}); + + jetHist.add("recmatched/pt/PtParticleType", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); + + // gen matched + jetHist.add("genmatched/hRecMatchedJetPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH2F, {{100, 0., 100.}, {400, -20., 20.}}); + jetHist.add("genmatched/hRecMatchedJetPhi", "matched jet #varphi (Rec level);#varphi_{T,jet part}; #varphi_{jet part}-#varphi_{jet det}", HistType::kTH2F, {{700, 0., 7.}, {200, -5., 5.}}); + jetHist.add("genmatched/hRecMatchedJetEta", "matched jet #eta (Rec level);#eta_{T,jet part}; #eta_{jet part}-#eta_{jet det} ", HistType::kTH2F, {{200, -1., 1.}, {500, -2.5, 2.5}}); + + ///////// + jetHist.add("genmatched/hRecJetPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH1F, {{100, 0., 100.}}); + jetHist.add("genmatched/hGenJetPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH1F, {{100, 0., 100.}}); + jetHist.add("genmatched/hRecJetWithGenPt", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH1F, {{100, 0., 100.}}); + jetHist.add("genmatched/hGenJetPtMatched", "matched jet pT (Rec level);#it{p}_{T,jet part} (GeV/#it{c}); #it{p}_{T,jet part} - #it{p}_{T,jet det}", HistType::kTH1F, {{100, 0., 100.}}); + + jetHist.add("genmatched/pt/PtParticleType", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); + } + } + + template + bool isTrackSelected(const TrackType track) + { + // standard track selection + if (track.pt() < cfgtrkMinPt) + return false; + if (std::abs(track.eta()) > cfgtrkMaxEta) + return false; + if (std::abs(track.dcaXY()) > cfgMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) + return false; + if (track.tpcNClsFindable() < cfgnFindableTPCClusters) + return false; + if (track.tpcNClsCrossedRows() < cfgnTPCCrossedRows) + return false; + if (track.tpcChi2NCl() > cfgnTPCChi2) + return false; + if (track.itsChi2NCl() > cfgnITSChi2) + return false; + if (cfgConnectedToPV && !track.isPVContributor()) + return false; + return true; + } + + int nEvents = 0; + template + void fillTrackInfo(const TracksType& trk, const JetType& jets) + { + + if (!isTrackSelected(trk)) + return; + if (trk.pt() > cMaxPt) + return; + jetHist.fill(HIST("tracks/h2TPCsignVsTPCmomentum"), trk.tpcInnerParam() / (1.f * trk.sign()), trk.tpcSignal()); + bool jetFlag = false; + float jetPt = -999.; + for (auto const& jet : jets) { + double delPhi = TVector2::Phi_mpi_pi(jet.phi() - trk.phi()); + double delEta = jet.eta() - trk.eta(); + double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + if (R < cfgjetR) + jetFlag = true; + jetPt = jet.pt(); + break; + } + // tof + // float gamma =-999; + float massTOF = -999; + if (trk.hasTOF()) { + // gamma = 1.f / TMath::Sqrt(1.f - (trk.beta() * trk.beta())); + massTOF = trk.p() * TMath::Sqrt(1.f / (trk.beta() * trk.beta()) - 1.f); + } + + if (addTOFplots && trk.hasTOF()) { + jetHist.fill(HIST("tracks/h2TOFbetaVsP"), trk.p() / (1.f * trk.sign()), trk.beta()); + } + if (jetFlag) { + jetHist.fill(HIST("tracks/h2TPCsignVsTPCmomentum_Jet"), trk.tpcInnerParam() / (1.f * trk.sign()), trk.tpcSignal()); + if (addTOFplots && trk.hasTOF()) { + jetHist.fill(HIST("tracks/h2TOFbetaVsP_Jet"), trk.p() / (1.f * trk.sign()), trk.beta()); + } + if (trk.sign() > 0) { // particle info + if (addpik) { + jetHist.fill(HIST("tracks/pion/h3PtVsPionNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPi(), jetPt); + jetHist.fill(HIST("tracks/kaon/h3PtVsKaonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaKa(), jetPt); + } + jetHist.fill(HIST("tracks/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); + jetHist.fill(HIST("tracks/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); + jetHist.fill(HIST("tracks/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); + jetHist.fill(HIST("tracks/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + + if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProton_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProton_jet"), trk.dcaZ(), trk.pt()); + } + if (cEnableDeuteronQA && std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteron_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteron_jet"), trk.dcaZ(), trk.pt()); + } + if (cEnableTritonQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDTr) { + jetHist.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTriton_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTriton_jet"), trk.dcaZ(), trk.pt()); + } + if (cEnableHeliumQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { + jetHist.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHelium_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHelium_jet"), trk.dcaZ(), trk.pt()); + } + + if (addTOFplots && trk.hasTOF()) { + if (!useTPCpreSel) { + jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + + jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + + jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + + jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + + jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); + + } else { + if (trk.tpcNSigmaPr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); + } + + if (trk.tpcNSigmaDe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); + } + if (trk.tpcNSigmaTr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); + } + if (trk.tpcNSigmaHe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); + } + } + // nSigma + if (addpik) { + jetHist.fill(HIST("tracks/pion/h2TofNsigmaPionVsPt_jet"), trk.tofNSigmaPi(), trk.pt()); + jetHist.fill(HIST("tracks/kaon/h2TofNsigmaKaonVsPt_jet"), trk.tofNSigmaKa(), trk.pt()); + } + + } // tof info + + } else { // anti-particle info + if (addpik) { + jetHist.fill(HIST("tracks/antiPion/h3PtVsPionNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPi(), jetPt); + jetHist.fill(HIST("tracks/antiKaon/h3PtVsKaonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaKa(), jetPt); + } + jetHist.fill(HIST("tracks/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); + jetHist.fill(HIST("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); + jetHist.fill(HIST("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); + jetHist.fill(HIST("tracks/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + + if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracks/antiProton/dca/after/hDCAxyVsPtantiProton_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiProton/dca/after/hDCAzVsPtantiProton_jet"), trk.dcaZ(), trk.pt()); + } + if (cEnableDeuteronQA && std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracks/antiDeuteron/dca/after/hDCAxyVsPtantiDeuteron_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/dca/after/hDCAzVsPtantiDeuteron_jet"), trk.dcaZ(), trk.pt()); + } + if (cEnableHeliumQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { + jetHist.fill(HIST("tracks/antiTriton/dca/after/hDCAxyVsPtantiTriton_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/dca/after/hDCAzVsPtantiTriton_jet"), trk.dcaZ(), trk.pt()); + } + if (cEnableTritonQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { + jetHist.fill(HIST("tracks/antiHelium/dca/after/hDCAxyVsPtantiHelium_jet"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/dca/after/hDCAzVsPtantiHelium_jet"), trk.dcaZ(), trk.pt()); + } + + if (addTOFplots && trk.hasTOF()) { + if (!useTPCpreSel) { + jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); + + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); + + jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); + + jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); + } else { + if (trk.tpcNSigmaPr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); + } + if (trk.tpcNSigmaDe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); + } + if (trk.tpcNSigmaTr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); + } + if (trk.tpcNSigmaHe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt_jet"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); + } + } + + if (addpik) { + if (!useTPCpreSel) { + jetHist.fill(HIST("tracks/antiPion/h2TofNsigmaantiPionVsPt_jet"), trk.tofNSigmaPi(), trk.pt()); + jetHist.fill(HIST("tracks/antiKaon/h2TofNsigmaantiKaonVsPt_jet"), trk.tofNSigmaKa(), trk.pt()); + } else { + if (trk.tpcNSigmaPi() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiPion/h2TofNsigmaantiPionVsPt_jet"), trk.tofNSigmaPi(), trk.pt()); + } + if (trk.tpcNSigmaKa() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiKaon/h2TofNsigmaantiKaonVsPt_jet"), trk.tofNSigmaKa(), trk.pt()); + } + } + } // pikEnd + } + } // anti-particle + //////////////////////////////////////// + // within jet end + ////////////////////////////////////////// + } else { + jetHist.fill(HIST("tracks/h2TPCsignVsTPCmomentum_OutJet"), trk.tpcInnerParam() / (1.f * trk.sign()), trk.tpcSignal()); + if (addTOFplots && trk.hasTOF()) { + jetHist.fill(HIST("tracks/h2TOFbetaVsP_OutJet"), trk.p() / (1.f * trk.sign()), trk.beta()); + } + if (trk.sign() > 0) { + jetHist.fill(HIST("tracks/proton/h3PtVsProtonNSigmaTPC"), trk.pt(), trk.tpcNSigmaPr()); // Pr + jetHist.fill(HIST("tracks/deuteron/h3PtVsDeuteronNSigmaTPC"), trk.pt(), trk.tpcNSigmaDe()); // De + jetHist.fill(HIST("tracks/helium/h3PtVsHeliumNSigmaTPC"), trk.pt(), trk.tpcNSigmaHe()); // He + jetHist.fill(HIST("tracks/triton/h3PtVsTritonNSigmaTPC"), trk.pt(), trk.tpcNSigmaTr()); // Tr + + if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProton"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProton"), trk.dcaZ(), trk.pt()); + } + if (cEnableDeuteronQA && std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteron"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteron"), trk.dcaZ(), trk.pt()); + } + if (cEnableTritonQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDTr) { + jetHist.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTriton"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTriton"), trk.dcaZ(), trk.pt()); + } + if (cEnableHeliumQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { + jetHist.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHelium"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHelium"), trk.dcaZ(), trk.pt()); + } + if (addTOFplots && trk.hasTOF()) { + if (!useTPCpreSel) { + jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); + + jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); + + jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); + + jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); + } else { + if (trk.tpcNSigmaPr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); + } + if (trk.tpcNSigmaDe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); + } + if (trk.tpcNSigmaTr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); + } + if (trk.tpcNSigmaHe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); + } + } + + } // tof info + } else { + jetHist.fill(HIST("tracks/antiProton/h3PtVsantiProtonNSigmaTPC"), trk.pt(), trk.tpcNSigmaPr()); // Pr + jetHist.fill(HIST("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPC"), trk.pt(), trk.tpcNSigmaDe()); // De + jetHist.fill(HIST("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPC"), trk.pt(), trk.tpcNSigmaHe()); // He + jetHist.fill(HIST("tracks/antiTriton/h3PtVsantiTritonNSigmaTPC"), trk.pt(), trk.tpcNSigmaTr()); // Tr + + if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracks/antiProton/dca/after/hDCAxyVsPtantiProton"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiProton/dca/after/hDCAzVsPtantiProton"), trk.dcaZ(), trk.pt()); + } + if (cEnableDeuteronQA && std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracks/antiDeuteron/dca/after/hDCAxyVsPtantiDeuteron"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/dca/after/hDCAzVsPtantiDeuteron"), trk.dcaZ(), trk.pt()); + } + if (cEnableHeliumQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { + jetHist.fill(HIST("tracks/antiTriton/dca/after/hDCAxyVsPtantiTriton"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/dca/after/hDCAzVsPtantiTriton"), trk.dcaZ(), trk.pt()); + } + if (cEnableTritonQA && std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { + jetHist.fill(HIST("tracks/antiHelium/dca/after/hDCAxyVsPtantiHelium"), trk.dcaXY(), trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/dca/after/hDCAzVsPtantiHelium"), trk.dcaZ(), trk.pt()); + } + + if (addTOFplots && trk.hasTOF()) { + if (!useTPCpreSel) { + jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); + + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); + + jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); + + jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); + } else { + if (trk.tpcNSigmaPr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); + } + if (trk.tpcNSigmaDe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); + } + if (trk.tpcNSigmaTr() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); + } + if (trk.tpcNSigmaHe() < useTPCpreSel) { + jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt"), massTOF, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); + } + } + } + } + + } //////////////////////////////////////// + // outside jet + //////////////////////////////////////// + } + + void processJetTracksData(aod::JCollision const& collision, chargedJetstrack const& chargedjets, soa::Join const& tracks, TrackCandidates const&) + { + + if (fabs(collision.posZ()) > 10) + return; + if (!jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel8)) + return; + + int nJets = 0; + + for (const auto& chargedjet : chargedjets) { + jetHist.fill(HIST("jet/h1JetPt"), chargedjet.pt()); + jetHist.fill(HIST("jet/h1JetEta"), chargedjet.eta()); + jetHist.fill(HIST("jet/h1JetPhi"), chargedjet.phi()); + nJets++; + } + + jetHist.fill(HIST("jet/nJetsPerEvent"), nJets); + jetHist.fill(HIST("vertexZ"), collision.posZ()); + if (nJets > 0) + jetHist.fill(HIST("jet/vertexZ"), collision.posZ()); + else + jetHist.fill(HIST("jetOut/vertexZ"), collision.posZ()); + + for (auto& track : tracks) { + auto trk = track.track_as(); + fillTrackInfo(trk, chargedjets); + } + } + + void processMCGen(o2::aod::JMcCollision const& collision, /*soa::SmallGroups> const& recoColls,*/ aod::JMcParticles const& mcParticles, soa::Filtered const& mcpjets) + { + jetHist.fill(HIST("mcpJet/eventStat"), 0.5); + jetHist.fill(HIST("mcpJet/eventStat"), 1.5); + + if (fabs(collision.posZ()) > 10) // bad vertex + return; + + jetHist.fill(HIST("mcpJet/eventStat"), 2.5); + + jetHist.fill(HIST("mcpJet/vertexZ"), collision.posZ()); + + bool INELgt0 = false; + for (const auto& mcParticle : mcParticles) { + if (fabs(mcParticle.eta()) < cfgtrkMaxEta) { + INELgt0 = true; + break; + } + } + if (!INELgt0) // not true INEL + return; + + jetHist.fill(HIST("mcpJet/eventStat"), 3.5); + + int nJets = 0; + for (auto& mcpjet : mcpjets) { + jetHist.fill(HIST("mcpJet/hJetPt"), mcpjet.pt()); + jetHist.fill(HIST("mcpJet/hJetEta"), mcpjet.eta()); + jetHist.fill(HIST("mcpJet/hJetPhi"), mcpjet.phi()); + nJets++; + } + jetHist.fill(HIST("mcpJet/nJetsPerEvent"), nJets); + + for (const auto& mcParticle : mcParticles) { + + if (!mcParticle.isPhysicalPrimary()) + continue; + if (fabs(mcParticle.eta()) > cfgtrkMaxEta) + continue; + if (fabs(mcParticle.y()) > cfgtrkMaxRap) + continue; + + bool jetFlag = false; + // float jetPt = -999.; + for (auto& mcpjet : mcpjets) { + double delPhi = TVector2::Phi_mpi_pi(mcpjet.phi() - mcParticle.phi()); + double delEta = mcpjet.eta() - mcParticle.eta(); + double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + if (R < cfgjetR) + jetFlag = true; + // jetPt = mcpjet.pt(); + break; + } // jet + if (mapPDGToValue(mcParticle.pdgCode()) != 0) { + jetHist.fill(HIST("mcpJet/pt/PtParticleType"), mcParticle.pt(), jetFlag, mapPDGToValue(mcParticle.pdgCode())); + } + + } // track + } // process mc + + void processMCRec(o2::aod::JCollision const& collisionJet, soa::Join const& tracks, + soa::Filtered const& mcdjets, TrackCandidatesMC const&, JetParticles const&) + { + jetHist.fill(HIST("mcdJet/eventStat"), 0.5); + // JEhistos.fill(HIST("nEvents_MCRec"), 0.5); + + if (!jetderiveddatautilities::selectCollision(collisionJet, jetderiveddatautilities::JCollisionSel::sel8)) + return; + // bool jetFlag = kFALSE; + + jetHist.fill(HIST("mcdJet/eventStat"), 1.5); + + if (fabs(collisionJet.posZ()) > 10) + return; + + jetHist.fill(HIST("mcdJet/eventStat"), 2.5); + bool INELgt0 = false; + for (const auto& track : tracks) { + if (fabs(track.eta()) < cfgtrkMaxEta) { + INELgt0 = true; + break; + } + } + if (!INELgt0) + return; + jetHist.fill(HIST("mcdJet/eventStat"), 3.5); + int nJets = 0; + for (auto& mcdjet : mcdjets) { + jetHist.fill(HIST("mcdJet/hJetPt"), mcdjet.pt()); + jetHist.fill(HIST("mcdJet/hJetEta"), mcdjet.eta()); + jetHist.fill(HIST("mcdJet/hJetPhi"), mcdjet.phi()); + nJets++; + } + + jetHist.fill(HIST("mcdJet/vertexZ"), collisionJet.posZ()); + jetHist.fill(HIST("mcdJet/nJetsPerEvent"), nJets); + + for (auto& track : tracks) { + auto fullTrack = track.track_as(); + if (!isTrackSelected(fullTrack)) + continue; + if (!track.has_mcParticle()) + continue; + auto mcTrack = track.mcParticle_as(); + if (fabs(mcTrack.eta()) > cfgtrkMaxEta) + continue; + if (!mcTrack.isPhysicalPrimary()) + continue; + + bool jetFlag = false; + // float jetPt = -999.; + for (auto& mcdjet : mcdjets) { + double delPhi = TVector2::Phi_mpi_pi(mcdjet.phi() - track.phi()); + double delEta = mcdjet.eta() - track.eta(); + double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + if (R < cfgjetR) + jetFlag = true; + // jetPt = mcdjet.pt(); + break; + } // jet + + if (mapPDGToValue(mcTrack.pdgCode()) != 0) { + jetHist.fill(HIST("mcdJet/pt/PtParticleType"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); + } + + } // tracks + } + + void processRecMatched(aod::JCollision const& collision, JetMCDetTable const& mcdjets, + soa::Join const& tracks, + JetMCPartTable const&, TrackCandidatesMC const&, aod::JMcParticles const&) + { + if (fabs(collision.posZ()) > 10) + return; + if (!jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel8)) + return; + + jetHist.fill(HIST("recmatched/vertexZ"), collision.posZ()); + bool INELgt0 = false; + for (const auto& track : tracks) { + if (fabs(track.eta()) < cfgtrkMaxEta) { + INELgt0 = true; + break; + } + } + if (!INELgt0) + return; + + std::vector mcdJetPt{}; + std::vector mcdJetPhi{}; + std::vector mcdJetEta{}; + std::vector mcpJetPt{}; + std::vector mcpJetPhi{}; + std::vector mcpJetEta{}; + + for (auto& mcdjet : mcdjets) { + + if (!mcdjet.has_matchedJetGeo()) + continue; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + if (!mcpjet.has_matchedJetGeo()) + continue; + + mcdJetPt.push_back(mcdjet.pt()); + mcdJetPhi.push_back(mcdjet.phi()); + mcdJetEta.push_back(mcdjet.eta()); + mcpJetPt.push_back(mcpjet.pt()); + mcpJetPhi.push_back(mcpjet.phi()); + mcpJetEta.push_back(mcpjet.eta()); + + jetHist.fill(HIST("recmatched/hRecMatchedJetPt"), mcpjet.pt(), mcpjet.pt() - mcdjet.pt()); + jetHist.fill(HIST("recmatched/hRecMatchedJetPhi"), mcpjet.phi(), mcpjet.phi() - mcdjet.phi()); + jetHist.fill(HIST("recmatched/hRecMatchedJetEta"), mcpjet.eta(), mcpjet.eta() - mcdjet.eta()); + + jetHist.fill(HIST("recmatched/hRecJetPt"), mcdjet.pt()); + jetHist.fill(HIST("recmatched/hGenJetPt"), mcpjet.pt()); + jetHist.fill(HIST("recmatched/h2ResponseMatrix"), mcpjet.pt(), mcdjet.pt()); + + } // mcpJet + + } // mcdJet + + for (const auto& track : tracks) { + auto completeTrack = track.track_as(); + if (fabs(completeTrack.eta()) > cfgtrkMaxEta) + continue; + if (!isTrackSelected(completeTrack)) + continue; + if (!track.has_mcParticle()) + continue; + auto mcTrack = track.mcParticle_as(); + // add pid later + + bool jetFlag = false; + for (int iDJet = 0; iDJet < mcdJetPt.size(); iDJet++) { + double delPhi = TVector2::Phi_mpi_pi(mcdJetPhi[iDJet] - track.phi()); + double delEta = mcdJetEta[iDJet] - track.eta(); + double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + + if (R < cfgjetR) { + jetFlag = true; + break; + } + } + + if (mapPDGToValue(mcTrack.pdgCode()) != 0) { + jetHist.fill(HIST("recmatched/pt/PtParticleType"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); + } + } // tracks + } // process + + int nprocessSimJEEvents = 0; + void processGenMatched(aod::JMcCollision const& collision, + /*soa::SmallGroups> const& recocolls,*/ + JetMCDetTable const&, JetMCPartTable const& mcpjets, aod::JMcParticles const& mcParticles) + { + + if (cDebugLevel > 0) { + nprocessSimJEEvents++; + if ((nprocessSimJEEvents + 1) % 100000 == 0) + LOG(debug) << "Jet Events: " << nprocessSimJEEvents; + } + if (fabs(collision.posZ()) > 10) + return; + + jetHist.fill(HIST("genmatched/vertexZ"), collision.posZ()); + + bool INELgt0 = false; + for (const auto& mcParticle : mcParticles) { + if (fabs(mcParticle.eta()) < cfgtrkMaxEta) { + INELgt0 = true; + break; + } + } + if (!INELgt0) + return; + + std::vector mcdJetPt{}; + std::vector mcdJetPhi{}; + std::vector mcdJetEta{}; + std::vector mcpJetPt{}; + std::vector mcpJetPhi{}; + std::vector mcpJetEta{}; + + for (auto& mcpjet : mcpjets) { + jetHist.fill(HIST("genmatched/hGenJetPt"), mcpjet.pt()); + if (!mcpjet.has_matchedJetGeo()) + continue; + jetHist.fill(HIST("genmatched/hGenJetPtMatched"), mcpjet.pt()); + for (auto& mcdjet : mcpjet.template matchedJetGeo_as()) { + if (!mcdjet.has_matchedJetGeo()) + continue; + mcdJetPt.push_back(mcdjet.pt()); + mcdJetPhi.push_back(mcdjet.phi()); + mcdJetEta.push_back(mcdjet.eta()); + mcpJetPt.push_back(mcpjet.pt()); + mcpJetPhi.push_back(mcpjet.phi()); + mcpJetEta.push_back(mcpjet.eta()); + + jetHist.fill(HIST("genmatched/hRecJetPt"), mcpjet.pt()); + jetHist.fill(HIST("genmatched/hRecJetWithGenPt"), mcdjet.pt()); + jetHist.fill(HIST("genmatched/hRecMatchedJetPt"), mcpjet.pt(), mcpjet.pt() - mcdjet.pt()); + jetHist.fill(HIST("genmatched/hRecMatchedJetPhi"), mcpjet.phi(), mcpjet.phi() - mcdjet.phi()); + jetHist.fill(HIST("genmatched/hRecMatchedJetEta"), mcpjet.eta(), mcpjet.eta() - mcdjet.eta()); + + } // mcdJet + } // mcpJet + + for (const auto& mcParticle : mcParticles) { + if (fabs(mcParticle.eta()) > cfgtrkMaxEta) + continue; + // add pid later + + bool jetFlag = false; + for (int iDJet = 0; iDJet < mcpJetPt.size(); iDJet++) { + double delPhi = TVector2::Phi_mpi_pi(mcpJetPhi[iDJet] - mcParticle.phi()); + double delEta = mcpJetEta[iDJet] - mcParticle.eta(); + double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + + if (R < cfgjetR) { + jetFlag = true; + break; + } + } // DetJet + if (mapPDGToValue(mcParticle.pdgCode()) != 0) { + jetHist.fill(HIST("genmatched/pt/PtParticleType"), mcParticle.pt(), jetFlag, mapPDGToValue(mcParticle.pdgCode())); + } + } // jet constituents + + } // process + + PROCESS_SWITCH(nucleiInJets, processJetTracksData, "nuclei in Jets data", true); + PROCESS_SWITCH(nucleiInJets, processMCRec, "nuclei in Jets for detectorlevel Jets", true); + PROCESS_SWITCH(nucleiInJets, processMCGen, "nuclei in Jets MC particlelevel Jets", false); + PROCESS_SWITCH(nucleiInJets, processRecMatched, "nuclei in Jets rec matched", false); + PROCESS_SWITCH(nucleiInJets, processGenMatched, "nuclei in Jets gen matched", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"nuclei-in-jets"})}; +}; diff --git a/PWGJE/Tasks/phiInJets.cxx b/PWGJE/Tasks/phiInJets.cxx index 63cda10911c..19adf76e3b8 100644 --- a/PWGJE/Tasks/phiInJets.cxx +++ b/PWGJE/Tasks/phiInJets.cxx @@ -49,20 +49,6 @@ struct phiInJets { SliceCache cache; HistogramRegistry JEhistos{"JEhistos", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry registry{"registry", - {{"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{4000, 0., 200.}}}}, - {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_matched_REC_jet_pt", "matched_REC level jet pT;#it{p}_{T,jet part} (GeV/#it{c});Delta", {HistType::kTH2F, {{200, 0., 200.}, {400, -20., 20.}}}}, - {"h_matched_REC_jet_eta", "matched_REC level jet #eta;#eta_{jet part};Delta", {HistType::kTH2F, {{100, -1.0, 1.0}, {400, -20., 20.}}}}, - {"h_matched_REC_jet_phi", "matched_REC level jet #phi;#phi_{jet part};Delta", {HistType::kTH2F, {{80, -1.0, 7.}, {400, -20., 20.}}}}, - {"h_matched_GEN_jet_pt", "matched_GEN level jet pT;#it{p}_{T,jet part} (GeV/#it{c});Delta", {HistType::kTH2F, {{200, 0., 200.}, {400, -20., 20.}}}}, - {"h_matched_GEN_jet_eta", "matched_GEN level jet #eta;#eta_{jet part};Delta", {HistType::kTH2F, {{100, -1.0, 1.0}, {400, -20., 20.}}}}, - {"h_matched_GEN_jet_phi", "matched_GEN level jet #phi;#phi_{jet part};Delta", {HistType::kTH2F, {{80, -1.0, 7.}, {400, -20., 20.}}}}, - {"h_part_jet_pt", "particle level jet pT;#it{p}_{T,jet part} (GeV/#it{c});entries", {HistType::kTH1F, {{4000, 0., 200.}}}}, - {"h_part_jet_eta", "particle level jet #eta;#eta_{jet part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h_part_jet_phi", "particle level jet #phi;#phi_{jet part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}}}; - Configurable cfgeventSelections{"cfgeventSelections", "sel8", "choose event selection"}; Configurable cfgtrackSelections{"cfgtrackSelections", "globalTracks", "set track selections"}; @@ -86,6 +72,14 @@ struct phiInJets { Configurable cDebugLevel{"cDebugLevel", 0, "Resolution of Debug"}; Configurable cfgBR{"cfgBR", false, "Forces Gen. Charged BR Only"}; Configurable cfgSimPID{"cfgSimPID", false, "Enforces PID on the Gen. Rec level"}; + Configurable cfgSingleJet{"cfgSingleJet", false, "Enforces strict phi-jet correspondance"}; + Configurable cfgIsKstar{"cfgIsKstar", false, "Swaps Phi for Kstar analysis"}; + Configurable cfgDataHists{"cfgDataHists", false, "Enables DataHists"}; + Configurable cfgMCRecHists{"cfgMCRecHists", false, "Enables MCRecHists"}; + Configurable cfgMCGenHists{"cfgMCGenHists", false, "Enables MCGenHists"}; + Configurable cfgMCGenMATCHEDHists{"cfgMCGenMATCHEDHists", false, "Enables MCGenMATCHEDHists"}; + Configurable cfgMCRecMATCHEDHists{"cfgMCRecMATCHEDHists", false, "Enables MCRecMATCHEDHists"}; + // CONFIG DONE ///////////////////////////////////////// //INIT @@ -97,135 +91,184 @@ struct phiInJets { const AxisSpec axisEta{30, -1.5, +1.5, "#eta"}; const AxisSpec axisPhi{200, -1, +7, "#phi"}; const AxisSpec axisPt{200, 0, +200, "#pt"}; - const AxisSpec MinvAxis = {400, 0.95, 1.35}; + const AxisSpec MinvAxis = {500, 0.75, 1.25}; const AxisSpec PtAxis = {200, 0, 20.0}; const AxisSpec MultAxis = {100, 0, 100}; - const AxisSpec dRAxis = {100, 0, 3.6}; - - JEhistos.add("ptJEHistogramPion", "ptJEHistogramPion", kTH1F, {PtAxis}); - JEhistos.add("ptJEHistogramKaon", "ptJEHistogramKaon", kTH1F, {PtAxis}); - JEhistos.add("ptJEHistogramProton", "ptJEHistogramProton", kTH1F, {PtAxis}); - JEhistos.add("ptJEHistogramPhi", "ptJEHistogramPhi", kTH1F, {PtAxis}); - JEhistos.add("ptJEHistogramPhi_JetTrigger", "ptJEHistogramPhi_JetTrigger", kTH1F, {PtAxis}); - JEhistos.add("minvJEHistogramPhi", "minvJEHistogramPhi", kTH1F, {MinvAxis}); - - JEhistos.add("Resp_Matrix", "Resp_Matrix", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) - JEhistos.add("Resp_Matrix_MATCHED", "Resp_Matrix_MATCHED", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) - - JEhistos.add("ptGeneratedPion", "ptGeneratedPion", kTH1F, {PtAxis}); - JEhistos.add("ptGeneratedKaon", "ptGeneratedKaon", kTH1F, {PtAxis}); - JEhistos.add("ptGeneratedProton", "ptGeneratedProton", kTH1F, {PtAxis}); - JEhistos.add("ptGeneratedPhi", "ptGeneratedPhi", kTH1F, {PtAxis}); - JEhistos.add("ptGeneratedPhi_ALLBR", "ptGeneratedPhi_ALLBR", kTH1F, {PtAxis}); - - JEhistos.add("ptGeneratedPhi_JetTrigger", "ptGeneratedPhi_JetTrigger", kTH1F, {PtAxis}); - - JEhistos.add("mGeneratedPhi", "mGeneratedPhi", kTH1F, {MinvAxis}); - - JEhistos.add("etaHistogram", "etaHistogram", kTH1F, {axisEta}); - JEhistos.add("phiHistogram", "phiHistogram", kTH1F, {axisPhi}); - JEhistos.add("FJetaHistogram", "FJetaHistogram", kTH1F, {axisEta}); - JEhistos.add("FJphiHistogram", "FJphiHistogram", kTH1F, {axisPhi}); - JEhistos.add("FJptHistogram", "FJptHistogram", kTH1F, {axisPt}); - JEhistos.add("FJetaHistogram_MCRec", "FJetaHistogram_MCRec", kTH1F, {axisEta}); - JEhistos.add("FJphiHistogram_MCRec", "FJphiHistogram_MCRec", kTH1F, {axisPhi}); - JEhistos.add("FJptHistogram_MCRec", "FJptHistogram_MCRec", kTH1F, {axisPt}); - JEhistos.add("FJetaHistogram_MCTrue", "FJetaHistogram_MCTrue", kTH1F, {axisEta}); - JEhistos.add("FJphiHistogram_MCTrue", "FJphiHistogram_MCTrue", kTH1F, {axisPhi}); - JEhistos.add("FJptHistogram_MCTrue", "FJptHistogram_MCTrue", kTH1F, {axisPt}); - - JEhistos.add("FJnchHistogram", "FJnchHistogram", kTH1F, {MultAxis}); - JEhistos.add("nEvents", "nEvents", kTH1F, {{4, 0.0, 4.0}}); - JEhistos.add("nEvents_MCRec", "nEvents_MCRec", kTH1F, {{4, 0.0, 4.0}}); - JEhistos.add("nEvents_MCGen", "nEvents_MCGen", kTH1F, {{4, 0.0, 4.0}}); - JEhistos.add("nEvents_MCRec_MATCHED", "nEvents_MCRec_MATCHED", kTH1F, {{4, 0.0, 4.0}}); - JEhistos.add("nEvents_MCGen_MATCHED", "nEvents_MCGen_MATCHED", kTH1F, {{4, 0.0, 4.0}}); - - JEhistos.add("hMCTrue_nonmatch_hUSS_Kangle_v_pt", "hMCTrue_nonmatch_hUSS_Kangle_v_pt", kTH2F, {axisEta, PtAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_Kangle_v_pt", "hMCRec_nonmatch_hUSS_Kangle_v_pt", kTH2F, {axisEta, PtAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE_pt_v_eta", "hMCRec_nonmatch_hUSS_INSIDE_pt_v_eta", kTH2F, {PtAxis, axisEta}); - JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE_pt_v_eta", "hMCTrue_nonmatch_hUSS_INSIDE_pt_v_eta", kTH2F, {PtAxis, axisEta}); - JEhistos.add("JetVsPhi_GEN", "JetVsPhi_GEN", kTH2F, {{4000, 0., 200.}, {200, 0, 20.0}}); - JEhistos.add("JetVsPhi_REC", "JetVsPhi_REC", kTH2F, {{4000, 0., 200.}, {200, 0, 20.0}}); - JEhistos.add("nJetsPerEvent", "nJetsPerEvent", kTH1F, {{10, 0.0, 10.0}}); - - JEhistos.add("hDCArToPv", "DCArToPv", kTH1F, {{300, 0.0, 3.0}}); - JEhistos.add("hDCAzToPv", "DCAzToPv", kTH1F, {{300, 0.0, 3.0}}); - JEhistos.add("rawpT", "rawpT", kTH1F, {{1000, 0.0, 10.0}}); - JEhistos.add("rawDpT", "rawDpT", kTH2F, {{1000, 0.0, 10.0}, {300, -1.5, 1.5}}); - JEhistos.add("hIsPrim", "hIsPrim", kTH1F, {{2, -0.5, +1.5}}); - JEhistos.add("hIsGood", "hIsGood", kTH1F, {{2, -0.5, +1.5}}); - JEhistos.add("hIsPrimCont", "hIsPrimCont", kTH1F, {{2, -0.5, +1.5}}); - JEhistos.add("hFindableTPCClusters", "hFindableTPCClusters", kTH1F, {{200, 0, 200}}); - JEhistos.add("hFindableTPCRows", "hFindableTPCRows", kTH1F, {{200, 0, 200}}); - JEhistos.add("hClustersVsRows", "hClustersVsRows", kTH1F, {{200, 0, 2}}); - JEhistos.add("hTPCChi2", "hTPCChi2", kTH1F, {{200, 0, 100}}); - JEhistos.add("hITSChi2", "hITSChi2", kTH1F, {{200, 0, 100}}); - - JEhistos.add("hUSS", "hUSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hUSS_1D", "hUSS_1D", kTH1F, {MinvAxis}); - JEhistos.add("hUSS_1D_2_3", "hUSS_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hLSS", "hLSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hLSS_1D", "hLSS_1D", kTH1F, {MinvAxis}); - JEhistos.add("hLSS_1D_2_3", "hLSS_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hUSS_INSIDE", "hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hUSS_INSIDE_1D", "hUSS_INSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hUSS_INSIDE_1D_2_3", "hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hLSS_INSIDE", "hLSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hLSS_INSIDE_1D", "hLSS_INSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hLSS_INSIDE_1D_2_3", "hLSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hUSS_OUTSIDE", "hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hUSS_OUTSIDE_1D", "hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hUSS_OUTSIDE_1D_2_3", "hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hLSS_OUTSIDE", "hLSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hLSS_OUTSIDE_1D", "hLSS_OUTSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hLSS_OUTSIDE_1D_2_3", "hLSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); - - JEhistos.add("hMCTrue_hUSS_INSIDE", "hMCTrue_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCTrue_hUSS_INSIDE_1D", "hMCTrue_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_hUSS_INSIDE_1D_2_3", "hMCTrue_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_hUSS_OUTSIDE", "hMCTrue_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCTrue_hUSS_OUTSIDE_1D", "hMCTrue_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_hUSS_OUTSIDE_1D_2_3", "hMCTrue_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_hUSS_OUTSIDE_TRIG", "hMCTrue_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCTrue_hUSS_OUTSIDE_TRIG_1D", "hMCTrue_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCTrue_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); - - JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE", "hMCTrue_nonmatch_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE_1D", "hMCTrue_nonmatch_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE_1D_2_3", "hMCTrue_nonmatch_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE", "hMCTrue_nonmatch_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_1D", "hMCTrue_nonmatch_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_1D_2_3", "hMCTrue_nonmatch_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG", "hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D", "hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); - - JEhistos.add("hMCRec_hUSS", "hMCRec_hUSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_hUSS_1D", "hMCRec_hUSS_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_1D_2_3", "hMCRec_hUSS_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_INSIDE", "hMCRec_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_hUSS_INSIDE_1D", "hMCRec_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_INSIDE_1D_2_3", "hMCRec_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_OUTSIDE", "hMCRec_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_hUSS_OUTSIDE_1D", "hMCRec_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_OUTSIDE_1D_2_3", "hMCRec_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_OUTSIDE_TRIG", "hMCRec_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_hUSS_OUTSIDE_TRIG_1D", "hMCRec_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCRec_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); - - JEhistos.add("hMCRec_nonmatch_hUSS", "hMCRec_nonmatch_hUSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_1D", "hMCRec_nonmatch_hUSS_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_1D_2_3", "hMCRec_nonmatch_hUSS_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE", "hMCRec_nonmatch_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE_1D", "hMCRec_nonmatch_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE_1D_2_3", "hMCRec_nonmatch_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE", "hMCRec_nonmatch_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_1D", "hMCRec_nonmatch_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_1D_2_3", "hMCRec_nonmatch_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG", "hMCRec_nonmatch_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D", "hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); - JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); + const AxisSpec dRAxis = {100, 0, 100}; + + // Now we define histograms. Due to saving space, we only reserve histogram memory for histograms we will be filling. + + if (cfgDataHists) { + JEhistos.add("nEvents", "nEvents", kTH1F, {{4, 0.0, 4.0}}); + + JEhistos.add("hDCArToPv", "DCArToPv", kTH1F, {{300, 0.0, 3.0}}); + JEhistos.add("hDCAzToPv", "DCAzToPv", kTH1F, {{300, 0.0, 3.0}}); + JEhistos.add("rawpT", "rawpT", kTH1F, {{1000, 0.0, 10.0}}); + JEhistos.add("rawDpT", "rawDpT", kTH2F, {{1000, 0.0, 10.0}, {300, -1.5, 1.5}}); + JEhistos.add("hIsPrim", "hIsPrim", kTH1F, {{2, -0.5, +1.5}}); + JEhistos.add("hIsGood", "hIsGood", kTH1F, {{2, -0.5, +1.5}}); + JEhistos.add("hIsPrimCont", "hIsPrimCont", kTH1F, {{2, -0.5, +1.5}}); + JEhistos.add("hFindableTPCClusters", "hFindableTPCClusters", kTH1F, {{200, 0, 200}}); + JEhistos.add("hFindableTPCRows", "hFindableTPCRows", kTH1F, {{200, 0, 200}}); + JEhistos.add("hClustersVsRows", "hClustersVsRows", kTH1F, {{200, 0, 2}}); + JEhistos.add("hTPCChi2", "hTPCChi2", kTH1F, {{200, 0, 100}}); + JEhistos.add("hITSChi2", "hITSChi2", kTH1F, {{200, 0, 100}}); + JEhistos.add("etaHistogram", "etaHistogram", kTH1F, {axisEta}); + JEhistos.add("phiHistogram", "phiHistogram", kTH1F, {axisPhi}); + + JEhistos.add("hNResoPerEvent", "hNResoPerEvent", kTH1F, {{10, 0, 10}}); + JEhistos.add("hNResoPerEventWJet", "hNResoPerEventWJet", kTH1F, {{10, 0, 10}}); + JEhistos.add("hNResoPerEventInJet", "hNResoPerEventInJet", kTH1F, {{10, 0, 10}}); + + JEhistos.add("FJetaHistogram", "FJetaHistogram", kTH1F, {axisEta}); + JEhistos.add("FJphiHistogram", "FJphiHistogram", kTH1F, {axisPhi}); + JEhistos.add("FJptHistogram", "FJptHistogram", kTH1F, {axisPt}); + JEhistos.add("nJetsPerEvent", "nJetsPerEvent", kTH1F, {{10, 0.0, 10.0}}); + + JEhistos.add("hUSS", "hUSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hUSS_1D", "hUSS_1D", kTH1F, {MinvAxis}); + JEhistos.add("hUSS_1D_2_3", "hUSS_1D_2_3", kTH1F, {MinvAxis}); + JEhistos.add("hLSS", "hLSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hLSS_1D", "hLSS_1D", kTH1F, {MinvAxis}); + JEhistos.add("hLSS_1D_2_3", "hLSS_1D_2_3", kTH1F, {MinvAxis}); + JEhistos.add("hUSS_INSIDE", "hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hUSS_INSIDE_1D", "hUSS_INSIDE_1D", kTH1F, {MinvAxis}); + JEhistos.add("hUSS_INSIDE_1D_2_3", "hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); + JEhistos.add("hLSS_INSIDE", "hLSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hLSS_INSIDE_1D", "hLSS_INSIDE_1D", kTH1F, {MinvAxis}); + JEhistos.add("hLSS_INSIDE_1D_2_3", "hLSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); + } + + if (cfgMCRecHists) { + JEhistos.add("nEvents_MCRec", "nEvents_MCRec", kTH1F, {{4, 0.0, 4.0}}); + + JEhistos.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{4000, 0., 200.}}}); + JEhistos.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + JEhistos.add("h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + + JEhistos.add("ptJEHistogramPion", "ptJEHistogramPion", kTH1F, {PtAxis}); + JEhistos.add("ptJEHistogramKaon", "ptJEHistogramKaon", kTH1F, {PtAxis}); + JEhistos.add("ptJEHistogramProton", "ptJEHistogramProton", kTH1F, {PtAxis}); + JEhistos.add("ptJEHistogramPhi", "ptJEHistogramPhi", kTH1F, {PtAxis}); + JEhistos.add("ptJEHistogramPhi_JetTrigger", "ptJEHistogramPhi_JetTrigger", kTH1F, {PtAxis}); + JEhistos.add("minvJEHistogramPhi", "minvJEHistogramPhi", kTH1F, {MinvAxis}); + JEhistos.add("hNRealPhiVPhiCand", "hNRealPhiVPhiCand", kTH2F, {{10, 0, 10}, {10, 0, 10}}); + JEhistos.add("hNRealPhiWithJetVPhiCand", "hNRealPhiWithJetVPhiCand", kTH2F, {{10, 0, 10}, {10, 0, 10}}); + JEhistos.add("hNRealPhiInJetVPhiCand", "hNRealPhiInJetVPhiCand", kTH2F, {{10, 0, 10}, {10, 0, 10}}); + + JEhistos.add("hMCRec_nonmatch_hUSS_KtoKangle_v_pt", "hMCRec_nonmatch_hUSS_KtoKangle_v_pt", kTH2F, {axisEta, PtAxis}); + JEhistos.add("hMCRec_nonmatch_hUSS_Kangle_v_pt", "hMCRec_nonmatch_hUSS_Kangle_v_pt", kTH2F, {axisEta, PtAxis}); + JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE_pt_v_eta", "hMCRec_nonmatch_hUSS_INSIDE_pt_v_eta", kTH2F, {PtAxis, axisEta}); + JEhistos.add("JetVsPhi_REC", "JetVsPhi_REC", kTH2F, {{4000, 0., 200.}, {200, 0, 20.0}}); + + JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE", "hMCRec_nonmatch_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE_1D", "hMCRec_nonmatch_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); + JEhistos.add("hMCRec_nonmatch_hUSS_INSIDE_1D_2_3", "hMCRec_nonmatch_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); + } + + if (cfgMCGenHists) { + JEhistos.add("nEvents_MCGen", "nEvents_MCGen", kTH1F, {{4, 0.0, 4.0}}); + + JEhistos.add("h_part_jet_pt", "particle level jet pT;#it{p}_{T,jet part} (GeV/#it{c});entries", {HistType::kTH1F, {{4000, 0., 200.}}}); + JEhistos.add("h_part_jet_eta", "particle level jet #eta;#eta_{jet part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + JEhistos.add("h_part_jet_phi", "particle level jet #phi;#phi_{jet part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + + JEhistos.add("ptGeneratedPion", "ptGeneratedPion", kTH1F, {PtAxis}); + JEhistos.add("ptGeneratedKaon", "ptGeneratedKaon", kTH1F, {PtAxis}); + JEhistos.add("ptGeneratedProton", "ptGeneratedProton", kTH1F, {PtAxis}); + JEhistos.add("ptGeneratedPhi", "ptGeneratedPhi", kTH1F, {PtAxis}); + JEhistos.add("ptGeneratedPhi_ALLBR", "ptGeneratedPhi_ALLBR", kTH1F, {PtAxis}); + + JEhistos.add("ptGeneratedPhi_JetTrigger", "ptGeneratedPhi_JetTrigger", kTH1F, {PtAxis}); + JEhistos.add("mGeneratedPhi", "mGeneratedPhi", kTH1F, {MinvAxis}); + + JEhistos.add("hMCTrue_nonmatch_hUSS_Kangle_v_pt", "hMCTrue_nonmatch_hUSS_Kangle_v_pt", kTH2F, {axisEta, PtAxis}); + JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE_pt_v_eta", "hMCTrue_nonmatch_hUSS_INSIDE_pt_v_eta", kTH2F, {PtAxis, axisEta}); + JEhistos.add("JetVsPhi_GEN", "JetVsPhi_GEN", kTH2F, {{4000, 0., 200.}, {200, 0, 20.0}}); + + JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE", "hMCTrue_nonmatch_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE_1D", "hMCTrue_nonmatch_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); + JEhistos.add("hMCTrue_nonmatch_hUSS_INSIDE_1D_2_3", "hMCTrue_nonmatch_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); + } + + if (cfgMCGenMATCHEDHists) { + JEhistos.add("nEvents_MCGen_MATCHED", "nEvents_MCGen_MATCHED", kTH1F, {{4, 0.0, 4.0}}); + + JEhistos.add("h_matched_GEN_jet_pt", "matched_GEN level jet pT;#it{p}_{T,jet part} (GeV/#it{c});Delta", {HistType::kTH2F, {{200, 0., 200.}, {400, -20., 20.}}}); + JEhistos.add("h_matched_GEN_jet_eta", "matched_GEN level jet #eta;#eta_{jet part};Delta", {HistType::kTH2F, {{100, -1.0, 1.0}, {400, -20., 20.}}}); + JEhistos.add("h_matched_GEN_jet_phi", "matched_GEN level jet #phi;#phi_{jet part};Delta", {HistType::kTH2F, {{80, -1.0, 7.}, {400, -20., 20.}}}); + JEhistos.add("2DGenToRec", "2DGenToRec", kTH2F, {PtAxis, axisPt}); + JEhistos.add("2DGenToRec_constrained", "2DGenToRec_constrained", kTH2F, {PtAxis, axisPt}); + + JEhistos.add("RespGen_Matrix_MATCHED", "RespGen_Matrix_MATCHED", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) + JEhistos.add("RespGen_Matrix_MATCHED_rand0", "RespGen_Matrix_MATCHED_rand0", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) + JEhistos.add("RespGen_Matrix_MATCHED_rand1", "RespGen_Matrix_MATCHED_rand1", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) + + JEhistos.add("hMCTrue_hUSS_INSIDE", "hMCTrue_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hMCTrue_hUSS_INSIDE_1D", "hMCTrue_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); + JEhistos.add("hMCTrue_hUSS_INSIDE_1D_2_3", "hMCTrue_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); + } + + if (cfgMCRecMATCHEDHists) { + JEhistos.add("nEvents_MCRec_MATCHED", "nEvents_MCRec_MATCHED", kTH1F, {{4, 0.0, 4.0}}); + + JEhistos.add("h_matched_REC_jet_pt", "matched_REC level jet pT;#it{p}_{T,jet part} (GeV/#it{c});Delta", {HistType::kTH2F, {{200, 0., 200.}, {400, -20., 20.}}}); + JEhistos.add("h_matched_REC_jet_eta", "matched_REC level jet #eta;#eta_{jet part};Delta", {HistType::kTH2F, {{100, -1.0, 1.0}, {400, -20., 20.}}}); + JEhistos.add("h_matched_REC_jet_phi", "matched_REC level jet #phi;#phi_{jet part};Delta", {HistType::kTH2F, {{80, -1.0, 7.}, {400, -20., 20.}}}); + + JEhistos.add("Resp_Matrix_MATCHED", "Resp_Matrix_MATCHED", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) + JEhistos.add("Resp_Matrix_MATCHED_rand0", "Resp_Matrix_MATCHED_rand0", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) + JEhistos.add("Resp_Matrix_MATCHED_rand1", "Resp_Matrix_MATCHED_rand1", HistType::kTHnSparseD, {PtAxis, axisPt, PtAxis, axisPt}); // REC(Phi,Jet), GEN(Phi,Jet) + + JEhistos.add("2DRecToGen", "2DRecToGen", kTH2F, {PtAxis, axisPt}); + JEhistos.add("2DRecToGen_constrained", "2DRecToGen_constrained", kTH2F, {PtAxis, axisPt}); + + JEhistos.add("hMCRec_hUSS_INSIDE", "hMCRec_hUSS_INSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + JEhistos.add("hMCRec_hUSS_INSIDE_1D", "hMCRec_hUSS_INSIDE_1D", kTH1F, {MinvAxis}); + JEhistos.add("hMCRec_hUSS_INSIDE_1D_2_3", "hMCRec_hUSS_INSIDE_1D_2_3", kTH1F, {MinvAxis}); + } + // JEhistos.add("FJetaHistogram_MCRec", "FJetaHistogram_MCRec", kTH1F, {axisEta}); + // JEhistos.add("FJphiHistogram_MCRec", "FJphiHistogram_MCRec", kTH1F, {axisPhi}); + // JEhistos.add("FJptHistogram_MCRec", "FJptHistogram_MCRec", kTH1F, {axisPt}); + // JEhistos.add("FJetaHistogram_MCTrue", "FJetaHistogram_MCTrue", kTH1F, {axisEta}); + // JEhistos.add("FJphiHistogram_MCTrue", "FJphiHistogram_MCTrue", kTH1F, {axisPhi}); + // JEhistos.add("FJptHistogram_MCTrue", "FJptHistogram_MCTrue", kTH1F, {axisPt}); + // JEhistos.add("hUSS_OUTSIDE", "hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hUSS_OUTSIDE_1D", "hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hUSS_OUTSIDE_1D_2_3", "hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hLSS_OUTSIDE", "hLSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hLSS_OUTSIDE_1D", "hLSS_OUTSIDE_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hLSS_OUTSIDE_1D_2_3", "hLSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_hUSS_OUTSIDE", "hMCTrue_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCTrue_hUSS_OUTSIDE_1D", "hMCTrue_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_hUSS_OUTSIDE_1D_2_3", "hMCTrue_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_hUSS_OUTSIDE_TRIG", "hMCTrue_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCTrue_hUSS_OUTSIDE_TRIG_1D", "hMCTrue_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCTrue_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE", "hMCTrue_nonmatch_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_1D", "hMCTrue_nonmatch_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_1D_2_3", "hMCTrue_nonmatch_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG", "hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D", "hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_hUSS", "hMCRec_hUSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCRec_hUSS_1D", "hMCRec_hUSS_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_hUSS_1D_2_3", "hMCRec_hUSS_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_hUSS_OUTSIDE", "hMCRec_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCRec_hUSS_OUTSIDE_1D", "hMCRec_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_hUSS_OUTSIDE_1D_2_3", "hMCRec_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_hUSS_OUTSIDE_TRIG", "hMCRec_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCRec_hUSS_OUTSIDE_TRIG_1D", "hMCRec_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCRec_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS", "hMCRec_nonmatch_hUSS", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_1D", "hMCRec_nonmatch_hUSS_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_1D_2_3", "hMCRec_nonmatch_hUSS_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE", "hMCRec_nonmatch_hUSS_OUTSIDE", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_1D", "hMCRec_nonmatch_hUSS_OUTSIDE_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_1D_2_3", "hMCRec_nonmatch_hUSS_OUTSIDE_1D_2_3", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG", "hMCRec_nonmatch_hUSS_OUTSIDE_TRIG", kTH3F, {dRAxis, PtAxis, MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D", "hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D", kTH1F, {MinvAxis}); + // JEhistos.add("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", "hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3", kTH1F, {MinvAxis}); // EVENT SELECTION eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(cfgeventSelections)); @@ -233,10 +276,11 @@ struct phiInJets { } // end of init double massKa = o2::constants::physics::MassKPlus; + double massPi = o2::constants::physics::MassPiMinus; using EventCandidates = soa::Join; // , aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs using TrackCandidates = soa::Join; + aod::pidTPCKa, aod::pidTOFKa, aod::pidTPCPi, aod::pidTOFPi>; Filter jetCuts = aod::jet::pt > cfgjetPtMin&& aod::jet::r == nround(cfgjetR.node() * 100.0f); // Function for track quality cuts @@ -285,7 +329,24 @@ struct phiInJets { ///////////////////////////////////////////////////////////////////////////// template - bool trackPID(const T& candidate) + bool trackPID(const T& candidate, bool FT) + { + bool pid = false; + + if (!cfgIsKstar) { + pid = trackPIDKaon(candidate); + + } else { + if (!FT) + pid = trackPIDPion(candidate); + else + pid = trackPIDKaon(candidate); + } + return pid; + } + + template + bool trackPIDKaon(const T& candidate) { bool tpcPIDPassed{false}, tofPIDPassed{false}; if (std::abs(candidate.tpcNSigmaKa()) < cfgnTPCPID) @@ -303,46 +364,115 @@ struct phiInJets { } return false; } + + template + bool trackPIDPion(const T& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaPi()) < cfgnTPCPID) + tpcPIDPassed = true; + + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cfgnTOFPID) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// + template + double DistinguishJets(const JetType& jets, const TLorentzVector lResonance) + { + if (cDebugLevel > 0) + std::cout << "oof, multiple jets fit to the same phi. Time to find the best phi-jet link" << std::endl; + + double best_R = 0; + double best_jetpt = 0; + for (auto const& jet : jets) { + double phidiff = TVector2::Phi_mpi_pi(jet.phi() - lResonance.Phi()); + double etadiff = jet.eta() - lResonance.Eta(); + double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); + if (R < cfgjetR && best_R == 0) { + best_R = R; + best_jetpt = jet.pt(); + } else if (R < best_R) { + best_R = R; + best_jetpt = jet.pt(); + } + } // jetloop + return best_jetpt; + } + + template + double DistinguishJetsMC(const Jet_pt& jet_pt, const Jet_phi& jet_phi, const Jet_eta& jet_eta, const TLorentzVector lResonance) + { + if (cDebugLevel > 0) + std::cout << "oof, multiple jets fit to the same phi. Time to find the best phi-jet link" << std::endl; + + double best_R = 0; + double best_jetpt = 0; + for (std::vector::size_type i = 0; i < jet_pt.size(); i++) { + double phidiff = TVector2::Phi_mpi_pi(jet_phi[i] - lResonance.Phi()); + double etadiff = jet_eta[i] - lResonance.Eta(); + double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); + if (R < cfgjetR && best_R == 0) { + best_R = R; + best_jetpt = jet_pt[i]; + } else if (R < best_R) { + best_R = R; + best_jetpt = jet_pt[i]; + } + } // jetloop + return best_jetpt; + } + + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// template - void minvReconstruction(double mult, const TracksType& trk1, const TracksType& trk2, const JetType& jets) + int minvReconstruction(double mult, const TracksType& trk1, const TracksType& trk2, const JetType& jets) { TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; if (!trackSelection(trk1) || !trackSelection(trk2)) - return; + return -1; - if (!trackPID(trk1) || !trackPID(trk2)) - return; + if (!trackPID(trk1, true) || !trackPID(trk2, false)) + return -1; - if (trk1.index() >= trk2.index()) - return; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + if (!cfgIsKstar) { + if (trk1.globalIndex() >= trk2.globalIndex()) + return -1; // For Phi, we only need to iterate each pair once + } else { + if (trk1.globalIndex() == trk2.globalIndex()) + return -1; // For Kstar, we need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + } lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + if (!cfgIsKstar) + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + else + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); + lResonance = lDecayDaughter1 + lDecayDaughter2; if (std::abs(lResonance.Eta()) > cfgtrkMaxEta) - return; + return -1; ///////////////////////////////////////////////////////////////////////////// // Fill Global Event Minv if (trk1.sign() * trk2.sign() < 0) { - if (!IsMC) { - JEhistos.fill(HIST("hUSS_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hUSS_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hUSS"), mult, lResonance.Pt(), lResonance.M()); - } - - if (IsMC) { - JEhistos.fill(HIST("hMCRec_hUSS_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_hUSS_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_hUSS"), mult, lResonance.Pt(), lResonance.M()); - } + JEhistos.fill(HIST("hUSS_1D"), lResonance.M()); + if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + JEhistos.fill(HIST("hUSS_1D_2_3"), lResonance.M()); + JEhistos.fill(HIST("hUSS"), mult, lResonance.Pt(), lResonance.M()); } else if (trk1.sign() * trk2.sign() > 0) { @@ -354,70 +484,90 @@ struct phiInJets { ///////////////////////////////////////////////////////////////////////////// bool jetFlag = false; + int goodjets = 0; + double jetpt = 0; for (auto const& jet : jets) { - double phidiff = TVector2::Phi_mpi_pi(jet.phi() - lResonance.Phi()); double etadiff = jet.eta() - lResonance.Eta(); double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); - if (R < cfgjetR) + if (R < cfgjetR) { jetFlag = true; + jetpt = jet.pt(); + goodjets++; + } } + if (cfgSingleJet) + if (goodjets > 1) + jetpt = DistinguishJets(jets, lResonance); + ///////////////////////////////////////////////////////////////////////////// // Fill inside Jet if (jetFlag) { if (trk1.sign() * trk2.sign() < 0) { - if (!IsMC) { - JEhistos.fill(HIST("hUSS_INSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hUSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hUSS_INSIDE"), mult, lResonance.Pt(), lResonance.M()); - } - - if (IsMC) { - JEhistos.fill(HIST("hMCRec_hUSS_INSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_hUSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_hUSS_INSIDE"), mult, lResonance.Pt(), lResonance.M()); - } + JEhistos.fill(HIST("hUSS_INSIDE_1D"), lResonance.M()); + if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + JEhistos.fill(HIST("hUSS_INSIDE_1D_2_3"), lResonance.M()); + JEhistos.fill(HIST("hUSS_INSIDE"), jetpt, lResonance.Pt(), lResonance.M()); } else if (trk1.sign() * trk2.sign() > 0) { JEhistos.fill(HIST("hLSS_INSIDE_1D"), lResonance.M()); if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) JEhistos.fill(HIST("hLSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hLSS_INSIDE"), mult, lResonance.Pt(), lResonance.M()); + JEhistos.fill(HIST("hLSS_INSIDE"), jetpt, lResonance.Pt(), lResonance.M()); } } // jetflag ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Fill outside Jet - if (!jetFlag) { - if (trk1.sign() * trk2.sign() < 0) { - if (!IsMC) { - JEhistos.fill(HIST("hUSS_OUTSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hUSS_OUTSIDE"), mult, lResonance.Pt(), lResonance.M()); - } - - if (IsMC) { - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE"), mult, lResonance.Pt(), lResonance.M()); - } - - } else if (trk1.sign() * trk2.sign() > 0) { - - JEhistos.fill(HIST("hLSS_OUTSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hLSS_OUTSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hLSS_OUTSIDE"), mult, lResonance.Pt(), lResonance.M()); - } - } //! jetflag + // if (!jetFlag) { + // if (trk1.sign() * trk2.sign() < 0) { + // if (!IsMC) { + // JEhistos.fill(HIST("hUSS_OUTSIDE_1D"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hUSS_OUTSIDE_1D_2_3"), lResonance.M()); + // JEhistos.fill(HIST("hUSS_OUTSIDE"), jetpt, lResonance.Pt(), lResonance.M()); + // } + + // if (IsMC) { + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE"), jetpt, lResonance.Pt(), lResonance.M()); + // } + + // } else if (trk1.sign() * trk2.sign() > 0) { + + // JEhistos.fill(HIST("hLSS_OUTSIDE_1D"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hLSS_OUTSIDE_1D_2_3"), lResonance.M()); + // JEhistos.fill(HIST("hLSS_OUTSIDE"), jetpt, lResonance.Pt(), lResonance.M()); + // } + // } //! jetflag ///////////////////////////////////////////////////////////////////////////// + if (!cfgIsKstar) { + if (lResonance.M() > 1.005 && lResonance.M() < 1.035) { + if (jetFlag) + return 3; + if (goodjets > 0) + return 2; + return 1; + } else { + return -1; + } + } else { + if (lResonance.M() > 0.85 && lResonance.M() < 0.95) { + if (jetFlag) + return 3; + if (goodjets > 0) + return 2; + return 1; + } else { + return -1; + } + } } // MinvReconstruction ///////////////////////////////////////////////////////////////////////////// @@ -427,8 +577,12 @@ struct phiInJets { { if (cDebugLevel > 0) { nEvents++; - if ((nEvents + 1) % 10000 == 0) + if ((nEvents + 1) % 10000 == 0) { + std::cout << "Ay Lmao" << std::endl; + double histmem = JEhistos.getSize(); + std::cout << histmem << std::endl; std::cout << "Processed Data Events: " << nEvents << std::endl; + } } JEhistos.fill(HIST("nEvents"), 0.5); @@ -437,17 +591,30 @@ struct phiInJets { if (!jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::JCollisionSel::sel8)) return; + int nReso = 0; + int nResoWTrig = 0; + int nResoInTrig = 0; for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks, tracks))) { - auto trk1 = track1.track_as>(); - auto trk2 = track2.track_as>(); - minvReconstruction(1.0, trk1, trk2, chargedjets); + auto trk1 = track1.track_as>(); + auto trk2 = track2.track_as>(); + int Reso = minvReconstruction(1.0, trk1, trk2, chargedjets); + if (Reso > 0) + nReso++; + if (Reso > 1) + nResoWTrig++; + if (Reso > 2) + nResoInTrig++; } + // Here we have to fill the number of reso candidates per event + JEhistos.fill(HIST("hNResoPerEvent"), nReso); + JEhistos.fill(HIST("hNResoPerEventWJet"), nResoWTrig); + JEhistos.fill(HIST("hNResoPerEventInJet"), nResoInTrig); + int nJets = 0; for (auto chargedjet : chargedjets) { JEhistos.fill(HIST("FJetaHistogram"), chargedjet.eta()); JEhistos.fill(HIST("FJphiHistogram"), chargedjet.phi()); JEhistos.fill(HIST("FJptHistogram"), chargedjet.pt()); - // JEhistos.fill(HIST("FJnchHistogram"), chargedjet.tracks().size()); nJets++; } @@ -457,7 +624,7 @@ struct phiInJets { // return; for (auto& trackC : tracks) { - auto originalTrack = trackC.track_as>(); + auto originalTrack = trackC.track_as>(); JEhistos.fill(HIST("hDCArToPv"), originalTrack.dcaXY()); JEhistos.fill(HIST("hDCAzToPv"), originalTrack.dcaZ()); JEhistos.fill(HIST("rawpT"), originalTrack.pt()); @@ -487,7 +654,7 @@ struct phiInJets { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - using myCompleteTracks = soa::Join; + using myCompleteTracks = soa::Join; using myCompleteJetTracks = soa::Join; int nJEEvents = 0; int nprocessRecEvents = 0; @@ -495,8 +662,11 @@ struct phiInJets { { if (cDebugLevel > 0) { nprocessRecEvents++; - if ((nprocessRecEvents + 1) % 10000 == 0) + if ((nprocessRecEvents + 1) % 10000 == 0) { + double histmem = JEhistos.getSize(); + std::cout << histmem << std::endl; std::cout << "processRec: " << nprocessRecEvents << std::endl; + } } JEhistos.fill(HIST("nEvents_MCRec"), 0.5); @@ -527,20 +697,24 @@ struct phiInJets { mcd_pt.push_back(mcdjet.pt()); mcd_eta.push_back(mcdjet.eta()); mcd_phi.push_back(mcdjet.phi()); - registry.fill(HIST("h_jet_pt"), mcdjet.pt()); - registry.fill(HIST("h_jet_eta"), mcdjet.eta()); - registry.fill(HIST("h_jet_phi"), mcdjet.phi()); + JEhistos.fill(HIST("h_jet_pt"), mcdjet.pt()); + JEhistos.fill(HIST("h_jet_eta"), mcdjet.eta()); + JEhistos.fill(HIST("h_jet_phi"), mcdjet.phi()); } if (hasJets) JEhistos.fill(HIST("nEvents_MCRec"), 2.5); + double PhiCand = 0; + double RealPhiCand = 0; + double RealPhiCandWithJet = 0; + double RealPhiCandInJet = 0; // Track Eff for (const auto& track : tracks) { auto originalTrack = track.track_as(); if (!trackSelection(originalTrack)) continue; if (cfgSimPID) - if (!trackPID(originalTrack)) + if (!trackPID(originalTrack, true)) continue; if (track.has_mcParticle()) { @@ -560,24 +734,46 @@ struct phiInJets { if (!trackSelection(originalTrack2)) continue; if (cfgSimPID) - if (!trackPID(originalTrack2)) + if (!trackPID(originalTrack2, false)) continue; - - if (originalTrack.index() >= originalTrack2.index()) + if (!cfgIsKstar) { + if (originalTrack.globalIndex() >= originalTrack2.globalIndex()) + continue; + } else { + if (originalTrack.globalIndex() == originalTrack2.globalIndex()) + continue; + } + if (fabs(originalTrack.eta()) > cfgtrkMaxEta || fabs(originalTrack2.eta()) > cfgtrkMaxEta) continue; - if (fabs(originalTrack.eta()) > cfgtrkMaxEta || fabs(originalTrack2.eta()) > cfgtrkMaxEta) + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + lDecayDaughter1.SetXYZM(originalTrack.px(), originalTrack.py(), originalTrack.pz(), massKa); + if (!cfgIsKstar) + lDecayDaughter2.SetXYZM(originalTrack2.px(), originalTrack2.py(), originalTrack2.pz(), massKa); + else + lDecayDaughter2.SetXYZM(originalTrack2.px(), originalTrack2.py(), originalTrack2.pz(), massPi); + lResonance = lDecayDaughter1 + lDecayDaughter2; + + if (fabs(lResonance.Eta()) > cfgtrkMaxEta) continue; - // check PID + if (lResonance.M() > 1.005 && lResonance.M() < 1.035) + PhiCand++; + // check PID if (track.has_mcParticle() && track2.has_mcParticle()) { auto part1 = track.mcParticle(); auto part2 = track2.mcParticle(); if (fabs(part1.pdgCode()) != 321) continue; // Not Kaon - if (fabs(part2.pdgCode()) != 321) - continue; // Not Kaon + if (!cfgIsKstar) { + if (fabs(part2.pdgCode()) != 321) + continue; // Not Kaon + } else { + if (fabs(part2.pdgCode()) != 211) + continue; // Not Kaon + } + if (!part1.has_mothers()) continue; // Not decaying Kaon if (!part2.has_mothers()) @@ -597,23 +793,40 @@ struct phiInJets { mothers2PDG.push_back(part2_mom.pdgCode()); } - if (mothers1PDG[0] != 333) - continue; // mother not phi - if (mothers2PDG[0] != 333) - continue; // mother not phi + if (!cfgIsKstar) { + if (mothers1PDG[0] != 333) + continue; // mother not phi + if (mothers2PDG[0] != 333) + continue; // mother not phi + } else { + if (mothers1PDG[0] != 313) + continue; // mother not phi + if (mothers2PDG[0] != 313) + continue; // mother not phi + } if (mothers1[0] != mothers2[0]) continue; // Kaons not from the same phi - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - lDecayDaughter1.SetXYZM(originalTrack.px(), originalTrack.py(), originalTrack.pz(), massKa); - lDecayDaughter2.SetXYZM(originalTrack2.px(), originalTrack2.py(), originalTrack2.pz(), massKa); - lResonance = lDecayDaughter1 + lDecayDaughter2; - if (fabs(lResonance.Eta()) > cfgtrkMaxEta) - continue; + double phidiff_Kaons = TVector2::Phi_mpi_pi(lDecayDaughter2.Phi() - lDecayDaughter1.Phi()); + double etadiff_Kaons = lDecayDaughter2.Eta() - lDecayDaughter1.Eta(); + double R_Kaons = TMath::Sqrt((etadiff_Kaons * etadiff_Kaons) + (phidiff_Kaons * phidiff_Kaons)); + JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_KtoKangle_v_pt"), R_Kaons, lResonance.Pt()); JEhistos.fill(HIST("ptJEHistogramPhi"), lResonance.Pt()); + if (lResonance.M() > 1.005 && lResonance.M() < 1.035) + RealPhiCand++; + + // Now we do jets bool jetFlag = false; + int goodjets = 0; + double jetpt = 0; + for (int i = 0; i < mcd_pt.size(); i++) { + if (i == 0) { + if (lResonance.M() > 1.005 && lResonance.M() < 1.035) { + RealPhiCandWithJet++; + } + } double phidiff = TVector2::Phi_mpi_pi(mcd_phi[i] - lResonance.Phi()); double etadiff = mcd_eta[i] - lResonance.Eta(); double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); @@ -628,33 +841,26 @@ struct phiInJets { JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_Kangle_v_pt"), R_K1, lResonance.Pt()); JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_Kangle_v_pt"), R_K2, lResonance.Pt()); } - if (R < cfgjetR) + if (R < cfgjetR) { jetFlag = true; - } + jetpt = mcd_pt[i]; + goodjets++; + } + } // R check for jets + + if (cfgSingleJet) + if (goodjets > 1) + jetpt = DistinguishJetsMC(mcd_pt, mcd_phi, mcd_eta, lResonance); if (jetFlag) { + if (lResonance.M() > 1.005 && lResonance.M() < 1.035) + RealPhiCandInJet++; JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_INSIDE_pt_v_eta"), lResonance.Pt(), lResonance.Eta()); JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_INSIDE_1D"), lResonance.M()); if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_INSIDE"), 1.0, lResonance.Pt(), lResonance.M()); - - } else if (!jetFlag && mcd_pt.size() > 0) { - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); - - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); - - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_OUTSIDE_TRIG"), 1.0, lResonance.Pt(), lResonance.M()); - - } else if (!jetFlag) { - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_OUTSIDE_1D"), lResonance.M()); - - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - - JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_OUTSIDE"), 1.0, lResonance.Pt(), lResonance.M()); - } //! jetflag + JEhistos.fill(HIST("hMCRec_nonmatch_hUSS_INSIDE"), jetpt, lResonance.Pt(), lResonance.M()); + } if (hasJets) { JEhistos.fill(HIST("ptJEHistogramPhi_JetTrigger"), lResonance.Pt()); @@ -666,6 +872,10 @@ struct phiInJets { } // mcpart check } // tracks2 } // tracks1 + JEhistos.fill(HIST("hNRealPhiVPhiCand"), PhiCand, RealPhiCand); + JEhistos.fill(HIST("hNRealPhiWithJetVPhiCand"), PhiCand, RealPhiCandWithJet); + JEhistos.fill(HIST("hNRealPhiInJetVPhiCand"), PhiCand, RealPhiCandInJet); + // Jet Eff } PROCESS_SWITCH(phiInJets, processRec, "pikp detector level MC JE", true); @@ -678,8 +888,11 @@ struct phiInJets { { if (cDebugLevel > 0) { nprocessSimEvents++; - if ((nprocessSimEvents + 1) % 10000 == 0) + if ((nprocessSimEvents + 1) % 10000 == 0) { + double histmem = JEhistos.getSize(); + std::cout << histmem << std::endl; std::cout << "processSim: " << nprocessSimEvents << std::endl; + } } JEhistos.fill(HIST("nEvents_MCGen"), 0.5); @@ -717,9 +930,9 @@ struct phiInJets { mcp_eta.push_back(mcpjet.eta()); mcp_phi.push_back(mcpjet.phi()); - registry.fill(HIST("h_part_jet_pt"), mcpjet.pt()); - registry.fill(HIST("h_part_jet_eta"), mcpjet.eta()); - registry.fill(HIST("h_part_jet_phi"), mcpjet.phi()); + JEhistos.fill(HIST("h_part_jet_pt"), mcpjet.pt()); + JEhistos.fill(HIST("h_part_jet_eta"), mcpjet.eta()); + JEhistos.fill(HIST("h_part_jet_phi"), mcpjet.phi()); } if (hasJets) JEhistos.fill(HIST("nEvents_MCGen"), 2.5); @@ -737,15 +950,31 @@ struct phiInJets { if (fabs(mcParticle.eta()) <= cfgtrkMaxEta) { // watch out for context!!! TLorentzVector lResonance; lResonance.SetPxPyPzE(mcParticle.px(), mcParticle.py(), mcParticle.pz(), mcParticle.e()); - if (abs(mcParticle.pdgCode()) == 333) { + + int GenPID = 0; + if (!cfgIsKstar) + GenPID = 333; + else + GenPID = 313; + + if (abs(mcParticle.pdgCode()) == GenPID) { JEhistos.fill(HIST("ptGeneratedPhi_ALLBR"), mcParticle.pt()); bool skip = false; + // First we check for Forced BR - if (mcParticle.has_daughters()) - for (auto& dgth : mcParticle.daughters_as()) - if (fabs(dgth.pdgCode()) != 321) - skip = true; + // if we check for Phi + if (!cfgIsKstar) { + if (mcParticle.has_daughters()) + for (auto& dgth : mcParticle.daughters_as()) + if (fabs(dgth.pdgCode()) != 321) + skip = true; + } else { + if (mcParticle.has_daughters()) + for (auto& dgth : mcParticle.daughters_as()) + if (fabs(dgth.pdgCode()) != 321 || fabs(dgth.pdgCode()) != 211) + skip = true; + } if (skip && cfgBR) continue; @@ -754,10 +983,12 @@ struct phiInJets { ////////////////////////////Implementation of phi finding + int goodjets = 0; + double jetpt = 0; TLorentzVector lResonance; lResonance.SetPxPyPzE(mcParticle.px(), mcParticle.py(), mcParticle.pz(), mcParticle.e()); bool jetFlag = false; - for (int i = 0; i < mcp_pt.size(); i++) { + for (std::vector::size_type i = 0; i < mcp_pt.size(); i++) { double phidiff = TVector2::Phi_mpi_pi(mcp_phi[i] - lResonance.Phi()); double etadiff = mcp_eta[i] - lResonance.Eta(); double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); @@ -770,34 +1001,40 @@ struct phiInJets { JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_Kangle_v_pt"), R_K, lResonance.Pt()); } } - if (R < cfgjetR) + if (R < cfgjetR) { jetFlag = true; + jetpt = mcp_pt[i]; + goodjets++; + } } + if (cfgSingleJet) + if (goodjets > 1) + jetpt = DistinguishJetsMC(mcp_pt, mcp_phi, mcp_eta, lResonance); if (jetFlag) { JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_INSIDE_pt_v_eta"), lResonance.Pt(), lResonance.Eta()); JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_INSIDE_1D"), lResonance.M()); if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_INSIDE"), 1.0, lResonance.Pt(), lResonance.M()); + JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_INSIDE"), jetpt, lResonance.Pt(), lResonance.M()); + } + // else if (!jetFlag && mcp_pt.size() > 0) { + // JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); - } else if (!jetFlag && mcp_pt.size() > 0) { - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); + // JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG"), jetpt, lResonance.Pt(), lResonance.M()); - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_TRIG"), 1.0, lResonance.Pt(), lResonance.M()); + // } else if (!jetFlag) { + // JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_1D"), lResonance.M()); - } else if (!jetFlag) { - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_1D"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - - JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE"), 1.0, lResonance.Pt(), lResonance.M()); + // JEhistos.fill(HIST("hMCTrue_nonmatch_hUSS_OUTSIDE"), jetpt, lResonance.Pt(), lResonance.M()); - } //! jetflag + // } //! jetflag ////////////////////////////Phi found if (hasJets) { @@ -819,19 +1056,24 @@ struct phiInJets { using JetMCPTable = soa::Filtered>; using JetMCDTable = soa::Filtered>; - // void processMatchedGen(o2::aod::JMcCollision const& collision, aod::JMcParticles const& mcParticles, soa::Filtered const& mcpjets) int nprocessSimJEEvents = 0; void processMatchedGen(aod::JMcCollision const& collision, soa::SmallGroups> const& recocolls, JetMCDTable const& /*mcdjets*/, JetMCPTable const& mcpjets, - aod::JMcParticles const& mcParticles) + myCompleteJetTracks const& tracks, + myCompleteTracks const&, + aod::JMcParticles const& mcParticles, + aod::McParticles const&) { if (cDebugLevel > 0) { nprocessSimJEEvents++; - if ((nprocessSimJEEvents + 1) % 10000 == 0) - std::cout << "JEvents: " << nprocessSimJEEvents << std::endl; + if ((nprocessSimJEEvents + 1) % 10000 == 0) { + double histmem = JEhistos.getSize(); + std::cout << histmem << std::endl; + std::cout << "processMatchedGen Events: " << nprocessSimJEEvents << std::endl; + } } JEhistos.fill(HIST("nEvents_MCGen_MATCHED"), 0.5); @@ -875,9 +1117,9 @@ struct phiInJets { if (!mcdjet.has_matchedJetGeo()) continue; hasJets = kTRUE; - registry.fill(HIST("h_matched_GEN_jet_pt"), mcpjet.pt(), mcdjet.pt() - mcpjet.pt()); - registry.fill(HIST("h_matched_GEN_jet_phi"), mcpjet.phi(), mcdjet.phi() - mcpjet.phi()); - registry.fill(HIST("h_matched_GEN_jet_eta"), mcpjet.eta(), mcdjet.eta() - mcpjet.eta()); + JEhistos.fill(HIST("h_matched_GEN_jet_pt"), mcpjet.pt(), mcdjet.pt() - mcpjet.pt()); + JEhistos.fill(HIST("h_matched_GEN_jet_phi"), mcpjet.phi(), mcdjet.phi() - mcpjet.phi()); + JEhistos.fill(HIST("h_matched_GEN_jet_eta"), mcpjet.eta(), mcdjet.eta() - mcpjet.eta()); mcd_pt.push_back(mcdjet.pt()); mcd_eta.push_back(mcdjet.eta()); @@ -896,50 +1138,157 @@ struct phiInJets { if (fabs(mcParticle.eta()) > cfgtrkMaxEta) continue; - if (fabs(mcParticle.pdgCode()) == 333) { + int GenPID = 0; + + if (!cfgIsKstar) + GenPID = 333; + else + GenPID = 313; + + if (fabs(mcParticle.pdgCode()) == GenPID) { bool skip = false; + double phi_dgth_px[2] = {0}; + double phi_dgth_py[2] = {0}; + double phi_dgth_pz[2] = {0}; + double TEMP_phi_dgth_px[2] = {0}; + double TEMP_phi_dgth_py[2] = {0}; + double TEMP_phi_dgth_pz[2] = {0}; + + bool good_daughter[2] = {false}; + int dgth_index = 0; // First we check for Forced BR - if (mcParticle.has_daughters()) - for (auto& dgth : mcParticle.daughters_as()) - if (fabs(dgth.pdgCode()) != 321) - skip = true; + // if we check for Phi + if (!cfgIsKstar) { + if (mcParticle.has_daughters()) { + for (auto& dgth : mcParticle.daughters_as()) { + if (fabs(dgth.pdgCode()) != 321) { + skip = true; + break; + } + for (const auto& track : tracks) { + auto trk = track.track_as(); + if (!trackSelection(trk)) + continue; + if (fabs(trk.eta()) > cfgtrkMaxEta) + continue; + if (cfgSimPID) { + if (!trackPID(trk, true)) + continue; + } + if (!trk.has_mcParticle()) + continue; + auto part = trk.mcParticle(); + if (part.globalIndex() == dgth.globalIndex()) { + TEMP_phi_dgth_px[dgth_index] = track.px(); + TEMP_phi_dgth_py[dgth_index] = track.py(); + TEMP_phi_dgth_pz[dgth_index] = track.pz(); + good_daughter[dgth_index] = true; + dgth_index++; + if (dgth_index == 2) { + phi_dgth_px[0] = TEMP_phi_dgth_px[0]; + phi_dgth_py[0] = TEMP_phi_dgth_py[0]; + phi_dgth_pz[0] = TEMP_phi_dgth_pz[0]; + phi_dgth_px[1] = TEMP_phi_dgth_px[1]; + phi_dgth_py[1] = TEMP_phi_dgth_py[1]; + phi_dgth_pz[1] = TEMP_phi_dgth_pz[1]; + break; + } + } // index check + } // track loop + } // mc daughter loop + } // check if particle has daughters + } else { // check for kstar + if (mcParticle.has_daughters()) + for (auto& dgth : mcParticle.daughters_as()) + if (fabs(dgth.pdgCode()) != 321 || fabs(dgth.pdgCode()) != 211) + skip = true; + } if (skip && cfgBR) continue; + + int goodjets = 0; + double jetpt_mcd = 0; + double jetpt_mcp = 0; TLorentzVector lResonance; + TLorentzVector lResonance_REC; + TLorentzVector lDecayDaughter1_REC; + TLorentzVector lDecayDaughter2_REC; lResonance.SetPxPyPzE(mcParticle.px(), mcParticle.py(), mcParticle.pz(), mcParticle.e()); + lDecayDaughter1_REC.SetXYZM(phi_dgth_px[0], phi_dgth_py[0], phi_dgth_pz[0], massKa); + lDecayDaughter2_REC.SetXYZM(phi_dgth_px[1], phi_dgth_py[1], phi_dgth_pz[1], massKa); + lResonance_REC = lDecayDaughter1_REC + lDecayDaughter2_REC; + // if (cDebugLevel > 0) + // if (good_daughter[0] && good_daughter[1]) + // std::cout << "Reconstructed level phi pT: " << lResonance_REC.Pt() << std::endl; + bool jetFlag = false; - for (int i = 0; i < mcp_pt.size(); i++) { + for (std::vector::size_type i = 0; i < mcp_pt.size(); i++) { double phidiff = TVector2::Phi_mpi_pi(mcp_phi[i] - lResonance.Phi()); double etadiff = mcp_eta[i] - lResonance.Eta(); double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); - if (R < cfgjetR) + if (R < cfgjetR) { jetFlag = true; + jetpt_mcp = mcp_pt[i]; + jetpt_mcd = mcd_pt[i]; + goodjets++; + } + } + if (cfgSingleJet) { + if (goodjets > 1) { + jetpt_mcp = DistinguishJetsMC(mcp_pt, mcp_phi, mcp_eta, lResonance); + jetpt_mcd = DistinguishJetsMC(mcd_pt, mcd_phi, mcd_eta, lResonance_REC); + } } if (jetFlag) { + if (cDebugLevel > 0) { + std::cout << "******************************************" << std::endl; + std::cout << "GEN TO REC LEVEL: " << std::endl; + std::cout << "Rec. Phi Pt: " << lResonance_REC.Pt() << std::endl; + std::cout << "Rec. Phi Eta: " << lResonance_REC.Eta() << std::endl; + std::cout << "Rec. Jet Pt: " << jetpt_mcd << std::endl; + std::cout << "Gen. Phi Pt: " << lResonance.Pt() << std::endl; + std::cout << "Gen. Phi Eta: " << lResonance.Eta() << std::endl; + std::cout << "Gen. Jet Pt: " << jetpt_mcp << std::endl; + std::cout << "******************************************" << std::endl; + } + + JEhistos.fill(HIST("RespGen_Matrix_MATCHED"), lResonance_REC.Pt(), jetpt_mcd, lResonance.Pt(), jetpt_mcp); + unsigned int seed = static_cast(std::chrono::system_clock::now().time_since_epoch().count()); + int dice = rand_r(&seed) % 2; + if (dice > 0) + JEhistos.fill(HIST("RespGen_Matrix_MATCHED_rand0"), lResonance_REC.Pt(), jetpt_mcd, lResonance.Pt(), jetpt_mcp); + else + JEhistos.fill(HIST("RespGen_Matrix_MATCHED_rand1"), lResonance_REC.Pt(), jetpt_mcd, lResonance.Pt(), jetpt_mcp); + + JEhistos.fill(HIST("2DGenToRec"), lResonance.Pt(), jetpt_mcp); + // //check constrained eff + if (good_daughter[0] && good_daughter[1] && lResonance_REC.Pt() > 0 && lResonance_REC.Pt() < 20.0 && jetpt_mcd > 8 && jetpt_mcd < 200) + JEhistos.fill(HIST("2DGenToRec_constrained"), lResonance.Pt(), jetpt_mcp); + JEhistos.fill(HIST("hMCTrue_hUSS_INSIDE_1D"), lResonance.M()); if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) JEhistos.fill(HIST("hMCTrue_hUSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCTrue_hUSS_INSIDE"), 1.0, lResonance.Pt(), lResonance.M()); - - } else if (!jetFlag && mcp_pt.size() > 0) { - JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); + JEhistos.fill(HIST("hMCTrue_hUSS_INSIDE"), jetpt_mcp, lResonance.Pt(), lResonance.M()); + } + // else if (!jetFlag && mcp_pt.size() > 0) { + // JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_TRIG"), 1.0, lResonance.Pt(), lResonance.M()); + // JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_TRIG"), jetpt_mcp, lResonance.Pt(), lResonance.M()); - } else if (!jetFlag) { - JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_1D"), lResonance.M()); + // } else if (!jetFlag) { + // JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE"), 1.0, lResonance.Pt(), lResonance.M()); + // JEhistos.fill(HIST("hMCTrue_hUSS_OUTSIDE"), jetpt_mcp, lResonance.Pt(), lResonance.M()); - } //! jetflag + // } //! jetflag } // chech for phi } // MC Particles } // main fcn @@ -959,8 +1308,11 @@ struct phiInJets { if (cDebugLevel > 0) { nprocessRecJEEvents++; - if ((nprocessRecJEEvents + 1) % 10000 == 0) - std::cout << "JEvents: " << nprocessRecJEEvents << std::endl; + if ((nprocessRecJEEvents + 1) % 10000 == 0) { + double histmem = JEhistos.getSize(); + std::cout << histmem << std::endl; + std::cout << "processMatched Rec Events: " << nprocessRecJEEvents << std::endl; + } } JEhistos.fill(HIST("nEvents_MCRec_MATCHED"), 0.5); @@ -996,9 +1348,9 @@ struct phiInJets { if (!mcpjet.has_matchedJetGeo()) continue; hasJets = kTRUE; - registry.fill(HIST("h_matched_REC_jet_pt"), mcpjet.pt(), mcdjet.pt() - mcpjet.pt()); - registry.fill(HIST("h_matched_REC_jet_phi"), mcpjet.phi(), mcdjet.phi() - mcpjet.phi()); - registry.fill(HIST("h_matched_REC_jet_eta"), mcpjet.eta(), mcdjet.eta() - mcpjet.eta()); + JEhistos.fill(HIST("h_matched_REC_jet_pt"), mcpjet.pt(), mcdjet.pt() - mcpjet.pt()); + JEhistos.fill(HIST("h_matched_REC_jet_phi"), mcpjet.phi(), mcdjet.phi() - mcpjet.phi()); + JEhistos.fill(HIST("h_matched_REC_jet_eta"), mcpjet.eta(), mcdjet.eta() - mcpjet.eta()); mcd_pt.push_back(mcdjet.pt()); mcd_eta.push_back(mcdjet.eta()); @@ -1016,17 +1368,22 @@ struct phiInJets { auto trk1 = track1.track_as(); for (const auto& track2 : tracks) { auto trk2 = track2.track_as(); - if (trk1.index() >= trk2.index()) - continue; + if (!cfgIsKstar) { + if (trk1.globalIndex() >= trk2.globalIndex()) + continue; + } else { + if (trk1.globalIndex() == trk2.globalIndex()) + continue; + } if (fabs(trk1.eta()) > cfgtrkMaxEta || fabs(trk2.eta()) > cfgtrkMaxEta) continue; if ((trk1.sign() * trk2.sign()) > 0) continue; // Not K+K- if (trackSelection(trk1) && trackSelection(trk2)) { if (cfgSimPID) { - if (!trackPID(trk1)) + if (!trackPID(trk1, true)) continue; - if (!trackPID(trk2)) + if (!trackPID(trk2, false)) continue; } if (track1.has_mcParticle() && track2.has_mcParticle()) { @@ -1034,8 +1391,13 @@ struct phiInJets { auto part2 = track2.mcParticle(); if (fabs(part1.pdgCode()) != 321) continue; // Not Kaon - if (fabs(part2.pdgCode()) != 321) - continue; // Not Kaon + if (!cfgIsKstar) { + if (fabs(part2.pdgCode()) != 321) + continue; // Not Kaon + } else { + if (fabs(part2.pdgCode()) != 211) + continue; // Not Kaon + } if (!part1.has_mothers()) continue; // Not decaying Kaon if (!part2.has_mothers()) @@ -1058,65 +1420,101 @@ struct phiInJets { mothers2PDG.push_back(part2_mom.pdgCode()); mothers2Pt.push_back(part2_mom.pt()); } - if (mothers1PDG[0] != 333) - continue; // mother not phi - if (mothers2PDG[0] != 333) - continue; // mother not phi + if (!cfgIsKstar) { + if (mothers1PDG[0] != 333) + continue; // mother not phi + if (mothers2PDG[0] != 333) + continue; // mother not phi + } else { + if (mothers1PDG[0] != 313) + continue; // mother not phi + if (mothers2PDG[0] != 313) + continue; // mother not phi + } if (mothers1[0] != mothers2[0]) continue; // Kaons not from the same phi TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); - lResonance = lDecayDaughter1 + lDecayDaughter2; + if (!cfgIsKstar) + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + else + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); + lResonance = lDecayDaughter1 + lDecayDaughter2; if (fabs(lResonance.Eta()) > cfgtrkMaxEta) continue; bool jetFlag = false; - for (int i = 0; i < mcd_pt.size(); i++) { + int goodjets = 0; + double jetpt_mcp = 0; + double jetpt_mcd = 0; + for (std::vector::size_type i = 0; i < mcd_pt.size(); i++) { double phidiff = TVector2::Phi_mpi_pi(mcd_phi[i] - lResonance.Phi()); double etadiff = mcd_eta[i] - lResonance.Eta(); double R = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); - if (R < cfgjetR) + if (R < cfgjetR) { + jetpt_mcd = mcd_pt[i]; + jetpt_mcp = mcp_pt[i]; + goodjets++; jetFlag = true; + } + } - if (jetFlag) { // Fill Resp. Matrix - if (cDebugLevel > 0) { - std::cout << "******************************************" << std::endl; - std::cout << "Rec. Phi Pt: " << lResonance.Pt() << std::endl; - std::cout << "Rec. Jet Pt: " << mcd_pt[i] << std::endl; - std::cout << "Gen. Phi Pt: " << mothers1Pt[0] << std::endl; - std::cout << "Gen. Jet Pt: " << mcp_pt[i] << std::endl; - std::cout << "******************************************" << std::endl; - } - JEhistos.fill(HIST("Resp_Matrix_MATCHED"), lResonance.Pt(), mcd_pt[i], mothers1Pt[0], mcp_pt[i]); + if (cfgSingleJet) { + if (goodjets > 1) { + jetpt_mcd = DistinguishJetsMC(mcd_pt, mcd_phi, mcd_eta, lResonance); + jetpt_mcp = DistinguishJetsMC(mcp_pt, mcp_phi, mcp_eta, lResonance); } } + if (jetFlag) { // Fill Resp. Matrix + if (cDebugLevel > 0) { + std::cout << "******************************************" << std::endl; + std::cout << "REC TO GEN LEVEL: " << std::endl; + std::cout << "Rec. Phi Pt: " << lResonance.Pt() << std::endl; + std::cout << "Rec. Jet Pt: " << jetpt_mcd << std::endl; + std::cout << "Gen. Phi Pt: " << mothers1Pt[0] << std::endl; + std::cout << "Gen. Jet Pt: " << jetpt_mcp << std::endl; + std::cout << "******************************************" << std::endl; + } + JEhistos.fill(HIST("Resp_Matrix_MATCHED"), lResonance.Pt(), jetpt_mcd, mothers1Pt[0], jetpt_mcp); + unsigned int seed = static_cast(std::chrono::system_clock::now().time_since_epoch().count()); + int dice = rand_r(&seed) % 2; + if (dice > 0) + JEhistos.fill(HIST("Resp_Matrix_MATCHED_rand0"), lResonance.Pt(), jetpt_mcd, mothers1Pt[0], jetpt_mcp); + else + JEhistos.fill(HIST("Resp_Matrix_MATCHED_rand1"), lResonance.Pt(), jetpt_mcd, mothers1Pt[0], jetpt_mcp); + + JEhistos.fill(HIST("2DRecToGen"), lResonance.Pt(), jetpt_mcd); + // check constrained eff + if (mothers1Pt[0] > 0 && mothers1Pt[0] < 20.0 && jetpt_mcp > 8 && jetpt_mcp < 200) + JEhistos.fill(HIST("2DRecToGen_constrained"), lResonance.Pt(), jetpt_mcd); + } + // Fill 3D Invariant mass distributions if (jetFlag) { JEhistos.fill(HIST("hMCRec_hUSS_INSIDE_1D"), lResonance.M()); if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) JEhistos.fill(HIST("hMCRec_hUSS_INSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_hUSS_INSIDE"), 1.0, lResonance.Pt(), lResonance.M()); - - } else if (!jetFlag && mcd_pt.size() > 0) { - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); + JEhistos.fill(HIST("hMCRec_hUSS_INSIDE"), jetpt_mcd, lResonance.Pt(), lResonance.M()); + } + // else if (!jetFlag && mcd_pt.size() > 0) { + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_TRIG_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_TRIG_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_TRIG"), 1.0, lResonance.Pt(), lResonance.M()); + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_TRIG"), jetpt_mcd, lResonance.Pt(), lResonance.M()); - } else if (!jetFlag) { - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D"), lResonance.M()); + // } else if (!jetFlag) { + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D"), lResonance.M()); - if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); + // if (lResonance.Pt() > 2.0 && lResonance.Pt() < 3) + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE_1D_2_3"), lResonance.M()); - JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE"), 1.0, lResonance.Pt(), lResonance.M()); + // JEhistos.fill(HIST("hMCRec_hUSS_OUTSIDE"), jetpt_mcd, lResonance.Pt(), lResonance.M()); - } //! jetflag + // } //! jetflag } // pass track cut } // has mc particle diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx new file mode 100644 index 00000000000..b2dd899d872 --- /dev/null +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -0,0 +1,571 @@ +// Copyright 2019-2020 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. + +/// \file statPromptPhoton.cxx +/// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance hadrochemistry analysis. +/// +/// +/// \author Adrian Fereydon Nassirpour + +#include +#include + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "CommonConstants/PhysicsConstants.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" + +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/Constants.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" + +#include "CommonDataFormat/InteractionRecord.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct statPromptPhoton { + SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; + Configurable cfgConnectedToPV{"cfgConnectedToPV", true, "PV contributor track selection"}; + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; + Configurable cfgnFindableTPCClusters{"cfgnFindableTPCClusters", 50, "nFindable TPC Clusters"}; + Configurable cfgnTPCCrossedRows{"cfgnTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfgnRowsOverFindable{"cfgnRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; + Configurable cfgnTPCChi2{"cfgnTPChi2", 4.0, "nTPC Chi2 per Cluster"}; + Configurable cfgnITSChi2{"cfgnITShi2", 36.0, "nITS Chi2 per Cluster"}; + Configurable cfgClusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default, 0 = kV1Default"}; + Configurable cfgMinTime{"MinTime", -30., "Minimum cluster time for time cut"}; + Configurable cfgMaxTime{"MaxTime", +35., "Maximum cluster time for time cut"}; + Configurable cfgMinClusterEnergy{"MinClusterEnergy", 0.7f, "Minimal cluster energy"}; + Configurable cfgMinNCells{"MinNCelss", 2, "Minimal amount of cells per cluster"}; + Configurable cfgMaxNLM{"MaxNLM", 2, "Maximal amount of local Maxima per cluster"}; + Configurable cfgExoticContribution{"ExoticContribution", false, "Exotic cluster in the data"}; + Configurable cfgtrkMinPt{"cfgtrkMinPt", 0.15, "set track min pT"}; + Configurable cfgtrkMaxEta{"cfgtrkMaxEta", 0.6, "set track max Eta"}; + Configurable cfgMinR{"MinR", 0.1, "Min. Radii of Delta R cone around photon trigger"}; + Configurable cfgMaxR{"MaxR", 0.4, "Max. Radii of Delta R cone around photon trigger"}; + Configurable cfgMinTrig{"MinTrig", 1, "Min. Trigger energy/momentum"}; + Configurable cfgMaxTrig{"MaxTrig", 5, "Max. Trigger energy/momentum"}; + Configurable cfgVtxCut{"cfgVtxCut", 10.0, "V_z cut selection"}; + + // INIT + void init(InitContext const&) + { + std::vector ptBinning = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 12.0}; + AxisSpec pthadAxis = {ptBinning, "#it{p}_{T}^{had sum} [GeV/c]"}; + + histos.add("REC_nEvents", "REC_nEvents", kTH1F, {{4, 0.0, 4.0}}); + histos.add("REC_PtHadSum_Photon", "REC_PtHadSum_Photon", kTH1F, {pthadAxis}); + + histos.add("REC_Trigger_Energy", "REC_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_True_Trigger_Energy", "REC_True_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_True_Prompt_Trigger_Energy", "REC_True_Prompt_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); + + histos.add("REC_Trigger_V_PtHadSum_Stern", "REC_Trigger_V_PtHadSum_Stern", kTH2F, {{100, 0, 100}, pthadAxis}); + histos.add("REC_Trigger_V_PtHadSum_Photon", "REC_Trigger_V_PtHadSum_Photon", kTH2F, {{100, 0, 100}, pthadAxis}); + histos.add("REC_TrueTrigger_V_PtHadSum_Photon", "REC_Trigger_V_PtHadSum_Photon", kTH2F, {{100, 0, 100}, pthadAxis}); + histos.add("REC_dR_Photon", "REC_dR_Photon", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); + histos.add("REC_dR_Stern", "REC_dR_Stern", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); + + histos.add("GEN_True_Photon_Energy", "GEN_True_Photon_Energy", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_True_Prompt_Photon_Energy", "GEN_True_Prompt_Photon_Energy", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_Trigger_V_PtHadSum_Stern", "GEN_Trigger_V_PtHadSum_Stern", kTH2F, {{100, 0, 100}, pthadAxis}); + histos.add("GEN_Trigger_V_PtHadSum_Photon", "GEN_Trigger_V_PtHadSum_Photon", kTH2F, {{100, 0, 100}, pthadAxis}); + histos.add("GEN_TrueTrigger_V_PtHadSum_Photon", "GEN_Trigger_V_PtHadSum_Photon", kTH2F, {{100, 0, 100}, pthadAxis}); + histos.add("GEN_dR_Photon", "GEN_dR_Photon", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); + histos.add("GEN_dR_Stern", "GEN_dR_Stern", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); + + } // end of init + + Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == cfgClusterDefinition) && (o2::aod::emcalcluster::time >= cfgMinTime) && (o2::aod::emcalcluster::time <= cfgMaxTime) && (o2::aod::emcalcluster::energy > cfgMinClusterEnergy) && (o2::aod::emcalcluster::nCells >= cfgMinNCells) && (o2::aod::emcalcluster::nlm <= cfgMaxNLM) && (o2::aod::emcalcluster::isExotic == cfgExoticContribution); + Filter emccellfilter = aod::calo::caloType == 1; // mc emcal cell + Filter PosZFilter = nabs(aod::collision::posZ) < cfgVtxCut; + Filter mcPosZFilter = nabs(aod::mccollision::posZ) < cfgVtxCut; + + using MCCells = o2::soa::Join; + + using MCClusters = o2::soa::Join; + using selectedCollisions = soa::Join; + using selectedMCCollisions = aod::McCollisions; + + using TrackCandidates = soa::Join; + + using filteredMCCells = o2::soa::Filtered; + using filteredMCClusters = soa::Filtered; + using filteredCollisions = soa::Filtered; + using filteredMCCollisions = soa::Filtered; + + Preslice perClusterMatchedTracks = o2::aod::emcalclustercell::emcalclusterId; + // Helper functions + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + template + + double GetPtHadSum(const Tracks& tracks, const Trigger& trigger, double MinR, double MaxR, bool IsStern, bool IsParticle, bool DodR) + { + double eta_trigger, phi_trigger; + if constexpr (requires { trigger.eta(); }) { + eta_trigger = trigger.eta(); + phi_trigger = trigger.phi(); + } else if constexpr (requires { trigger.Eta(); }) { + eta_trigger = trigger.Eta(); + phi_trigger = trigger.Phi(); + } + double pthadsum = 0; + + for (auto& track : tracks) { + double phi_track = track.phi(); + double eta_track = track.eta(); + double pt_track = track.pt(); + + if (!IsParticle) { + if constexpr (requires { track.trackId(); }) { + auto originaltrack = track.template track_as>(); + if (!trackSelection(originaltrack)) { + continue; + } // reject track + } else if constexpr (requires { track.sign(); }) { // checking for JTrack + // done checking for JTrack, now default to normal tracks + if (!trackSelection(track)) { + continue; + } // reject track + } // done checking for JTrack + } else { + if constexpr (requires { track.isPhysicalPrimary(); }) { + if (track.pt() < 0.15) { + continue; + } + if (std::abs(track.eta()) > cfgtrkMaxEta) { + continue; + } + if (track.getGenStatusCode() < 20) { + continue; + } + if (!track.isPhysicalPrimary()) { + continue; + } + int pdg = std::abs(track.pdgCode()); + if (pdg != 211 && pdg != 321 && pdg != 2212) { + continue; + } + } + } + if (IsStern || IsParticle) { + if constexpr (requires { trigger.globalIndex(); }) { + if (trigger.globalIndex() == track.globalIndex()) + continue; + } + } + double phidiff = TVector2::Phi_mpi_pi(phi_track - phi_trigger); + double etadiff = std::abs(eta_track - eta_trigger); + double dR = TMath::Sqrt((etadiff * etadiff) + (phidiff * phidiff)); + + if (DodR) { + if (dR > MinR && dR < MaxR) { + if (!IsParticle) { + if (IsStern) { + histos.fill(HIST("REC_dR_Stern"), dR); + } + if (!IsStern) { + histos.fill(HIST("REC_dR_Photon"), dR); + } + } else { + if (IsStern) { + histos.fill(HIST("GEN_dR_Stern"), dR); + } + if (!IsStern) { + histos.fill(HIST("GEN_dR_Photon"), dR); + } + } + } + } + if (dR > MinR && dR < MaxR) { + pthadsum += pt_track; + } + + } // end of track loop + return pthadsum; + } // end of GetPtHadSum + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + template + bool trackSelection(const TrackType track) + { + // basic track cuts + if (track.pt() < cfgtrkMinPt) + return false; + + if (std::abs(track.eta()) > cfgtrkMaxEta) + return false; + + if (std::abs(track.dcaXY()) > cfgMaxDCArToPVcut) + return false; + + if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) + return false; + + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + + if (track.tpcNClsFindable() < cfgnFindableTPCClusters) + return false; + + if (track.tpcNClsCrossedRows() < cfgnTPCCrossedRows) + return false; + + if (track.tpcCrossedRowsOverFindableCls() > cfgnRowsOverFindable) + return false; + + if (track.tpcChi2NCl() > cfgnTPCChi2) + return false; + + if (track.itsChi2NCl() > cfgnITSChi2) + return false; + + if (cfgConnectedToPV && !track.isPVContributor()) + return false; + + return true; + }; // end of track selection + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////// + // PROCESS + + // int nEvents = 0; + int nEventsRecMC = 0; + int nEventsGenMC = 0; + // aod::StoredMcParticles_001 const& + void processMCRec(filteredCollisions::iterator const& collision, filteredMCClusters const& mcclusters, aod::McParticles const&, o2::aod::EMCALClusterCells const& /*emccluscells*/, o2::aod::EMCALMatchedTracks const& matchedtracks, TrackCandidates const& tracks) + { + + nEventsRecMC++; + if ((nEventsRecMC + 1) % 10000 == 0) { + std::cout << "Processed Rec MC Events: " << nEventsRecMC << std::endl; + } + histos.fill(HIST("REC_nEvents"), 0.5); + + if (fabs(collision.posZ()) > cfgVtxCut) + return; + if (!collision.sel8()) + return; + + // now we do clusters + for (auto& mccluster : mcclusters) { + bool photontrigger = false; + double photonPt = 0.0; + double truephotonPt = 0.0; + auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, mccluster.globalIndex()); + + // first, we do the data-level analysis + if (tracksofcluster.size() < 1) { + if (mccluster.energy() > cfgMinTrig && mccluster.energy() < cfgMaxTrig) { + if (fabs(mccluster.eta()) <= cfgtrkMaxEta) { + photontrigger = true; + photonPt = mccluster.energy(); + } + } + } + + if (photontrigger) { + double pthadsum = GetPtHadSum(tracks, mccluster, cfgMinR, cfgMaxR, false, false, true); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), photonPt, pthadsum); + histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum); + histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy()); + + // now we check the realness of our prompt photons + auto ClusterParticles = mccluster.mcParticle_as(); + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() == 22) { + histos.fill(HIST("REC_True_Trigger_Energy"), clusterparticle.e()); + if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 70) { + histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); + TLorentzVector lRealPhoton; + lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); + double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); + truephotonPt = clusterparticle.e(); + histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); + } + } // photon check + } // photon trigger loop + } // clusterparticle loop + + } // cluster loop + + // clusters done, now we do the sternheimer tracks + + for (auto& track : tracks) { + bool sterntrigger = false; + double sternPt = 0.0; + if (!trackSelection(track)) { + continue; + } + if (track.pt() > cfgMinTrig && track.pt() < cfgMaxTrig) { + if (fabs(track.eta()) <= cfgtrkMaxEta) { + sterntrigger = true; + sternPt = track.pt(); + } + } + + if (sterntrigger) { + bool doStern = true; + double sterncount = 1.0; + while (doStern) { + double pthadsum = GetPtHadSum(tracks, track, cfgMinR, cfgMaxR, true, false, true); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, 2.0 / sternPt); + if (sterncount < sternPt) { + sterncount++; + } else { + doStern = false; + } + } // While sternin' + } // stern trigger loop + } // track loop + + histos.fill(HIST("REC_nEvents"), 1.5); + } // end of process + + PROCESS_SWITCH(statPromptPhoton, processMCRec, "process MC data", true); + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + void processMCGen(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles) + { + nEventsGenMC++; + if ((nEventsGenMC + 1) % 10000 == 0) { + std::cout << "Processed Gen MC Events: " << nEventsGenMC << std::endl; + } + if (fabs(collision.posZ()) > cfgVtxCut) + return; + + if (recocolls.size() <= 0) // not reconstructed + return; + for (auto& recocoll : recocolls) { // poorly reconstructed + if (!recocoll.sel8()) + return; + if (fabs(recocoll.posZ()) > cfgVtxCut) + + return; + } + + for (auto& mcPhoton : mcParticles) { + bool photontrigger = false; + if (mcPhoton.pt() < 0.15) + continue; + if (std::abs(mcPhoton.eta()) > cfgtrkMaxEta) + continue; + if (mcPhoton.getGenStatusCode() < 20) + continue; + + // first we check for pthadsums for all charged particles a la sternheimer + if (mcPhoton.isPhysicalPrimary()) { + int pdg = std::abs(mcPhoton.pdgCode()); + if (pdg == 211 || pdg == 321 || pdg == 2212) { + bool sterntrigger = false; + double sternPt = 0.0; + if (mcPhoton.pt() > cfgMinTrig && mcPhoton.pt() < cfgMaxTrig) { + if (fabs(mcPhoton.eta()) <= cfgtrkMaxEta) { + sterntrigger = true; + sternPt = mcPhoton.pt(); + } + } + // stern trigger + if (sterntrigger) { + bool doStern = true; + double sterncount = 1.0; + while (doStern) { + TLorentzVector lParticleTrigger; + lParticleTrigger.SetPxPyPzE(mcPhoton.px(), mcPhoton.py(), mcPhoton.pz(), mcPhoton.e()); + double pthadsum = GetPtHadSum(mcParticles, lParticleTrigger, cfgMinR, cfgMaxR, true, true, true); + histos.fill(HIST("GEN_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, 2.0 / sternPt); + if (sterncount < sternPt) { + sterncount++; + } else { + doStern = false; + } + } // While sternin' + } // stern trigger loop + } // check if charged pikp + } // check for primary particles + + // now we do all photons + if (mcPhoton.pdgCode() == 22) { + histos.fill(HIST("GEN_True_Photon_Energy"), mcPhoton.e()); + if (mcPhoton.pt() > cfgMinTrig && mcPhoton.pt() < cfgMaxTrig) { + if (fabs(mcPhoton.eta()) <= cfgtrkMaxEta) { + photontrigger = true; + } + } // check for photon trigger + if (photontrigger) { + TLorentzVector lRealPhoton; + lRealPhoton.SetPxPyPzE(mcPhoton.px(), mcPhoton.py(), mcPhoton.pz(), mcPhoton.e()); + double truepthadsum = GetPtHadSum(mcParticles, lRealPhoton, cfgMinR, cfgMaxR, false, true, false); + histos.fill(HIST("GEN_Trigger_V_PtHadSum_Photon"), mcPhoton.e(), truepthadsum); + } + // now we do all PROMPT photons + if (std::abs(mcPhoton.getGenStatusCode()) > 19 && std::abs(mcPhoton.getGenStatusCode()) < 70) { + if (mcPhoton.isPhysicalPrimary()) { + histos.fill(HIST("GEN_True_Prompt_Photon_Energy"), mcPhoton.e()); + if (photontrigger) { + TLorentzVector lRealPromptPhoton; + lRealPromptPhoton.SetPxPyPzE(mcPhoton.px(), mcPhoton.py(), mcPhoton.pz(), mcPhoton.e()); + double truepthadsum = GetPtHadSum(mcParticles, lRealPromptPhoton, cfgMinR, cfgMaxR, false, true, true); + histos.fill(HIST("GEN_TrueTrigger_V_PtHadSum_Photon"), mcPhoton.e(), truepthadsum); + } // photontrigger + } // check for primary photons + } // prompt photon check + + } // photon check + + } // loop over mc particles + + } // end of process + + PROCESS_SWITCH(statPromptPhoton, processMCGen, "process MC Gen", true); + + Filter PosZFilter_JE = nabs(aod::jcollision::posZ) < cfgVtxCut; + Filter clusterDefinitionSelection_JE = (o2::aod::jcluster::definition == cfgClusterDefinition) && (o2::aod::jcluster::time >= cfgMinTime) && (o2::aod::jcluster::time <= cfgMaxTime) && (o2::aod::jcluster::energy > cfgMinClusterEnergy) && (o2::aod::jcluster::nCells >= cfgMinNCells) && (o2::aod::jcluster::nlm <= cfgMaxNLM) && (o2::aod::jcluster::isExotic == cfgExoticContribution); + + using jTrackCandidates = soa::Join; + using jMCClusters = o2::soa::Join; + using jselectedCollisions = soa::Join; + using jfilteredCollisions = soa::Filtered; + using jfilteredMCClusters = soa::Filtered; + + int nEventsRecMC_JE = 0; + + void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, aod::JMcParticles const&, o2::aod::EMCALClusterCells const& /*emccluscells*/, o2::aod::EMCALMatchedTracks const& matchedtracks, jTrackCandidates const& tracks, TrackCandidates const&) + { + nEventsRecMC_JE++; + if ((nEventsRecMC_JE + 1) % 10000 == 0) { + std::cout << "Processed JE Rec MC Events: " << nEventsRecMC_JE << std::endl; + } + + histos.fill(HIST("REC_nEvents"), 0.5); + + if (fabs(collision.posZ()) > cfgVtxCut) + return; + if (!collision.sel8()) + return; + + // now we do clusters + for (auto& mccluster : mcclusters) { + bool photontrigger = false; + double photonPt = 0.0; + double truephotonPt = 0.0; + auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, mccluster.globalIndex()); + + // first, we do the data-level analysis + if (tracksofcluster.size() < 1) { + if (mccluster.energy() > cfgMinTrig && mccluster.energy() < cfgMaxTrig) { + if (fabs(mccluster.eta()) <= cfgtrkMaxEta) { + photontrigger = true; + photonPt = mccluster.energy(); + } + } + } + if (photontrigger) { + double pthadsum = GetPtHadSum(tracks, mccluster, cfgMinR, cfgMaxR, false, false, true); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), photonPt, pthadsum); + histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum); + histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy()); + + // now we check the realness of our prompt photons + auto ClusterParticles = mccluster.mcParticle_as(); + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() == 22) { + histos.fill(HIST("REC_True_Trigger_Energy"), clusterparticle.e()); + if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 70) { + histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); + TLorentzVector lRealPhoton; + lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); + double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); + truephotonPt = clusterparticle.e(); + histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); + } + } // photon check + } // photon trigger loop + } // clusterparticle loop + } // cluster loop + + // clusters done, now we do the sternheimer tracks + for (auto& track : tracks) { + bool sterntrigger = false; + double sternPt = 0.0; + auto ogtrack = track.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (track.pt() > cfgMinTrig && track.pt() < cfgMaxTrig) { + if (fabs(track.eta()) <= cfgtrkMaxEta) { + sterntrigger = true; + sternPt = track.pt(); + } + } + + if (sterntrigger) { + bool doStern = true; + double sterncount = 1.0; + while (doStern) { + double pthadsum = GetPtHadSum(tracks, track, cfgMinR, cfgMaxR, true, false, true); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, 2.0 / sternPt); + if (sterncount < sternPt) { + sterncount++; + } else { + doStern = false; + } + } // While sternin' + } // stern trigger loop + } // track loop + + histos.fill(HIST("REC_nEvents"), 1.5); + + } // end of process + + PROCESS_SWITCH(statPromptPhoton, processMCRec_JE, "processJE MC data", false); + +}; // end of main struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index 8ec1537bf32..67821db8a8c 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -55,17 +55,20 @@ struct TrackEfficiencyJets { Configurable checkPrimaryPart{"checkPrimaryPart", true, "0: doesn't check mcparticle.isPhysicalPrimary() - 1: checks particle.isPhysicalPrimary()"}; Configurable checkCentrality{"checkCentrality", false, ""}; Configurable acceptSplitCollisions{"acceptSplitCollisions", 0, "0: only look at mcCollisions that are not split; 1: accept split mcCollisions, 2: accept split mcCollisions but only look at the first reco collision associated with it"}; - Configurable trackEtaAcceptance{"trackEtaAcceptance", 0.9, "eta acceptance"}; + Configurable trackEtaAcceptanceCountQA{"trackEtaAcceptanceCountQA", 0.9, "eta acceptance"}; // removed from actual cuts for now because all the histograms have an eta axis Configurable centralityMin{"centralityMin", -999, ""}; Configurable centralityMax{"centralityMax", 999, ""}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable trackDcaZmax{"trackDcaZmax", 99, "additional cut on dcaZ to PV for tracks; uniformTracks in particular don't cut on this at all"}; + Configurable nBinsLowPt{"nBinsLowPt", 200, "number of pt bins for low pt (below 10GeV) efficiency histograms"}; // Track QA process function configurables: - Configurable trackQAEtaMin{"trackEtaMin", -0.9, "minimum eta acceptance for tracks in the processTracks QA"}; - Configurable trackQAEtaMax{"trackEtaMax", 0.9, "maximum eta acceptance for tracks in the processTracks QA"}; - Configurable trackQAPtMin{"trackPtMin", 0.15, "minimum pT acceptance for tracks in the processTracks QA"}; - Configurable trackQAPtMax{"trackPtMax", 100.0, "maximum pT acceptance for tracks in the processTracks QA"}; + Configurable trackQAEtaMin{"trackQAEtaMin", -0.9, "minimum eta acceptance for tracks in the processTracks QA"}; + Configurable trackQAEtaMax{"trackQAEtaMax", 0.9, "maximum eta acceptance for tracks in the processTracks QA"}; + Configurable trackQAPtMin{"trackQAPtMin", 0.15, "minimum pT acceptance for tracks in the processTracks QA"}; + Configurable trackQAPtMax{"trackQAPtMax", 100.0, "maximum pT acceptance for tracks in the processTracks QA"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range; only applied for reconstructed tracks, not mc particles"}; + Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum occupancy of tracks in neighbouring collisions in a given time range; only applied for reconstructed tracks, not mc particles"}; int eventSelection = -1; int trackSelection = -1; @@ -91,8 +94,21 @@ struct TrackEfficiencyJets { registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); - registry.fill(HIST("h3_centrality_track_pt_track_sigma1overpt"), collision.centrality(), track.pt(), track.sigma1Pt(), weight); - registry.fill(HIST("h3_centrality_track_pt_track_sigmapt"), collision.centrality(), track.pt(), track.sigma1Pt() * track.pt(), weight); + registry.fill(HIST("h2_track_pt_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); + registry.fill(HIST("h2_track_pt_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); + registry.fill(HIST("h2_track_pt_high_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); + registry.fill(HIST("h2_track_pt_high_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); + } + } + + template + void fillParticlesHistograms(T const& collision, U const& mcparticles, float weight = 1.0) + { + for (auto const& mcparticle : mcparticles) { + registry.fill(HIST("h2_centrality_particle_pt"), collision.centrality(), mcparticle.pt(), weight); + registry.fill(HIST("h2_centrality_particle_eta"), collision.centrality(), mcparticle.eta(), weight); + registry.fill(HIST("h2_centrality_particle_phi"), collision.centrality(), mcparticle.phi(), weight); + registry.fill(HIST("h2_centrality_particle_energy"), collision.centrality(), mcparticle.energy(), weight); } } @@ -113,48 +129,91 @@ struct TrackEfficiencyJets { registry.add("hMcPartCutsCounts", "McPart cuts count checks", {HistType::kTH1F, {{10, 0., 10.}}}); registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(1, "allPartsInSelMcColl"); - registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(2, "isPrimary"); - registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(3, "etaAccept"); - registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(4, "isCharged"); + registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(2, "isCharged"); + registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(3, "isPrimary"); + registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(4, "etaAccept"); // not actually applied here but it will give an idea of what will be done in the post processing registry.add("hTrackCutsCounts", "Track cuts count checks", {HistType::kTH1F, {{10, 0., 10.}}}); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(1, "allTracksInSelColl"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(2, "trackSel"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(3, "hasMcParticle"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "mcPartIsPrimary"); - registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + + AxisSpec ptAxis_eff = {nBinsLowPt, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisHigh_eff = {18, 10., 100., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec etaAxis_eff = {100, -1.0, 1.0, "#eta"}; + AxisSpec phiAxis_eff = {200, -1.0, 7., "#phi"}; + + // ptAxisLow + registry.add("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + + registry.add("h3_track_pt_track_eta_track_phi_nonassociatedtrack", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_primary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); - AxisSpec ptAxis = {500, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec etaAxis = {100, -1.0, 1.0, "#eta"}; - AxisSpec phiAxis = {200, -1.0, 7., "#phi"}; + registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis_eff, etaAxis_eff, phiAxis_eff}}); - registry.add("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); + registry.add("h2_particle_pt_track_pt_residual_associatedtrack_primary", "(#it{p}_{T, mcpart} - #it{p}_{T, track}) / #it{p}_{T, mcpart}; #it{p}_{T, mcpart} (GeV/#it{c})", {HistType::kTH2F, {ptAxis_eff, {200, -1., 1.}}}); - registry.add("h3_track_pt_track_eta_track_phi_nonassociatedtrack", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); - registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_primary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); - registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); - registry.add("h3_track_pt_track_eta_track_phi_associatedtrack_split", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); + // ptAxisHigh + registry.add("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); - registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); - registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); - registry.add("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxis, etaAxis, phiAxis}}); + registry.add("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_high_track_eta_track_phi_associatedtrack_primary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_high_track_eta_track_phi_associatedtrack_nonprimary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_primary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_nonprimary", "#it{p}_{T, track} (GeV/#it{c}); #eta_{track}; #phi_{track}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); - registry.add("h2_particle_pt_track_pt_diif_associatedtrack_primary", "(#it{p}_{T, mcpart} - #it{p}_{T, track}) / #it{p}_{T, mcpart}; #it{p}_{T, mcpart} (GeV/#it{c})", {HistType::kTH2F, {ptAxis, {200, -1., 1.}}}); + registry.add("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_primary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_primary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + registry.add("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_nonprimary", "#it{p}_{T, mcpart} (GeV/#it{c}); #eta_{mcpart}; #phi_{mcpart}", {HistType::kTH3F, {ptAxisHigh_eff, etaAxis_eff, phiAxis_eff}}); + + registry.add("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary", "(#it{p}_{T, mcpart} - #it{p}_{T, track}) / #it{p}_{T, mcpart}; #it{p}_{T, mcpart} (GeV/#it{c})", {HistType::kTH2F, {ptAxisHigh_eff, {200, -1., 1.}}}); } if (doprocessTracks || doprocessTracksWeighted) { - AxisSpec centAxis = {101, 0., 101., "centrality (%)"}; - registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + AxisSpec centAxis = {121, -10., 111., "centrality (%)"}; registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {centAxis, {200, 0., 200.}}}); registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {centAxis, {100, -1.0, 1.0}}}); registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {centAxis, {160, -1.0, 7.}}}); registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {centAxis, {100, 0.0, 100.0}}}); - registry.add("h3_centrality_track_pt_track_sigmapt", "#it{p}_{T,track} (GeV/#it{c}); #sigma(#it{p}_{T})", {HistType::kTH3F, {centAxis, {100, 0., 100.}, {200, 0.0, 2.0}}}); - registry.add("h3_centrality_track_pt_track_sigma1overpt", "#it{p}_{T,track} (GeV/#it{c}); #sigma(#it{p}_{T})/#it{p}_{T}", {HistType::kTH3F, {centAxis, {1000, 0., 100.}, {200, 0.0, 2.0}}}); - if (doprocessTracksWeighted) { - registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - } + registry.add("h2_track_pt_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {100000, 0.0, 100.0}}}); + registry.add("h2_track_pt_high_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {100000, 0.0, 100.0}}}); + registry.add("h2_track_pt_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {1000, 0.0, 10.0}}}); + registry.add("h2_track_pt_high_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {1000, 0.0, 10.0}}}); + } + + if (doprocessParticles || doprocessParticlesWeighted) { + AxisSpec centAxis = {121, -10., 111., "centrality (%)"}; + registry.add("h2_centrality_particle_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {centAxis, {200, 0., 200.}}}); + registry.add("h2_centrality_particle_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {centAxis, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_particle_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {centAxis, {160, -1.0, 7.}}}); + registry.add("h2_centrality_particle_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {centAxis, {100, 0.0, 100.0}}}); + } + + if (doprocessTracks || doprocessTracksWeighted) { + AxisSpec centAxis = {121, -10., 111., "centrality (%)"}; + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + } + if (doprocessParticles || doprocessParticlesWeighted) { + AxisSpec centAxis = {121, -10., 111., "centrality (%)"}; + registry.add("h_mccollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_mccollisions", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + } + if (doprocessTracksWeighted) { + registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + } + if (doprocessParticlesWeighted) { + registry.add("h_mccollisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); } } @@ -162,6 +221,7 @@ struct TrackEfficiencyJets { // filters for processTracks QA functions only: Filter trackCuts = (aod::jtrack::pt >= trackQAPtMin && aod::jtrack::pt < trackQAPtMax && aod::jtrack::eta > trackQAEtaMin && aod::jtrack::eta < trackQAEtaMax); + Filter particleCuts = (aod::jmcparticle::pt >= trackQAPtMin && aod::jmcparticle::pt < trackQAPtMax && aod::jmcparticle::eta > trackQAEtaMin && aod::jmcparticle::eta < trackQAEtaMax); Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); void processEFficiencyPurity(JetMcCollision const& mcCollision, @@ -224,22 +284,25 @@ struct TrackEfficiencyJets { for (auto& jMcParticle : jMcParticles) { registry.fill(HIST("hMcPartCutsCounts"), 0.5); // allPartsInSelMcColl - if (checkPrimaryPart && !jMcParticle.isPhysicalPrimary()) { // global tracks should be mostly primaries + if (!isChargedParticle(jMcParticle.pdgCode())) { continue; } - registry.fill(HIST("hMcPartCutsCounts"), 1.5); // isPrimary + registry.fill(HIST("hMcPartCutsCounts"), 1.5); // isCharged - if (!(abs(jMcParticle.eta()) < trackEtaAcceptance)) { - continue; - } - registry.fill(HIST("hMcPartCutsCounts"), 2.5); // etaAccept + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi()); - if (!isChargedParticle(jMcParticle.pdgCode())) { + if (checkPrimaryPart && !jMcParticle.isPhysicalPrimary()) { // global tracks should be mostly primaries continue; } - registry.fill(HIST("hMcPartCutsCounts"), 3.5); // isCharged + registry.fill(HIST("hMcPartCutsCounts"), 2.5); // isPrimary registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi()); + + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi()); + + if ((abs(jMcParticle.eta()) < trackEtaAcceptanceCountQA)) { // removed from actual cuts for now because all the histograms have an eta axis + registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing + } } std::vector seenMcParticlesVector; // is reset every mc collision @@ -266,6 +329,8 @@ struct TrackEfficiencyJets { if (!track.has_mcParticle()) { registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi()); + + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi()); continue; } registry.fill(HIST("hTrackCutsCounts"), 2.5); @@ -274,6 +339,20 @@ struct TrackEfficiencyJets { if (!jMcParticleFromTrack.isPhysicalPrimary()) { registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + + if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + } else { + seenMcParticlesVector.push_back(jMcParticleFromTrack.globalIndex()); + } + continue; } @@ -281,16 +360,23 @@ struct TrackEfficiencyJets { registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); - registry.fill(HIST("h2_particle_pt_track_pt_diif_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); + registry.fill(HIST("h2_particle_pt_track_pt_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); + + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split"), track.pt(), track.eta(), track.phi()); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); + + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); } else { seenMcParticlesVector.push_back(jMcParticleFromTrack.globalIndex()); } - if (abs(jMcParticleFromTrack.eta()) < trackEtaAcceptance) { // not actually applied here but it will give an idea of what will be done in the post processing + if (abs(jMcParticleFromTrack.eta()) < trackEtaAcceptanceCountQA) { // not actually applied here but it will give an idea of what will be done in the post processing registry.fill(HIST("hTrackCutsCounts"), 4.5); } } @@ -308,6 +394,11 @@ struct TrackEfficiencyJets { } registry.fill(HIST("h_collisions"), 1.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 1.5); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_collisions"), 2.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); fillTrackHistograms(collision, tracks); } PROCESS_SWITCH(TrackEfficiencyJets, processTracks, "QA for charged tracks", false); @@ -324,9 +415,113 @@ struct TrackEfficiencyJets { } registry.fill(HIST("h_collisions"), 1.5); registry.fill(HIST("h_collisions_weighted"), 1.5, eventWeight); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_collisions"), 2.5); + registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); fillTrackHistograms(collision, tracks, eventWeight); } PROCESS_SWITCH(TrackEfficiencyJets, processTracksWeighted, "QA for charged tracks weighted", false); + + void processParticles(JetMcCollision const& mcCollision, + soa::SmallGroups const& collisions, + soa::Filtered const& mcparticles) + { + registry.fill(HIST("h_mccollisions"), 0.5); + registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 0.5); + + if (!(abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + if (collisions.size() < 1) { + return; + } + if (acceptSplitCollisions == 0 && collisions.size() > 1) { + return; + } + + bool hasSel8Coll = false; + bool centralityCheck = false; + if (acceptSplitCollisions == 2) { // check only that the first reconstructed collision passes the check + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } else { // check that at least one of the reconstructed collisions passes the checks + for (auto& collision : collisions) { + if (jetderiveddatautilities::selectCollision(collision, eventSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } + } + if (!hasSel8Coll) { + return; + } + if (!centralityCheck) { + return; + } + + registry.fill(HIST("h_mccollisions"), 1.5); + registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 1.5); + fillParticlesHistograms(collisions.begin(), mcparticles); + } + PROCESS_SWITCH(TrackEfficiencyJets, processParticles, "QA for charged particles", false); + + void processParticlesWeighted(JetMcCollision const& mcCollision, + soa::SmallGroups const& collisions, + soa::Filtered const& mcparticles) + { + float eventWeight = mcCollision.weight(); + registry.fill(HIST("h_mccollisions"), 0.5); + registry.fill(HIST("h_mccollisions_weighted"), 0.5, eventWeight); + + if (!(abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + if (collisions.size() < 1) { + return; + } + if (acceptSplitCollisions == 0 && collisions.size() > 1) { + return; + } + + bool hasSel8Coll = false; + bool centralityCheck = false; + if (acceptSplitCollisions == 2) { // check only that the first reconstructed collision passes the check + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } else { // check that at least one of the reconstructed collisions passes the checks + for (auto& collision : collisions) { + if (jetderiveddatautilities::selectCollision(collision, eventSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } + } + if (!hasSel8Coll) { + return; + } + if (!centralityCheck) { + return; + } + + registry.fill(HIST("h_mccollisions"), 1.5); + registry.fill(HIST("h_mccollisions_weighted"), 1.5, eventWeight); + fillParticlesHistograms(collisions.begin(), mcparticles, eventWeight); + } + PROCESS_SWITCH(TrackEfficiencyJets, processParticlesWeighted, "QA for charged particles weighted", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"track-efficiency"})}; } diff --git a/PWGJE/Tasks/triggerCorrelations.cxx b/PWGJE/Tasks/triggerCorrelations.cxx index e215bae706e..bb2d43e1f95 100644 --- a/PWGJE/Tasks/triggerCorrelations.cxx +++ b/PWGJE/Tasks/triggerCorrelations.cxx @@ -44,79 +44,31 @@ struct TriggerCorrelationsTask { HistogramRegistry registry; - int nChTrigs; - int nFullTrigs; - int nChHFTrigs; - int nAllTrigs; - - int chTrigOffset; - int fullTrigOffset; - int chHFTrigOffset; - + std::vector triggerMaskBits; void init(o2::framework::InitContext&) { - std::vector trigSelChLabels = {"chargedLow", "chargedHigh", "trackLowPt", "trackHighPt"}; - std::vector trigSelFullLabels = {"fullHigh", "fullLow", "neutralHigh", "neutralLow", "gammaVeryHighEMCAL", "gammaHighEMCAL", "gammaLowEMCAL", "gammaVeryLowEMCAL", "gammaVeryHighDCAL", "gammaHighDCAL", "gammaLowDCAL", "gammaVeryLowDCAL"}; - std::vector trigSelChHFLabels = {"chargedD0Low", "chargedD0High", "chargedLcLow", "chargedLcHigh"}; - nChTrigs = trigSelChLabels.size(); - nFullTrigs = trigSelFullLabels.size(); - nChHFTrigs = trigSelChHFLabels.size(); - nAllTrigs = nChTrigs + nFullTrigs + nChHFTrigs; - chTrigOffset = 0; - fullTrigOffset = chTrigOffset + nChTrigs; - chHFTrigOffset = fullTrigOffset + nFullTrigs; - registry.add("triggerCorrelations", "Correlation between jet triggers", HistType::kTH2D, {{nAllTrigs, -0.5, static_cast(nAllTrigs) - 0.5, "primary trigger"}, {nAllTrigs, -0.5, static_cast(nAllTrigs) - 0.5, "secondary trigger"}}); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(jetderiveddatautilities::JTriggerMasks); + + std::vector trigSelLabels = {"JetChLowPt", "JetChHighPt", "TrackLowPt", "TrackHighPt", "JetD0ChLowPt", "JetD0ChHighPt", "JetLcChLowPt", "JetLcChHighPt", "EMCALReadout", "JetFullHighPt", "JetFullLowPt", "JetNeutralHighPt", "JetNeutralLowPt", "GammaVeryHighPtEMCAL", "GammaVeryHighPtDCAL", "GammaHighPtEMCAL", "GammaHighPtDCAL", "GammaLowPtEMCAL", "GammaLowPtDCAL", "GammaVeryLowPtEMCAL", "GammaVeryLowPtDCAL"}; + registry.add("triggerCorrelations", "Correlation between jet triggers", HistType::kTH2D, {{static_cast(trigSelLabels.size()), -0.5, static_cast(trigSelLabels.size()) - 0.5, "primary trigger"}, {static_cast(trigSelLabels.size()), -0.5, static_cast(trigSelLabels.size()) - 0.5, "secondary trigger"}}); auto triggerCorrelation = registry.get(HIST("triggerCorrelations")); - for (auto iChTrigs = 0; iChTrigs < nChTrigs; iChTrigs++) { - triggerCorrelation->GetXaxis()->SetBinLabel(iChTrigs + chTrigOffset + 1, trigSelChLabels[iChTrigs].data()); - triggerCorrelation->GetYaxis()->SetBinLabel(iChTrigs + chTrigOffset + 1, trigSelChLabels[iChTrigs].data()); - } - for (auto iFullTrigs = 0; iFullTrigs < nFullTrigs; iFullTrigs++) { - triggerCorrelation->GetXaxis()->SetBinLabel(iFullTrigs + fullTrigOffset + 1, trigSelFullLabels[iFullTrigs].data()); - triggerCorrelation->GetYaxis()->SetBinLabel(iFullTrigs + fullTrigOffset + 1, trigSelFullLabels[iFullTrigs].data()); - } - for (auto iChHFTrigs = 0; iChHFTrigs < nChHFTrigs; iChHFTrigs++) { - triggerCorrelation->GetXaxis()->SetBinLabel(iChHFTrigs + chHFTrigOffset + 1, trigSelChHFLabels[iChHFTrigs].data()); - triggerCorrelation->GetYaxis()->SetBinLabel(iChHFTrigs + chHFTrigOffset + 1, trigSelChHFLabels[iChHFTrigs].data()); + for (std::vector::size_type iTrigs = 0; iTrigs < trigSelLabels.size(); iTrigs++) { + triggerCorrelation->GetXaxis()->SetBinLabel(iTrigs + 1, trigSelLabels[iTrigs].data()); + triggerCorrelation->GetYaxis()->SetBinLabel(iTrigs + 1, trigSelLabels[iTrigs].data()); } } template - void fillCorrelationsHistogram(T const& collision, bool fill = false, int iTrig = -1) + void fillCorrelationsHistogram(T const& collision, bool fill = false, int iCurrentTrig = -1) { - - for (auto iChTrigs = 0; iChTrigs < nChTrigs; iChTrigs++) { - if (fill) { - if (jetderiveddatautilities::selectChargedTrigger(collision, iChTrigs + 1)) { - registry.fill(HIST("triggerCorrelations"), iTrig, iChTrigs + chTrigOffset); - } - } else { - if (jetderiveddatautilities::selectChargedTrigger(collision, iChTrigs + 1)) { - fillCorrelationsHistogram(collision, true, iChTrigs + chTrigOffset); - } - } - } - - for (auto iFullTrigs = 0; iFullTrigs < nFullTrigs; iFullTrigs++) { - if (fill) { - if (jetderiveddatautilities::selectFullTrigger(collision, iFullTrigs + 1)) { - registry.fill(HIST("triggerCorrelations"), iTrig, iFullTrigs + fullTrigOffset); - } - } else { - if (jetderiveddatautilities::selectFullTrigger(collision, iFullTrigs + 1)) { - fillCorrelationsHistogram(collision, true, iFullTrigs + fullTrigOffset); - } - } - } - - for (auto iChHFTrigs = 0; iChHFTrigs < nFullTrigs; iChHFTrigs++) { + for (std::vector::size_type iTrig = 0; iTrig < triggerMaskBits.size(); iTrig++) { if (fill) { - if (jetderiveddatautilities::selectChargedHFTrigger(collision, iChHFTrigs + 1)) { - registry.fill(HIST("triggerCorrelations"), iTrig, iChHFTrigs + chHFTrigOffset); + if (jetderiveddatautilities::selectTrigger(collision, triggerMaskBits[iTrig])) { + registry.fill(HIST("triggerCorrelations"), iCurrentTrig, iTrig); } } else { - if (jetderiveddatautilities::selectChargedHFTrigger(collision, iChHFTrigs + 1)) { - fillCorrelationsHistogram(collision, true, iChHFTrigs + chHFTrigOffset); + if (jetderiveddatautilities::selectTrigger(collision, triggerMaskBits[iTrig])) { + fillCorrelationsHistogram(collision, true, iTrig); } } } diff --git a/PWGJE/Tasks/v0jetspectra.cxx b/PWGJE/Tasks/v0jetspectra.cxx index dad55b12e52..b2e681e90c7 100644 --- a/PWGJE/Tasks/v0jetspectra.cxx +++ b/PWGJE/Tasks/v0jetspectra.cxx @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// jet spectra for v0 fragmentation study -// +/// \brief Jet spectra for ch+V0 jets +/// /// \author Gijs van Weelden // diff --git a/PWGJE/Tasks/v0qa.cxx b/PWGJE/Tasks/v0qa.cxx new file mode 100644 index 00000000000..3d84c5b3f8f --- /dev/null +++ b/PWGJE/Tasks/v0qa.cxx @@ -0,0 +1,382 @@ +// Copyright 2019-2020 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. + +/// \brief QA task for V0s in the jets framework, based on the LF v0cascadesqa task +// +/// \author Gijs van Weelden +// + +#include "TH1F.h" +#include "TTree.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/RunningWorkflowInfo.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include "CommonConstants/PhysicsConstants.h" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// V0 jets +using MCDV0Jets = aod::V0ChargedMCDetectorLevelJets; +using MCDV0JetsWithConstituents = soa::Join; +using MatchedMCDV0Jets = soa::Join; +using MatchedMCDV0JetsWithConstituents = soa::Join; + +using MCPV0Jets = aod::V0ChargedMCParticleLevelJets; +using MCPV0JetsWithConstituents = soa::Join; +using MatchedMCPV0Jets = soa::Join; +using MatchedMCPV0JetsWithConstituents = soa::Join; + +struct V0QA { + HistogramRegistry registry{"registry"}; // CallSumw2 = false? + + Configurable evSel{"evSel", "sel8WithoutTimeFrameBorderCut", "choose event selection"}; + Configurable v0cospaMin{"v0cospaMin", 0.995, "Minimum V0 cosine of pointing angle"}; + Configurable v0radiusMin{"v0radiusMin", 0.5, "Minimum V0 radius (cm)"}; + Configurable dcav0dauMax{"dcav0dauMax", 1.0, "Maximum DCA between V0 daughters (cm)"}; + Configurable dcapiMin{"dcapiMin", 0.1, "Minimum DCA of pion daughter to PV (cm)"}; + Configurable dcaprMin{"dcaprMin", 0.1, "Minimum DCA of proton daughter to PV (cm)"}; + Configurable yK0SMax{"yK0SMax", 0.5, "Maximum rapidity of K0S"}; + Configurable yLambdaMax{"yLambdaMax", 0.5, "Maximum rapidity of Lambda(bar)"}; + Configurable lifetimeK0SMax{"lifetimeK0SMax", 20.0, "Maximum lifetime of K0S (cm)"}; + Configurable lifetimeLambdaMax{"lifetimeLambdaMax", 30.0, "Maximum lifetime of Lambda (cm)"}; + Configurable yPartMax{"yPartMax", 0.5, "Maximum rapidity of particles"}; + Configurable vertexZCut{"vertexZCut", 10.0, "Vertex Z cut"}; + + Filter jetCollisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; + + // PresliceUnsorted CollisionsPerMcCollision = aod::jv0indices::mcCollisionId; + + ConfigurableAxis binPtJet{"ptJet", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binPtV0{"ptV0", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binEta{"binEta", {100, -1.0f, 1.0f}, ""}; + ConfigurableAxis binPhi{"binPhi", {static_cast(TMath::Pi()) * 10 / 2, 0.0f, 2. * static_cast(TMath::Pi())}, ""}; + + ConfigurableAxis binInvMassK0S{"binInvMassK0S", {200, 0.4f, 0.6f}, ""}; + ConfigurableAxis binInvMassLambda{"binInvMassLambda", {200, 1.07f, 1.17f}, ""}; + ConfigurableAxis binV0Radius{"R", {100., 0.0f, 50.0f}, ""}; + + int eventSelection = -1; + + void init(InitContext&) + { + eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(evSel)); + + const AxisSpec axisJetPt{binPtJet, "Jet Pt (GeV/c)"}; + const AxisSpec axisV0Pt{binPtV0, "V0 Pt (GeV/c)"}; + const AxisSpec axisEta{binEta, "Eta"}; + const AxisSpec axisPhi{binPhi, "Phi"}; + const AxisSpec axisV0Radius{binV0Radius, "V0 Radius (cm)"}; + const AxisSpec axisK0SM{binInvMassK0S, "M(#pi^{+} #pi^{-}) (GeV/c^{2})"}; + const AxisSpec axisLambdaM{binInvMassLambda, "M(p #pi^{-}) (GeV/c^{2})"}; + const AxisSpec axisAntiLambdaM{binInvMassLambda, "M(#bar{p} #pi^{+}) (GeV/c^{2})"}; + + if (doprocessMcD) { + registry.add("hEvents", "Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); + registry.add("K0SPtEtaMass", "K0S Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisK0SM}); + registry.add("InvMassK0STrue", "Invariant mass of K0S", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisK0SM}); + registry.add("InvMassLambdaTrue", "Invariant mass of Lambda", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisLambdaM}); + registry.add("LambdaPtEtaMass", "Lambda Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisLambdaM}); + registry.add("InvMassAntiLambdaTrue", "Invariant mass of AntiLambda", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisAntiLambdaM}); + registry.add("AntiLambdaPtEtaMass", "AntiLambda Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisAntiLambdaM}); + } + if (doprocessMcP) { + registry.add("hMcEvents", "MC Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); + registry.add("GeneratedK0S", "Generated K0S", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Radius}); + registry.add("GeneratedLambda", "Generated Lambda", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Radius}); + registry.add("GeneratedAntiLambda", "Generated AntiLambda", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Radius}); + } + if (doprocessMcDJets) { + registry.add("hJetEvents", "Jet Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); + registry.add("JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("InvMassJetK0STrue", "Invariant mass of K0S in jets", HistType::kTH3D, {axisJetPt, axisV0Pt, axisK0SM}); + registry.add("JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("InvMassJetLambdaTrue", "Invariant mass of Lambda in jets", HistType::kTH3D, {axisJetPt, axisV0Pt, axisLambdaM}); + registry.add("JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("InvMassJetAntiLambdaTrue", "Invariant mass of AntiLambda in jets", HistType::kTH3D, {axisJetPt, axisV0Pt, axisAntiLambdaM}); + } + if (doprocessMcPJets) { + registry.add("hMcJetEvents", "MC Jet Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); + registry.add("GeneratedJetK0S", "Generated Jet K0S", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("GeneratedJetLambda", "Generated Jet Lambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("GeneratedJetAntiLambda", "Generated Jet AntiLambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + } + } // init + + template + bool isCollisionReconstructed(T const& collision, U const& eventSelection) + { + if (!collision.has_mcCollision()) { + return false; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return false; + } + return true; + } + + void processDummy(CandidatesV0MCD const&) {} + PROCESS_SWITCH(V0QA, processDummy, "Dummy process function turned on by default", true); + + void processMcD(soa::Filtered::iterator const& jcoll, JetMcCollisions const&, soa::Join const& v0s, aod::McParticles const&) + { + registry.fill(HIST("hEvents"), 0.5); + if (!isCollisionReconstructed(jcoll, eventSelection)) { + return; + } + registry.fill(HIST("hEvents"), 1.5); + double weight = jcoll.mcCollision().weight(); + + for (const auto& v0 : v0s) { + if (!v0.has_mcParticle()) { + continue; + } + int pdg = v0.mcParticle().pdgCode(); + + if (v0.v0cosPA() < v0cospaMin) + continue; + if (v0.v0radius() < v0radiusMin) + continue; + if (v0.dcaV0daughters() > dcav0dauMax) + continue; + + // K0S + if (TMath::Abs(pdg) == 310) { + if (TMath::Abs(v0.dcapostopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.dcanegtopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.yK0Short()) > yK0SMax) + continue; + float ctauK0S = v0.distovertotmom(jcoll.posX(), jcoll.posY(), jcoll.posZ()) * o2::constants::physics::MassK0Short; + if (ctauK0S > lifetimeK0SMax) + continue; + + registry.fill(HIST("K0SPtEtaMass"), v0.pt(), v0.eta(), v0.mK0Short(), weight); + registry.fill(HIST("InvMassK0STrue"), v0.pt(), v0.v0radius(), v0.mK0Short(), weight); + } + // Lambda + if (pdg == 3122) { + if (TMath::Abs(v0.dcapostopv()) < dcaprMin) + continue; + if (TMath::Abs(v0.dcanegtopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.yLambda()) > yLambdaMax) + continue; + float ctauLambda = v0.distovertotmom(jcoll.posX(), jcoll.posY(), jcoll.posZ()) * o2::constants::physics::MassLambda0; + if (ctauLambda > lifetimeLambdaMax) + continue; + + registry.fill(HIST("LambdaPtEtaMass"), v0.pt(), v0.eta(), v0.mLambda(), weight); + registry.fill(HIST("InvMassLambdaTrue"), v0.pt(), v0.v0radius(), v0.mLambda(), weight); + } + if (pdg == -3122) { + if (TMath::Abs(v0.dcapostopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.dcanegtopv()) < dcaprMin) + continue; + if (TMath::Abs(v0.yLambda()) > yLambdaMax) + continue; + float ctauAntiLambda = v0.distovertotmom(jcoll.posX(), jcoll.posY(), jcoll.posZ()) * o2::constants::physics::MassLambda0Bar; + if (ctauAntiLambda > lifetimeLambdaMax) + continue; + + registry.fill(HIST("AntiLambdaPtEtaMass"), v0.pt(), v0.eta(), v0.mAntiLambda(), weight); + registry.fill(HIST("InvMassAntiLambdaTrue"), v0.pt(), v0.v0radius(), v0.mAntiLambda(), weight); + } + } + } + PROCESS_SWITCH(V0QA, processMcD, "Reconstructed true V0s", false); + + void processMcP(JetMcCollision const& mccoll, CandidatesV0MCP const& pv0s, soa::SmallGroups const& collisions) + { + registry.fill(HIST("hMcEvents"), 0.5); + bool isReconstructed = false; + + for (auto collision : collisions) { + if (!isCollisionReconstructed(collision, eventSelection)) { + continue; + } + if (collision.mcCollision().globalIndex() != mccoll.globalIndex()) { + continue; + } + isReconstructed = true; + break; + } + if (!isReconstructed) { + return; + } + + registry.fill(HIST("hMcEvents"), 1.5); + double weight = mccoll.weight(); + + for (auto& pv0 : pv0s) { + if (!pv0.has_daughters()) + continue; + if (!pv0.isPhysicalPrimary()) + continue; + if (TMath::Abs(pv0.y() > yPartMax)) + continue; + + // Can calculate this from CandidatesV0MCD (contains decay vertex) + double R_Decay = 1.0; + + if (pv0.pdgCode() == 310) { + registry.fill(HIST("GeneratedK0S"), pv0.pt(), pv0.eta(), R_Decay, weight); + } + if (pv0.pdgCode() == 3122) { + registry.fill(HIST("GeneratedLambda"), pv0.pt(), pv0.eta(), R_Decay, weight); + } + if (pv0.pdgCode() == -3122) { + registry.fill(HIST("GeneratedAntiLambda"), pv0.pt(), pv0.eta(), R_Decay, weight); + } + } + } + PROCESS_SWITCH(V0QA, processMcP, "Particle level V0s", false); + + void processMcDJets(soa::Filtered::iterator const& jcoll, JetMcCollisions const&, MCDV0JetsWithConstituents const& jets, soa::Join const&, aod::McParticles const&) + { + registry.fill(HIST("hJetEvents"), 0.5); + if (!isCollisionReconstructed(jcoll, eventSelection)) { + return; + } + registry.fill(HIST("hJetEvents"), 1.5); + double weight = jcoll.mcCollision().weight(); + + for (const auto& jet : jets) { + // if (!jetfindingutilities::isInEtaAcceptance(jet, -99., -99., v0EtaMin, v0EtaMax)) + for (const auto& v0 : jet.template candidates_as>()) { + if (!v0.has_mcParticle()) { + continue; + } + int pdg = v0.mcParticle().pdgCode(); + + if (v0.v0cosPA() < v0cospaMin) + continue; + if (v0.v0radius() < v0radiusMin) + continue; + if (v0.dcaV0daughters() > dcav0dauMax) + continue; + + // K0S + if (TMath::Abs(pdg) == 310) { + if (TMath::Abs(v0.dcapostopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.dcanegtopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.yK0Short()) > yK0SMax) + continue; + float ctauK0S = v0.distovertotmom(jcoll.posX(), jcoll.posY(), jcoll.posZ()) * o2::constants::physics::MassK0Short; + if (ctauK0S > lifetimeK0SMax) + continue; + + registry.fill(HIST("JetPtEtaK0SPt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("InvMassJetK0STrue"), jet.pt(), v0.pt(), v0.mK0Short(), weight); + } + // Lambda + if (pdg == 3122) { + if (TMath::Abs(v0.dcapostopv()) < dcaprMin) + continue; + if (TMath::Abs(v0.dcanegtopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.yLambda()) > yLambdaMax) + continue; + float ctauLambda = v0.distovertotmom(jcoll.posX(), jcoll.posY(), jcoll.posZ()) * o2::constants::physics::MassLambda0; + if (ctauLambda > lifetimeLambdaMax) + continue; + + registry.fill(HIST("JetPtEtaLambdaPt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("InvMassJetLambdaTrue"), jet.pt(), v0.pt(), v0.mLambda(), weight); + } + if (pdg == -3122) { + if (TMath::Abs(v0.dcapostopv()) < dcapiMin) + continue; + if (TMath::Abs(v0.dcanegtopv()) < dcaprMin) + continue; + if (TMath::Abs(v0.yLambda()) > yLambdaMax) + continue; + float ctauAntiLambda = v0.distovertotmom(jcoll.posX(), jcoll.posY(), jcoll.posZ()) * o2::constants::physics::MassLambda0Bar; + if (ctauAntiLambda > lifetimeLambdaMax) + continue; + + registry.fill(HIST("JetPtEtaAntiLambdaPt"), jet.pt(), jet.eta(), v0.pt(), weight); + registry.fill(HIST("InvMassJetAntiLambdaTrue"), jet.pt(), v0.pt(), v0.mAntiLambda(), weight); + } + } + } + } + PROCESS_SWITCH(V0QA, processMcDJets, "Reconstructed true V0s in jets", false); + + void processMcPJets(JetMcCollision const& mccoll, soa::SmallGroups const& collisions, MCPV0JetsWithConstituents const& jets, CandidatesV0MCP const&) + { + registry.fill(HIST("hMcJetEvents"), 0.5); + bool isReconstructed = false; + + for (auto collision : collisions) { + if (!isCollisionReconstructed(collision, eventSelection)) { + continue; + } + if (collision.mcCollision().globalIndex() != mccoll.globalIndex()) { + continue; + } + isReconstructed = true; + break; + } + if (!isReconstructed) { + return; + } + + registry.fill(HIST("hMcJetEvents"), 1.5); + double weight = mccoll.weight(); + + for (auto& jet : jets) { + // if (!jetfindingutilities::isInEtaAcceptance(jet, -99., -99., v0EtaMin, v0EtaMax)) + for (const auto& pv0 : jet.template candidates_as()) { + if (!pv0.has_daughters()) + continue; + if (!pv0.isPhysicalPrimary()) + continue; + if (TMath::Abs(pv0.y() > yPartMax)) + continue; // TODO: Should actually check the jets + + if (pv0.pdgCode() == 310) { + registry.fill(HIST("GeneratedJetK0S"), jet.pt(), jet.eta(), pv0.pt(), weight); + } + if (pv0.pdgCode() == 3122) { + registry.fill(HIST("GeneratedJetLambda"), jet.pt(), jet.eta(), pv0.pt(), weight); + } + if (pv0.pdgCode() == -3122) { + registry.fill(HIST("GeneratedJetAntiLambda"), jet.pt(), jet.eta(), pv0.pt(), weight); + } + } + } + } + PROCESS_SWITCH(V0QA, processMcPJets, "Particle level V0s in jets", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"jet-v0qa"})}; +} diff --git a/PWGLF/DataModel/LFClusterStudiesTable.h b/PWGLF/DataModel/LFClusterStudiesTable.h new file mode 100644 index 00000000000..88ca35a85d3 --- /dev/null +++ b/PWGLF/DataModel/LFClusterStudiesTable.h @@ -0,0 +1,122 @@ +// Copyright 2019-2020 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. +// +// Author: Giorgio Alberto Lucia + +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#ifndef PWGLF_DATAMODEL_LFCLUSTERSTUDIESTABLE_H_ +#define PWGLF_DATAMODEL_LFCLUSTERSTUDIESTABLE_H_ + +namespace o2::aod +{ + +namespace LFClusterStudiesTables +{ +DECLARE_SOA_COLUMN(PMother, pMother, float); +DECLARE_SOA_COLUMN(PtMother, ptMother, float); +DECLARE_SOA_COLUMN(EtaMother, etaMother, float); +DECLARE_SOA_COLUMN(PhiMother, phiMother, float); +DECLARE_SOA_COLUMN(MassMother, massMother, float); +DECLARE_SOA_COLUMN(PdgCodeMother, pdgCodeMother, int); +DECLARE_SOA_COLUMN(RadiusMother, radiusMother, float); +DECLARE_SOA_COLUMN(DcaMotherPV, dcaMotherPV, float); +DECLARE_SOA_COLUMN(CosPAMother, cosPAMother, float); +DECLARE_SOA_COLUMN(AlphaAPMother, alphaAPMother, float); +DECLARE_SOA_COLUMN(QtAPMother, qtAPMother, float); +DECLARE_SOA_COLUMN(McPdgCodeMother, mcPdgCodeMother, int); + +/** + * PartID: + * 0: e + * 1: #pi + * 2: K + * 3: p + * 4: d + * 5: ^{3}He + */ +DECLARE_SOA_COLUMN(PartID, partID, uint8_t); +DECLARE_SOA_COLUMN(PartIDMc, partIDMc, int); +DECLARE_SOA_COLUMN(IsPositive, isPositive, bool); + +DECLARE_SOA_COLUMN(P, p, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(PTPC, pTPC, float); +DECLARE_SOA_COLUMN(PIDinTrk, pidInTrk, uint32_t); +DECLARE_SOA_COLUMN(PDGCode, pdgCode, int); +DECLARE_SOA_COLUMN(DcaToPV, dcaToPV, float); +DECLARE_SOA_COLUMN(ItsClusterSize, itsClusterSize, uint32_t); +DECLARE_SOA_COLUMN(TpcSignal, tpcSignal, float); +DECLARE_SOA_COLUMN(TpcNcls, tpcNcls, uint8_t); +DECLARE_SOA_COLUMN(TpcNSigma, tpcNSigma, float); +DECLARE_SOA_COLUMN(TofNSigma, tofNSigma, float); +DECLARE_SOA_COLUMN(TofMass, tofMass, float); +DECLARE_SOA_COLUMN(Chi2its, chi2its, float); +DECLARE_SOA_COLUMN(Chi2tpc, chi2tpc, float); +DECLARE_SOA_COLUMN(HasTPC, hasTPC, bool); +DECLARE_SOA_COLUMN(McPdgCode, mcPdgCode, int); + +} // namespace LFClusterStudiesTables + +DECLARE_SOA_TABLE( + ClStTable, "AOD", "CLSTTABLE", + LFClusterStudiesTables::P, + LFClusterStudiesTables::Eta, + LFClusterStudiesTables::Phi, + LFClusterStudiesTables::ItsClusterSize, + LFClusterStudiesTables::PartID); + +DECLARE_SOA_TABLE( + ClStTableMc, "AOD", "CLSTTABLEMC", + LFClusterStudiesTables::P, + LFClusterStudiesTables::Eta, + LFClusterStudiesTables::Phi, + LFClusterStudiesTables::ItsClusterSize, + LFClusterStudiesTables::PartID, + LFClusterStudiesTables::PartIDMc); + +DECLARE_SOA_TABLE( + ClStTableExtra, "AOD", "CLSTTABLEEXTRA", + LFClusterStudiesTables::P, + LFClusterStudiesTables::Eta, + LFClusterStudiesTables::Phi, + LFClusterStudiesTables::ItsClusterSize, + LFClusterStudiesTables::PartID, + LFClusterStudiesTables::PTPC, + LFClusterStudiesTables::PIDinTrk, + LFClusterStudiesTables::TpcNSigma, + LFClusterStudiesTables::TofNSigma, + LFClusterStudiesTables::TofMass, + LFClusterStudiesTables::CosPAMother, + LFClusterStudiesTables::MassMother); + +DECLARE_SOA_TABLE( + ClStTableMcExt, "AOD", "CLSTTABLEMCEXT", + LFClusterStudiesTables::P, + LFClusterStudiesTables::Eta, + LFClusterStudiesTables::Phi, + LFClusterStudiesTables::ItsClusterSize, + LFClusterStudiesTables::PartID, + LFClusterStudiesTables::PartIDMc, + LFClusterStudiesTables::PTPC, + LFClusterStudiesTables::PIDinTrk, + LFClusterStudiesTables::TpcNSigma, + LFClusterStudiesTables::TofNSigma, + LFClusterStudiesTables::TofMass, + LFClusterStudiesTables::CosPAMother, + LFClusterStudiesTables::MassMother); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFCLUSTERSTUDIESTABLE_H_ diff --git a/PWGLF/DataModel/LFDoubleCascTables.h b/PWGLF/DataModel/LFDoubleCascTables.h new file mode 100644 index 00000000000..49e3b6604de --- /dev/null +++ b/PWGLF/DataModel/LFDoubleCascTables.h @@ -0,0 +1,73 @@ +// Copyright 2019-2020 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. + +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#ifndef PWGLF_DATAMODEL_LFDOUBLECASCTABLES_H_ +#define PWGLF_DATAMODEL_LFDOUBLECASCTABLES_H_ + +namespace o2::aod +{ + +namespace DoubleCascTables +{ +DECLARE_SOA_COLUMN(PtCasc1, ptCasc1, float); // signed pt of the cascade +DECLARE_SOA_COLUMN(EtaCasc1, etaCasc1, float); +DECLARE_SOA_COLUMN(PhiCasc1, phiCasc1, float); +DECLARE_SOA_COLUMN(CascDecLength1, cascDecLength1, float); +DECLARE_SOA_COLUMN(OmegaMassCasc1, omegaMassCasc1, float); +DECLARE_SOA_COLUMN(XiMassCasc1, xiMassCasc1, float); +DECLARE_SOA_COLUMN(CosPACasc1, cosPACasc1, float); +DECLARE_SOA_COLUMN(DcaBachPVCasc1, dcaBachPVCasc1, float); +DECLARE_SOA_COLUMN(DcaV0BachCasc1, dcaV0BachCasc1, float); +DECLARE_SOA_COLUMN(NSigmaKBach1, nSigmaKBach1, float); + +DECLARE_SOA_COLUMN(PtCasc2, ptCasc2, float); +DECLARE_SOA_COLUMN(EtaCasc2, etaCasc2, float); +DECLARE_SOA_COLUMN(PhiCasc2, phiCasc2, float); +DECLARE_SOA_COLUMN(CascDecLength2, cascDecLength2, float); +DECLARE_SOA_COLUMN(OmegaMassCasc2, omegaMassCasc2, float); +DECLARE_SOA_COLUMN(XiMassCasc2, xiMassCasc2, float); +DECLARE_SOA_COLUMN(CosPACasc2, cosPACasc2, float); +DECLARE_SOA_COLUMN(DcaBachPVCasc2, dcaBachPVCasc2, float); +DECLARE_SOA_COLUMN(DcaV0BachCasc2, dcaV0BachCasc2, float); +DECLARE_SOA_COLUMN(NSigmaKBach2, nSigmaKBach2, float); + +DECLARE_SOA_COLUMN(DoubleOmegaMass, doubleOmegaMass, float); +} // namespace DoubleCascTables + +DECLARE_SOA_TABLE(DoubleCascTable, "AOD", "DOUBLECASCTABLE", + DoubleCascTables::PtCasc1, + DoubleCascTables::EtaCasc1, + DoubleCascTables::PhiCasc1, + DoubleCascTables::CascDecLength1, + DoubleCascTables::OmegaMassCasc1, + DoubleCascTables::XiMassCasc1, + DoubleCascTables::CosPACasc1, + DoubleCascTables::DcaBachPVCasc1, + DoubleCascTables::DcaV0BachCasc1, + DoubleCascTables::NSigmaKBach1, + DoubleCascTables::PtCasc2, + DoubleCascTables::EtaCasc2, + DoubleCascTables::PhiCasc2, + DoubleCascTables::CascDecLength2, + DoubleCascTables::OmegaMassCasc2, + DoubleCascTables::XiMassCasc2, + DoubleCascTables::CosPACasc2, + DoubleCascTables::DcaBachPVCasc2, + DoubleCascTables::DcaV0BachCasc2, + DoubleCascTables::NSigmaKBach2, + DoubleCascTables::DoubleOmegaMass); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFDOUBLECASCTABLES_H_ diff --git a/PWGLF/DataModel/LFEbyeTables.h b/PWGLF/DataModel/LFEbyeTables.h index 00f6c732d44..b102ad97030 100644 --- a/PWGLF/DataModel/LFEbyeTables.h +++ b/PWGLF/DataModel/LFEbyeTables.h @@ -22,6 +22,10 @@ namespace LFEbyeCollTable { DECLARE_SOA_COLUMN(Centrality, centrality, uint8_t); DECLARE_SOA_COLUMN(Zvtx, zvtx, float); +DECLARE_SOA_COLUMN(ZvtxMask, zvtxMask, uint8_t); +DECLARE_SOA_COLUMN(TriggerMask, triggerMask, uint8_t); +DECLARE_SOA_COLUMN(Ntracklets, ntracklets, uint8_t); +DECLARE_SOA_COLUMN(V0Multiplicity, v0Multiplicity, uint8_t); } // namespace LFEbyeCollTable DECLARE_SOA_TABLE(CollEbyeTables, "AOD", "COLLEBYETABLE", @@ -30,9 +34,18 @@ DECLARE_SOA_TABLE(CollEbyeTables, "AOD", "COLLEBYETABLE", LFEbyeCollTable::Zvtx); using CollEbyeTable = CollEbyeTables::iterator; +DECLARE_SOA_TABLE(MiniCollTables, "AOD", "MINICOLLTABLE", + o2::soa::Index<>, + LFEbyeCollTable::ZvtxMask, + LFEbyeCollTable::TriggerMask, + LFEbyeCollTable::Ntracklets, + LFEbyeCollTable::V0Multiplicity); +using MiniCollTable = MiniCollTables::iterator; + namespace LFEbyeTable { DECLARE_SOA_INDEX_COLUMN(CollEbyeTable, collEbyeTable); +DECLARE_SOA_INDEX_COLUMN(MiniCollTable, miniCollTable); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Mass, mass, float); @@ -53,6 +66,10 @@ DECLARE_SOA_COLUMN(GenPt, genPt, float); DECLARE_SOA_COLUMN(GenEta, genEta, float); DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); DECLARE_SOA_COLUMN(IsReco, isReco, bool); +DECLARE_SOA_COLUMN(EtaMask, etaMask, uint8_t); +DECLARE_SOA_COLUMN(SelMask, selMask, int); +DECLARE_SOA_COLUMN(OuterPID, outerPID, float); +DECLARE_SOA_COLUMN(GenEtaMask, genEtaMask, uint8_t); } // namespace LFEbyeTable DECLARE_SOA_TABLE(NucleiEbyeTables, "AOD", "NUCLEBYETABLE", @@ -120,6 +137,27 @@ DECLARE_SOA_TABLE(McLambdaEbyeTables, "AOD", "MCLAMBEBYETABLE", LFEbyeTable::PdgCode, LFEbyeTable::IsReco); using McLambdaEbyeTable = McLambdaEbyeTables::iterator; + +DECLARE_SOA_TABLE(MiniTrkTables, "AOD", "MINITRKTABLE", + o2::soa::Index<>, + LFEbyeTable::MiniCollTableId, + LFEbyeTable::Pt, + LFEbyeTable::EtaMask, + LFEbyeTable::SelMask, + LFEbyeTable::OuterPID); +using MiniTrkTable = MiniTrkTables::iterator; + +DECLARE_SOA_TABLE(McMiniTrkTables, "AOD", "MCMINITRKTABLE", + o2::soa::Index<>, + LFEbyeTable::MiniCollTableId, + LFEbyeTable::Pt, + LFEbyeTable::EtaMask, + LFEbyeTable::SelMask, + LFEbyeTable::OuterPID, + LFEbyeTable::GenPt, + LFEbyeTable::GenEtaMask, + LFEbyeTable::IsReco); +using McMiniTrkTable = McMiniTrkTables::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFEBYETABLES_H_ diff --git a/PWGLF/DataModel/LFHStrangeCorrelationTables.h b/PWGLF/DataModel/LFHStrangeCorrelationTables.h index 53cf20bc7eb..b800182e28f 100644 --- a/PWGLF/DataModel/LFHStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFHStrangeCorrelationTables.h @@ -22,10 +22,13 @@ #ifndef PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ #define PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ +#include #include "Framework/AnalysisDataModel.h" #include "Common/Core/RecoDecay.h" #include "CommonConstants/PhysicsConstants.h" -#include + +// Simple checker +#define bitcheck(var, nbit) ((var) & (1 << (nbit))) namespace o2::aod { @@ -34,9 +37,10 @@ namespace o2::aod namespace triggerTracks { DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_COLUMN(MCPhysicalPrimary, mcPhysicalPrimary, bool); // true physical primary flag DECLARE_SOA_INDEX_COLUMN_FULL(Track, track, int, Tracks, "_Trigger"); //! } // namespace triggerTracks -DECLARE_SOA_TABLE(TriggerTracks, "AOD", "TRIGGERTRACKS", o2::soa::Index<>, triggerTracks::CollisionId, triggerTracks::TrackId); +DECLARE_SOA_TABLE(TriggerTracks, "AOD", "TRIGGERTRACKS", o2::soa::Index<>, triggerTracks::CollisionId, triggerTracks::MCPhysicalPrimary, triggerTracks::TrackId); /// _________________________________________ /// Table for storing assoc track indices namespace assocPions @@ -51,44 +55,38 @@ namespace assocV0s { DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_INDEX_COLUMN(V0Core, v0Core); //! -DECLARE_SOA_COLUMN(CompatibleK0Short, compatibleK0Short, bool); // compatible with K0Short -DECLARE_SOA_COLUMN(CompatibleLambda, compatibleLambda, bool); // compatible with Lambda -DECLARE_SOA_COLUMN(CompatibleAntiLambda, compatibleAntiLambda, bool); // compatible with AntiLambda + +// dEdx compatibility is done via encoded integer: 0: passes loose; 1: passes normal, 2: passes tight; definition of loose/normal/tight is in hStrangeCorrelationFilter +DECLARE_SOA_COLUMN(CompatibleK0Short, compatibleK0Short, int); // compatible with K0Short dEdx, encoded syst checks +DECLARE_SOA_COLUMN(CompatibleLambda, compatibleLambda, int); // compatible with Lambda dEdx, encoded syst checks +DECLARE_SOA_COLUMN(CompatibleAntiLambda, compatibleAntiLambda, int); // compatible with AntiLambda dEdx, encoded syst checks + DECLARE_SOA_COLUMN(MCTrueK0Short, mcTrueK0Short, bool); // true K0Short in MC DECLARE_SOA_COLUMN(MCTrueLambda, mcTrueLambda, bool); // true Lambda in MC DECLARE_SOA_COLUMN(MCTrueAntiLambda, mcTrueAntiLambda, bool); // true AntiLambda in MC -DECLARE_SOA_COLUMN(MassRegionK0Short, massRegionK0Short, int); // -DECLARE_SOA_COLUMN(MassRegionLambda, massRegionLambda, int); // -DECLARE_SOA_COLUMN(MassRegionAntiLambda, massRegionAntiLambda, int); // +DECLARE_SOA_COLUMN(MCPhysicalPrimary, mcPhysicalPrimary, bool); // true physical primary flag +DECLARE_SOA_COLUMN(NSigmaMassK0Short, nSigmaMassK0Short, float); // +DECLARE_SOA_COLUMN(NSigmaMassLambda, nSigmaMassLambda, float); // +DECLARE_SOA_COLUMN(NSigmaMassAntiLambda, nSigmaMassAntiLambda, float); // DECLARE_SOA_DYNAMIC_COLUMN(Compatible, compatible, //! check compatibility with a hypothesis of a certain number (0 - K0, 1 - L, 2 - Lbar) - [](bool cK0Short, bool cLambda, bool cAntiLambda, int value) -> bool { - if (value == 0 && cK0Short) - return true; - if (value == 1 && cLambda) - return true; - if (value == 2 && cAntiLambda) - return true; - return false; - }); -DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegionCheck, invMassRegionCheck, - [](int rK0Short, int rLambda, int rAntiLambda, int value, int region) -> bool { - if (value == 0 && rK0Short == region) + [](int cK0Short, int cLambda, int cAntiLambda, int value, int compatibilityLevel) -> bool { + if (value == 0 && bitcheck(cK0Short, compatibilityLevel)) return true; - if (value == 1 && rLambda == region) + if (value == 1 && bitcheck(cLambda, compatibilityLevel)) return true; - if (value == 2 && rAntiLambda == region) + if (value == 2 && bitcheck(cAntiLambda, compatibilityLevel)) return true; return false; }); -DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegion, invMassRegion, - [](int rK0Short, int rLambda, int rAntiLambda, int value) -> int { +DECLARE_SOA_DYNAMIC_COLUMN(InvMassNSigma, invMassNSigma, + [](float rK0Short, float rLambda, float rAntiLambda, int value) -> float { if (value == 0) return rK0Short; if (value == 1) return rLambda; if (value == 2) return rAntiLambda; - return -1; + return 1000.0f; }); DECLARE_SOA_DYNAMIC_COLUMN(MCTrue, mcTrue, [](int mcTrueK0Short, int mcTrueLambda, int mcTrueAntiLambda, int value) -> bool { @@ -109,12 +107,12 @@ DECLARE_SOA_TABLE(AssocV0s, "AOD", "ASSOCV0S", o2::soa::Index<>, assocV0s::MCTrueK0Short, assocV0s::MCTrueLambda, assocV0s::MCTrueAntiLambda, - assocV0s::MassRegionK0Short, - assocV0s::MassRegionLambda, - assocV0s::MassRegionAntiLambda, + assocV0s::MCPhysicalPrimary, + assocV0s::NSigmaMassK0Short, + assocV0s::NSigmaMassLambda, + assocV0s::NSigmaMassAntiLambda, + assocV0s::InvMassNSigma, assocV0s::Compatible, - assocV0s::InvMassRegionCheck, - assocV0s::InvMassRegion, assocV0s::MCTrue); /// _________________________________________ /// Table for storing associated casc indices @@ -122,47 +120,39 @@ namespace assocCascades { DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_INDEX_COLUMN(CascData, cascData); //! -DECLARE_SOA_COLUMN(CompatibleXiMinus, compatibleXiMinus, bool); // compatible with XiMinus -DECLARE_SOA_COLUMN(CompatibleXiPlus, compatibleXiPlus, bool); // compatible with XiPlus -DECLARE_SOA_COLUMN(CompatibleOmegaMinus, compatibleOmegaMinus, bool); // compatible with OmegaMinus -DECLARE_SOA_COLUMN(CompatibleOmegaPlus, compatibleOmegaPlus, bool); // compatible with OmegaPlus + +// dEdx compatibility is done via encoded integer: 0: passes loose; 1: passes normal, 2: passes tight; definition of loose/normal/tight is in hStrangeCorrelationFilter +DECLARE_SOA_COLUMN(CompatibleXiMinus, compatibleXiMinus, int); // compatible with XiMinus +DECLARE_SOA_COLUMN(CompatibleXiPlus, compatibleXiPlus, int); // compatible with XiPlus +DECLARE_SOA_COLUMN(CompatibleOmegaMinus, compatibleOmegaMinus, int); // compatible with OmegaMinus +DECLARE_SOA_COLUMN(CompatibleOmegaPlus, compatibleOmegaPlus, int); // compatible with OmegaPlus + DECLARE_SOA_COLUMN(MCTrueXiMinus, mcTrueXiMinus, bool); // true XiMinus in mc DECLARE_SOA_COLUMN(MCTrueXiPlus, mcTrueXiPlus, bool); // true XiPlus in mc DECLARE_SOA_COLUMN(MCTrueOmegaMinus, mcTrueOmegaMinus, bool); // true OmegaMinus in mc DECLARE_SOA_COLUMN(MCTrueOmegaPlus, mcTrueOmegaPlus, bool); // true OmegaPlus in mc -DECLARE_SOA_COLUMN(MassRegionXi, massRegionXi, int); // -DECLARE_SOA_COLUMN(MassRegionOmega, massRegionOmega, int); // +DECLARE_SOA_COLUMN(MCPhysicalPrimary, mcPhysicalPrimary, bool); // physical primary in MC +DECLARE_SOA_COLUMN(NSigmaMassXi, nSigmaMassXi, float); // +DECLARE_SOA_COLUMN(NSigmaMassOmega, nSigmaMassOmega, float); // DECLARE_SOA_DYNAMIC_COLUMN(Compatible, compatible, //! check compatibility with a hypothesis of a certain number (0 - K0, 1 - L, 2 - Lbar) - [](bool cXiMinus, bool cXiPlus, bool cOmegaMinus, bool cOmegaPlus, int value) -> bool { - if (value == 0 && cXiMinus) - return true; - if (value == 1 && cXiPlus) - return true; - if (value == 2 && cOmegaMinus) - return true; - if (value == 3 && cOmegaPlus) - return true; - return false; - }); -DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegionCheck, invMassRegionCheck, - [](int rXi, int rOmega, int value, int region) -> bool { - if (value == 0 && rXi == region) + [](int cXiMinus, int cXiPlus, int cOmegaMinus, int cOmegaPlus, int value, int compatibilityLevel) -> bool { + if (value == 0 && bitcheck(cXiMinus, compatibilityLevel)) return true; - if (value == 1 && rXi == region) + if (value == 1 && bitcheck(cXiPlus, compatibilityLevel)) return true; - if (value == 2 && rOmega == region) + if (value == 2 && bitcheck(cOmegaMinus, compatibilityLevel)) return true; - if (value == 3 && rOmega == region) + if (value == 3 && bitcheck(cOmegaPlus, compatibilityLevel)) return true; return false; }); -DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegion, invMassRegion, - [](int rXi, int rOmega, int value) -> int { +DECLARE_SOA_DYNAMIC_COLUMN(InvMassNSigma, invMassNSigma, + [](float rXi, float rOmega, int value) -> float { if (value == 0 || value == 1) return rXi; if (value == 2 || value == 3) return rOmega; - return -1; + return 1000.0f; }); DECLARE_SOA_DYNAMIC_COLUMN(MCTrue, mcTrue, [](int mcTrueXiMinus, int mcTrueXiPlus, int mcTrueOmegaMinus, int mcTrueOmegaPlus, int value) -> bool { @@ -186,11 +176,11 @@ DECLARE_SOA_TABLE(AssocCascades, "AOD", "ASSOCCASCADES", o2::soa::Index<>, assoc assocCascades::MCTrueXiPlus, assocCascades::MCTrueOmegaMinus, assocCascades::MCTrueOmegaPlus, - assocCascades::MassRegionXi, - assocCascades::MassRegionOmega, + assocCascades::MCPhysicalPrimary, + assocCascades::NSigmaMassXi, + assocCascades::NSigmaMassOmega, + assocCascades::InvMassNSigma, assocCascades::Compatible, - assocCascades::InvMassRegionCheck, - assocCascades::InvMassRegion, assocCascades::MCTrue); } // namespace o2::aod diff --git a/PWGLF/DataModel/LFHypernucleiTables.h b/PWGLF/DataModel/LFHypernucleiTables.h index ba81c59b502..46955373222 100644 --- a/PWGLF/DataModel/LFHypernucleiTables.h +++ b/PWGLF/DataModel/LFHypernucleiTables.h @@ -56,12 +56,14 @@ DECLARE_SOA_COLUMN(NTPCclusHe, nTPCclusHe, uint8_t); // Number of DECLARE_SOA_COLUMN(NTPCclusPi, nTPCclusPi, uint8_t); // Number of TPC clusters of the Pi daughter DECLARE_SOA_COLUMN(TPCsignalHe, tpcSignalHe, uint16_t); // TPC signal of the He daughter DECLARE_SOA_COLUMN(TPCsignalPi, tpcSignalPi, uint16_t); // TPC signal of the Pi daughter -DECLARE_SOA_COLUMN(Tracked, tracked, bool); // bool: true for tracked candidates +DECLARE_SOA_COLUMN(TPCChi2He, tpcChi2He, float); // TPC chi2 of the He daughter +DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, int); // int: zero for non-tracked candidates DECLARE_SOA_COLUMN(Flags, flags, uint8_t); // Flags for PID in tracking (bits [0, 3] for negative daughter, [4,7] for positive daughter) DECLARE_SOA_COLUMN(TPCmomHe, tpcMomHe, float); // TPC momentum of the He daughter DECLARE_SOA_COLUMN(TPCmomPi, tpcMomPi, float); // TPC momentum of the Pi daughter DECLARE_SOA_COLUMN(ITSclusterSizesHe, itsClusterSizesHe, uint32_t); // ITS cluster size of the He daughter DECLARE_SOA_COLUMN(ITSclusterSizesPi, itsClusterSizesPi, uint32_t); // ITS cluster size of the Pi daughter +DECLARE_SOA_COLUMN(ITSclusterSizesHyp, itsClusterSizesHyp, uint32_t); // ITS cluster size of the Pi daughter DECLARE_SOA_COLUMN(DcaHe, dcaHe, float); // DCA between He daughter and V0 DECLARE_SOA_COLUMN(DcaPi, dcaPi, float); // DCA between pi daughter and V0 DECLARE_SOA_COLUMN(GenPt, genPt, float); // Pt of the hypertriton @@ -88,9 +90,9 @@ DECLARE_SOA_TABLE(DataHypCands, "AOD", "HYPCANDS", hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, - hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, + hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, - hyperrec::Flags, hyperrec::Tracked); + hyperrec::Flags, hyperrec::TrackedClSize); DECLARE_SOA_TABLE(DataHypCandsFlow, "AOD", "HYPCANDSFLOW", o2::soa::Index<>, @@ -106,9 +108,9 @@ DECLARE_SOA_TABLE(DataHypCandsFlow, "AOD", "HYPCANDSFLOW", hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, - hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, + hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, - hyperrec::Flags, hyperrec::Tracked); + hyperrec::Flags, hyperrec::TrackedClSize); DECLARE_SOA_TABLE(MCHypCands, "AOD", "MCHYPCANDS", o2::soa::Index<>, @@ -121,9 +123,9 @@ DECLARE_SOA_TABLE(MCHypCands, "AOD", "MCHYPCANDS", hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, - hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, + hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, - hyperrec::Flags, hyperrec::Tracked, + hyperrec::Flags, hyperrec::TrackedClSize, hyperrec::GenPt, hyperrec::GenPhi, hyperrec::GenEta, diff --git a/PWGLF/DataModel/LFLithium4Tables.h b/PWGLF/DataModel/LFLithium4Tables.h index 50c5acb5cca..1e65ffcf23b 100644 --- a/PWGLF/DataModel/LFLithium4Tables.h +++ b/PWGLF/DataModel/LFLithium4Tables.h @@ -44,6 +44,8 @@ DECLARE_SOA_COLUMN(InnerParamTPCPr, innerParamTPCPr, float); DECLARE_SOA_COLUMN(NClsTPCHe3, nClsTPCHe3, uint8_t); DECLARE_SOA_COLUMN(NSigmaTPCHe3, nSigmaTPCHe3, float); DECLARE_SOA_COLUMN(NSigmaTPCPr, nSigmaTOFPr, float); +DECLARE_SOA_COLUMN(Chi2TPCHe3, chi2TPCHe3, float); +DECLARE_SOA_COLUMN(Chi2TPCPr, chi2TPCPr, float); DECLARE_SOA_COLUMN(MassTOFHe3, massTOFHe3, float); DECLARE_SOA_COLUMN(MassTOFPr, massTOFPr, float); DECLARE_SOA_COLUMN(PIDtrkHe3, pidTrkHe3, uint32_t); @@ -59,7 +61,11 @@ DECLARE_SOA_COLUMN(IsBkgLS, isBkgLS, bool); DECLARE_SOA_COLUMN(IsBkgEM, isBkgEM, bool); DECLARE_SOA_COLUMN(PtMCHe3, ptMCHe3, float); +DECLARE_SOA_COLUMN(EtaMCHe3, etaMCHe3, float); +DECLARE_SOA_COLUMN(PhiMCHe3, phiMCHe3, float); DECLARE_SOA_COLUMN(PtMCPr, ptMCPr, float); +DECLARE_SOA_COLUMN(EtaMCPr, etaMCPr, float); +DECLARE_SOA_COLUMN(PhiMCPr, phiMCPr, float); DECLARE_SOA_COLUMN(SignedPtMC, signedPtMC, float); DECLARE_SOA_COLUMN(MassMC, massMC, float); @@ -83,6 +89,8 @@ DECLARE_SOA_TABLE(Lithium4Table, "AOD", "LITHIUM4TABLE", Lithium4TablesNS::NClsTPCHe3, Lithium4TablesNS::NSigmaTPCHe3, Lithium4TablesNS::NSigmaTPCPr, + Lithium4TablesNS::Chi2TPCHe3, + Lithium4TablesNS::Chi2TPCPr, Lithium4TablesNS::MassTOFHe3, Lithium4TablesNS::MassTOFPr, Lithium4TablesNS::PIDtrkHe3, @@ -111,6 +119,8 @@ DECLARE_SOA_TABLE(Lithium4TableMC, "AOD", "LITHIUM4TABLEMC", Lithium4TablesNS::NClsTPCHe3, Lithium4TablesNS::NSigmaTPCHe3, Lithium4TablesNS::NSigmaTPCPr, + Lithium4TablesNS::Chi2TPCHe3, + Lithium4TablesNS::Chi2TPCPr, Lithium4TablesNS::MassTOFHe3, Lithium4TablesNS::MassTOFPr, Lithium4TablesNS::PIDtrkHe3, @@ -122,7 +132,11 @@ DECLARE_SOA_TABLE(Lithium4TableMC, "AOD", "LITHIUM4TABLEMC", Lithium4TablesNS::IsBkgLS, Lithium4TablesNS::IsBkgEM, Lithium4TablesNS::PtMCHe3, + Lithium4TablesNS::EtaMCHe3, + Lithium4TablesNS::PhiMCHe3, Lithium4TablesNS::PtMCPr, + Lithium4TablesNS::EtaMCPr, + Lithium4TablesNS::PhiMCPr, Lithium4TablesNS::SignedPtMC, Lithium4TablesNS::MassMC) diff --git a/PWGLF/DataModel/LFLnnTables.h b/PWGLF/DataModel/LFLnnTables.h index 2ee0fa22839..11fa0304df5 100644 --- a/PWGLF/DataModel/LFLnnTables.h +++ b/PWGLF/DataModel/LFLnnTables.h @@ -58,6 +58,7 @@ DECLARE_SOA_COLUMN(TPCsignalPi, tpcSignalPi, uint16_t); // TPC DECLARE_SOA_COLUMN(Flags, flags, uint8_t); // Flags for PID in tracking (bits [0, 3] for negative daughter, [4,7] for positive daughter) DECLARE_SOA_COLUMN(TPCmom3H, tpcMom3H, float); // TPC momentum of the 3H daughter DECLARE_SOA_COLUMN(TPCmomPi, tpcMomPi, float); // TPC momentum of the Pi daughter +DECLARE_SOA_COLUMN(MassTrTOF, mass2TrTOF, float); // TOF 3H mass DECLARE_SOA_COLUMN(ITSclusterSizes3H, itsClusterSizes3H, uint32_t); // ITS cluster size of the 3H daughter DECLARE_SOA_COLUMN(ITSclusterSizesPi, itsClusterSizesPi, uint32_t); // ITS cluster size of the Pi daughter DECLARE_SOA_COLUMN(Dca3H, dca3H, float); // DCA between 3H daughter and V0 @@ -87,6 +88,7 @@ DECLARE_SOA_TABLE(DataLnnCands, "AOD", "LNNCANDS", lnnrec::DcaV0Daug, lnnrec::Dca3H, lnnrec::DcaPi, lnnrec::NSigma3H, lnnrec::NTPCclus3H, lnnrec::NTPCclusPi, lnnrec::TPCmom3H, lnnrec::TPCmomPi, lnnrec::TPCsignal3H, lnnrec::TPCsignalPi, + lnnrec::MassTrTOF, lnnrec::ITSclusterSizes3H, lnnrec::ITSclusterSizesPi, lnnrec::Flags); @@ -102,6 +104,7 @@ DECLARE_SOA_TABLE(MCLnnCands, "AOD", "MCLNNCANDS", lnnrec::DcaV0Daug, lnnrec::Dca3H, lnnrec::DcaPi, lnnrec::NSigma3H, lnnrec::NTPCclus3H, lnnrec::NTPCclusPi, lnnrec::TPCmom3H, lnnrec::TPCmomPi, lnnrec::TPCsignal3H, lnnrec::TPCsignalPi, + lnnrec::MassTrTOF, lnnrec::ITSclusterSizes3H, lnnrec::ITSclusterSizesPi, lnnrec::Flags, lnnrec::GenPt, @@ -119,4 +122,4 @@ using DataLnnCand = DataLnnCands::iterator; using MCLnnCand = MCLnnCands::iterator; } // namespace o2::aod -#endif // PWGLF_DATAMODEL_LFLNNTABLES_H_ \ No newline at end of file +#endif // PWGLF_DATAMODEL_LFLNNTABLES_H_ diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index 92e5b4085ca..93178f9ce2a 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -24,6 +24,13 @@ namespace o2::aod { namespace NPCascadeTable { +DECLARE_SOA_COLUMN(MatchingChi2, matchingChi2, float); +DECLARE_SOA_COLUMN(ITSClusSize, itsClusSize, float); +DECLARE_SOA_COLUMN(IsGoodMatch, isGoodMatch, bool); +DECLARE_SOA_COLUMN(IsGoodCascade, isGoodCascade, bool); +DECLARE_SOA_COLUMN(PdgCodeMom, pdgCodeMom, int); +DECLARE_SOA_COLUMN(PdgCodeGrandma, pdgCodeGrandma, int); + DECLARE_SOA_COLUMN(PvX, pvX, float); DECLARE_SOA_COLUMN(PvY, pvY, float); DECLARE_SOA_COLUMN(PvZ, pvZ, float); @@ -91,9 +98,15 @@ DECLARE_SOA_COLUMN(gPt, genPt, float); DECLARE_SOA_COLUMN(gEta, genEta, float); DECLARE_SOA_COLUMN(gPhi, genPhi, float); DECLARE_SOA_COLUMN(PDGcode, pdgCode, int); +DECLARE_SOA_COLUMN(DCAxMC, dcaXmc, float); +DECLARE_SOA_COLUMN(DCAyMC, dcaYmc, float); +DECLARE_SOA_COLUMN(DCAzMC, dcaZmc, float); +DECLARE_SOA_COLUMN(MCcollisionMatch, mcCollisionMatch, bool); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", + NPCascadeTable::MatchingChi2, + NPCascadeTable::ITSClusSize, NPCascadeTable::PvX, NPCascadeTable::PvY, NPCascadeTable::PvZ, @@ -146,6 +159,12 @@ DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", NPCascadeTable::BachPionTOFNSigma) DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", + NPCascadeTable::MatchingChi2, + NPCascadeTable::ITSClusSize, + NPCascadeTable::IsGoodMatch, + NPCascadeTable::IsGoodCascade, + NPCascadeTable::PdgCodeMom, + NPCascadeTable::PdgCodeGrandma, NPCascadeTable::PvX, NPCascadeTable::PvY, NPCascadeTable::PvZ, @@ -199,7 +218,11 @@ DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::gPt, NPCascadeTable::gEta, NPCascadeTable::gPhi, - NPCascadeTable::PDGcode) + NPCascadeTable::PDGcode, + NPCascadeTable::DCAxMC, + NPCascadeTable::DCAyMC, + NPCascadeTable::DCAzMC, + NPCascadeTable::MCcollisionMatch) } // namespace o2::aod diff --git a/PWGLF/DataModel/LFNucleiTables.h b/PWGLF/DataModel/LFNucleiTables.h index fe8459a18a6..dd7b72abb67 100644 --- a/PWGLF/DataModel/LFNucleiTables.h +++ b/PWGLF/DataModel/LFNucleiTables.h @@ -22,8 +22,6 @@ #ifndef PWGLF_DATAMODEL_LFNUCLEITABLES_H_ #define PWGLF_DATAMODEL_LFNUCLEITABLES_H_ -using namespace o2; - namespace o2::aod { namespace fullEvent diff --git a/PWGLF/DataModel/LFResonanceTables.h b/PWGLF/DataModel/LFResonanceTables.h index ca0e5fca08e..18658529dda 100644 --- a/PWGLF/DataModel/LFResonanceTables.h +++ b/PWGLF/DataModel/LFResonanceTables.h @@ -66,6 +66,7 @@ DECLARE_SOA_COLUMN(IsINELgt0, isINELgt0, bool); //! INEL>0 DECLARE_SOA_COLUMN(IsTriggerTVX, isTriggerTVX, bool); //! TriggerTVX DECLARE_SOA_COLUMN(IsInSel8, isInSel8, bool); //! InSel8 DECLARE_SOA_COLUMN(IsInAfterAllCuts, isInAfterAllCuts, bool); //! InAfterAllCuts +DECLARE_SOA_COLUMN(ImpactParameter, impactParameter, float); //! ImpactParameter } // namespace resocollision DECLARE_SOA_TABLE(ResoCollisions, "AOD", "RESOCOLLISION", @@ -89,7 +90,8 @@ DECLARE_SOA_TABLE(ResoMCCollisions, "AOD", "RESOMCCOL", resocollision::IsINELgt0, resocollision::IsTriggerTVX, resocollision::IsInSel8, - resocollision::IsInAfterAllCuts); + resocollision::IsInAfterAllCuts, + resocollision::ImpactParameter); using ResoMCCollision = ResoMCCollisions::iterator; // Resonance Daughters diff --git a/PWGLF/DataModel/LFResonanceTablesMergeDF.h b/PWGLF/DataModel/LFResonanceTablesMergeDF.h index fc407d49c83..bceb237faff 100644 --- a/PWGLF/DataModel/LFResonanceTablesMergeDF.h +++ b/PWGLF/DataModel/LFResonanceTablesMergeDF.h @@ -20,6 +20,7 @@ #ifndef PWGLF_DATAMODEL_LFRESONANCETABLESMERGEDF_H_ #define PWGLF_DATAMODEL_LFRESONANCETABLESMERGEDF_H_ +#include #include #include "Common/DataModel/PIDResponse.h" @@ -80,7 +81,9 @@ DECLARE_SOA_COLUMN(IsGlobalTrackWoDCA, isGlobalTrackWoDCA, bool); //! Is glob DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, bool); //! Is global track DECLARE_SOA_COLUMN(IsPrimaryTrack, isPrimaryTrack, bool); //! Is primary track DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); //! Is primary vertex contributor -DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Has TOF +DECLARE_SOA_COLUMN(HasITS, hasITS, bool); +DECLARE_SOA_COLUMN(HasTPC, hasTPC, bool); +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Has TOF DECLARE_SOA_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, float); DECLARE_SOA_COLUMN(DaughDCA, daughDCA, float); //! DCA between daughters DECLARE_SOA_COLUMN(CascDaughDCA, cascdaughDCA, float); //! DCA between daughters from cascade @@ -126,6 +129,8 @@ DECLARE_SOA_TABLE(ResoTrackDFs, "AOD", "RESOTRACKDFs", o2::aod::track::DcaZ, o2::aod::track::X, o2::aod::track::Alpha, + resodaughterdf::HasITS, + resodaughterdf::HasTPC, resodaughterdf::HasTOF, o2::aod::pidtpc::TPCNSigmaPi, o2::aod::pidtpc::TPCNSigmaKa, diff --git a/PWGLF/DataModel/LFSigmaTables.h b/PWGLF/DataModel/LFSigmaTables.h index eff96b32785..b5a909733c7 100644 --- a/PWGLF/DataModel/LFSigmaTables.h +++ b/PWGLF/DataModel/LFSigmaTables.h @@ -22,9 +22,6 @@ #ifndef PWGLF_DATAMODEL_LFSIGMATABLES_H_ #define PWGLF_DATAMODEL_LFSIGMATABLES_H_ -using namespace o2; -using namespace o2::framework; - // Creating output TTree for sigma analysis namespace o2::aod { diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index c61c1b25a7b..afc076d1a54 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -41,6 +41,7 @@ DECLARE_SOA_COLUMN(TPCfindableCls, tpcFindableCls, uint8_t); DECLARE_SOA_COLUMN(TPCcrossedRows, tpcCrossedRows, uint8_t); DECLARE_SOA_COLUMN(ITSclsMap, itsClsMap, uint8_t); DECLARE_SOA_COLUMN(TPCnCls, tpcNCls, uint8_t); +DECLARE_SOA_COLUMN(TPCnClsShared, tpcNClsShared, uint8_t); DECLARE_SOA_COLUMN(ITSclusterSizes, itsClusterSizes, uint32_t); DECLARE_SOA_COLUMN(gPt, genPt, float); DECLARE_SOA_COLUMN(gEta, genEta, float); @@ -83,6 +84,7 @@ DECLARE_SOA_TABLE(NucleiTable, "AOD", "NUCLEITABLE", NucleiTableNS::TPCcrossedRows, NucleiTableNS::ITSclsMap, NucleiTableNS::TPCnCls, + NucleiTableNS::TPCnClsShared, NucleiTableNS::ITSclusterSizes); DECLARE_SOA_TABLE(NucleiTableFlow, "AOD", "NUCLEITABLEFLOW", @@ -116,6 +118,7 @@ DECLARE_SOA_TABLE(NucleiTableMC, "AOD", "NUCLEITABLEMC", NucleiTableNS::TPCcrossedRows, NucleiTableNS::ITSclsMap, NucleiTableNS::TPCnCls, + NucleiTableNS::TPCnClsShared, NucleiTableNS::ITSclusterSizes, NucleiTableNS::gPt, NucleiTableNS::gEta, diff --git a/PWGLF/DataModel/LFSlimStrangeTables.h b/PWGLF/DataModel/LFSlimStrangeTables.h index 95505bef0f5..423a412bb6d 100644 --- a/PWGLF/DataModel/LFSlimStrangeTables.h +++ b/PWGLF/DataModel/LFSlimStrangeTables.h @@ -41,16 +41,25 @@ DECLARE_SOA_COLUMN(PzPos, pzPos, float); DECLARE_SOA_COLUMN(PxNeg, pxNeg, float); DECLARE_SOA_COLUMN(PyNeg, pyNeg, float); DECLARE_SOA_COLUMN(PzNeg, pzNeg, float); +DECLARE_SOA_COLUMN(PxPosMC, pxPosMC, float); +DECLARE_SOA_COLUMN(PyPosMC, pyPosMC, float); +DECLARE_SOA_COLUMN(PzPosMC, pzPosMC, float); +DECLARE_SOA_COLUMN(PxNegMC, pxNegMC, float); +DECLARE_SOA_COLUMN(PyNegMC, pyNegMC, float); +DECLARE_SOA_COLUMN(PzNegMC, pzNegMC, float); DECLARE_SOA_COLUMN(GenPt, gentPt, float); DECLARE_SOA_COLUMN(GenEta, genEta, float); DECLARE_SOA_COLUMN(GenCt, genCt, float); DECLARE_SOA_COLUMN(GenLen, genLen, float); DECLARE_SOA_COLUMN(PDGCodeDauPos, pdgCodeDauPos, int); +DECLARE_SOA_COLUMN(PDGCodeMotherDauPos, pdgCodeMotherDauPos, int); DECLARE_SOA_COLUMN(PDGCodeDauNeg, pdgCodeDauNeg, int); +DECLARE_SOA_COLUMN(PDGCodeMotherDauNeg, pdgCodeMotherDauNeg, int); DECLARE_SOA_COLUMN(PDGCode, pdgCode, int); DECLARE_SOA_COLUMN(PDGCodeMother, pdgCodeMother, int); DECLARE_SOA_COLUMN(IsReco, isReco, bool); DECLARE_SOA_COLUMN(IsFD, isFD, uint8_t); +DECLARE_SOA_COLUMN(PDGMatchMotherSecondMother, pdgMatchMotherSecondMother, int); } // namespace SlimLambdaTables DECLARE_SOA_TABLE(LambdaTableML, "AOD", "LAMBDATABLEML", @@ -89,10 +98,13 @@ DECLARE_SOA_TABLE(McLambdaTableML, "AOD", "MCLAMBDATABLEML", SlimLambdaTables::GenEta, SlimLambdaTables::GenCt, SlimLambdaTables::PDGCodeDauPos, + SlimLambdaTables::PDGCodeMotherDauPos, SlimLambdaTables::PDGCodeDauNeg, + SlimLambdaTables::PDGCodeMotherDauNeg, SlimLambdaTables::PDGCode, SlimLambdaTables::PDGCodeMother, - SlimLambdaTables::IsReco); + SlimLambdaTables::IsReco, + SlimLambdaTables::PDGMatchMotherSecondMother); DECLARE_SOA_TABLE(V0TableAP, "AOD", "V0TABLEAP", SlimLambdaTables::Eta, @@ -119,6 +131,12 @@ DECLARE_SOA_TABLE(McV0TableAP, "AOD", "MCV0TABLEAP", SlimLambdaTables::PxNeg, SlimLambdaTables::PyNeg, SlimLambdaTables::PzNeg, + SlimLambdaTables::PxPosMC, + SlimLambdaTables::PyPosMC, + SlimLambdaTables::PzPosMC, + SlimLambdaTables::PxNegMC, + SlimLambdaTables::PyNegMC, + SlimLambdaTables::PzNegMC, SlimLambdaTables::Radius, SlimLambdaTables::DcaV0PV, SlimLambdaTables::DcaPosPV, diff --git a/PWGLF/DataModel/LFStrangenessMLTables.h b/PWGLF/DataModel/LFStrangenessMLTables.h index 544958c388f..abae8814856 100644 --- a/PWGLF/DataModel/LFStrangenessMLTables.h +++ b/PWGLF/DataModel/LFStrangenessMLTables.h @@ -18,9 +18,6 @@ #ifndef PWGLF_DATAMODEL_LFSTRANGENESSMLTABLES_H_ #define PWGLF_DATAMODEL_LFSTRANGENESSMLTABLES_H_ -using namespace o2; -using namespace o2::framework; - // Creating output TTree for ML analysis namespace o2::aod { @@ -238,6 +235,18 @@ DECLARE_SOA_TABLE(CascMLCandidates, "AOD", "CAMLCANDIDATES", cascmlcandidates::IsXiPlus, cascmlcandidates::IsOmegaMinus, cascmlcandidates::IsOmegaPlus); + +namespace CascMLSelection +{ +DECLARE_SOA_COLUMN(XiBDTScore, xiBDTScore, float); +DECLARE_SOA_COLUMN(OmegaBDTScore, omegaBDTScore, float); +} // namespace CascMLSelection + +DECLARE_SOA_TABLE(CascXiMLScores, "AOD", "CASCXIMLSCORES", + CascMLSelection::XiBDTScore); +DECLARE_SOA_TABLE(CascOmMLScores, "AOD", "CASCOMMLSCORES", + CascMLSelection::OmegaBDTScore); + } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFSTRANGENESSMLTABLES_H_ diff --git a/PWGLF/DataModel/LFStrangenessPIDTables.h b/PWGLF/DataModel/LFStrangenessPIDTables.h index 36a345b87ad..e689dc28141 100644 --- a/PWGLF/DataModel/LFStrangenessPIDTables.h +++ b/PWGLF/DataModel/LFStrangenessPIDTables.h @@ -137,15 +137,15 @@ DECLARE_SOA_COLUMN(BachTOFEventTime, bachTOFEventTime, float); //! bachelor tr // delta-times DECLARE_SOA_COLUMN(PosTOFDeltaTXiPi, posTOFDeltaTXiPi, float); //! positive track TOFDeltaT from pion <- lambda <- xi expectation -DECLARE_SOA_COLUMN(PosTOFDeltaTXiPr, posTOFDeltaTXiPr, float); //! positive track TOFDeltaT from pion <- lambda <- xi expectation +DECLARE_SOA_COLUMN(PosTOFDeltaTXiPr, posTOFDeltaTXiPr, float); //! positive track TOFDeltaT from proton <- lambda <- xi expectation DECLARE_SOA_COLUMN(NegTOFDeltaTXiPi, negTOFDeltaTXiPi, float); //! negative track TOFDeltaT from pion <- lambda <- xi expectation -DECLARE_SOA_COLUMN(NegTOFDeltaTXiPr, negTOFDeltaTXiPr, float); //! negative track TOFDeltaT from pion <- lambda <- xi expectation +DECLARE_SOA_COLUMN(NegTOFDeltaTXiPr, negTOFDeltaTXiPr, float); //! negative track TOFDeltaT from proton <- lambda <- xi expectation DECLARE_SOA_COLUMN(BachTOFDeltaTXiPi, bachTOFDeltaTXiPi, float); //! bachelor track TOFDeltaT from pion <- xi expectation DECLARE_SOA_COLUMN(PosTOFDeltaTOmPi, posTOFDeltaTOmPi, float); //! positive track TOFDeltaT from pion <- lambda <- omega expectation -DECLARE_SOA_COLUMN(PosTOFDeltaTOmPr, posTOFDeltaTOmPr, float); //! positive track TOFDeltaT from pion <- lambda <- omega expectation +DECLARE_SOA_COLUMN(PosTOFDeltaTOmPr, posTOFDeltaTOmPr, float); //! positive track TOFDeltaT from proton <- lambda <- omega expectation DECLARE_SOA_COLUMN(NegTOFDeltaTOmPi, negTOFDeltaTOmPi, float); //! negative track TOFDeltaT from pion <- lambda <- omega expectation -DECLARE_SOA_COLUMN(NegTOFDeltaTOmPr, negTOFDeltaTOmPr, float); //! negative track TOFDeltaT from pion <- lambda <- omega expectation -DECLARE_SOA_COLUMN(BachTOFDeltaTOmPi, bachTOFDeltaTOmPi, float); //! bachelor track TOFDeltaT from pion <- omega expectation +DECLARE_SOA_COLUMN(NegTOFDeltaTOmPr, negTOFDeltaTOmPr, float); //! negative track TOFDeltaT from proton <- lambda <- omega expectation +DECLARE_SOA_COLUMN(BachTOFDeltaTOmKa, bachTOFDeltaTOmKa, float); //! bachelor track TOFDeltaT from kaon <- omega expectation // n-sigmas DECLARE_SOA_COLUMN(TOFNSigmaXiLaPi, tofNSigmaXiLaPi, float); //! meson track NSigma from pion <- lambda <- xi expectation @@ -170,7 +170,7 @@ DECLARE_SOA_TABLE(CascTOFPIDs, "AOD", "CASCTOFPID", // processed information for cascdata::BachTOFDeltaTXiPi, cascdata::PosTOFDeltaTOmPi, cascdata::PosTOFDeltaTOmPr, cascdata::NegTOFDeltaTOmPi, cascdata::NegTOFDeltaTOmPr, - cascdata::BachTOFDeltaTOmPi); + cascdata::BachTOFDeltaTOmKa); DECLARE_SOA_TABLE(CascTOFNSigmas, "AOD", "CascTOFNSigmas", // Nsigmas for cascades cascdata::TOFNSigmaXiLaPi, cascdata::TOFNSigmaXiLaPr, cascdata::TOFNSigmaXiPi, cascdata::TOFNSigmaOmLaPi, cascdata::TOFNSigmaOmLaPr, cascdata::TOFNSigmaOmKa); diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index 9baca729fb4..15f74f66aca 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -20,11 +20,33 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/McCollisionExtra.h" #include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGUD/DataModel/UDTables.h" namespace o2::aod { +namespace stracollision +{ +DECLARE_SOA_DYNAMIC_COLUMN(IsUPC, isUPC, //! check whether this is a UPC or hadronic collision + [](int value) -> bool { return value <= 2 ? true : false; }); +DECLARE_SOA_DYNAMIC_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, //! get the total sum of the FV0 A amplitudes + [](float value) -> float { return value; }); +DECLARE_SOA_DYNAMIC_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, //! get the total sum of the FT0 A amplitudes + [](float value) -> float { return value; }); +DECLARE_SOA_DYNAMIC_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, //! get the total sum of the FT0 C amplitudes + [](float value) -> float { return value; }); +DECLARE_SOA_DYNAMIC_COLUMN(TotalFDDAmplitudeA, totalFDDAmplitudeA, //! get the total sum of the FDD A amplitudes + [](float value) -> float { return value; }); +DECLARE_SOA_DYNAMIC_COLUMN(TotalFDDAmplitudeC, totalFDDAmplitudeC, //! get the total sum of the FDD C amplitudes + [](float value) -> float { return value; }); +DECLARE_SOA_DYNAMIC_COLUMN(EnergyCommonZNA, energyCommonZNA, //! get the total sum of the ZN A amplitudes + [](float value) -> float { return value; }); +DECLARE_SOA_DYNAMIC_COLUMN(EnergyCommonZNC, energyCommonZNC, //! get the total sum of the ZN A amplitudes + [](float value) -> float { return value; }); +} // namespace stracollision + //______________________________________________________ // Collision declarations for derived data analysis // this is optional but will ensure full flexibility @@ -34,13 +56,16 @@ DECLARE_SOA_TABLE(StraCollisions, "AOD", "STRACOLLISION", //! basic collision pr DECLARE_SOA_TABLE(StraCents, "AOD", "STRACENTS", //! centrality percentiles cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentFV0A); +// !!! DEPRECATED TABLE: StraRawCents_000 !!! All info in StraEvSels_001, in order to group all event characteristics in a unique table. Please use StraEvSels_001 DECLARE_SOA_TABLE(StraRawCents_000, "AOD", "STRARAWCENTS", //! debug information mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, mult::MultNTracksPVeta1); +// !!! DEPRECATED TABLE: StraRawCents_001 !!! All info in StraEvSels_001, in order to group all event characteristics in a unique table. Please use StraEvSels_001 DECLARE_SOA_TABLE_VERSIONED(StraRawCents_001, "AOD", "STRARAWCENTS", 1, //! debug information mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, // FIT detectors mult::MultNTracksPVeta1, // track multiplicities mult::MultZNA, mult::MultZNC, mult::MultZEM1, // ZDC signals mult::MultZEM2, mult::MultZPA, mult::MultZPC); +// !!! DEPRECATED TABLE: StraRawCents_002 !!! All info in StraEvSels_001, in order to group all event characteristics in a unique table. Please use StraEvSels_001 DECLARE_SOA_TABLE_VERSIONED(StraRawCents_002, "AOD", "STRARAWCENTS", 2, //! debug information mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, // FIT detectors mult::MultNTracksPVeta1, // track multiplicities with eta cut for INEL>0 @@ -48,6 +73,7 @@ DECLARE_SOA_TABLE_VERSIONED(StraRawCents_002, "AOD", "STRARAWCENTS", 2, mult::MultAllTracksTPCOnly, mult::MultAllTracksITSTPC, // track multiplicities, all, no eta cut mult::MultZNA, mult::MultZNC, mult::MultZEM1, // ZDC signals mult::MultZEM2, mult::MultZPA, mult::MultZPC); +// !!! DEPRECATED TABLE: StraRawCents_003 !!! All info in StraEvSels_001, in order to group all event characteristics in a unique table. Please use StraEvSels_001 DECLARE_SOA_TABLE_VERSIONED(StraRawCents_003, "AOD", "STRARAWCENTS", 3, //! debug information mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, // FIT detectors mult::MultNTracksPVeta1, // track multiplicities with eta cut for INEL>0 @@ -58,6 +84,7 @@ DECLARE_SOA_TABLE_VERSIONED(StraRawCents_003, "AOD", "STRARAWCENTS", 3, //! mult::MultAllTracksITSTPC, // ITSTPC track multiplicities, all, no eta cut mult::MultZNA, mult::MultZNC, mult::MultZEM1, // ZDC signals mult::MultZEM2, mult::MultZPA, mult::MultZPC); +// !!! DEPRECATED TABLE: StraRawCents_004 !!! All info in StraEvSels_001, in order to group all event characteristics in a unique table. Please use StraEvSels_001 DECLARE_SOA_TABLE_VERSIONED(StraRawCents_004, "AOD", "STRARAWCENTS", 4, //! debug information mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, // FIT detectors mult::MultNTracksPVeta1, // track multiplicities with eta cut for INEL>0 @@ -69,8 +96,40 @@ DECLARE_SOA_TABLE_VERSIONED(StraRawCents_004, "AOD", "STRARAWCENTS", 4, //! mult::MultZNA, mult::MultZNC, mult::MultZEM1, // ZDC signals mult::MultZEM2, mult::MultZPA, mult::MultZPC, evsel::NumTracksInTimeRange); // add occupancy as extra -DECLARE_SOA_TABLE(StraEvSels, "AOD", "STRAEVSELS", //! event selection: sel8 +DECLARE_SOA_TABLE(StraEvSels_000, "AOD", "STRAEVSELS", //! event selection: sel8 evsel::Sel8, evsel::Selection); +DECLARE_SOA_TABLE_VERSIONED(StraEvSels_001, "AOD", "STRAEVSELS", 1, //! debug information + evsel::Sel8, evsel::Selection, //! event selection: sel8 + mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, // FIT detectors + mult::MultFDDA, mult::MultFDDC, + mult::MultNTracksPVeta1, // track multiplicities with eta cut for INEL>0 + mult::MultPVTotalContributors, // number of PV contribs total + mult::MultNTracksGlobal, // global track multiplicities + mult::MultNTracksITSTPC, // track multiplicities, PV contribs, no eta cut + mult::MultAllTracksTPCOnly, // TPConly track multiplicities, all, no eta cut + mult::MultAllTracksITSTPC, // ITSTPC track multiplicities, all, no eta cut + mult::MultZNA, mult::MultZNC, mult::MultZEM1, // ZDC signals + mult::MultZEM2, mult::MultZPA, mult::MultZPC, + evsel::NumTracksInTimeRange, // add occupancy as extra + udcollision::GapSide, // UPC info: 0 for side A, 1 for side C, 2 for both sides, 3 neither A or C, 4 not enough or too many pv contributors + udcollision::TotalFT0AmplitudeA, // UPC info: re-assigned FT0-A amplitude, in case of SG event, from the most active bc + udcollision::TotalFT0AmplitudeC, // UPC info: re-assigned FT0-C amplitude, in case of SG event, from the most active bc + udcollision::TotalFV0AmplitudeA, // UPC info: re-assigned FV0-A amplitude, in case of SG event, from the most active bc + udcollision::TotalFDDAmplitudeA, // UPC info: re-assigned FDD-A amplitude, in case of SG event, from the most active bc + udcollision::TotalFDDAmplitudeC, // UPC info: re-assigned FDD-C amplitude, in case of SG event, from the most active bc + udzdc::EnergyCommonZNA, // UPC info: re-assigned ZN-A amplitude, in case of SG event, from the most active bc + udzdc::EnergyCommonZNC, // UPC info: re-assigned ZN-C amplitude, in case of SG event, from the most active bc + + // Dynamic columns for manipulating information + // stracollision::TotalFV0AmplitudeA, + // stracollision::TotalFT0AmplitudeA, + // stracollision::TotalFT0AmplitudeC, + // stracollision::TotalFDDAmplitudeA, + // stracollision::TotalFDDAmplitudeC, + // stracollision::EnergyCommonZNA, + // stracollision::EnergyCommonZNC, + stracollision::IsUPC); + DECLARE_SOA_TABLE(StraFT0AQVs, "AOD", "STRAFT0AQVS", //! t0a Qvec qvec::QvecFT0ARe, qvec::QvecFT0AIm, qvec::SumAmplFT0A); DECLARE_SOA_TABLE(StraFT0CQVs, "AOD", "STRAFT0CQVS", //! t0c Qvec @@ -88,6 +147,7 @@ DECLARE_SOA_TABLE(StraStamps, "AOD", "STRASTAMPS", //! information for ID-ing ma bc::RunNumber, timestamp::Timestamp); using StraRawCents = StraRawCents_004; +using StraEvSels = StraEvSels_001; using StraCollision = StraCollisions::iterator; using StraCent = StraCents::iterator; @@ -294,6 +354,9 @@ DECLARE_SOA_COLUMN(PzPosMC, pzPosMC, float); //! V0 positive DECLARE_SOA_COLUMN(PxNegMC, pxNegMC, float); //! V0 positive daughter px (GeV/c) DECLARE_SOA_COLUMN(PyNegMC, pyNegMC, float); //! V0 positive daughter py (GeV/c) DECLARE_SOA_COLUMN(PzNegMC, pzNegMC, float); //! V0 positive daughter pz (GeV/c) +DECLARE_SOA_COLUMN(PxMC, pxMC, float); //! V0 px (GeV/c) +DECLARE_SOA_COLUMN(PyMC, pyMC, float); //! V0 py (GeV/c) +DECLARE_SOA_COLUMN(PzMC, pzMC, float); //! V0 pz (GeV/c) //______________________________________________________ // Binned content for generated particles: derived data @@ -464,6 +527,22 @@ DECLARE_SOA_DYNAMIC_COLUMN(IsPhotonTPConly, isPhotonTPConly, //! is tpc-only pho [](uint8_t V0Type) -> bool { return V0Type & (1 << 1); }); DECLARE_SOA_DYNAMIC_COLUMN(IsCollinear, isCollinear, //! is collinear V0 [](uint8_t V0Type) -> bool { return V0Type & (1 << 2); }); + +DECLARE_SOA_DYNAMIC_COLUMN(RapidityMC, rapidityMC, //! rapidity (0:K0, 1:L, 2:Lbar) + [](float PxMC, float PyMC, float PzMC, int value) -> float { + if (value == 0) + return RecoDecay::y(std::array{PxMC, PyMC, PzMC}, o2::constants::physics::MassKaonNeutral); + if (value == 1 || value == 2) + return RecoDecay::y(std::array{PxMC, PyMC, PzMC}, o2::constants::physics::MassLambda); + return 0.0f; + }); + +DECLARE_SOA_DYNAMIC_COLUMN(NegativePtMC, negativeptMC, //! negative daughter pT + [](float pxnegMC, float pynegMC) -> float { return RecoDecay::sqrtSumOfSquares(pxnegMC, pynegMC); }); +DECLARE_SOA_DYNAMIC_COLUMN(PositivePtMC, positiveptMC, //! positive daughter pT + [](float pxposMC, float pyposMC) -> float { return RecoDecay::sqrtSumOfSquares(pxposMC, pyposMC); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtMC, ptMC, //! V0 pT + [](float pxMC, float pyMC) -> float { return RecoDecay::sqrtSumOfSquares(pxMC, pyMC); }); } // namespace v0data DECLARE_SOA_TABLE(V0Indices, "AOD", "V0INDEX", //! index table when using AO2Ds @@ -666,6 +745,19 @@ DECLARE_SOA_TABLE_VERSIONED(V0MCCores_001, "AOD", "V0MCCORE", 1, //! debug infor v0data::PxPosMC, v0data::PyPosMC, v0data::PzPosMC, v0data::PxNegMC, v0data::PyNegMC, v0data::PzNegMC); +DECLARE_SOA_TABLE_VERSIONED(V0MCCores_002, "AOD", "V0MCCORE", 2, //! debug information + v0data::ParticleIdMC, //! MC properties of the V0 for posterior analysis + v0data::PDGCode, v0data::PDGCodeMother, + v0data::PDGCodePositive, v0data::PDGCodeNegative, + v0data::IsPhysicalPrimary, v0data::XMC, v0data::YMC, v0data::ZMC, + v0data::PxPosMC, v0data::PyPosMC, v0data::PzPosMC, + v0data::PxNegMC, v0data::PyNegMC, v0data::PzNegMC, + v0data::PxMC, v0data::PyMC, v0data::PzMC, + v0data::RapidityMC, + v0data::NegativePtMC, + v0data::PositivePtMC, + v0data::PtMC); + DECLARE_SOA_TABLE(StoredV0MCCores_000, "AOD", "V0MCCORE", //! MC properties of the V0 for posterior analysis v0data::PDGCode, v0data::PDGCodeMother, v0data::PDGCodePositive, v0data::PDGCodeNegative, @@ -683,6 +775,16 @@ DECLARE_SOA_TABLE_VERSIONED(StoredV0MCCores_001, "AOD", "V0MCCORE", 1, //! debug v0data::PxNegMC, v0data::PyNegMC, v0data::PzNegMC, o2::soa::Marker<1>); +DECLARE_SOA_TABLE_VERSIONED(StoredV0MCCores_002, "AOD", "V0MCCORE", 2, //! debug information + v0data::ParticleIdMC, //! MC properties of the V0 for posterior analysis + v0data::PDGCode, v0data::PDGCodeMother, + v0data::PDGCodePositive, v0data::PDGCodeNegative, + v0data::IsPhysicalPrimary, v0data::XMC, v0data::YMC, v0data::ZMC, + v0data::PxPosMC, v0data::PyPosMC, v0data::PzPosMC, + v0data::PxNegMC, v0data::PyNegMC, v0data::PzNegMC, + v0data::PxMC, v0data::PyMC, v0data::PzMC, + o2::soa::Marker<1>); + DECLARE_SOA_TABLE(V0MCCollRefs, "AOD", "V0MCCOLLREF", //! refers MC candidate back to proper MC Collision o2::soa::Index<>, v0data::StraMCCollisionId, o2::soa::Marker<2>); @@ -696,8 +798,8 @@ DECLARE_SOA_TABLE(V0MCMothers, "AOD", "V0MCMOTHER", //! optional table for MC mo DECLARE_SOA_TABLE(StoredV0MCMothers, "AOD1", "V0MCMOTHER", //! optional table for MC mothers o2::soa::Index<>, v0data::MotherMCPartId, o2::soa::Marker<1>); -using V0MCCores = V0MCCores_001; -using StoredV0MCCores = StoredV0MCCores_001; +using V0MCCores = V0MCCores_002; +using StoredV0MCCores = StoredV0MCCores_002; using V0Index = V0Indices::iterator; using V0Core = V0Cores::iterator; @@ -708,6 +810,7 @@ using V0fCDatas = soa::Join; using V0fCData = V0fCDatas::iterator; using V0MCDatas = soa::Join; using V0MCData = V0MCDatas::iterator; +using V0MCCore = V0MCCores::iterator; // definitions of indices for interlink tables namespace v0data @@ -762,6 +865,7 @@ DECLARE_SOA_COLUMN(IsTrueLambda, isTrueLambda, bool); //! PDG DECLARE_SOA_COLUMN(IsTrueAntiLambda, isTrueAntiLambda, bool); //! PDG checked correctly in MC DECLARE_SOA_COLUMN(IsTrueHypertriton, isTrueHypertriton, bool); //! PDG checked correctly in MC DECLARE_SOA_COLUMN(IsTrueAntiHypertriton, isTrueAntiHypertriton, bool); //! PDG checked correctly in MC +DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); //! physical primary // dE/dx compatibility bools DECLARE_SOA_COLUMN(IsdEdxGamma, isdEdxGamma, bool); //! compatible with dE/dx hypotheses @@ -783,6 +887,7 @@ DECLARE_SOA_TABLE(V0Tags, "AOD", "V0TAGS", v0tag::IsTrueAntiLambda, v0tag::IsTrueHypertriton, v0tag::IsTrueAntiHypertriton, + v0tag::IsPhysicalPrimary, v0tag::IsdEdxGamma, v0tag::IsdEdxK0Short, v0tag::IsdEdxLambda, @@ -947,8 +1052,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(CascRadius, cascradius, //! // CosPAs DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, //! [](float Xlambda, float Ylambda, float Zlambda, float PxLambda, float PyLambda, float PzLambda, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{Xlambda, Ylambda, Zlambda}, std::array{PxLambda, PyLambda, PzLambda}); }); +// DECLARE_SOA_DYNAMIC_COLUMN(CascCosPA, casccosPA, //! +// [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(CascCosPA, casccosPA, //! - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); + [](float X, float Y, float Z, float PxBach, float PxPos, float PxNeg, float PyBach, float PyPos, float PyNeg, float PzBach, float PzPos, float PzNeg, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{PxBach + PxPos + PxNeg, PyBach + PyPos + PyNeg, PzBach + PzPos + PzNeg}); }); DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, //! [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); @@ -995,6 +1102,24 @@ DECLARE_SOA_DYNAMIC_COLUMN(BachelorEta, bacheloreta, //! bachelor daughter eta [](float PxPos, float PyPos, float PzPos) -> float { return RecoDecay::eta(std::array{PxPos, PyPos, PzPos}); }); DECLARE_SOA_DYNAMIC_COLUMN(BachelorPhi, bachelorphi, //! bachelor daughter phi [](float PxPos, float PyPos) -> float { return RecoDecay::phi(PxPos, PyPos); }); + +DECLARE_SOA_DYNAMIC_COLUMN(RapidityMC, rapidityMC, //! rapidity (0, 1: Xi; 2, 3: Omega) + [](float PxMC, float PyMC, float PzMC, int value) -> float { + if (value == 0 || value == 1) + return RecoDecay::y(std::array{PxMC, PyMC, PzMC}, o2::constants::physics::MassXiMinus); + if (value == 2 || value == 3) + return RecoDecay::y(std::array{PxMC, PyMC, PzMC}, o2::constants::physics::MassOmegaMinus); + return 0.0f; + }); + +DECLARE_SOA_DYNAMIC_COLUMN(NegativePtMC, negativeptMC, //! negative daughter pT + [](float pxNegMC, float pyNegMC) -> float { return RecoDecay::sqrtSumOfSquares(pxNegMC, pyNegMC); }); +DECLARE_SOA_DYNAMIC_COLUMN(PositivePtMC, positiveptMC, //! positive daughter pT + [](float pxPosMC, float pyPosMC) -> float { return RecoDecay::sqrtSumOfSquares(pxPosMC, pyPosMC); }); +DECLARE_SOA_DYNAMIC_COLUMN(BachelorPtMC, bachelorptMC, //! bachelor daughter pT + [](float pxBachMC, float pyBachMC) -> float { return RecoDecay::sqrtSumOfSquares(pxBachMC, pyBachMC); }); +DECLARE_SOA_DYNAMIC_COLUMN(PtMC, ptMC, //! cascade pT + [](float pxMC, float pyMC) -> float { return RecoDecay::sqrtSumOfSquares(pxMC, pyMC); }); } // namespace cascdata //______________________________________________________ @@ -1079,7 +1204,7 @@ DECLARE_SOA_TABLE(StoredCascCores, "AOD", "CASCCORE", //! core information about cascdata::V0Radius, cascdata::CascRadius, cascdata::V0CosPA, - cascdata::CascCosPA, + cascdata::CascCosPA, cascdata::DCAV0ToPV, // Invariant masses @@ -1122,7 +1247,7 @@ DECLARE_SOA_TABLE(StoredKFCascCores, "AOD", "KFCASCCORE", //! cascdata::V0Radius, cascdata::CascRadius, cascdata::V0CosPA, - cascdata::CascCosPA, + cascdata::CascCosPA, cascdata::DCAV0ToPV, // Invariant masses @@ -1160,7 +1285,7 @@ DECLARE_SOA_TABLE(StoredTraCascCores, "AOD", "TRACASCCORE", //! cascdata::V0Radius, cascdata::CascRadius, cascdata::V0CosPA, - cascdata::CascCosPA, + cascdata::CascCosPA, cascdata::DCAV0ToPV, // Invariant masses @@ -1188,7 +1313,12 @@ DECLARE_SOA_TABLE(CascMCCores, "AOD", "CASCMCCORE", //! bachelor-baryon correlat cascdata::PxPosMC, cascdata::PyPosMC, cascdata::PzPosMC, cascdata::PxNegMC, cascdata::PyNegMC, cascdata::PzNegMC, cascdata::PxBachMC, cascdata::PyBachMC, cascdata::PzBachMC, - cascdata::PxMC, cascdata::PyMC, cascdata::PzMC); + cascdata::PxMC, cascdata::PyMC, cascdata::PzMC, + cascdata::RapidityMC, + cascdata::NegativePtMC, + cascdata::PositivePtMC, + cascdata::BachelorPtMC, + cascdata::PtMC); namespace cascdata { @@ -1312,10 +1442,11 @@ namespace casctag DECLARE_SOA_COLUMN(IsInteresting, isInteresting, bool); //! will this be built or not? // MC association bools -DECLARE_SOA_COLUMN(IsTrueXiMinus, isTrueXiMinus, bool); //! PDG checked correctly in MC -DECLARE_SOA_COLUMN(IsTrueXiPlus, isTrueXiPlus, bool); //! PDG checked correctly in MC -DECLARE_SOA_COLUMN(IsTrueOmegaMinus, isTrueOmegaMinus, bool); //! PDG checked correctly in MC -DECLARE_SOA_COLUMN(IsTrueOmegaPlus, isTrueOmegaPlus, bool); //! PDG checked correctly in MC +DECLARE_SOA_COLUMN(IsTrueXiMinus, isTrueXiMinus, bool); //! PDG checked correctly in MC +DECLARE_SOA_COLUMN(IsTrueXiPlus, isTrueXiPlus, bool); //! PDG checked correctly in MC +DECLARE_SOA_COLUMN(IsTrueOmegaMinus, isTrueOmegaMinus, bool); //! PDG checked correctly in MC +DECLARE_SOA_COLUMN(IsTrueOmegaPlus, isTrueOmegaPlus, bool); //! PDG checked correctly in MC +DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); //! physical primary // dE/dx compatibility bools DECLARE_SOA_COLUMN(IsdEdxXiMinus, isdEdxXiMinus, bool); //! compatible with dE/dx hypotheses @@ -1329,6 +1460,7 @@ DECLARE_SOA_TABLE(CascTags, "AOD", "CASCTAGS", casctag::IsTrueXiPlus, casctag::IsTrueOmegaMinus, casctag::IsTrueOmegaPlus, + casctag::IsPhysicalPrimary, casctag::IsdEdxXiMinus, casctag::IsdEdxXiPlus, casctag::IsdEdxOmegaMinus, diff --git a/PWGLF/DataModel/QC/strangenessTablesQC.h b/PWGLF/DataModel/QC/strangenessTablesQC.h index 042fbd3f2be..ccf1724dc4b 100644 --- a/PWGLF/DataModel/QC/strangenessTablesQC.h +++ b/PWGLF/DataModel/QC/strangenessTablesQC.h @@ -13,16 +13,12 @@ /// /// \author Roman Nepeivoda (roman.nepeivoda@cern.ch) -#ifndef PWGLF_DATAMODEL_STRANGENESSTABLESQC_H_ -#define PWGLF_DATAMODEL_STRANGENESSTABLESQC_H_ +#ifndef PWGLF_DATAMODEL_QC_STRANGENESSTABLESQC_H_ +#define PWGLF_DATAMODEL_QC_STRANGENESSTABLESQC_H_ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - namespace o2::aod { namespace cascadesQC @@ -116,4 +112,4 @@ DECLARE_SOA_TABLE(VZerosQC, "AOD", "VZEROSQC", o2::soa::Index<>, vZerosQC::PosPhi, vZerosQC::NegPhi); } // namespace o2::aod -#endif // PWGLF_DATAMODEL_STRANGENESSTABLESQC_H_ +#endif // PWGLF_DATAMODEL_QC_STRANGENESSTABLESQC_H_ diff --git a/PWGLF/DataModel/SPCalibrationTables.h b/PWGLF/DataModel/SPCalibrationTables.h new file mode 100644 index 00000000000..82d622e2c8c --- /dev/null +++ b/PWGLF/DataModel/SPCalibrationTables.h @@ -0,0 +1,71 @@ +// Copyright 2019-2020 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. + +/// \file SPCalibrationTables.h +/// +/// author: prottay das 07/09/2024 +/// email: prottay.das@cern.ch + +#ifndef PWGLF_DATAMODEL_SPCALIBRATIONTABLES_H_ +#define PWGLF_DATAMODEL_SPCALIBRATIONTABLES_H_ + +#include + +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace spcalibrationtable +{ +DECLARE_SOA_COLUMN(TriggerEvent, triggerevent, bool); +DECLARE_SOA_COLUMN(TriggerEventRunNo, triggereventrunno, int); +DECLARE_SOA_COLUMN(Cent, cent, float); +DECLARE_SOA_COLUMN(Vz, vz, float); +DECLARE_SOA_COLUMN(ZNAEN1, znaen1, float); +DECLARE_SOA_COLUMN(ZNAEN2, znaen2, float); +DECLARE_SOA_COLUMN(ZNAEN3, znaen3, float); +DECLARE_SOA_COLUMN(ZNAEN4, znaen4, float); +DECLARE_SOA_COLUMN(ZNCEN1, zncen1, float); +DECLARE_SOA_COLUMN(ZNCEN2, zncen2, float); +DECLARE_SOA_COLUMN(ZNCEN3, zncen3, float); +DECLARE_SOA_COLUMN(ZNCEN4, zncen4, float); +DECLARE_SOA_COLUMN(QXZDCA, qxZDCA, float); +DECLARE_SOA_COLUMN(QXZDCC, qxZDCC, float); +DECLARE_SOA_COLUMN(QYZDCA, qyZDCA, float); +DECLARE_SOA_COLUMN(QYZDCC, qyZDCC, float); +DECLARE_SOA_COLUMN(PsiZDCC, psiZDCC, float); +DECLARE_SOA_COLUMN(PsiZDCA, psiZDCA, float); +} // namespace spcalibrationtable +DECLARE_SOA_TABLE(SPCalibrationTables, "AOD", "SPCALCOLS", + spcalibrationtable::TriggerEvent, + spcalibrationtable::TriggerEventRunNo, + spcalibrationtable::Cent, + spcalibrationtable::Vz, + spcalibrationtable::ZNAEN1, + spcalibrationtable::ZNAEN2, + spcalibrationtable::ZNAEN3, + spcalibrationtable::ZNAEN4, + spcalibrationtable::ZNCEN1, + spcalibrationtable::ZNCEN2, + spcalibrationtable::ZNCEN3, + spcalibrationtable::ZNCEN4, + spcalibrationtable::QXZDCA, + spcalibrationtable::QXZDCC, + spcalibrationtable::QYZDCA, + spcalibrationtable::QYZDCC, + spcalibrationtable::PsiZDCC, + spcalibrationtable::PsiZDCA); +using SPCalibrationTable = SPCalibrationTables::iterator; +} // namespace o2::aod +#endif // PWGLF_DATAMODEL_SPCALIBRATIONTABLES_H_ diff --git a/PWGLF/DataModel/Vtx3BodyTables.h b/PWGLF/DataModel/Vtx3BodyTables.h index 521ca091efc..0165a52f2ce 100644 --- a/PWGLF/DataModel/Vtx3BodyTables.h +++ b/PWGLF/DataModel/Vtx3BodyTables.h @@ -43,6 +43,9 @@ DECLARE_SOA_COLUMN(Z, z, float); //! decay position Z // Saved from finding: DCAs DECLARE_SOA_COLUMN(DCAVtxDaughters, dcaVtxdaughters, float); //! DCA among daughters +DECLARE_SOA_COLUMN(DCAXYTrack0ToPV, dcaXYtrack0topv, float); //! DCAXY of prong0 to PV +DECLARE_SOA_COLUMN(DCAXYTrack1ToPV, dcaXYtrack1topv, float); //! DCAXY of prong1 to PV +DECLARE_SOA_COLUMN(DCAXYTrack2ToPV, dcaXYtrack2topv, float); //! DCAXY of prong2 to PV DECLARE_SOA_COLUMN(DCATrack0ToPV, dcatrack0topv, float); //! DCA of prong0 to PV DECLARE_SOA_COLUMN(DCATrack1ToPV, dcatrack1topv, float); //! DCA of prong1 to PV DECLARE_SOA_COLUMN(DCATrack2ToPV, dcatrack2topv, float); //! DCA of prong2 to PV @@ -132,6 +135,7 @@ DECLARE_SOA_TABLE_FULL(StoredVtx3BodyDatas, "Vtx3BodyDatas", "AOD", "Vtx3BodyDAT vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, vtx3body::DCAVtxDaughters, + vtx3body::DCAXYTrack0ToPV, vtx3body::DCAXYTrack1ToPV, vtx3body::DCAXYTrack2ToPV, vtx3body::DCATrack0ToPV, vtx3body::DCATrack1ToPV, vtx3body::DCATrack2ToPV, vtx3body::TOFNSigmaBachDe, @@ -246,15 +250,19 @@ DECLARE_SOA_COLUMN(TPCNSigmaPion, tpcNSigmaPion, float); //! nsigma of T DECLARE_SOA_COLUMN(TPCNSigmaBachelor, tpcNSigmaBachelor, float); //! nsigma of TPC PID of the bachelor daughter DECLARE_SOA_COLUMN(TOFNSigmaBachelor, tofNSigmaBachelor, float); //! nsigma of TOF PID of the bachelor daughter // DCA to PV -DECLARE_SOA_COLUMN(DCAProtonToPV, dcaProtontoPV, float); //! DCA of the proton daughter to pv -DECLARE_SOA_COLUMN(DCAPionToPV, dcaPiontoPV, float); //! DCA of the pion daughter to pv -DECLARE_SOA_COLUMN(DCABachelorToPV, dcaBachelortoPV, float); //! DCA of the bachelor daughter to pv +DECLARE_SOA_COLUMN(DCAXYProtonToPV, dcaxyProtontoPV, float); //! DCAXY of the proton daughter to pv +DECLARE_SOA_COLUMN(DCAXYPionToPV, dcaxyPiontoPV, float); //! DCAXY of the pion daughter to pv +DECLARE_SOA_COLUMN(DCAXYBachelorToPV, dcaxyBachelortoPV, float); //! DCAXY of the bachelor daughter to pv +DECLARE_SOA_COLUMN(DCAProtonToPV, dcaProtontoPV, float); //! DCA of the proton daughter to pv +DECLARE_SOA_COLUMN(DCAPionToPV, dcaPiontoPV, float); //! DCA of the pion daughter to pv +DECLARE_SOA_COLUMN(DCABachelorToPV, dcaBachelortoPV, float); //! DCA of the bachelor daughter to pv // for MC DECLARE_SOA_COLUMN(GenP, genP, float); // P of the hypertriton DECLARE_SOA_COLUMN(GenPt, genPt, float); // pT of the hypertriton DECLARE_SOA_COLUMN(GenCt, genCt, float); // ct of the hypertriton DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // Phi of the hypertriton DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton +DECLARE_SOA_COLUMN(GenRapidity, genRapidity, float); // Rapidity of the hypertriton DECLARE_SOA_COLUMN(IsReco, isReco, bool); // bool: true for reco DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for signal DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); // pdgCode of the mcparticle, -1 for fake pair @@ -284,6 +292,7 @@ DECLARE_SOA_TABLE(Hyp3BodyCands, "AOD", "HYP3BODYCANDS", hyp3body::ITSNclusSizeProton, hyp3body::ITSNclusSizePion, hyp3body::ITSNclusSizeBachelor, hyp3body::TPCNSigmaProton, hyp3body::TPCNSigmaPion, hyp3body::TPCNSigmaBachelor, hyp3body::TOFNSigmaBachelor, + hyp3body::DCAXYProtonToPV, hyp3body::DCAXYPionToPV, hyp3body::DCAXYBachelorToPV, hyp3body::DCAProtonToPV, hyp3body::DCAPionToPV, hyp3body::DCABachelorToPV); // output table for MC @@ -309,6 +318,7 @@ DECLARE_SOA_TABLE(MCHyp3BodyCands, "AOD", "MCHYP3BODYCANDS", hyp3body::ITSNclusSizeProton, hyp3body::ITSNclusSizePion, hyp3body::ITSNclusSizeBachelor, hyp3body::TPCNSigmaProton, hyp3body::TPCNSigmaPion, hyp3body::TPCNSigmaBachelor, hyp3body::TOFNSigmaBachelor, + hyp3body::DCAXYProtonToPV, hyp3body::DCAXYPionToPV, hyp3body::DCAXYBachelorToPV, hyp3body::DCAProtonToPV, hyp3body::DCAPionToPV, hyp3body::DCABachelorToPV, // MC information hyp3body::GenP, @@ -316,6 +326,7 @@ DECLARE_SOA_TABLE(MCHyp3BodyCands, "AOD", "MCHYP3BODYCANDS", hyp3body::GenCt, hyp3body::GenPhi, hyp3body::GenEta, + hyp3body::GenRapidity, hyp3body::IsSignal, hyp3body::IsReco, hyp3body::PdgCode, @@ -440,7 +451,6 @@ using McKFVtx3BodyLabel = McKFVtx3BodyLabels::iterator; DECLARE_SOA_TABLE(McFullKFVtx3BodyLabels, "AOD", "MCFULLKFVTXLABEL", //! Table joinable with Decay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) mcfullvtx3bodylabel::McParticleId); using McFullKFVtx3BodyLabel = McFullKFVtx3BodyLabels::iterator; - } // namespace o2::aod #endif // PWGLF_DATAMODEL_VTX3BODYTABLES_H_ diff --git a/PWGLF/DataModel/cascqaanalysis.h b/PWGLF/DataModel/cascqaanalysis.h index 1616120ba23..5bc77d96d10 100644 --- a/PWGLF/DataModel/cascqaanalysis.h +++ b/PWGLF/DataModel/cascqaanalysis.h @@ -25,10 +25,8 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "TRandom.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; +#include "Math/Vector4D.h" +#include "Math/Boost.h" namespace o2::aod { @@ -43,6 +41,8 @@ enum EvFlags : uint8_t { }; DECLARE_SOA_COLUMN(CollisionZ, zcoll, float); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); DECLARE_SOA_COLUMN(MultFV0A, multFV0A, float); DECLARE_SOA_COLUMN(Sign, sign, int); @@ -115,7 +115,7 @@ namespace cascadesflow DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); -DECLARE_SOA_COLUMN(Sign, sign, int); +DECLARE_SOA_COLUMN(Sign, sign, int16_t); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); @@ -126,11 +126,17 @@ DECLARE_SOA_COLUMN(V2CSP, v2CSP, float); DECLARE_SOA_COLUMN(PsiT0C, psiT0C, float); DECLARE_SOA_COLUMN(BDTResponseXi, bdtResponseXi, float); DECLARE_SOA_COLUMN(BDTResponseOmega, bdtResponseOmega, float); +DECLARE_SOA_COLUMN(CosThetaStarLambdaFromOmega, cosThetaStarLambdaFromOmega, float); +DECLARE_SOA_COLUMN(CosThetaStarLambdaFromXi, cosThetaStarLambdaFromXi, float); +DECLARE_SOA_COLUMN(CosThetaStarProton, cosThetaStarProton, float); } // namespace cascadesflow DECLARE_SOA_TABLE(MyCascades, "AOD", "MYCASCADES", o2::soa::Index<>, - mycascades::CollisionZ, mycascades::MultFT0M, mycascades::MultFV0A, mycascades::Sign, mycascades::Pt, mycascades::RapXi, mycascades::RapOmega, mycascades::Eta, mycascades::MassXi, mycascades::MassOmega, mycascades::MassLambdaDau, mycascades::CascRadius, mycascades::V0Radius, + mycascades::CollisionZ, + mycascades::CentFT0M, mycascades::CentFV0A, + mycascades::MultFT0M, mycascades::MultFV0A, + mycascades::Sign, mycascades::Pt, mycascades::RapXi, mycascades::RapOmega, mycascades::Eta, mycascades::MassXi, mycascades::MassOmega, mycascades::MassLambdaDau, mycascades::CascRadius, mycascades::V0Radius, mycascades::CascCosPA, mycascades::V0CosPA, mycascades::DCAPosToPV, mycascades::DCANegToPV, mycascades::DCABachToPV, mycascades::DCACascDaughters, mycascades::DCAV0Daughters, mycascades::DCAV0ToPV, mycascades::PosEta, mycascades::NegEta, mycascades::BachEta, mycascades::PosITSHits, mycascades::NegITSHits, mycascades::BachITSHits, @@ -154,7 +160,7 @@ DECLARE_SOA_TABLE(CascTraining, "AOD", "CascTraining", o2::soa::Index<>, mycascades::DCABachToPV, mycascades::DCACascDaughters, mycascades::DCAV0Daughters, mycascades::DCAV0ToPV, mycascades::BachBaryonCosPA, mycascades::BachBaryonDCAxyToPV, mycascades::McPdgCode); DECLARE_SOA_TABLE(CascAnalysis, "AOD", "CascAnalysis", o2::soa::Index<>, - cascadesflow::CentFT0C, cascadesflow::Sign, cascadesflow::Pt, cascadesflow::Eta, cascadesflow::Phi, cascadesflow::MassXi, cascadesflow::MassOmega, cascadesflow::V2CSP, cascadesflow::V2CEP, cascadesflow::PsiT0C, cascadesflow::BDTResponseXi, cascadesflow::BDTResponseOmega); + cascadesflow::CentFT0C, cascadesflow::Sign, cascadesflow::Pt, cascadesflow::Eta, cascadesflow::Phi, cascadesflow::MassXi, cascadesflow::MassOmega, cascadesflow::V2CSP, cascadesflow::V2CEP, cascadesflow::PsiT0C, cascadesflow::BDTResponseXi, cascadesflow::BDTResponseOmega, cascadesflow::CosThetaStarLambdaFromOmega, cascadesflow::CosThetaStarLambdaFromXi, cascadesflow::CosThetaStarProton); namespace myMCcascades { @@ -175,6 +181,9 @@ DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); DECLARE_SOA_COLUMN(NAssocColl, nAssocColl, int); // Number of reconstructed collisions assoceated to the generated one of this cascade DECLARE_SOA_COLUMN(NChInFT0M, nChInFT0M, float); // Number of charged particles in FT0M acceptance +DECLARE_SOA_COLUMN(NChInFV0A, nChInFV0A, float); // Number of charged particles in FV0A acceptance +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); // centr. (mult.) % FT0M +DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); // centr. (mult.) % FV0A DECLARE_SOA_COLUMN(AssCollisionTypeFilterBitMask, assCollisionTypeFilterBitMask, uint8_t); DECLARE_SOA_COLUMN(McCollisionTypeFilterBitMask, mcCollisionTypeFilterBitMask, uint8_t); @@ -196,7 +205,9 @@ DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt1, isINELgt1, //! True if the Event belongs t DECLARE_SOA_TABLE(MyMCCascades, "AOD", "MYMCCASCADES", o2::soa::Index<>, myMCcascades::CollisionZ, myMCcascades::Sign, myMCcascades::PdgCode, myMCcascades::Y, myMCcascades::Eta, myMCcascades::Phi, myMCcascades::Pt, - myMCcascades::IsPrimary, myMCcascades::NAssocColl, myMCcascades::NChInFT0M, + myMCcascades::IsPrimary, myMCcascades::NAssocColl, + myMCcascades::NChInFT0M, myMCcascades::NChInFV0A, + myMCcascades::CentFT0M, myMCcascades::CentFV0A, myMCcascades::AssCollisionTypeFilterBitMask, myMCcascades::McCollisionTypeFilterBitMask, myMCcascades::IsINELassoc, diff --git a/PWGLF/DataModel/pidTOFGeneric.h b/PWGLF/DataModel/pidTOFGeneric.h new file mode 100644 index 00000000000..047ec6aa477 --- /dev/null +++ b/PWGLF/DataModel/pidTOFGeneric.h @@ -0,0 +1,158 @@ +// Copyright 2019-2020 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. + +#ifndef PWGLF_DATAMODEL_PIDTOFGENERIC_H_ +#define PWGLF_DATAMODEL_PIDTOFGENERIC_H_ +#include "CommonDataFormat/InteractionRecord.h" +#include "Common/Core/PID/PIDTOF.h" + +namespace o2::aod +{ +namespace evtime +{ + +DECLARE_SOA_COLUMN(EvTime, evTime, float); //! Event time. Can be obtained via a combination of detectors e.g. TOF, FT0A, FT0C +DECLARE_SOA_COLUMN(EvTimeErr, evTimeErr, float); //! Error of event time. Can be obtained via a combination of detectors e.g. TOF, FT0A, FT0C +DECLARE_SOA_COLUMN(EvTimeTOF, evTimeTOF, float); //! Event time computed with the TOF detector +DECLARE_SOA_COLUMN(EvTimeTOFErr, evTimeTOFErr, float); //! Error of the event time computed with the TOF detector +DECLARE_SOA_COLUMN(EvTimeFT0, evTimeFT0, float); //! Event time computed with the FT0 detector +DECLARE_SOA_COLUMN(EvTimeFT0Err, evTimeFT0Err, float); //! Error of the event time computed with the FT0 detector +} // namespace evtime + +DECLARE_SOA_TABLE(EvTimeTOFFT0, "AOD", "EvTimeTOFFT0", //! Table of the event time. One entry per collision. + evtime::EvTime, + evtime::EvTimeErr, + evtime::EvTimeTOF, + evtime::EvTimeTOFErr, + evtime::EvTimeFT0, + evtime::EvTimeFT0Err); + +namespace tracktime +{ + +DECLARE_SOA_COLUMN(EvTimeForTrack, evTimeForTrack, float); //! Event time. Removed the bias for the specific track +DECLARE_SOA_COLUMN(EvTimeErrForTrack, evTimeErrForTrack, float); //! Error of event time. Removed the bias for the specific track +} // namespace tracktime + +DECLARE_SOA_TABLE(EvTimeTOFFT0ForTrack, "AOD", "EvTimeForTrack", //! Table of the event time. One entry per track. + tracktime::EvTimeForTrack, + tracktime::EvTimeErrForTrack); + +namespace pidtofgeneric +{ + +static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps + +template +class TofPidNewCollision +{ + public: + TofPidNewCollision() = default; + ~TofPidNewCollision() = default; + + o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + + template + using ResponseImplementation = o2::pid::tof::ExpTimes; + static constexpr auto responseEl = ResponseImplementation(); + static constexpr auto responseMu = ResponseImplementation(); + static constexpr auto responsePi = ResponseImplementation(); + static constexpr auto responseKa = ResponseImplementation(); + static constexpr auto responsePr = ResponseImplementation(); + static constexpr auto responseDe = ResponseImplementation(); + static constexpr auto responseTr = ResponseImplementation(); + static constexpr auto responseHe = ResponseImplementation(); + static constexpr auto responseAl = ResponseImplementation(); + + void SetParams(o2::pid::tof::TOFResoParamsV2 const& para) + { + mRespParamsV2.setParameters(para); + } + + float GetTOFNSigma(o2::track::PID::ID pidId, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D = true) + { + float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; + float expTime = track.length() * sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v + + float evTime = correctedcol.evTime(); + float evTimeErr = correctedcol.evTimeErr(); + float tofsignal = track.trackTime() * 1000 + expTime; // in ps + float expSigma, tofNsigma; + + if (originalcol.globalIndex() == correctedcol.globalIndex()) { + evTime = track.evTimeForTrack(); + evTimeErr = track.evTimeErrForTrack(); + } else { + if (EnableBCAO2D) { + auto originalbc = originalcol.template bc_as(); + auto correctedbc = correctedcol.template bc_as(); + o2::InteractionRecord originalIR = o2::InteractionRecord::long2IR(originalbc.globalBC()); + o2::InteractionRecord correctedIR = o2::InteractionRecord::long2IR(correctedbc.globalBC()); + tofsignal += originalIR.differenceInBCNS(correctedIR) * 1000; + } else { + auto originalbc = originalcol.template foundBC_as(); + auto correctedbc = correctedcol.template foundBC_as(); + o2::InteractionRecord originalIR = o2::InteractionRecord::long2IR(originalbc.globalBC()); + o2::InteractionRecord correctedIR = o2::InteractionRecord::long2IR(correctedbc.globalBC()); + tofsignal += originalIR.differenceInBCNS(correctedIR) * 1000; + } + } + + switch (pidId) { + case 0: + expSigma = responseEl.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseEl.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 1: + expSigma = responseMu.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseMu.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 2: + expSigma = responsePi.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responsePi.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 3: + expSigma = responseKa.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseKa.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 4: + expSigma = responsePr.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responsePr.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 5: + expSigma = responseDe.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 6: + expSigma = responseTr.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseTr.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 7: + expSigma = responseHe.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseHe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + case 8: + expSigma = responseAl.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseAl.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + break; + default: + LOG(fatal) << "Wrong particle ID in TofPidSecondary class"; + return -999; + } + + return tofNsigma; + } +}; + +} // namespace pidtofgeneric +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_PIDTOFGENERIC_H_ diff --git a/PWGLF/DataModel/spectraTOF.h b/PWGLF/DataModel/spectraTOF.h index bffc12d3a88..00b9e60ee26 100644 --- a/PWGLF/DataModel/spectraTOF.h +++ b/PWGLF/DataModel/spectraTOF.h @@ -40,14 +40,9 @@ #include "TPDGCode.h" -using namespace o2; -using namespace o2::track; -using namespace o2::framework; -using namespace o2::framework::expressions; - -static constexpr PID::ID Np = 9; +static constexpr o2::track::PID::ID Np = 9; static constexpr int NCharges = 2; -static constexpr PID::ID NpCharge = Np * NCharges; +static constexpr o2::track::PID::ID NpCharge = Np * NCharges; static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "{}^{3}He", "#alpha"}; static constexpr const char* pN[Np] = {"el", "mu", "pi", "ka", "pr", "de", "tr", "he", "al"}; static constexpr const char* cN[NCharges] = {"pos", "neg"}; diff --git a/PWGLF/DataModel/v0qaanalysis.h b/PWGLF/DataModel/v0qaanalysis.h index 3d1b51a5bea..05c90791bde 100644 --- a/PWGLF/DataModel/v0qaanalysis.h +++ b/PWGLF/DataModel/v0qaanalysis.h @@ -16,10 +16,6 @@ #ifndef PWGLF_DATAMODEL_V0QAANALYSIS_H_ #define PWGLF_DATAMODEL_V0QAANALYSIS_H_ -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - namespace o2::aod { diff --git a/PWGLF/TableProducer/Common/CMakeLists.txt b/PWGLF/TableProducer/Common/CMakeLists.txt index a3c26273a81..e68b511978d 100644 --- a/PWGLF/TableProducer/Common/CMakeLists.txt +++ b/PWGLF/TableProducer/Common/CMakeLists.txt @@ -15,6 +15,11 @@ o2physics_add_dpl_workflow(epvector PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(spvector + SOURCES spvector.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tpcpid SOURCES lfTPCPID.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -28,4 +33,4 @@ o2physics_add_dpl_workflow(zdcsp o2physics_add_dpl_workflow(mc-centrality SOURCES mcCentrality.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Common/epvector.cxx b/PWGLF/TableProducer/Common/epvector.cxx index 25823ef6edd..f5c2aad66b9 100644 --- a/PWGLF/TableProducer/Common/epvector.cxx +++ b/PWGLF/TableProducer/Common/epvector.cxx @@ -108,6 +108,8 @@ struct epvector { void init(o2::framework::InitContext&) { + std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; + const AxisSpec centAxis{configAxisCentrality, "V0M (%)"}; // AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec multiplicity = {5000, -500, 500, "TPC Multiplicity"}; @@ -117,9 +119,12 @@ struct epvector { AxisSpec qyFT0Axis = {80000, -10000.0, 10000.0, "Qy"}; AxisSpec phiAxis = {500, -6.28, 6.28, "phi"}; AxisSpec vzAxis = {400, -20, 20, "vz"}; - AxisSpec resAxis = {400, -2, 2, "vz"}; + AxisSpec resAxis = {200, -2, 2, "Resv2"}; + AxisSpec resAxisSP = {800, -80, 80, "ResSP"}; + AxisSpec qAxis = {100, 0, 10, "Q axis"}; AxisSpec shiftAxis = {10, 0, 10, "shift"}; AxisSpec basisAxis = {2, 0, 2, "basis"}; + AxisSpec occupancyAxis = {occupancyBinning, "occupancy"}; histos.add("hCentrality", "hCentrality", kTH1F, {{8, 0, 80.0}}); histos.add("Vz", "Vz", kTH1F, {{400, -20.0, 20.0}}); @@ -139,9 +144,26 @@ struct epvector { histos.add("QxTPCR", "QxTPCR", kTH2F, {centAxis, multiplicity}); histos.add("QyTPCR", "QyTPCR", kTH2F, {centAxis, multiplicity}); histos.add("PsiTPCR", "PsiTPCR", kTH2F, {centAxis, phiAxis}); - histos.add("ResFT0CTPC", "ResFT0CTPC", kTH2F, {centAxis, resAxis}); - histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH2F, {centAxis, resAxis}); - histos.add("ResFT0ATPC", "ResFT0ATPC", kTH2F, {centAxis, resAxis}); + + histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH3F, {centAxis, resAxis, occupancyAxis}); + histos.add("ResFT0CTPC", "ResFT0CTPC", kTH3F, {centAxis, resAxis, occupancyAxis}); + histos.add("ResFT0ATPC", "ResFT0ATPC", kTH3F, {centAxis, resAxis, occupancyAxis}); + histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH3F, {centAxis, resAxis, occupancyAxis}); + histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH3F, {centAxis, resAxis, occupancyAxis}); + histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH3F, {centAxis, resAxis, occupancyAxis}); + + histos.add("ResFT0CFT0ASP", "ResFT0CFT0ASP", kTH3F, {centAxis, resAxisSP, occupancyAxis}); + histos.add("ResFT0CTPCSP", "ResFT0CTPCSP", kTH3F, {centAxis, resAxisSP, occupancyAxis}); + histos.add("ResFT0ATPCSP", "ResFT0ATPCSP", kTH3F, {centAxis, resAxisSP, occupancyAxis}); + histos.add("ResFT0CTPCLSP", "ResFT0CTPCLSP", kTH3F, {centAxis, resAxisSP, occupancyAxis}); + histos.add("ResFT0CTPCRSP", "ResFT0CTPCRSP", kTH3F, {centAxis, resAxisSP, occupancyAxis}); + histos.add("ResTPCRTPCLSP", "ResTPCRTPCLSP", kTH3F, {centAxis, resAxisSP, occupancyAxis}); + + histos.add("QFT0C", "QFT0C", kTH3F, {centAxis, qAxis, occupancyAxis}); + histos.add("QFT0A", "QFT0A", kTH3F, {centAxis, qAxis, occupancyAxis}); + histos.add("QTPCL", "QTPCL", kTH3F, {centAxis, qAxis, occupancyAxis}); + histos.add("QTPCR", "QTPCR", kTH3F, {centAxis, qAxis, occupancyAxis}); + histos.add("QTPC", "QTPC", kTH3F, {centAxis, qAxis, occupancyAxis}); histos.add("ShiftFT0C", "ShiftFT0C", kTProfile3D, {centAxis, basisAxis, shiftAxis}); @@ -266,7 +288,7 @@ struct epvector { if (useGainCallib && (currentRunNumber != lastRunNumber)) { gainprofile = ccdb->getForTimeStamp(ConfGainPath.value, bc.timestamp()); } - + int occupancy = coll.trackOccupancyInTimeRange(); histos.fill(HIST("hCentrality"), centrality); histos.fill(HIST("Vz"), vz); @@ -302,7 +324,7 @@ struct epvector { } for (auto& trk : tracks) { - if (!selectionTrack(trk) || abs(trk.eta()) > 0.8 || trk.pt() > cfgCutPTMax || abs(trk.eta()) < cfgMinEta) { + if (!selectionTrack(trk) || TMath::Abs(trk.eta()) > 0.8 || trk.pt() > cfgCutPTMax || TMath::Abs(trk.eta()) < cfgMinEta) { continue; } qxTPC = qxTPC + trk.pt() * TMath::Cos(2.0 * trk.phi()); @@ -365,9 +387,31 @@ struct epvector { histos.fill(HIST("QyTPCR"), centrality, qyTPCR); histos.fill(HIST("PsiTPCR"), centrality, psiTPCR); - histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC))); - histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); - histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiTPC - psiFT0A))); + histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A)), occupancy); + histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC)), occupancy); + histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiFT0A - psiTPC)), occupancy); + histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCR)), occupancy); + histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(2.0 * (psiTPCR - psiTPCL)), occupancy); + + double qFT0Cmag = TMath::Sqrt(qxFT0C * qxFT0C + qyFT0C * qyFT0C); + double qFT0Amag = TMath::Sqrt(qxFT0A * qxFT0A + qyFT0A * qyFT0A); + double qTPCmag = TMath::Sqrt(qxTPC * qxTPC + qyTPC * qyTPC); + double qTPCLmag = TMath::Sqrt(qxTPCL * qxTPCL + qyTPCL * qyTPCL); + double qTPCRmag = TMath::Sqrt(qxTPCR * qxTPCR + qyTPCR * qyTPCR); + + histos.fill(HIST("QTPC"), centrality, qTPCmag, occupancy); + histos.fill(HIST("QTPCL"), centrality, qTPCLmag, occupancy); + histos.fill(HIST("QTPCR"), centrality, qTPCRmag, occupancy); + histos.fill(HIST("QFT0C"), centrality, qFT0Cmag, occupancy); + histos.fill(HIST("QFT0A"), centrality, qFT0Amag, occupancy); + + histos.fill(HIST("ResFT0CFT0ASP"), centrality, qFT0Cmag * qFT0Amag * TMath::Cos(2.0 * (psiFT0C - psiFT0A)), occupancy); + histos.fill(HIST("ResFT0CTPCSP"), centrality, qFT0Cmag * qTPCmag * TMath::Cos(2.0 * (psiFT0C - psiTPC)), occupancy); + histos.fill(HIST("ResFT0ATPCSP"), centrality, qFT0Amag * qTPCmag * TMath::Cos(2.0 * (psiFT0A - psiTPC)), occupancy); + histos.fill(HIST("ResFT0CTPCLSP"), centrality, qFT0Cmag * qTPCLmag * TMath::Cos(2.0 * (psiFT0C - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CTPCRSP"), centrality, qFT0Cmag * qTPCRmag * TMath::Cos(2.0 * (psiFT0C - psiTPCR)), occupancy); + histos.fill(HIST("ResTPCRTPCLSP"), centrality, qTPCRmag * qTPCLmag * TMath::Cos(2.0 * (psiTPCR - psiTPCL)), occupancy); for (int ishift = 1; ishift <= 10; ishift++) { histos.fill(HIST("ShiftFT0C"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiFT0C)); diff --git a/PWGLF/TableProducer/Common/spvector.cxx b/PWGLF/TableProducer/Common/spvector.cxx new file mode 100644 index 00000000000..413ab46e35a --- /dev/null +++ b/PWGLF/TableProducer/Common/spvector.cxx @@ -0,0 +1,476 @@ +// Copyright 2019-2020 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. +// +// \author: prottay das 07/09/2024 +// \email: prottay.das@cern.ch + +// C++/ROOT includes. +#include +#include +#include +#include +#include +#include +#include +#include +#include "Math/Vector4D.h" +#include "TRandom3.h" +#include "TF1.h" + +// o2Physics includes. +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "FT0Base/Geometry.h" +#include "FV0Base/Geometry.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" +#include "Common/Core/EventPlaneHelper.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +// o2 includes. +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "DetectorsCommonDataFormats/AlignParam.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +using BCsRun3 = soa::Join; + +struct spvector { + + Produces spcalibrationtable; + + // Configurables. + struct : ConfigurableGroup { + Configurable cfgURL{"cfgURL", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; + } cfgCcdbParam; + + // Enable access to the CCDB for the offset and correction constants and save them in dedicated variables. + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Centrality cut"}; + Configurable cfgCutPT{"cfgCutPT", 0.15, "PT cut on daughter track"}; + Configurable cfgCutPTMax{"cfgCutPTMax", 3.0, "Max PT cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + Configurable cfgMinEta{"cfgMinEta", 0.1, "Min Eta cut on daughter track"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; + + Configurable QxyNbins{"QxyNbins", 100, "Number of bins in QxQy histograms"}; + Configurable lbinQxy{"lbinQxy", -5.0, "lower bin value in QxQy histograms"}; + Configurable hbinQxy{"hbinQxy", 5.0, "higher bin value in QxQy histograms"}; + // Configurable ZDCgainNbins{"ZDCgainNbins", 500, "Number of bins in Gaineq histograms"}; + // Configurable lbinZDCgain{"lbinZDCgain", 0.0, "lower bin value in Gaineq histograms"}; + // Configurable hbinZDCgain{"hbinZDCgain", 1000.0, "higher bin value in Gaineq histograms"}; + Configurable VxNbins{"VxNbins", 25, "Number of bins in Vx histograms"}; + Configurable lbinVx{"lbinVx", -0.05, "lower bin value in Vx histograms"}; + Configurable hbinVx{"hbinVx", 0.0, "higher bin value in Vx histograms"}; + Configurable VyNbins{"VyNbins", 25, "Number of bins in Vy histograms"}; + Configurable lbinVy{"lbinVy", -0.02, "lower bin value in Vy histograms"}; + Configurable hbinVy{"hbinVy", 0.02, "higher bin value in Vy histograms"}; + Configurable CentNbins{"CentNbins", 16, "Number of bins in cent histograms"}; + Configurable lbinCent{"lbinCent", 0.0, "lower bin value in cent histograms"}; + Configurable hbinCent{"hbinCent", 80.0, "higher bin value in cent histograms"}; + Configurable QA{"QA", false, "QA histograms"}; + Configurable tablewrite{"tablewrite", false, "Boolean for writing table"}; + Configurable useGainCallib{"useGainCallib", false, "use gain calibration"}; + // Configurable useRecentere{"useRecentere", false, "use Recentering"}; + Configurable useRecentereSp{"useRecentereSp", false, "use Recentering with Sparse"}; + // Configurable useRecentereVxy{"useRecentereVxy", false, "use Recentering for Vxy"}; + Configurable recwitherror{"recwitherror", false, "use Recentering with error"}; + // Configurable useShift{"useShift", false, "use Shift"}; + Configurable ConfGainPath{"ConfGainPath", "Users/p/prottay/My/Object/NewPbPbpass4_10092024/gaincallib", "Path to gain calibration"}; + // Configurable ConfRecentere{"ConfRecentere", "Users/p/prottay/My/Object/NewPbPbpass4_23082024/recenter", "Path for recentere"}; + Configurable ConfRecentereSp{"ConfRecentereSp", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse Path for recentere"}; + /* + Configurable ConfRecentereVxyQxA{"ConfRecentereVxyQxA", "Users/p/prottay/My/Object/NewPbPbpass4_23082024/recenter", "Path for recentereVxyQxA"}; + Configurable ConfRecentereVxyQyA{"ConfRecentereVxyQyA", "Users/p/prottay/My/Object/NewPbPbpass4_23082024/recenter", "Path for recentereVxyQyA"}; + Configurable ConfRecentereVxyQxC{"ConfRecentereVxyQxC", "Users/p/prottay/My/Object/NewPbPbpass4_23082024/recenter", "Path for recentereVxyQxC"}; + Configurable ConfRecentereVxyQyC{"ConfRecentereVxyQyC", "Users/p/prottay/My/Object/NewPbPbpass4_23082024/recenter", "Path for recentereVxyQyC"}; + Configurable ConfShift{"ConfShift", "Users/p/prottay/My/Object/Finaltest2/recenereall", "Path for Shift"}; + */ + // ConfigurableAxis configAxisCentrality{"configAxisCentrality", {16, 0.0, 80}, "centrality bining"}; + + // Event selection cuts - Alex + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fMultMultPVCut = nullptr; + + int mRunNumber{-1}; + + template + bool eventSelected(TCollision collision, const float& centrality) + { + auto multNTracksPV = collision.multNTracksPV(); + if (multNTracksPV < fMultPVCutLow->Eval(centrality)) + return 0; + if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) + return 0; + + return 1; + } + + void initCCDB(BCsRun3::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + } + + void init(o2::framework::InitContext&) + { + + // const AxisSpec centAxis{configAxisCentrality, "V0M (%)"}; + // AxisSpec amplitudeZDC = {configAxisZDCgain, "ZDC amplitude"}; + // AxisSpec amplitudeZDC = {ZDCgainNbins, lbinZDCgain, hbinZDCgain, "ZDC amplitude"}; + AxisSpec channelZDCAxis = {8, 0.0, 8.0, "ZDC tower"}; + AxisSpec qxZDCAxis = {QxyNbins, lbinQxy, hbinQxy, "Qx"}; + AxisSpec qyZDCAxis = {QxyNbins, lbinQxy, hbinQxy, "Qy"}; + AxisSpec phiAxis = {50, -6.28, 6.28, "phi"}; + AxisSpec vzAxis = {20, -10, 10, "vz"}; + AxisSpec vxAxis = {VxNbins, lbinVx, hbinVx, "vx"}; + AxisSpec vyAxis = {VyNbins, lbinVy, hbinVy, "vy"}; + AxisSpec centAxis = {CentNbins, lbinCent, hbinCent, "V0M (%)"}; + + histos.add("hCentrality", "hCentrality", kTH1F, {{centAxis}}); + histos.add("hpQxZDCAC", "hpQxZDCAC", kTProfile, {centAxis}); + histos.add("hpQyZDCAC", "hpQyZDCAC", kTProfile, {centAxis}); + histos.add("hpQxZDCAQyZDCC", "hpQxZDCAQyZDCC", kTProfile, {centAxis}); + histos.add("hpQxZDCCQyZDCA", "hpQxZDCCQyZDCA", kTProfile, {centAxis}); + /*histos.add("QxZDCC", "QxZDCC", kTHnSparseF, {{16,0.0,80.0}, {25,-0.05,0.0}, {25,-0.02,0.02}, {20,-10.0,10.0}, {qxZDCAxis}}); + histos.add("QyZDCC", "QyZDCC", kTHnSparseF, {{16,0.0,80.0}, {25,-0.05,0.0}, {25,-0.02,0.02}, {20,-10.0,10.0}, {qyZDCAxis}}); + histos.add("QxZDCA", "QxZDCA", kTHnSparseF, {{16,0.0,80.0}, {25,-0.05,0.0}, {25,-0.02,0.02}, {20,-10.0,10.0}, {qxZDCAxis}}); + histos.add("QyZDCA", "QyZDCA", kTHnSparseF, {{16,0.0,80.0}, {25,-0.05,0.0}, {25,-0.02,0.02}, {20,-10.0,10.0}, {qxZDCAxis}});*/ + histos.add("hsQxyZDCAC", "hsyQxyZDCAC", kTHnSparseF, {{centAxis}, {vxAxis}, {vyAxis}, {vzAxis}, {4, 0, 4}}); + /*histos.add("hpQxVZDCC", "hpQxVZDCC", kTProfile3D, {centAxis, vxAxis, vyAxis}); + histos.add("hpQyVZDCC", "hpQyVZDCC", kTProfile3D, {centAxis, vxAxis, vyAxis}); + histos.add("hpQxVZDCA", "hpQxVZDCA", kTProfile3D, {centAxis, vxAxis, vyAxis}); + histos.add("hpQyVZDCA", "hpQyVZDCA", kTProfile3D, {centAxis, vxAxis, vyAxis});*/ + histos.add("PsiZDCC", "PsiZDCC", kTH2F, {centAxis, phiAxis}); + histos.add("PsiZDCA", "PsiZDCA", kTH2F, {centAxis, phiAxis}); + histos.add("ZDCAmp", "ZDCAmp", kTProfile2D, {channelZDCAxis, vzAxis}); + + if (QA) { + histos.add("Vz", "Vz", kTH1F, {vzAxis}); + histos.add("hpCosPsiAPsiC", "hpCosPsiAPsiC", kTProfile, {centAxis}); + histos.add("hpSinPsiAPsiC", "hpSinPsiAPsiC", kTProfile, {centAxis}); + } + // histos.add("hZDCAmp", "hZDCAmp", kTH3F, {channelZDCAxis, vzAxis, amplitudeZDC}); + + // Event selection cut additional - Alex + fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + fMultPVCutLow->SetParameters(2834.66, -87.0127, 0.915126, -0.00330136, 332.513, -12.3476, 0.251663, -0.00272819, 1.12242e-05); + fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + fMultPVCutHigh->SetParameters(2834.66, -87.0127, 0.915126, -0.00330136, 332.513, -12.3476, 0.251663, -0.00272819, 1.12242e-05); + fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x)", 0, 100); + fMultCutLow->SetParameters(1893.94, -53.86, 0.502913, -0.0015122, 109.625, -1.19253); + fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 3.*([4]+[5]*x)", 0, 100); + fMultCutHigh->SetParameters(1893.94, -53.86, 0.502913, -0.0015122, 109.625, -1.19253); + fMultMultPVCut = new TF1("fMultMultPVCut", "[0]+[1]*x+[2]*x*x", 0, 5000); + fMultMultPVCut->SetParameters(-0.1, 0.785, -4.7e-05); + + ccdb->setURL(cfgCcdbParam.cfgURL); + ccdbApi.init("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } + + int currentRunNumber = -999; + int lastRunNumber = -999; + TH2D* gainprofile; + // TH3D* hrecentere; + THnSparseF* hrecentereSp; + /* + TH3D* hrecentereVxyQxA; + TH3D* hrecentereVxyQyA; + TH3D* hrecentereVxyQxC; + TH3D* hrecentereVxyQyC; + */ + + // Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); + // Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + + using MyCollisions = soa::Join; + // using MyTracks = soa::Filtered>; + + Preslice zdcPerCollision = aod::collision::bcId; + + // void process(MyCollisions::iterator const& collision, aod::FT0s const& /*ft0s*/, BCsRun3 const& bcs, aod::Zdcs const&, MyTracks const&) + void process(MyCollisions::iterator const& collision, aod::FT0s const& /*ft0s*/, BCsRun3 const& bcs, aod::Zdcs const&) + { + + auto centrality = collision.centFT0C(); + + if (bcs.size() != 0) { + gRandom->SetSeed(bcs.iteratorAt(0).globalBC()); + } + + auto bc = collision.foundBC_as(); + if (!bc.has_zdc()) { + return; + } + + currentRunNumber = collision.foundBC_as().runNumber(); + auto vz = collision.posZ(); + auto vx = collision.posX(); + auto vy = collision.posY(); + bool triggerevent = false; + + float psiZDCC = -99; + float psiZDCA = -99; + auto qxZDCA = 0.0; + auto qxZDCC = 0.0; + auto qyZDCA = 0.0; + auto qyZDCC = 0.0; + auto sumA = 0.0; + auto sumC = 0.0; + + auto zdc = bc.zdc(); + auto zncEnergy = zdc.energySectorZNC(); + auto znaEnergy = zdc.energySectorZNA(); + + if (znaEnergy[0] < 0.0 || znaEnergy[1] < 0.0 || znaEnergy[2] < 0.0 || znaEnergy[3] < 0.0) + return; + if (zncEnergy[0] < 0.0 || zncEnergy[1] < 0.0 || zncEnergy[2] < 0.0 || zncEnergy[3] < 0.0) + return; + + if (collision.sel8() && centrality < cfgCutCentrality && TMath::Abs(vz) < cfgCutVertex && collision.has_foundFT0() && eventSelected(collision, centrality) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + triggerevent = true; + if (useGainCallib && (currentRunNumber != lastRunNumber)) { + gainprofile = ccdb->getForTimeStamp(ConfGainPath.value, bc.timestamp()); + } + + histos.fill(HIST("hCentrality"), centrality); + if (QA) { + histos.fill(HIST("Vz"), vz); + } + + initCCDB(bc); + + auto gainequal = 1.0; + constexpr float x[4] = {-1.75, 1.75, -1.75, 1.75}; + constexpr float y[4] = {-1.75, -1.75, 1.75, 1.75}; + + for (std::size_t iChA = 0; iChA < 8; iChA++) { + auto chanelid = iChA; + if (useGainCallib && gainprofile) { + gainequal = gainprofile->GetBinContent(gainprofile->FindBin(vz, chanelid + 0.5)); + } + + if (iChA < 4) { + + if (znaEnergy[iChA] <= 0.0) { + return; + } else { + float ampl = gainequal * znaEnergy[iChA]; + qxZDCA = qxZDCA + ampl * x[iChA]; + qyZDCA = qyZDCA + ampl * y[iChA]; + sumA = sumA + ampl; + histos.fill(HIST("ZDCAmp"), chanelid + 0.5, vz, ampl); + // histos.fill(HIST("hZDCAmp"), chanelid + 0.5, vz, ampl); + } + } else { + + if (zncEnergy[iChA - 4] <= 0.0) { + return; + } else { + float ampl = gainequal * zncEnergy[iChA - 4]; + qxZDCC = qxZDCC + ampl * x[iChA - 4]; + qyZDCC = qyZDCC + ampl * y[iChA - 4]; + sumC = sumC + ampl; + histos.fill(HIST("ZDCAmp"), chanelid + 0.5, vz, ampl); + // histos.fill(HIST("hZDCAmp"), chanelid + 0.5, vz, ampl); + } + } + } + + if (sumA > 0) { + qxZDCA = qxZDCA / sumA; + qyZDCA = qyZDCA / sumA; + } + if (sumC > 0) { + qxZDCC = qxZDCC / sumC; + qyZDCC = qyZDCC / sumC; + } + + if (sumA <= 1e-4 || sumC <= 1e-4) { + qxZDCA = 0.0; + qxZDCC = 0.0; + qyZDCA = 0.0; + qyZDCC = 0.0; + return; + } + + if (useRecentereSp && (currentRunNumber != lastRunNumber)) { + hrecentereSp = ccdb->getForTimeStamp>(ConfRecentereSp.value, bc.timestamp()); + } + + if (useRecentereSp && hrecentereSp) { + + int binCoords[5]; + + // Get axes of the THnSparse + TAxis* centralityAxis = hrecentereSp->GetAxis(0); // Axis 0: centrality + TAxis* vxAxis = hrecentereSp->GetAxis(1); // Axis 1: vx + TAxis* vyAxis = hrecentereSp->GetAxis(2); // Axis 2: vy + TAxis* vzAxis = hrecentereSp->GetAxis(3); // Axis 3: vz + TAxis* channelAxis = hrecentereSp->GetAxis(4); // Axis 4: channel + + // Find bin indices for centrality, vx, vy, vz, and channel (for meanxA, 0.5) + binCoords[0] = centralityAxis->FindBin(centrality); // Centrality + binCoords[1] = vxAxis->FindBin(vx); // vx + binCoords[2] = vyAxis->FindBin(vy); // vy + binCoords[3] = vzAxis->FindBin(vz); // vz + binCoords[4] = channelAxis->FindBin(0.5); // Channel for meanxA + + // Get the global bin for meanxA + int globalBinMeanxA = hrecentereSp->GetBin(binCoords); + float meanxA = hrecentereSp->GetBinContent(globalBinMeanxA); + + // Repeat for other channels (meanyA, meanxC, meanyC) + binCoords[4] = channelAxis->FindBin(1.5); // Channel for meanyA + int globalBinMeanyA = hrecentereSp->GetBin(binCoords); + float meanyA = hrecentereSp->GetBinContent(globalBinMeanyA); + + binCoords[4] = channelAxis->FindBin(2.5); // Channel for meanxC + int globalBinMeanxC = hrecentereSp->GetBin(binCoords); + float meanxC = hrecentereSp->GetBinContent(globalBinMeanxC); + + binCoords[4] = channelAxis->FindBin(3.5); // Channel for meanyC + int globalBinMeanyC = hrecentereSp->GetBin(binCoords); + float meanyC = hrecentereSp->GetBinContent(globalBinMeanyC); + + qxZDCA = qxZDCA - meanxA; + qyZDCA = qyZDCA - meanyA; + qxZDCC = qxZDCC - meanxC; + qyZDCC = qyZDCC - meanyC; + } + + /* + if (useRecentere && (currentRunNumber != lastRunNumber)) { + hrecentere = ccdb->getForTimeStamp(ConfRecentere.value, bc.timestamp()); + } + + if (useRecentere && hrecentere) { + if (recwitherror) { + qxZDCA = (qxZDCA - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 0.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, vz, 0.5)); + qyZDCA = (qyZDCA - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 1.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, vz, 1.5)); + qxZDCC = (qxZDCC - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 2.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, vz, 2.5)); + qyZDCC = (qyZDCC - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 3.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, vz, 3.5)); + } else { + + qxZDCA = (qxZDCA - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 0.5))); + qyZDCA = (qyZDCA - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 1.5))); + qxZDCC = (qxZDCC - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 2.5))); + qyZDCC = (qyZDCC - hrecentere->GetBinContent(hrecentere->FindBin(centrality, vz, 3.5))); + } + } + + + if (useRecentereVxy && (currentRunNumber != lastRunNumber)) { + hrecentereVxyQxA = ccdb->getForTimeStamp(ConfRecentereVxyQxA.value, bc.timestamp()); + hrecentereVxyQyA = ccdb->getForTimeStamp(ConfRecentereVxyQyA.value, bc.timestamp()); + hrecentereVxyQxC = ccdb->getForTimeStamp(ConfRecentereVxyQxC.value, bc.timestamp()); + hrecentereVxyQyC = ccdb->getForTimeStamp(ConfRecentereVxyQyC.value, bc.timestamp()); + } + + if (useRecentereVxy && hrecentereVxyQxA && hrecentereVxyQyA && hrecentereVxyQxC && hrecentereVxyQyC) { + if (recwitherror) { + qxZDCA = (qxZDCA - hrecentereVxyQxA->GetBinContent(hrecentereVxyQxA->FindBin(centrality, vx, vy))) / hrecentereVxyQxA->GetBinError(hrecentereVxyQxA->FindBin(centrality, vx, vy)); + qyZDCA = (qyZDCA - hrecentereVxyQyA->GetBinContent(hrecentereVxyQyA->FindBin(centrality, vx, vy))) / hrecentereVxyQyA->GetBinError(hrecentereVxyQyA->FindBin(centrality, vx, vy)); + qxZDCC = (qxZDCC - hrecentereVxyQxC->GetBinContent(hrecentereVxyQxC->FindBin(centrality, vx, vy))) / hrecentereVxyQxC->GetBinError(hrecentereVxyQxC->FindBin(centrality, vx, vy)); + qyZDCC = (qyZDCC - hrecentereVxyQyC->GetBinContent(hrecentereVxyQyC->FindBin(centrality, vx, vy))) / hrecentereVxyQyC->GetBinError(hrecentereVxyQyC->FindBin(centrality, vx, vy)); + } else { + + qxZDCA = (qxZDCA - hrecentereVxyQxA->GetBinContent(hrecentereVxyQxA->FindBin(centrality, vx, vy))); + qyZDCA = (qyZDCA - hrecentereVxyQyA->GetBinContent(hrecentereVxyQyA->FindBin(centrality, vx, vy))); + qxZDCC = (qxZDCC - hrecentereVxyQxC->GetBinContent(hrecentereVxyQxC->FindBin(centrality, vx, vy))); + qyZDCC = (qyZDCC - hrecentereVxyQyC->GetBinContent(hrecentereVxyQyC->FindBin(centrality, vx, vy))); + } + } + + */ + + psiZDCC = 1.0 * TMath::ATan2(qyZDCC, qxZDCC); + psiZDCA = 1.0 * TMath::ATan2(qyZDCA, qxZDCA); + + histos.fill(HIST("hpQxZDCAC"), centrality, (qxZDCA * qxZDCC)); + histos.fill(HIST("hpQyZDCAC"), centrality, (qyZDCA * qyZDCC)); + histos.fill(HIST("hpQxZDCAQyZDCC"), centrality, (qxZDCA * qyZDCC)); + histos.fill(HIST("hpQxZDCCQyZDCA"), centrality, (qxZDCC * qyZDCA)); + /* + histos.fill(HIST("QxZDCC"), centrality, vx, vy, vz, qxZDCC); + histos.fill(HIST("QyZDCC"), centrality, vx, vy, vz, qyZDCC); + histos.fill(HIST("QxZDCA"), centrality, vx, vy, vz, qxZDCA); + histos.fill(HIST("QyZDCA"), centrality, vx, vy, vz, qyZDCA);*/ + + histos.fill(HIST("hsQxyZDCAC"), centrality, vx, vy, vz, 0.5, qxZDCA); + histos.fill(HIST("hsQxyZDCAC"), centrality, vx, vy, vz, 1.5, qyZDCA); + histos.fill(HIST("hsQxyZDCAC"), centrality, vx, vy, vz, 2.5, qxZDCC); + histos.fill(HIST("hsQxyZDCAC"), centrality, vx, vy, vz, 3.5, qyZDCC); + /* + histos.fill(HIST("hpQxVZDCC"), centrality, vx, vy, qxZDCC); + histos.fill(HIST("hpQyVZDCC"), centrality, vx, vy, qyZDCC); + histos.fill(HIST("hpQxVZDCA"), centrality, vx, vy, qxZDCA); + histos.fill(HIST("hpQyVZDCA"), centrality, vx, vy, qyZDCA);*/ + if (QA) { + histos.fill(HIST("hpCosPsiAPsiC"), centrality, (TMath::Cos(psiZDCA - psiZDCC))); + histos.fill(HIST("hpSinPsiAPsiC"), centrality, (TMath::Sin(psiZDCA - psiZDCC))); + } + histos.fill(HIST("PsiZDCA"), centrality, psiZDCA); + histos.fill(HIST("PsiZDCC"), centrality, psiZDCC); + + lastRunNumber = currentRunNumber; + } + + if (tablewrite) { + spcalibrationtable(triggerevent, lastRunNumber, centrality, vz, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qyZDCA, qxZDCC, qyZDCC, psiZDCC, psiZDCA); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Nuspex/CMakeLists.txt b/PWGLF/TableProducer/Nuspex/CMakeLists.txt index af846903610..5f9f4380def 100644 --- a/PWGLF/TableProducer/Nuspex/CMakeLists.txt +++ b/PWGLF/TableProducer/Nuspex/CMakeLists.txt @@ -26,7 +26,7 @@ o2physics_add_dpl_workflow(hyper-kink-reco-task o2physics_add_dpl_workflow(hypertriton-reco-task SOURCES hyperRecoTask.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lnn-reco-task @@ -46,7 +46,7 @@ o2physics_add_dpl_workflow(nucleustreecreator o2physics_add_dpl_workflow(lithium4analysis SOURCES lithium4analysis.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(nuclei-spectra @@ -73,3 +73,13 @@ o2physics_add_dpl_workflow(ebye-maker SOURCES ebyeMaker.cxx PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(cluster-studies-tree-creator + SOURCES LFTreeCreatorClusterStudies.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pidtof-generic + SOURCES pidTOFGeneric.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFBase + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx b/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx new file mode 100644 index 00000000000..676572e035d --- /dev/null +++ b/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx @@ -0,0 +1,1331 @@ +// Copyright 2019-2020 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. +// +// TableProducer to generate Trees for pure protons ans pions (from Lambda), Kaons (from Omegas), deuterons (identified with TOF) and He3 (identified with TPC). +// The output trees contain the ITS cluster size information. +// +// Author: Giorgio Alberto Lucia + +#include +#include +#include +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/DataModel/PIDResponse.h" +#include "DCAFitter/DCAFitterN.h" + +#include "PWGLF/DataModel/LFClusterStudiesTable.h" + +#include "TDatabasePDG.h" +#include "TPDGCode.h" + +using namespace ::o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using Track = o2::track::TrackParCov; +using TracksFullIU = soa::Join; +using TracksFullIUMc = soa::Join; +using CollisionsCustom = soa::Join; + +namespace BetheBloch +{ + +constexpr double defaultParams[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +static const std::vector parNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; + +} // namespace BetheBloch + +enum V0Type : uint8_t { + K0s = 0, + Lambda, + AntiLambda, + Photon, + V0TypeAll +}; + +enum CascadeType : uint8_t { + XiMinus = 0, + OmegaMinus +}; + +enum Selections { + kNoCut = 0, + kSel8, + kVtxZ, + kAll +}; + +enum V0Selections { + kV0NoCut = 0, + kV0DaughterQuality, + kV0DaughterDCA, + // kV0DCA, + kV0Radius, + kV0CosPA, + kV0PID, + kV0DaughterDCAtoPV, + kV0All +}; + +enum CascSelections { + kCascNoCut = 0, + kCascDCA, + kCascCosPA, + kAcceptedOmega, + kRejectedXi, + kNSigmaTPC, + kCascAll +}; + +enum DeSelections { + kDeNoCut = 0, + kDeNClsIts, + kDePIDtpc, + kDePIDtof, + kDeAll +}; + +enum He3Selections { + kHe3NoCut = 0, + kHe3NClsIts, + kHe3PIDtpc, + kHe3PIDtof, + kHe3All +}; + +enum PartID { + none = 0, + el, + pi, + ka, + pr, + de, + he +}; + +struct LfTreeCreatorClusterStudies { + + Service m_ccdb; + int m_runNumber; + int m_collisionCounter = 0; + float m_d_bz; + uint32_t m_randomSeed = 0.; + + Configurable setting_fillV0{"fillV0", true, "Fill the V0 tree"}; + Configurable setting_fillK{"fillK", true, "Fill the K tree"}; + Configurable setting_fillDe{"fillDe", true, "Fill the De tree"}; + Configurable setting_fillHe3{"fillHe3", true, "Fill the He3 tree"}; + Configurable setting_fillPKPi{"fillPKPPi", true, "Fill the p, K, pi tree"}; + Configurable setting_smallTable{"smallTable", true, "Use a small table for testing"}; + + Configurable setting_materialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; + + Configurable setting_zVtxMax{"zVtxMax", 10.f, "Maximum z vertex position"}; + + Configurable setting_downscaleFactor{"downscaleFactor", 1.f, "Downscale factor for the V0 candidates"}; + Configurable setting_applyAdditionalEvSel{"applyAdditionalEvSel", false, "Apply additional event selection"}; + + Configurable track_nClsItsMin{"track_NclsItsMin", 0.f, "Minimum number of ITS clusters for the V0 daughters"}; + Configurable track_nClsTpcMin{"track_NclsTpcMin", 100.f, "Minimum number of TPC clusters for the V0 daughters"}; + Configurable track_nClsTpcMaxShared{"track_NclsTpcMaxShared", 5.f, "Maximum number of shared TPC clusters for the V0 daughters"}; + + // Configurable v0setting_etaMaxV0{"etaMaxV0", 0.8f, "Maximum eta for the V0 daughters"}; + Configurable v0setting_etaMaxV0dau{"etaMaxV0dau", 0.8f, "Maximum eta for the V0 daughters"}; + Configurable v0setting_dcaV0daughters{"v0setting_dcaV0daughters", 0.5f, "DCA between the V0 daughters"}; + Configurable v0setting_dcaV0toPV{"v0setting_dcaV0fromPV", 1.f, "DCA of the V0 to the primary vertex"}; + Configurable v0setting_dcaDaughtersToPV{"v0setting_dcaDaughtersToPV", 1.f, "DCA of the daughters to the primary vertex"}; + Configurable v0setting_radiusMax{"v0setting_radiusMax", 100.f, "Maximum radius of the V0 accepted"}; + Configurable v0setting_radiusMin{"v0setting_radiusMin", 5.f, "Minimum radius of the V0 accepted"}; + Configurable v0setting_cosPA{"v0setting_cosPA", 0.99f, "Cosine of the pointing angle of the V0"}; + Configurable v0setting_nsigmatpc{"v0setting_nsigmaTPC", 4.f, "Number of sigmas for the TPC PID"}; + Configurable v0setting_massWindowLambda{"v0setting_massWindowLambda", 0.02f, "Mass window for the Lambda"}; + Configurable v0setting_massWindowK0s{"v0setting_massWindowK0s", 0.02f, "Mass window for the K0s"}; + Configurable v0setting_nsigmatpcEl{"v0setting_nsigmaTPCEl", 1.f, "Number of sigmas for the TPC PID for electrons"}; + Configurable v0setting_nsigmatpcPi{"v0setting_nsigmaTPCPi", 2.f, "Number of sigmas for the TPC PID for pions"}; + Configurable v0setting_nsigmatpcPr{"v0setting_nsigmaTPCPr", 2.f, "Number of sigmas for the TPC PID for protons"}; + Configurable lambdasetting_qtAPcut{"lambdasetting_qtAPcut", 0.02f, "Cut on the qt for the Armenteros-Podolanski plot for photon rejection"}; + Configurable lambdasetting_pmin{"lambdasetting_pmin", 0.0f, "Minimum momentum for the V0 daughters"}; + + Configurable cascsetting_dcaCascDaughters{"casc_setting_dcaV0daughters", 0.1f, "DCA between the V0 daughters"}; + Configurable cascsetting_cosPA{"casc_setting_cosPA", 0.99f, "Cosine of the pointing angle of the V0"}; + Configurable cascsetting_massWindowOmega{"casc_setting_massWindowOmega", 0.01f, "Mass window for the Omega"}; + Configurable cascsetting_massWindowXi{"casc_setting_massWindowXi", 0.01f, "Mass window for the Xi"}; + Configurable cascsetting_nsigmatpc{"casc_setting_nsigmaTPC", 3.f, "Number of sigmas for the TPC PID"}; + + Configurable desetting_nClsIts{"desetting_nClsIts", 6, "Minimum number of ITS clusters"}; + Configurable desetting_nsigmatpc{"desetting_nsigmaCutTPC", 2.f, "Number of sigmas for the TPC PID"}; + Configurable desetting_nsigmatof{"desetting_nsigmaCutTOF", 2.f, "Number of sigmas for the TOF PID"}; + Configurable he3setting_nClsIts{"he3setting_nClsIts", 6, "Minimum number of ITS clusters"}; + Configurable he3setting_compensatePIDinTracking{"he3setting_compensatePIDinTracking", true, "Compensate PID in tracking"}; + Configurable he3setting_nsigmatpc{"he3setting_nsigmaCutTPC", 2.f, "Number of sigmas for the TPC PID"}; + Configurable he3setting_tofmasslow{"he3setting_tofmasslow", 1.8f, "Lower limit for the TOF mass"}; + Configurable he3setting_tofmasshigh{"he3setting_tofmasshigh", 4.2f, "Upper limit for the TOF mass"}; + + // Bethe Bloch parameters + std::array m_BBparamsDe, m_BBparamsHe; + Configurable> setting_BetheBlochParams{"setting_BetheBlochParams", {BetheBloch::defaultParams[0], 2, 6, {"De", "He3"}, BetheBloch::parNames}, "TPC Bethe-Bloch parameterisation for nuclei"}; + + Preslice m_perCollisionV0 = o2::aod::v0::collisionId; + Preslice m_perCollisionCascade = o2::aod::cascade::collisionId; + Preslice m_perCol = aod::track::collisionId; + Preslice m_perColMC = aod::track::collisionId; + + HistogramRegistry m_hAnalysis{ + "LFTreeCreator", + {{"collision_selections", "Collision selection; selection; counts", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, + {"v0_selections", "V0 selection; selection; counts", {HistType::kTH1F, {{V0Selections::kV0All, -0.5, static_cast(V0Selections::kV0All) - 0.5}}}}, + {"casc_selections", "Cascade selection; selection; counts", {HistType::kTH1F, {{CascSelections::kCascAll, -0.5, static_cast(CascSelections::kCascAll) - 0.5}}}}, + {"de_selections", "Deuteron track selection; selection; counts", {HistType::kTH1F, {{DeSelections::kDeAll, -0.5, static_cast(DeSelections::kDeAll) - 0.5}}}}, + {"he3_selections", "He3 track selection; selection; counts", {HistType::kTH1F, {{He3Selections::kHe3All, -0.5, static_cast(He3Selections::kHe3All) - 0.5}}}}, + {"v0_type", "Selected V0; particle; counts", {HistType::kTH1F, {{V0Type::V0TypeAll, -0.5, static_cast(V0Type::V0TypeAll) - 0.5}}}}, + {"radiusV0", "Decay radius (xy) V0; radius (cm); counts", {HistType::kTH1F, {{100, 0., 100.}}}}, + {"massLambda", "#Lambda invariant mass; signed #it{p} (GeV/#it{c}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {{100, -5.f, 5.f}, {50, 1.08f, 1.18f}}}}, + {"Lambda_vs_K0s", "Mass #Lambda vs K^{0}_s; m_{K^{0}_{s}} (GeV/#it{c}^{2}); m_{#Lambda} (GeV/#it{c}^{2})", {HistType::kTH2F, {{50, 0.f, 1.f}, {70, 0.6f, 2.f}}}}, + {"armenteros_plot_before_selections", "Armenteros-Podolanski plot; #alpha; q_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, -1.f, 1.f}, {100, 0.f, 0.3f}}}}, + {"armenteros_plot", "Armenteros-Podolanski plot; #alpha; q_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, -1.f, 1.f}, {100, 0.f, 0.3f}}}}, + {"armenteros_plot_lambda", "Armenteros-Podolanski plot (#Lambda only); #alpha; q_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, -1.f, 1.f}, {100, 0.f, 0.3f}}}}, + {"armenteros_plot_gamma", "Armenteros-Podolanski plot (#gamma only); #alpha; q_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, -1.f, 1.f}, {100, 0.f, 0.3f}}}}, + {"photon_radiusV0", "Photon conversion radius (xy) V0; radius (cm); counts", {HistType::kTH1F, {{100, 0., 100.}}}}, + {"photon_conversion_position", "Photon conversion position; x (cm); y (cm)", {HistType::kTH2F, {{250, -5.f, 5.f}, {250, -5.f, 5.f}}}}, + {"photon_conversion_position_layer", "Photon conversion position (ITS layers); x (cm); y (cm)", {HistType::kTH2F, {{100, -5.f, 5.f}, {100, -5.f, 5.f}}}}, + {"Xi_vs_Omega", "Mass Xi vs Omega; mass Omega (GeV/#it{c}^{2}); mass Xi (GeV/#it{c}^{2})", {HistType::kTH2F, {{50, 1.f, 2.f}, {50, 1.f, 2.f}}}}, + {"massOmega", "Mass #Omega; signed #it{p}_{T} (GeV/#it{c}); mass (GeV/#it{c}^{2})", {HistType::kTH2F, {{100, -5.f, 5.f}, {100, 1.62f, 1.72f}}}}, + {"massOmegaWithBkg", "Mass Omega with Background; mass Omega (GeV/#it{c}^{2}); counts", {HistType::kTH1F, {{100, 1.62f, 1.72f}}}}, + {"nSigmaTPCEl", "nSigma TPC Electron; signed #it{p} (GeV/#it{c}); n#sigma_{TPC} e", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {60, -2.0f, 2.0f}}}}, + {"nSigmaTPCPi", "nSigma TPC Pion; signed #it{p} (GeV/#it{c}); n#sigma_{TPC} #pi", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {60, -3.0f, 3.0f}}}}, + {"nSigmaTPCKa", "nSigma TPC Kaon; signed #it{p} (GeV/#it{c}); n#sigma_{TPC} e", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {60, -4.0f, 4.0f}}}}, + {"nSigmaTPCPr", "nSigma TPC Proton; signed #it{p} (GeV/#it{c}); n#sigma_{TPC} p", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {60, -3.0f, 3.0f}}}}, + {"nSigmaTPCDe", "nSigma TPC Deuteron; signed #it{p} (GeV/#it{c}); n#sigma_{TPC} d", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -3.0f, 3.0f}}}}, + {"nSigmaTPCHe", "nSigma TPC He3; signed #it{p} (GeV/#it{c}); n#sigma_{TPC} ^{3}He", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -3.0f, 3.0f}}}}, + {"nSigmaTOFDe", "nSigma TOF Deuteron; signed #it{p} (GeV/#it{c}); n#sigma_{TOF} d", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -3.0f, 3.0f}}}}, + {"TOFmassDe", "TOF mass De; signed #it{p}_{T} (GeV/#it{c}); mass_{TOF} ^{3}He (GeV/#it{c}^2)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, 1.0f, 5.0f}}}}, + {"TOFmassHe", "TOF mass He3; signed #it{p}_{T} (GeV/#it{c}); mass_{TOF} ^{3}He (GeV/#it{c}^2)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, 1.0f, 5.0f}}}}, + {"pmatchingEl", "#it{p} matching e; signed #it{p}_{TPC} (GeV/#it{c}); #frac{#it{p}_{TPC} - #it{p}}{#it{p}_{TPC}}", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -0.5f, 0.5f}}}}, + {"pmatchingPi", "#it{p} matching #pi; signed #it{p}_{TPC} (GeV/#it{c}); #frac{#it{p}_{TPC} - #it{p}}{#it{p}_{TPC}}", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -0.5f, 0.5f}}}}, + {"pmatchingKa", "#it{p} matching K; signed #it{p}_{TPC} (GeV/#it{c}); #frac{#it{p}_{TPC} - #it{p}}{#it{p}_{TPC}}", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -0.5f, 0.5f}}}}, + {"pmatchingPr", "#it{p} matching p; signed #it{p}_{TPC} (GeV/#it{c}); #frac{#it{p}_{TPC} - #it{p}}{#it{p}_{TPC}}", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -0.5f, 0.5f}}}}, + {"pmatchingDe", "#it{p} matching d; signed #it{p}_{TPC} (GeV/#it{c}); #frac{#it{p}_{TPC} - #it{p}}{#it{p}_{TPC}}", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -0.5f, 0.5f}}}}, + {"pmatchingHe", "#it{p} matching ^{3}He; signed #it{p}_{TPC} (GeV/#it{c}); #frac{#it{p}_{TPC} - #it{p}}{#it{p}_{TPC}}", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, -0.5f, 0.5f}}}}, + {"zVtx", "Binning for the vertex z in cm", {HistType::kTH1F, {{100, -20.f, 20.f}}}}, + {"isPositive", "is the candidate positive?; isPositive; counts", {HistType::kTH1F, {{2, -0.5f, 1.5f}}}}}, + OutputObjHandlingPolicy::AnalysisObject, + false, + true}; // check histograms + + Produces m_ClusterStudiesTable; + Produces m_ClusterStudiesTableExtra; + Produces m_ClusterStudiesTableMc; + Produces m_ClusterStudiesTableMcExtra; + + struct V0TrackParCov { + int64_t globalIndex; + Track trackParCov; + }; + std::vector m_v0TrackParCovs; + + o2::vertexing::DCAFitterN<2> m_fitter; + o2::pid::tof::Beta m_responseBeta; + o2::pid::tof::Beta m_responseBetaMc; + + template + bool initializeFitter(const T& trackParCovA, const T& trackParCovB) + { + int nCand = 0; + try { + nCand = m_fitter.process(trackParCovA, trackParCovB); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return false; + } + if (nCand == 0) { + return false; + } + + return true; + } + + /** + * Compute the momentum of the track using the fitter + * @param itrack Index of the track in the fitter + * @param mom Array to store the momentum + */ + void computeTrackMomentum(const int itrack, std::array& mom) + { + auto fittedTrack = m_fitter.getTrack(itrack); + fittedTrack.getPxPyPzGlo(mom); + } + + void computeMotherMomentum(const std::array& momA, const std::array& momB, std::array& momMother) + { + momMother[0] = momA[0] + momB[0]; + momMother[1] = momA[1] + momB[1]; + momMother[2] = momA[2] + momB[2]; + } + + /** + * Compute the alpha for the Armenteros-Podolanski plot + */ + float computeAlphaAP(const std::array& momMother, const std::array& momP, const std::array& momN) + { + float lQlP = std::inner_product(momMother.begin(), momMother.end(), momP.begin(), 0.f); + float lQlN = std::inner_product(momMother.begin(), momMother.end(), momN.begin(), 0.f); + return (lQlP - lQlN) / (lQlP + lQlN); + } + + /** + * Compute the qt for the Armenteros-Podolanski plot + */ + float computeQtAP(const std::array& momMother, const std::array& momP) + { + float dp = std::inner_product(momMother.begin(), momMother.end(), momP.begin(), 0.f); + float p2V0 = std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f); + float p2A = std::inner_product(momP.begin(), momP.end(), momP.begin(), 0.f); + return std::sqrt(p2A - dp * dp / p2V0); + } + + float dcaMotherToPV(const std::array& decayVtx, const std::array& PV, std::array momMother) const + { + std::array relPos = {decayVtx[0] - PV[0], decayVtx[1] - PV[1], decayVtx[2] - PV[2]}; + float lmomMotherl = std::hypot(momMother[0], momMother[1], momMother[2]); + return std::sqrt((std::pow(relPos[1] * momMother[2] - relPos[2] * momMother[1], 2) + std::pow(relPos[2] * momMother[0] - relPos[0] * momMother[2], 2) + std::pow(relPos[0] * momMother[1] - relPos[1] * momMother[0], 2))) / lmomMotherl; + } + + template + float dcaToPV(const std::array& PV, T& trackParCov, gpu::gpustd::array& dcaInfo) + { + o2::base::Propagator::Instance()->propagateToDCABxByBz({PV[0], PV[1], PV[2]}, trackParCov, 2.f, m_fitter.getMatCorrType(), &dcaInfo); + return std::hypot(dcaInfo[0], dcaInfo[1]); + } + + float computeMassMother(const float massA, const float massB, const std::array& momA, const std::array& momB, const std::array& momMother) const + { + float eA = std::hypot(massA, std::hypot(momA[0], momA[1], momA[2])); + float eB = std::hypot(massB, std::hypot(momB[0], momB[1], momB[2])); + float lmomMotherl = std::hypot(momMother[0], momMother[1], momMother[2]); + float eMother = eA + eB; + return std::sqrt(eMother * eMother - lmomMotherl * lmomMotherl); + } + + bool collisionSelection(const CollisionsCustom::iterator& collision) + { + m_hAnalysis.fill(HIST("collision_selections"), Selections::kNoCut); + if (!collision.sel8()) { + return false; + } + m_hAnalysis.fill(HIST("collision_selections"), Selections::kSel8); + // if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + // return false; + // } + if (std::abs(collision.posZ()) > setting_zVtxMax) { + return false; + } + m_hAnalysis.fill(HIST("collision_selections"), Selections::kVtxZ); + return true; + } + + // ========================================================================================================= + + /** + * Select the V0 daughters based on the quality cuts + */ + template + bool qualityTrackSelection(const T& track) + { + if (std::abs(track.eta()) > v0setting_etaMaxV0dau) { + return false; + } + if (track.itsNCls() < track_nClsItsMin || + track.tpcNClsFound() < track_nClsTpcMin || + track.tpcNClsCrossedRows() < track_nClsTpcMin || + track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || + track.tpcNClsShared() > track_nClsTpcMaxShared) { + return false; + } + return true; + } + + bool qualitySelectionV0(const double /*dcaV0toPV*/, const double dcaV0daughters, const double radiusV0, const double cosPA) + { + if (std::abs(dcaV0daughters) > v0setting_dcaV0daughters) { + return false; + } + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0DaughterDCA); + if (radiusV0 > v0setting_radiusMax || radiusV0 < v0setting_radiusMin) { + return false; + } + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0Radius); + if (std::abs(cosPA) < v0setting_cosPA) { + return false; + } + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0CosPA); + return true; + } + + bool qualitySelectionCascade(const double dcaCascDaughters, const double cosPA) + { + if (std::abs(dcaCascDaughters) > cascsetting_dcaCascDaughters) { + return false; + } + m_hAnalysis.fill(HIST("casc_selections"), CascSelections::kCascDCA); + if (std::abs(cosPA) < cascsetting_cosPA) { + return false; + } + m_hAnalysis.fill(HIST("casc_selections"), CascSelections::kCascCosPA); + return true; + } + + // ========================================================================================================= + + template + bool nucleiTrackSelection(const T& track) + { + if (track.tpcNClsFound() < 90) { + return false; + } + return true; + } + + // ========================================================================================================= + + template + float computeNSigmaDe(const T& candidate) + { + float expTPCSignal = o2::tpc::BetheBlochAleph(static_cast(candidate.tpcInnerParam() / constants::physics::MassDeuteron), m_BBparamsDe[0], m_BBparamsDe[1], m_BBparamsDe[2], m_BBparamsDe[3], m_BBparamsDe[4]); + double resoTPC{expTPCSignal * m_BBparamsDe[5]}; + return static_cast((candidate.tpcSignal() - expTPCSignal) / resoTPC); + } + + template + bool selectionPIDtpcDe(const T& candidate) + { + auto nSigmaDe = computeNSigmaDe(candidate); + if (std::abs(nSigmaDe) < desetting_nsigmatpc) { + return true; + } + return false; + } + + template + float computeTOFmassDe(const T& candidate) + { + if constexpr (isMC) { + float beta = m_responseBetaMc.GetBeta(candidate); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + return candidate.tpcInnerParam() * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + } else { + float beta = m_responseBeta.GetBeta(candidate); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + return candidate.tpcInnerParam() * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + } + } + + // ========================================================================================================= + + template + float computeNSigmaHe3(const T& candidate) + { + bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParam = (heliumPID && he3setting_compensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); + float expTPCSignal = o2::tpc::BetheBlochAleph(static_cast(correctedTPCinnerParam * 2.f / constants::physics::MassHelium3), m_BBparamsHe[0], m_BBparamsHe[1], m_BBparamsHe[2], m_BBparamsHe[3], m_BBparamsHe[4]); + double resoTPC{expTPCSignal * m_BBparamsHe[5]}; + return static_cast((candidate.tpcSignal() - expTPCSignal) / resoTPC); + } + + template + bool selectionPIDtpcHe3(const T& candidate) + { + auto nSigmaHe3 = computeNSigmaHe3(candidate); + if (std::abs(nSigmaHe3) < he3setting_nsigmatpc) { + return true; + } + return false; + } + + template + float computeTOFmassHe3(const T& candidate) + { + if constexpr (isMC) { + float beta = m_responseBetaMc.GetBeta(candidate); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParamHe3 = (heliumPID && he3setting_compensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); + return correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + } else { + float beta = m_responseBeta.GetBeta(candidate); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParamHe3 = (heliumPID && he3setting_compensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); + return correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + } + return -999.f; + } + + // ========================================================================================================= + + template + void initCCDB(Bc const& bc) + { + if (m_runNumber == bc.runNumber()) { + return; + } + + auto timestamp = bc.timestamp(); + o2::parameters::GRPMagField* grpmag = 0x0; + + auto grpmagPath{"GLO/Config/GRPMagField"}; + grpmag = m_ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField for timestamp " << timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + + // Fetch magnetic field from ccdb for current collision + m_d_bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << m_d_bz << " kG"; + m_runNumber = bc.runNumber(); + m_fitter.setBz(m_d_bz); + + // o2::base::Propagator::Instance()->setMatLUT(lut); + } + + void init(o2::framework::InitContext&) + { + m_runNumber = 0; + m_d_bz = 0; + + m_ccdb->setURL("http://alice-ccdb.cern.ch"); + m_ccdb->setCaching(true); + m_ccdb->setLocalObjectValidityChecking(); + m_ccdb->setFatalWhenNull(false); + // lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + m_fitter.setPropagateToPCA(true); + m_fitter.setMaxR(200.); + m_fitter.setMinParamChange(1e-3); + m_fitter.setMinRelChi2Change(0.9); + m_fitter.setMaxDZIni(4); + m_fitter.setMaxDXYIni(4); + m_fitter.setMaxChi2(1e9); + m_fitter.setUseAbsDCA(true); + m_fitter.setWeightedFinalPCA(false); + int mat{static_cast(setting_materialCorrection)}; + m_fitter.setMatCorrType(static_cast(mat)); + + LOG(info) << "Bethe-Bloch parameters for He3:"; + for (int i = 0; i < 5; i++) { + m_BBparamsHe[i] = setting_BetheBlochParams->get("He3", Form("p%i", i)); + LOG(info) << "p" << i << ": " << m_BBparamsHe[i]; + } + m_BBparamsHe[5] = setting_BetheBlochParams->get("He3", "resolution"); + LOG(info) << "resolution: " << m_BBparamsHe[5]; + + LOG(info) << "Bethe-Bloch parameters for De:"; + for (int i = 0; i < 5; i++) { + m_BBparamsDe[i] = setting_BetheBlochParams->get("De", Form("p%i", i)); + LOG(info) << "p" << i << ": " << m_BBparamsDe[i]; + } + m_BBparamsDe[5] = setting_BetheBlochParams->get("De", "resolution"); + LOG(info) << "resolution: " << m_BBparamsDe[5]; + + std::vector collision_selection_labels = {"All", "sel8", "z_{VTX} < 10 cm"}; + for (int i = 0; i < Selections::kAll; i++) + m_hAnalysis.get(HIST("collision_selections"))->GetXaxis()->SetBinLabel(i + 1, collision_selection_labels[i].c_str()); + + std::vector V0_selection_labels = {"All", "daughter track quality", "V0 daughters dca", "V0 radius", "V0 cosPA", "V0 mass selection", "V0 daughter DCA to PV"}; + for (int i = 0; i < V0Selections::kV0All; i++) + m_hAnalysis.get(HIST("v0_selections"))->GetXaxis()->SetBinLabel(i + 1, V0_selection_labels[i].c_str()); + + std::vector Casc_selection_labels = {"All", "Casc DCA", "Casc CosPA", "Accepted Omega", "Veto Xi", "n#sigma_{TPC} K"}; + for (int i = 0; i < CascSelections::kCascAll; i++) + m_hAnalysis.get(HIST("casc_selections"))->GetXaxis()->SetBinLabel(i + 1, Casc_selection_labels[i].c_str()); + + std::vector De_selection_labels = {"All", "n clusters ITS", "n#sigma_{TPC} d", "n#sigma_{TOF} d"}; + for (int i = 0; i < DeSelections::kDeAll; i++) + m_hAnalysis.get(HIST("de_selections"))->GetXaxis()->SetBinLabel(i + 1, De_selection_labels[i].c_str()); + + std::vector He3_selection_labels = {"All", "n clusters ITS", "n#sigma_{TPC} ^{3}He", "TOF mass ^{3}He"}; + for (int i = 0; i < He3Selections::kHe3All; i++) + m_hAnalysis.get(HIST("he3_selections"))->GetXaxis()->SetBinLabel(i + 1, He3_selection_labels[i].c_str()); + + std::vector V0Type_labels = {"K0s", "#Lambda", "#bar{#Lambda}", "Photon"}; + for (int i = 0; i < V0Type::V0TypeAll; i++) + m_hAnalysis.get(HIST("v0_type"))->GetXaxis()->SetBinLabel(i + 1, V0Type_labels[i].c_str()); + } + + template + void fillV0Cand(const std::array& PV, const aod::V0s::iterator& v0, const Track&) + { + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0NoCut); + + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + if (!qualityTrackSelection(posTrack) || !qualityTrackSelection(negTrack)) { + return; + } + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0DaughterQuality); + + auto daughterTrackCovarianceA = getTrackParCov(posTrack); + auto daughterTrackCovarianceB = getTrackParCov(negTrack); + if (!initializeFitter(daughterTrackCovarianceA, daughterTrackCovarianceB)) { + return; + } + + std::array momPos, momNeg, momMother; + computeTrackMomentum(0, momPos); + computeTrackMomentum(1, momNeg); + computeMotherMomentum(momPos, momNeg, momMother); + ROOT::Math::SVector vec_decayVtx = m_fitter.getPCACandidate(); + std::array decayVtx = {static_cast(vec_decayVtx[0]), static_cast(vec_decayVtx[1]), static_cast(vec_decayVtx[2])}; + float alphaAP = computeAlphaAP(momMother, momPos, momNeg); + float qtAP = computeQtAP(momMother, momPos); + m_hAnalysis.fill(HIST("armenteros_plot_before_selections"), alphaAP, qtAP); + + gpu::gpustd::array dcaInfo; + V0TrackParCov v0TrackParCov{v0.globalIndex(), m_fitter.createParentTrackParCov()}; + float dcaV0daughters = std::sqrt(std::abs(m_fitter.getChi2AtPCACandidate())); + float radiusV0 = std::hypot(decayVtx[0], decayVtx[1]); + float dcaV0toPV = dcaToPV(PV, v0TrackParCov.trackParCov, dcaInfo); + float cosPA = RecoDecay::cpa(PV, decayVtx, momMother); + if (!qualitySelectionV0(dcaV0toPV, dcaV0daughters, radiusV0, cosPA)) { + return; + } + + // mass hypothesis + float massLambdaV0 = computeMassMother(o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, momPos, momNeg, momMother); + float massAntiLambdaV0 = computeMassMother(o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, momPos, momNeg, momMother); + float massK0sV0 = computeMassMother(o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged, momPos, momNeg, momMother); + m_hAnalysis.fill(HIST("Lambda_vs_K0s"), massK0sV0, massLambdaV0); + // float massPhotonV0 = computeMassMother(o2::constants::physics::MassElectron, o2::constants::physics::MassElectron, momPos, momNeg, momMother); + + uint8_t v0Bitmask(0); + if (v0.isPhotonV0()) { + SETBIT(v0Bitmask, Photon); + } + if (std::abs(massK0sV0 - o2::constants::physics::MassK0Short) < v0setting_massWindowK0s) { + SETBIT(v0Bitmask, K0s); + } + if ((std::abs(massLambdaV0 - o2::constants::physics::MassLambda0) < v0setting_massWindowLambda) && (alphaAP > 0)) { + SETBIT(v0Bitmask, Lambda); + } + if ((std::abs(massAntiLambdaV0 - o2::constants::physics::MassLambda0) < v0setting_massWindowLambda) && (alphaAP < 0)) { + SETBIT(v0Bitmask, AntiLambda); + } + if (v0Bitmask == 0 || (v0Bitmask & (v0Bitmask - 1)) != 0) { + return; + } + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0PID); + + uint8_t partID_pos{0}, partID_neg{0}; + if (TESTBIT(v0Bitmask, Lambda)) { + if (qtAP < lambdasetting_qtAPcut) + return; + if (std::abs(posTrack.tpcNSigmaPr()) > v0setting_nsigmatpcPr || std::abs(negTrack.tpcNSigmaPi()) > v0setting_nsigmatpcPi) + return; + if (std::hypot(momMother[0], momMother[1], momMother[2]) < lambdasetting_pmin) + return; + partID_pos = PartID::pr; + partID_neg = PartID::pi; + m_hAnalysis.fill(HIST("v0_type"), V0Type::Lambda); + } else if (TESTBIT(v0Bitmask, AntiLambda)) { + if (qtAP < lambdasetting_qtAPcut) + return; + if (std::abs(posTrack.tpcNSigmaPi()) > v0setting_nsigmatpcPr || std::abs(negTrack.tpcNSigmaPr()) > v0setting_nsigmatpcPi) + return; + if (std::hypot(momMother[0], momMother[1], momMother[2]) < lambdasetting_pmin) + return; + partID_pos = PartID::pi; + partID_neg = PartID::pr; + m_hAnalysis.fill(HIST("v0_type"), V0Type::AntiLambda); + } else if (TESTBIT(v0Bitmask, K0s)) { + m_hAnalysis.fill(HIST("v0_type"), V0Type::K0s); + return; // K0s not implemented + } else if (TESTBIT(v0Bitmask, Photon)) { + // require photon conversion to happen in one of the Inner Tracker layers (± 0.5 cm resolution) + m_hAnalysis.fill(HIST("photon_conversion_position"), decayVtx[0], decayVtx[1]); + m_hAnalysis.fill(HIST("photon_radiusV0"), radiusV0); + if (!(radiusV0 > 1.76 && radiusV0 < 4.71)) + return; + if (std::abs(posTrack.tpcNSigmaEl()) > v0setting_nsigmatpcEl || std::abs(negTrack.tpcNSigmaEl()) > v0setting_nsigmatpcEl) + return; + m_hAnalysis.fill(HIST("photon_conversion_position_layer"), decayVtx[0], decayVtx[1]); + partID_pos = PartID::el; + partID_neg = PartID::el; + m_hAnalysis.fill(HIST("v0_type"), V0Type::Photon); + } else { + return; + } + + float dcaToPVpos = dcaToPV(PV, daughterTrackCovarianceA, dcaInfo); + if (std::abs(dcaToPVpos) < v0setting_dcaDaughtersToPV /*&& std::abs(dcaInfo[0]) < v0setting_dcaDaughtersToPV*/) { + return; + } + float dcaToPVneg = dcaToPV(PV, daughterTrackCovarianceB, dcaInfo); + if (std::abs(dcaToPVneg) < v0setting_dcaDaughtersToPV /*&& std::abs(dcaInfo[0]) < v0setting_dcaDaughtersToPV*/) { + return; + } + + float massV0{0.f}; + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0DaughterDCAtoPV); + if (TESTBIT(v0Bitmask, Lambda)) { + massV0 = massLambdaV0; + m_hAnalysis.fill(HIST("massLambda"), std::hypot(momMother[0], momMother[1], momMother[2]), massLambdaV0); + m_hAnalysis.fill(HIST("armenteros_plot_lambda"), alphaAP, qtAP); + m_hAnalysis.fill(HIST("nSigmaTPCPr"), std::hypot(momPos[0], momPos[1], momPos[2]), posTrack.tpcNSigmaPr()); + m_hAnalysis.fill(HIST("nSigmaTPCPi"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, negTrack.tpcNSigmaPi()); + m_hAnalysis.fill(HIST("pmatchingPr"), posTrack.tpcInnerParam(), (posTrack.tpcInnerParam() - posTrack.p()) / posTrack.tpcInnerParam()); + m_hAnalysis.fill(HIST("pmatchingPi"), -negTrack.tpcInnerParam(), (negTrack.tpcInnerParam() - negTrack.p()) / negTrack.tpcInnerParam()); + + } else if (TESTBIT(v0Bitmask, AntiLambda)) { + massV0 = massAntiLambdaV0; + m_hAnalysis.fill(HIST("massLambda"), std::hypot(momMother[0], momMother[1], momMother[2]) * -1.f, massAntiLambdaV0); + // "signed" pt for antimatter + m_hAnalysis.fill(HIST("armenteros_plot_lambda"), alphaAP, qtAP); + m_hAnalysis.fill(HIST("nSigmaTPCPi"), std::hypot(momPos[0], momPos[1], momPos[2]), posTrack.tpcNSigmaPi()); + m_hAnalysis.fill(HIST("nSigmaTPCPi"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, negTrack.tpcNSigmaPr()); + m_hAnalysis.fill(HIST("pmatchingPi"), posTrack.tpcInnerParam(), (posTrack.tpcInnerParam() - posTrack.p()) / posTrack.tpcInnerParam()); + m_hAnalysis.fill(HIST("pmatchingPr"), -negTrack.tpcInnerParam(), (negTrack.tpcInnerParam() - negTrack.p()) / negTrack.tpcInnerParam()); + + } else if (TESTBIT(v0Bitmask, Photon)) { + massV0 = 0.f; + m_hAnalysis.fill(HIST("nSigmaTPCEl"), std::hypot(momPos[0], momPos[1], momPos[2]), posTrack.tpcNSigmaEl()); + m_hAnalysis.fill(HIST("nSigmaTPCEl"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, negTrack.tpcNSigmaEl()); + m_hAnalysis.fill(HIST("armenteros_plot_gamma"), alphaAP, qtAP); + m_hAnalysis.fill(HIST("pmatchingEl"), posTrack.tpcInnerParam(), (posTrack.tpcInnerParam() - posTrack.p()) / posTrack.tpcInnerParam()); + m_hAnalysis.fill(HIST("pmatchingEl"), -negTrack.tpcInnerParam(), (negTrack.tpcInnerParam() - negTrack.p()) / negTrack.tpcInnerParam()); + } + m_hAnalysis.fill(HIST("radiusV0"), radiusV0); + m_hAnalysis.fill(HIST("armenteros_plot"), alphaAP, qtAP); + m_v0TrackParCovs.push_back(v0TrackParCov); + + if (!setting_fillV0) { + return; + } + + if constexpr (isMC) { // MC + if (!posTrack.has_mcParticle() || !negTrack.has_mcParticle()) { + return; + } + + auto posMcParticle = posTrack.mcParticle(); + auto negMcParticle = negTrack.mcParticle(); + + if (setting_smallTable) { + m_ClusterStudiesTableMc( + std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos + RecoDecay::eta(momPos), // eta_pos + RecoDecay::phi(momPos), // phi_pos + posTrack.itsClusterSizes(), // itsClsize_pos + partID_pos, // partID_pos + posMcParticle.pdgCode()); // pdgCode_pos + m_ClusterStudiesTableMc( + std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg + RecoDecay::eta(momNeg), // eta_neg + RecoDecay::phi(momNeg), // phi_neg + negTrack.itsClusterSizes(), // itsClsize_neg + partID_neg, // partID_neg + negMcParticle.pdgCode()); // pdgCode_neg + } else { + m_ClusterStudiesTableMcExtra( + std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos + RecoDecay::eta(momPos), // eta_pos + RecoDecay::phi(momPos), // phi_pos + posTrack.itsClusterSizes(), // itsClsize_pos + partID_pos, // partID_pos + posMcParticle.pdgCode(), // pdgCode_pos + posTrack.tpcInnerParam() * posTrack.sign(), // pTPC_pos + posTrack.pidForTracking(), // pidInTrk_pos + -999.f, // TpcNSigma_pos + -999.f, // TofNSigma_pos + -999.f, // TofMass_pos + cosPA, // cosPA + massV0); // massV0 + m_ClusterStudiesTableMcExtra( + std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg + RecoDecay::eta(momNeg), // eta_neg + RecoDecay::phi(momNeg), // phi_neg + negTrack.itsClusterSizes(), // itsClsize_neg + partID_neg, // partID_neg + negMcParticle.pdgCode(), // pdgCode_pos + negTrack.tpcInnerParam() * negTrack.sign(), // pTPC_neg + negTrack.pidForTracking(), // pidInTrk_neg + -999.f, // TpcNSigma_neg + -999.f, // TofNSigma_neg + -999.f, // TofMass_neg + cosPA, // cosPA + massV0); // massV0 + } + } else { // data + if (setting_smallTable) { + m_ClusterStudiesTable( + std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos + RecoDecay::eta(momPos), // eta_pos + RecoDecay::phi(momPos), // phi_pos + posTrack.itsClusterSizes(), // itsClsize_pos + partID_pos); // partID_pos + m_ClusterStudiesTable( + std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg + RecoDecay::eta(momNeg), // eta_neg + RecoDecay::phi(momNeg), // phi_neg + negTrack.itsClusterSizes(), // itsClsize_neg + partID_neg); // partID_neg + } else { + m_ClusterStudiesTableExtra( + std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos + RecoDecay::eta(momPos), // eta_pos + RecoDecay::phi(momPos), // phi_pos + posTrack.itsClusterSizes(), // itsClsize_pos + partID_pos, // partID_pos + posTrack.tpcInnerParam() * posTrack.sign(), // pTPC_pos + posTrack.pidForTracking(), // pidInTrk_pos + -999.f, // TpcNSigma_pos + -999.f, // TofNSigma_pos + -999.f, // TofMass_pos + cosPA, // cosPA + massV0); // massV0 + m_ClusterStudiesTableExtra( + std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg + RecoDecay::eta(momNeg), // eta_neg + RecoDecay::phi(momNeg), // phi_neg + negTrack.itsClusterSizes(), // itsClsize_neg + partID_neg, // partID_neg + negTrack.tpcInnerParam() * negTrack.sign(), // pTPC_neg + negTrack.pidForTracking(), // pidInTrk_neg + -999.f, // TpcNSigma_neg + -999.f, // TofNSigma_neg + -999.f, // TofMass_neg + cosPA, // cosPA + massV0); // massV0 + } + } + + m_hAnalysis.fill(HIST("isPositive"), true); + m_hAnalysis.fill(HIST("isPositive"), false); + } + + template + void fillKCand(const std::array& PV, const aod::Cascades::iterator& cascade, const Track&) + { + m_hAnalysis.fill(HIST("casc_selections"), CascSelections::kCascNoCut); + + auto v0Track = cascade.template v0_as(); + auto bachelorTrack = cascade.template bachelor_as(); + + auto itv0 = std::find_if(m_v0TrackParCovs.begin(), m_v0TrackParCovs.end(), [&](const V0TrackParCov& v0) { return v0.globalIndex == v0Track.globalIndex(); }); + if (itv0 == m_v0TrackParCovs.end()) { + return; + } + + auto v0TrackCovariance = itv0->trackParCov; + auto bachelorTrackCovariance = getTrackParCov(bachelorTrack); + if (!initializeFitter(v0TrackCovariance, bachelorTrackCovariance)) { + return; + } + + std::array momV0, momBachelor, momMother; + computeTrackMomentum(0, momV0); + computeTrackMomentum(1, momBachelor); + computeMotherMomentum(momV0, momBachelor, momMother); + + ROOT::Math::SVector vec_decayVtx = m_fitter.getPCACandidate(); + std::array decayVtx = {static_cast(vec_decayVtx[0]), static_cast(vec_decayVtx[1]), static_cast(vec_decayVtx[2])}; + + float dcaV0daughters = std::sqrt(std::abs(m_fitter.getChi2AtPCACandidate())); + float cosPA = RecoDecay::cpa(PV, decayVtx, momMother); + + if (!qualitySelectionCascade(dcaV0daughters, cosPA)) { + return; + } + // gpu::gpustd::array dcaInfo; + // float dcaToPVbachelor = dcaToPV(PV, bachelorTrackCovariance, dcaInfo); + + float massXi = computeMassMother(o2::constants::physics::MassLambda0, o2::constants::physics::MassPionCharged, momV0, momBachelor, momMother); + float massOmega = computeMassMother(o2::constants::physics::MassLambda0, o2::constants::physics::MassKaonCharged, momV0, momBachelor, momMother); + m_hAnalysis.fill(HIST("Xi_vs_Omega"), massOmega, massXi); + if (std::abs(massOmega - o2::constants::physics::MassOmegaMinus) > cascsetting_massWindowOmega) { + return; + } + m_hAnalysis.fill(HIST("massOmegaWithBkg"), massOmega); + m_hAnalysis.fill(HIST("casc_selections"), CascSelections::kAcceptedOmega); + if (std::abs(massXi - o2::constants::physics::MassXiMinus) < cascsetting_massWindowXi) { + return; + } // enhance purity by rejecting Xi background + m_hAnalysis.fill(HIST("casc_selections"), CascSelections::kRejectedXi); + if (std::abs(bachelorTrack.tpcNSigmaKa()) > cascsetting_nsigmatpc) { + return; + } + m_hAnalysis.fill(HIST("casc_selections"), CascSelections::kNSigmaTPC); + m_hAnalysis.fill(HIST("massOmega"), std::hypot(momMother[0], momMother[1]) * bachelorTrack.sign(), massOmega); + m_hAnalysis.fill(HIST("pmatchingKa"), bachelorTrack.sign() * bachelorTrack.tpcInnerParam(), (bachelorTrack.tpcInnerParam() - bachelorTrack.p()) / bachelorTrack.tpcInnerParam()); + m_hAnalysis.fill(HIST("nSigmaTPCKa"), bachelorTrack.sign() * std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]), bachelorTrack.tpcNSigmaKa()); + + uint8_t partID_bachelor = PartID::ka; + + if constexpr (isMC) { + if (!bachelorTrack.has_mcParticle()) { + return; + } + auto mcParticle = bachelorTrack.mcParticle(); + + if (setting_smallTable) { + m_ClusterStudiesTableMc( + std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K + RecoDecay::eta(momBachelor), // eta_K + RecoDecay::phi(momBachelor), // phi_K + bachelorTrack.itsClusterSizes(), // itsClSize_K + partID_bachelor, // partID_K + mcParticle.pdgCode()); // pdgCode_K + } else { + m_ClusterStudiesTableMcExtra( + std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K + RecoDecay::eta(momBachelor), // eta_K + RecoDecay::phi(momBachelor), // phi_K + bachelorTrack.itsClusterSizes(), // itsClSize_K + partID_bachelor, // partID_K + mcParticle.pdgCode(), // pdgCode_K + bachelorTrack.tpcInnerParam() * bachelorTrack.sign(), // pTPC_K + bachelorTrack.pidForTracking(), // PIDinTrk_K + -999.f, // TpcNSigma_K + -999.f, // TofNSigma_K + -999.f, // TofMass_K + cosPA, // cosPA + massOmega); // massMother + } + } else { + if (setting_smallTable) { + m_ClusterStudiesTable( + std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K + RecoDecay::eta(momBachelor), // eta_K + RecoDecay::phi(momBachelor), // phi_K + bachelorTrack.itsClusterSizes(), // itsClSize_K + partID_bachelor); // partID_K + } else { + m_ClusterStudiesTableExtra( + std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K + RecoDecay::eta(momBachelor), // eta_K + RecoDecay::phi(momBachelor), // phi_K + bachelorTrack.itsClusterSizes(), // itsClSize_K + partID_bachelor, // partID_K + bachelorTrack.tpcInnerParam() * bachelorTrack.sign(), // pTPC_K + bachelorTrack.pidForTracking(), // PIDinTrk_K + -999.f, // TpcNSigma_K + -999.f, // TofNSigma_K + -999.f, // TofMass_K + cosPA, // cosPA + massOmega); + } + } + + m_hAnalysis.fill(HIST("isPositive"), bachelorTrack.p() > 0); + } + + template + void fillDeTable(const Track& track) + { + if (track.sign() > 0) { + return; + } + m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDeNoCut); + if (track.itsNCls() < desetting_nClsIts) { + return; + } + m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDeNClsIts); + if (!selectionPIDtpcDe(track)) { + return; + } + m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDePIDtpc); + if (!track.hasTOF() || std::abs(track.tofNSigmaDe()) > desetting_nsigmatof) { + return; + } + m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDePIDtof); + m_hAnalysis.fill(HIST("nSigmaTPCDe"), track.p() * track.sign(), computeNSigmaDe(track)); + m_hAnalysis.fill(HIST("nSigmaTOFDe"), track.p() * track.sign(), track.tofNSigmaDe()); + m_hAnalysis.fill(HIST("TOFmassDe"), track.p() * track.sign(), computeTOFmassDe(track)); + m_hAnalysis.fill(HIST("pmatchingDe"), track.sign() * track.tpcInnerParam(), (track.tpcInnerParam() - track.p()) / track.tpcInnerParam()); + + uint8_t partID = PartID::de; + + if constexpr (isMC) { + if (!track.has_mcParticle() || track.sign() > 0) { + return; + } + + auto mcParticle = track.mcParticle(); + + if (setting_smallTable) { + m_ClusterStudiesTableMc( + track.p() * track.sign(), // p_De, + track.eta(), // eta_De, + track.phi(), // phi_De, + track.itsClusterSizes(), // itsClSize_De, + partID, // pdgCode_De, + mcParticle.pdgCode()); // pdgCodeMc_De + } else { + m_ClusterStudiesTableMcExtra( + track.p() * track.sign(), // p_De, + track.eta(), // eta_De, + track.phi(), // phi_De, + track.itsClusterSizes(), // itsClSize_De, + partID, // pdgCode_De, + mcParticle.pdgCode(), // pdgCodeMc_De + track.tpcInnerParam() * track.sign(), // pTPC_De, + track.pidForTracking(), // PIDinTrk_De, + computeNSigmaDe(track), // TpcNSigma_De, + track.tofNSigmaDe(), // TofNSigma_De, + computeTOFmassDe(track), // TofMass_De, + -999.f, // cosPA, + -999.f); // massMother + } + } else { + if (setting_smallTable) { + m_ClusterStudiesTable( + track.p() * track.sign(), // p_De, + track.eta(), // eta_De, + track.phi(), // phi_De, + track.itsClusterSizes(), // itsClSize_De, + partID); // pdgCode_De + } else { + m_ClusterStudiesTableExtra( + track.p() * track.sign(), // p_De, + track.eta(), // eta_De, + track.phi(), // phi_De, + track.itsClusterSizes(), // itsClSize_De, + partID, // pdgCode_De, + track.tpcInnerParam() * track.sign(), // pTPC_De, + track.pidForTracking(), // PIDinTrk_De, + computeNSigmaDe(track), // TpcNSigma_De, + track.tofNSigmaDe(), // TofNSigma_De, + computeTOFmassDe(track), // TofMass_De, + -999.f, // cosPA, + -999.f); // massMother + } + } + + m_hAnalysis.fill(HIST("isPositive"), track.sign() > 0); + } + + template + void fillHe3Table(const Track& track) + { + m_hAnalysis.fill(HIST("he3_selections"), He3Selections::kHe3NoCut); + + if (track.itsNCls() < he3setting_nClsIts) { + return; + } + m_hAnalysis.fill(HIST("he3_selections"), He3Selections::kHe3NClsIts); + if (!selectionPIDtpcHe3(track)) { + return; + } + m_hAnalysis.fill(HIST("he3_selections"), He3Selections::kHe3PIDtpc); + float tofMass = track.hasTOF() ? computeTOFmassHe3(track) : -999.f; + if (track.hasTOF() && (tofMass < he3setting_tofmasslow || tofMass > he3setting_tofmasshigh)) { + return; + } + uint8_t partID = PartID::he; + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParam = (heliumPID && he3setting_compensatePIDinTracking) ? track.tpcInnerParam() / 2.f : track.tpcInnerParam(); + + m_hAnalysis.fill(HIST("he3_selections"), He3Selections::kHe3PIDtof); + m_hAnalysis.fill(HIST("nSigmaTPCHe"), track.p() * track.sign(), computeNSigmaHe3(track)); + m_hAnalysis.fill(HIST("TOFmassHe"), track.p() * track.sign(), tofMass); + m_hAnalysis.fill(HIST("pmatchingHe"), track.sign() * correctedTPCinnerParam, (correctedTPCinnerParam - track.p()) / correctedTPCinnerParam); + + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return; + } + auto mcParticle = track.mcParticle(); + + if (setting_smallTable) { + m_ClusterStudiesTableMc( + track.p() * track.sign(), // p_He3, + track.eta(), // eta_He3, + track.phi(), // phi_He3, + track.itsClusterSizes(), // itsClSize_He3, + partID, // pdgCode_He3, + mcParticle.pdgCode()); // pdgCodeMc_He3 + } else { + m_ClusterStudiesTableMcExtra( + track.p() * track.sign(), // p_He3 + track.eta(), // eta_He3 + track.phi(), // phi_He3 + track.itsClusterSizes(), // itsClSize_He3 + partID, // pdgCode_He3 + mcParticle.pdgCode(), // pdgCodeMc_He3 + correctedTPCinnerParam * track.sign(), // pTPC_He3 + track.pidForTracking(), // PIDinTrk_He3 + computeNSigmaHe3(track), // TpcNSigma_He3 + -999.f, // TofNSigma_He3 + tofMass, // TofMass_He3 + -999.f, // cosPA_He3 + -999.f); // massMother_He3 + } + + } else { + if (setting_smallTable) { + m_ClusterStudiesTable( + track.p() * track.sign(), // p_He3, + track.eta(), // eta_He3, + track.phi(), // phi_He3, + track.itsClusterSizes(), // itsClSize_He3, + partID); // pdgCode_He3 + } else { + m_ClusterStudiesTableExtra( + track.p() * track.sign(), // p_He3, + track.eta(), // eta_He3, + track.phi(), // phi_He3, + track.itsClusterSizes(), // itsClSize_He3, + partID, // pdgCode_He3, + correctedTPCinnerParam * track.sign(), // pTPC_He3, + track.pidForTracking(), // PIDinTrk_He3, + computeNSigmaHe3(track), // TpcNSigma_He3, + -999.f, // TofNSigma_He3, + tofMass, // TofMass_He3, + -999.f, // cosPA, + -999.f); // massMother + } + } + + m_hAnalysis.fill(HIST("isPositive"), track.sign() > 0); + } + + void fillPKPiTable(const TracksFullIU::iterator& track) + { + uint8_t partID = 0; + float tpcNSigma = 0.f; + if (std::abs(track.tpcNSigmaPi()) < v0setting_nsigmatpcPi && std::abs(track.tpcNSigmaKa()) > 3) { + partID = PartID::pi; + tpcNSigma = track.tpcNSigmaPi(); + m_hAnalysis.fill(HIST("nSigmaTPCPi"), track.p() * track.sign(), tpcNSigma); + } else if (std::abs(track.tpcNSigmaKa()) < cascsetting_nsigmatpc && (std::abs(track.tpcNSigmaPi()) > 3 /*&& std::abs(track.tpcNSigmaPr()) > 3*/)) { + partID = PartID::ka; + tpcNSigma = track.tpcNSigmaKa(); + m_hAnalysis.fill(HIST("nSigmaTPCKa"), track.p() * track.sign(), tpcNSigma); + } else if (std::abs(track.tpcNSigmaPr()) < v0setting_nsigmatpcPr && std::abs(track.tpcNSigmaKa()) > 3) { + partID = PartID::pr; + tpcNSigma = track.tpcNSigmaPr(); + m_hAnalysis.fill(HIST("nSigmaTPCPr"), track.p() * track.sign(), tpcNSigma); + } else { + return; + } + + if (setting_smallTable) { + m_ClusterStudiesTable( + track.p() * track.sign(), + track.eta(), + track.phi(), + track.itsClusterSizes(), + partID); + } else { + m_ClusterStudiesTableExtra( + track.p() * track.sign(), // p, + track.eta(), // eta, + track.phi(), // phi, + track.itsClusterSizes(), // itsClSize, + partID, // pdgCode, + track.tpcInnerParam() * track.sign(), // pTPC, + track.pidForTracking(), // PIDinTrk, + tpcNSigma, // TpcNSigma, + -999.f, // TofNSigma, + -999.f, // TofMass, + -999.f, // cosPA, + -999.f); // massMother + } + } + + // ========================================================================================================= + + void processDataV0Casc(CollisionsCustom const& collisions, TracksFullIU const& tracks, aod::V0s const& v0s, aod::Cascades const& cascades, aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (!collisionSelection(collision)) { + continue; + } + + m_hAnalysis.fill(HIST("zVtx"), collision.posZ()); + std::array PV = {collision.posX(), collision.posY(), collision.posZ()}; + + const uint64_t collIdx = collision.globalIndex(); + auto v0Table_thisCollision = v0s.sliceBy(m_perCollisionV0, collIdx); + auto cascTable_thisCollision = cascades.sliceBy(m_perCollisionCascade, collIdx); + v0Table_thisCollision.bindExternalIndices(&tracks); + cascTable_thisCollision.bindExternalIndices(&tracks); + cascTable_thisCollision.bindExternalIndices(&v0s); + + if (setting_fillV0 || setting_fillK) { + m_v0TrackParCovs.clear(); + for (auto& v0 : v0Table_thisCollision) { + fillV0Cand(PV, v0, tracks); + } + } + if (setting_fillK) { // the v0 loops are needed for the Ks + for (auto& cascade : cascTable_thisCollision) { + fillKCand(PV, cascade, tracks); + } + } + } + } + PROCESS_SWITCH(LfTreeCreatorClusterStudies, processDataV0Casc, "process Data V0 and cascade", false); + + void processDataNuclei(CollisionsCustom const& collisions, TracksFullIU const& tracks) + { + for (const auto& collision : collisions) { + if (!collisionSelection(collision)) { + continue; + } + + m_hAnalysis.fill(HIST("zVtx"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto TrackTable_thisCollision = tracks.sliceBy(m_perCol, collIdx); + TrackTable_thisCollision.bindExternalIndices(&tracks); + + for (auto track : TrackTable_thisCollision) { + if (!nucleiTrackSelection(track)) { + continue; + } + + if (setting_fillDe) + fillDeTable(track); + if (setting_fillHe3) + fillHe3Table(track); + } + } + } + PROCESS_SWITCH(LfTreeCreatorClusterStudies, processDataNuclei, "process Data Nuclei", false); + + /** + * @brief Produce a dataset with high purity p, K, #pi + */ + void processDataPKPi(CollisionsCustom const& collisions, TracksFullIU const& tracks) + { + for (const auto& collision : collisions) { + if (!collisionSelection(collision)) { + continue; + } + + m_hAnalysis.fill(HIST("zVtx"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto TrackTable_thisCollision = tracks.sliceBy(m_perCol, collIdx); + TrackTable_thisCollision.bindExternalIndices(&tracks); + + for (auto track : TrackTable_thisCollision) { + if (!qualityTrackSelection(track)) { + continue; + } + + if (setting_fillPKPi) + fillPKPiTable(track); + } + } + } + PROCESS_SWITCH(LfTreeCreatorClusterStudies, processDataPKPi, "process Data p, K, pi", false); + + void processMcV0Casc(CollisionsCustom const& collisions, TracksFullIUMc const& tracks, aod::V0s const& v0s, aod::Cascades const& cascades, aod::BCsWithTimestamps const&, aod::McParticles const&) + { + for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (!collisionSelection(collision)) { + continue; + } + + m_hAnalysis.fill(HIST("zVtx"), collision.posZ()); + std::array PV = {collision.posX(), collision.posY(), collision.posZ()}; + + const uint64_t collIdx = collision.globalIndex(); + auto v0Table_thisCollision = v0s.sliceBy(m_perCollisionV0, collIdx); + auto cascTable_thisCollision = cascades.sliceBy(m_perCollisionCascade, collIdx); + v0Table_thisCollision.bindExternalIndices(&tracks); + cascTable_thisCollision.bindExternalIndices(&tracks); + cascTable_thisCollision.bindExternalIndices(&v0s); + + m_v0TrackParCovs.clear(); + if (setting_fillV0 || setting_fillK) { + for (auto& v0 : v0Table_thisCollision) { + fillV0Cand(PV, v0, tracks); + } + } + + if (setting_fillK) { // the v0 loops are needed for the Ks + for (auto& cascade : cascTable_thisCollision) { + fillKCand(PV, cascade, tracks); + } + } + } + } + PROCESS_SWITCH(LfTreeCreatorClusterStudies, processMcV0Casc, "process Mc V0 and cascade", false); + + void processMcNuclei(CollisionsCustom const& collisions, TracksFullIUMc const& tracks, aod::BCs const&, aod::McParticles const&) + { + for (const auto& collision : collisions) { + if (!collisionSelection(collision)) { + continue; + } + + m_hAnalysis.fill(HIST("zVtx"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto TrackTable_thisCollision = tracks.sliceBy(m_perColMC, collIdx); + TrackTable_thisCollision.bindExternalIndices(&tracks); + + for (auto track : TrackTable_thisCollision) { + if (!nucleiTrackSelection(track)) { + continue; + } + + if (setting_fillDe) { + fillDeTable(track); + } + if (setting_fillHe3) { + fillHe3Table(track); + } + } + } + } + PROCESS_SWITCH(LfTreeCreatorClusterStudies, processMcNuclei, "process Mc Nuclei", false); + +}; // LfTreeCreatorClusterStudies + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index 449df0dfe66..406d6544929 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -27,6 +27,7 @@ #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "PWGLF/DataModel/pidTOFGeneric.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" @@ -58,9 +59,10 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +using ColwithEvTimes = o2::soa::Join; using MyCollisions = soa::Join; -using FullTracksExtIU = soa::Join; -using FullTracksExtPIDIU = soa::Join; +using FullTracksExtIU = soa::Join; +using FullTracksExtPIDIU = soa::Join; using MCLabeledTracksIU = soa::Join; struct decay3bodyBuilder { @@ -156,12 +158,12 @@ struct decay3bodyBuilder { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; // CCDB TOF PID paras + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable enableTimeDependentResponse{"enableTimeDependentResponse", false, "Flag to use the collision timestamp to fetch the PID Response"}; Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; // for KFParticle reconstruction struct : ConfigurableGroup { @@ -208,6 +210,7 @@ struct decay3bodyBuilder { float maxStep; // max step size (cm) for propagation o2::base::MatLayerCylSet* lut = nullptr; o2::vertexing::DCAFitterN<3> fitter3body; + o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; o2::pid::tof::TOFResoParamsV2 mRespParamsV2; void init(InitContext&) @@ -334,7 +337,8 @@ struct decay3bodyBuilder { } // Initial TOF PID Paras, copied from PIDTOF.h - ccdb->setTimestamp(bc.timestamp()); + timestamp.value = bc.timestamp(); + ccdb->setTimestamp(timestamp.value); // Not later than now objects ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); // TODO: implement the automatic pass name detection from metadata @@ -365,8 +369,8 @@ struct decay3bodyBuilder { mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); } } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << bc.timestamp(); - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, bc.timestamp()); + LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; + o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); paramCollection->print(); if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined if (fatalOnPassNotAvailable) { @@ -385,10 +389,12 @@ struct decay3bodyBuilder { mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), bc.timestamp()), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), bc.timestamp()), false); + mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); + mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); } } + + bachelorTOFPID.SetParams(mRespParamsV2); } //------------------------------------------------------------------ @@ -424,7 +430,8 @@ struct decay3bodyBuilder { //------------------------------------------------------------------ // 3body candidate builder - template + template + // void buildVtx3BodyDataTable(TCollisionTable const& /*allcollisions*/, TCollisionTable::iterator const& collision, TTrackTable const& /*tracks*/, aod::Decay3Bodys const& decay3bodys, int bachelorcharge = 1) void buildVtx3BodyDataTable(TCollisionTable const& collision, TTrackTable const& /*tracks*/, aod::Decay3Bodys const& decay3bodys, int bachelorcharge = 1) { @@ -447,14 +454,17 @@ struct decay3bodyBuilder { auto Track0Par = getTrackPar(t0); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track0Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); auto Track0dcaXY = dcaInfo[0]; + auto Track0dca = std::sqrt(Track0dcaXY * Track0dcaXY + dcaInfo[1] * dcaInfo[1]); auto Track1Par = getTrackPar(t1); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track1Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); auto Track1dcaXY = dcaInfo[0]; + auto Track1dca = std::sqrt(Track1dcaXY * Track1dcaXY + dcaInfo[1] * dcaInfo[1]); auto Track2Par = getTrackPar(t2); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track2Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); auto Track2dcaXY = dcaInfo[0]; + auto Track2dca = std::sqrt(Track2dcaXY * Track2dcaXY + dcaInfo[1] * dcaInfo[1]); auto Track0 = getTrackParCov(t0); auto Track1 = getTrackParCov(t1); @@ -496,17 +506,10 @@ struct decay3bodyBuilder { // Recalculate the TOF PID double tofNsigmaDe = -999; - static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps - - if (t2.hasTOF()) { - double bachExpTime = t2.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (t2.tofExpMom() * t2.tofExpMom())) / (kCSPEED * t2.tofExpMom()); // L*E/(p*c) = L/v - double tofsignal = t2.trackTime() * 1000 + bachExpTime; - // double bachtime = t2.trackTime() * 1000 + bachExpTime - collision.collisionTime(); // in ps - double expSigma = GetExpectedSigma(mRespParamsV2, t2, tofsignal, collision.collisionTimeRes(), o2::constants::physics::MassDeuteron); - double corrTofMom = t2.tofExpMom() / (1.f + t2.sign() * mRespParamsV2.getShift(t2.eta())); - double corrSignal = t2.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (corrTofMom * corrTofMom)) / (kCSPEED * corrTofMom) + mRespParamsV2.getTimeShift(t2.eta(), t2.sign()); - tofNsigmaDe = (tofsignal - collision.collisionTime() - corrSignal) / expSigma; + if (t2.has_collision() && t2.hasTOF()) { + auto originalcol = t2.template collision_as(); + tofNsigmaDe = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, t2, originalcol, collision); } registry.fill(HIST("hBachelorTOFNSigmaDe"), t2.sign() * t2.p(), tofNsigmaDe); @@ -517,7 +520,374 @@ struct decay3bodyBuilder { p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], fitter3body.getChi2AtPCACandidate(), Track0dcaXY, Track1dcaXY, Track2dcaXY, + Track0dca, Track1dca, Track2dca, + tofNsigmaDe); + } + } + + //------------------------------------------------------------------ + // 3body candidate builder with KFParticle + template + void buildVtx3BodyDataTableKFParticle(TCollision const& collision, aod::Decay3Bodys const& decay3bodys, int bachelorcharge) + { + LOG(debug) << "buildVtx3BodyDataTableKFParticle called."; + for (auto& vtx3body : decay3bodys) { + LOG(debug) << "Entered decay3bodys loop."; + + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxAll); + + auto trackPos = vtx3body.template track0_as(); + auto trackNeg = vtx3body.template track1_as(); + auto trackBach = vtx3body.template track2_as(); + auto trackParCovPos = getTrackParCov(trackPos); + auto trackParCovNeg = getTrackParCov(trackNeg); + auto trackParCovBach = getTrackParCov(trackBach); + LOG(debug) << "Got all daughter tracks."; + + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + KFParticle kfpv(kfpVertex); + LOG(debug) << "Created KF PV."; + + bool isMatter = trackBach.sign() > 0 ? true : false; + + // ---------- fill trackQA and vertexQA histograms + if (kfparticleConfigurations.doTrackQA) { + registry.fill(HIST("QA/Tracks/hTrackPosTPCNcls"), trackPos.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackNegTPCNcls"), trackNeg.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackBachTPCNcls"), trackBach.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackPosHasTPC"), trackPos.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackNegHasTPC"), trackNeg.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackBachHasTPC"), trackBach.hasTPC()); + if (isMatter) { + registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackPos.sign() * trackPos.tpcInnerParam(), trackPos.tpcNSigmaPr()); + registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackNeg.sign() * trackNeg.tpcInnerParam(), trackNeg.tpcNSigmaPi()); + registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackPos.pt()); + registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackNeg.pt()); + } else { + registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackNeg.sign() * trackNeg.tpcInnerParam(), trackNeg.tpcNSigmaPr()); + registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackPos.sign() * trackPos.tpcInnerParam(), trackPos.tpcNSigmaPi()); + registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackNeg.pt()); + registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackPos.pt()); + } + registry.fill(HIST("QA/Tracks/hTrackBachTPCPID"), trackBach.sign() * trackBach.tpcInnerParam(), trackBach.tpcNSigmaDe()); + registry.fill(HIST("QA/Tracks/hTrackBachPt"), trackBach.pt()); + } + + if (kfparticleConfigurations.doVertexQA) { + registry.fill(HIST("QA/Event/hVtxXKF"), kfpv.GetX()); + registry.fill(HIST("QA/Event/hVtxYKF"), kfpv.GetY()); + registry.fill(HIST("QA/Event/hVtxZKF"), kfpv.GetZ()); + registry.fill(HIST("QA/Event/hVtxCovXXKF"), kfpv.GetCovariance(0)); + registry.fill(HIST("QA/Event/hVtxCovYYKF"), kfpv.GetCovariance(2)); + registry.fill(HIST("QA/Event/hVtxCovZZKF"), kfpv.GetCovariance(5)); + registry.fill(HIST("QA/Event/hVtxCovXYKF"), kfpv.GetCovariance(1)); + registry.fill(HIST("QA/Event/hVtxCovXZKF"), kfpv.GetCovariance(3)); + registry.fill(HIST("QA/Event/hVtxCovYZKF"), kfpv.GetCovariance(4)); + registry.fill(HIST("QA/Event/hVtxX"), collision.posX()); + registry.fill(HIST("QA/Event/hVtxY"), collision.posY()); + registry.fill(HIST("QA/Event/hVtxZ"), collision.posZ()); + registry.fill(HIST("QA/Event/hVtxCovXX"), collision.covXX()); + registry.fill(HIST("QA/Event/hVtxCovYY"), collision.covYY()); + registry.fill(HIST("QA/Event/hVtxCovZZ"), collision.covZZ()); + registry.fill(HIST("QA/Event/hVtxCovXY"), collision.covXY()); + registry.fill(HIST("QA/Event/hVtxCovXZ"), collision.covXZ()); + registry.fill(HIST("QA/Event/hVtxCovYZ"), collision.covYZ()); + } + + // -------- STEP 1: track selection -------- + // collision ID --> not correct? tracks can have different collisions, but belong to one 3prong vertex! + // if (trackPos.collisionId() != trackNeg.collisionId() || trackPos.collisionId() != trackBach.collisionId() || trackNeg.collisionId() != trackBach.collisionId()) { + // continue; + // } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxCollIds); + // track IDs --> already checked in SVertexer! + + // track signs (pos, neg, bach) --> sanity check, should already be in SVertexer + if (trackPos.sign() != +1 || trackNeg.sign() != -1) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxCharge); + + // track eta + if (trackPos.eta() > kfparticleConfigurations.maxEta || trackNeg.eta() > kfparticleConfigurations.maxEta || trackBach.eta() > kfparticleConfigurations.maxEta) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxEta); + + // TPC PID + if (isMatter && !selectTPCPID(trackPos, trackNeg, trackBach)) { // hypertriton (proton, pi-, deuteron) + continue; + } else if (!isMatter && !selectTPCPID(trackNeg, trackPos, trackBach)) { // anti-hypertriton (anti-proton, pi+, deuteron) + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxTPCPID); + + // number of TPC clusters + if (trackBach.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsTrack) { + continue; + } + if (isMatter && (trackNeg.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsPion || trackPos.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsTrack)) { + continue; + } else if (!isMatter && (trackPos.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsPion || trackNeg.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsTrack)) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxTPCNcls); + + // number of TPC crossed rows + if (trackBach.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows) { + continue; + } + if (isMatter && (trackNeg.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRowsPion || trackPos.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows)) { + continue; + } else if (!isMatter && (trackPos.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRowsPion || trackNeg.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows)) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxTPCRows); + LOG(debug) << "Basic track selections done."; + + // track DCAxy and DCAz to PV associated with decay3body + o2::dataformats::VertexBase mPV; + o2::dataformats::DCA mDcaInfoCovPos; + o2::dataformats::DCA mDcaInfoCovNeg; + o2::dataformats::DCA mDcaInfoCovBach; + auto trackParCovPVPos = trackParCovPos; + auto trackParCovPVNeg = trackParCovNeg; + auto trackParCovPVBach = trackParCovBach; + mPV.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mPV.setCov(collision.covXX(), collision.covXX(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVPos, 2.f, matCorr, &mDcaInfoCovPos); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVNeg, 2.f, matCorr, &mDcaInfoCovNeg); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVBach, 2.f, matCorr, &mDcaInfoCovBach); + auto TrackPosDcaXY = mDcaInfoCovPos.getY(); + auto TrackNegDcaXY = mDcaInfoCovNeg.getY(); + auto TrackBachDcaXY = mDcaInfoCovBach.getY(); + if (isMatter && (fabs(TrackNegDcaXY) <= kfparticleConfigurations.mindcaXYPionPV || fabs(TrackPosDcaXY) <= kfparticleConfigurations.mindcaXYProtonPV)) { + continue; + } else if (!isMatter && (fabs(TrackPosDcaXY) <= kfparticleConfigurations.mindcaXYPionPV || fabs(TrackNegDcaXY) <= kfparticleConfigurations.mindcaXYProtonPV)) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxDCAxyPV); + if (isMatter && (fabs(mDcaInfoCovNeg.getZ()) <= kfparticleConfigurations.mindcaZPionPV || fabs(mDcaInfoCovPos.getZ()) <= kfparticleConfigurations.mindcaZProtonPV)) { + continue; + } else if (!isMatter && (fabs(mDcaInfoCovPos.getZ()) <= kfparticleConfigurations.mindcaZPionPV || fabs(mDcaInfoCovNeg.getZ()) <= kfparticleConfigurations.mindcaZProtonPV)) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxDCAzPV); + + // pT selection + if (trackBach.pt() <= kfparticleConfigurations.minDeuteronPt) { + continue; + } + if (isMatter && (trackNeg.pt() > kfparticleConfigurations.maxPionPt || trackPos.pt() <= kfparticleConfigurations.minProtonPt)) { + continue; + } else if (!isMatter && (trackPos.pt() > kfparticleConfigurations.maxPionPt || trackNeg.pt() <= kfparticleConfigurations.minProtonPt)) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxTrackPt); + + // -------- STEP 2: fit vertex with proton and pion -------- + // Fit vertex with DCA fitter to find minimization point --> uses material corrections implicitly + if (kfparticleConfigurations.kfDoDCAFitterPreMinimum) { + try { + fitter3body.process(trackParCovPos, trackParCovNeg, trackParCovBach); + } catch (std::runtime_error& e) { + LOG(error) << "Exception caught in DCA fitter process call: Not able to fit decay3body vertex!"; + continue; + } + // re-acquire tracks at vertex position from DCA fitter + trackParCovPos = fitter3body.getTrack(0); + trackParCovNeg = fitter3body.getTrack(1); + trackParCovBach = fitter3body.getTrack(2); + + LOG(debug) << "Minimum found with DCA fitter for decay3body."; + } + + // create KFParticle objects from tracks + KFParticle kfpProton, kfpPion; + if (isMatter) { + kfpProton = createKFParticleFromTrackParCov(trackParCovPos, trackPos.sign(), constants::physics::MassProton); + kfpPion = createKFParticleFromTrackParCov(trackParCovNeg, trackNeg.sign(), constants::physics::MassPionCharged); + } else if (!isMatter) { + kfpProton = createKFParticleFromTrackParCov(trackParCovNeg, trackNeg.sign(), constants::physics::MassProton); + kfpPion = createKFParticleFromTrackParCov(trackParCovPos, trackPos.sign(), constants::physics::MassPionCharged); + } + LOG(debug) << "KFParticle objects created from daughter tracks."; + + // Construct V0 + KFParticle KFV0; + int nDaughters = 2; + const KFParticle* Daughters[2] = {&kfpProton, &kfpPion}; + KFV0.SetConstructMethod(2); + try { + KFV0.Construct(Daughters, nDaughters); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create V0 vertex from daughter tracks." << e.what(); + continue; + } + KFV0.TransportToDecayVertex(); + LOG(debug) << "V0 constructed."; + + // check V0 mass and set mass constraint + float massV0, sigmaMassV0; + KFV0.GetMass(massV0, sigmaMassV0); + if (abs(massV0 - constants::physics::MassLambda) <= kfparticleConfigurations.lambdaMassWindow) { + continue; + } + KFParticle KFV0Mass = KFV0; + KFV0Mass.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); + float chi2massV0 = KFV0Mass.GetChi2() / KFV0Mass.GetNDF(); + LOG(debug) << "V0 mass constraint applied."; + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxNoV0); + + // -------- STEP 3: fit vertex with V0 and deuteron -------- + // Create KFParticle object from deuteron track + KFParticle kfpDeuteron; + kfpDeuteron = createKFParticleFromTrackParCov(trackParCovBach, trackBach.sign() * bachelorcharge, constants::physics::MassDeuteron); + LOG(debug) << "KFParticle created from deuteron track."; + // Add deuteron to V0 vertex + KFParticle KFHt; + KFHt = KFV0; + KFHt.SetConstructMethod(2); + try { + KFHt.AddDaughter(kfpDeuteron); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create Hyper triton from V0 and deuteron." << e.what(); + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxhasSV); + LOG(debug) << "Hypertriton vertex constructed."; + + // -------- STEP 4: selections after geometrical vertex fit -------- + // Get updated daughter tracks + kfpProton.SetProductionVertex(KFHt); + kfpPion.SetProductionVertex(KFHt); + kfpDeuteron.SetProductionVertex(KFHt); + LOG(debug) << "Topo constraint applied to daughters."; + // daughter DCAs + if ((kfpProton.GetDistanceFromParticle(kfpPion) >= kfparticleConfigurations.maxDcaProPi) || (kfpProton.GetDistanceFromParticle(kfpDeuteron) >= kfparticleConfigurations.maxDcaProDeu) || (kfpPion.GetDistanceFromParticle(kfpDeuteron) >= kfparticleConfigurations.maxDcaPiDe)) { + continue; + } + float DCAvtxDaughters3D = kfpProton.GetDistanceFromParticle(kfpPion) + kfpProton.GetDistanceFromParticle(kfpDeuteron) + kfpPion.GetDistanceFromParticle(kfpDeuteron); + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxDcaDau); + LOG(debug) << "DCA selection after vertex fit applied."; + + // daughter DCAs to vertex + if (kfpProton.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau || kfpPion.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVPion || kfpDeuteron.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxDcaDauVtx); + LOG(debug) << "DCA to vertex selection after vertex fit applied."; + + // -------- STEP 5: candidate selection after geometrical vertex fit -------- + // Pt selection + if (KFHt.GetPt() <= kfparticleConfigurations.minPtHt || KFHt.GetPt() >= kfparticleConfigurations.maxPtHt) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxPt); + + // Mass window + float massHt, sigmaMassHt; + KFHt.GetMass(massHt, sigmaMassHt); + if (massHt <= kfparticleConfigurations.minMassHt || massHt >= kfparticleConfigurations.maxMassHt) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxMass); + + // cos(PA) to PV + if (abs(cpaFromKF(KFHt, kfpv)) <= kfparticleConfigurations.minCosPA) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxCosPA); + + // cos(PA) xy to PV + if (abs(cpaXYFromKF(KFHt, kfpv)) <= kfparticleConfigurations.minCosPAxy) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxCosPAXY); + + // chi2 geometrical + float chi2geoNDF = KFHt.GetChi2() / KFHt.GetNDF(); + if (chi2geoNDF >= kfparticleConfigurations.maxChi2geo) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxChi2geo); + LOG(debug) << "Basic selections after vertex fit done."; + + // -------- STEP 6: topological constraint -------- + /// Set vertex constraint and topological selection + KFParticle KFHtPV = KFHt; + KFHtPV.SetProductionVertex(kfpv); + KFHtPV.TransportToDecayVertex(); + float chi2topoNDF = KFHtPV.GetChi2() / KFHtPV.GetNDF(); + if (kfparticleConfigurations.applyTopoSels && chi2topoNDF >= kfparticleConfigurations.maxChi2topo) { + continue; + } + registry.fill(HIST("hVtx3BodyCounterKFParticle"), kKfVtxChi2topo); + LOG(debug) << "Topological constraint applied."; + + //------------------------------------------------------------------ + // Recalculate the bachelor TOF PID + double tofNsigmaDe = -999; + static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps + if (trackBach.hasTOF()) { + double bachExpTime = trackBach.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (trackBach.tofExpMom() * trackBach.tofExpMom())) / (kCSPEED * trackBach.tofExpMom()); // L*E/(p*c) = L/v + double tofsignal = trackBach.trackTime() * 1000 + bachExpTime; + // double bachtime = trackBach.trackTime() * 1000 + bachExpTime - collision.collisionTime(); // in ps + + double expSigma = GetExpectedSigma(mRespParamsV2, trackBach, tofsignal, collision.collisionTimeRes(), o2::constants::physics::MassDeuteron); + double corrTofMom = trackBach.tofExpMom() / (1.f + trackBach.sign() * mRespParamsV2.getShift(trackBach.eta())); + double corrSignal = trackBach.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (corrTofMom * corrTofMom)) / (kCSPEED * corrTofMom) + mRespParamsV2.getTimeShift(trackBach.eta(), trackBach.sign()); + tofNsigmaDe = (tofsignal - collision.collisionTime() - corrSignal) / expSigma; + } + registry.fill(HIST("hBachelorTOFNSigmaDe"), trackBach.sign() * trackBach.p(), tofNsigmaDe); + LOG(debug) << "Bachelor TOF info calculated."; + + //------------------------------------------------------------------ + // table filling + kfvtx3bodydata( + collision.globalIndex(), trackPos.globalIndex(), trackNeg.globalIndex(), trackBach.globalIndex(), vtx3body.globalIndex(), + // hypertriton + massHt, + KFHt.GetX(), KFHt.GetY(), KFHt.GetZ(), + KFHt.GetPx(), KFHt.GetPy(), KFHt.GetPz(), KFHt.GetPt(), + KFHt.GetQ(), + KFHt.GetDistanceFromVertex(kfpv), KFHt.GetDistanceFromVertexXY(kfpv), + cpaFromKF(KFHt, kfpv), // before topo constraint + cpaXYFromKF(KFHt, kfpv), + cpaFromKF(KFHtPV, kfpv), // after topo constraint + cpaXYFromKF(KFHtPV, kfpv), + KFHtPV.GetDecayLength(), KFHtPV.GetDecayLengthXY(), // decay length defined after topological constraint + KFHtPV.GetDecayLength() / KFHtPV.GetErrDecayLength(), // ldl + chi2geoNDF, chi2topoNDF, + // V0 + massV0, chi2massV0, + // daughter momenta + kfpProton.GetPx(), kfpProton.GetPy(), kfpProton.GetPz(), + kfpPion.GetPx(), kfpPion.GetPy(), kfpPion.GetPz(), + kfpDeuteron.GetPx(), kfpDeuteron.GetPy(), kfpDeuteron.GetPz(), + // daughter DCAs KF + kfpProton.GetDistanceFromVertex(kfpv), + kfpPion.GetDistanceFromVertex(kfpv), + kfpDeuteron.GetDistanceFromVertex(kfpv), + kfpProton.GetDistanceFromVertexXY(kfpv), + kfpPion.GetDistanceFromVertexXY(kfpv), + kfpDeuteron.GetDistanceFromVertexXY(kfpv), + kfpProton.GetDistanceFromVertexXY(KFHt), + kfpPion.GetDistanceFromVertexXY(KFHt), + kfpDeuteron.GetDistanceFromVertexXY(KFHt), + kfpProton.GetDistanceFromParticle(kfpPion), + kfpProton.GetDistanceFromParticle(kfpDeuteron), + kfpPion.GetDistanceFromParticle(kfpDeuteron), + DCAvtxDaughters3D, + // daughter DCAs to PV propagated with material + TrackPosDcaXY, TrackNegDcaXY, TrackBachDcaXY, + // daughter signs + trackPos.sign(), + trackNeg.sign(), + trackBach.sign(), + // bachelor TOF PID tofNsigmaDe); + LOG(debug) << "Table filled."; } } @@ -890,6 +1260,8 @@ struct decay3bodyBuilder { //------------------------------------------------------------------ void processRun3(aod::Collision const& collision, FullTracksExtIU const& tracksIU, aod::Decay3Bodys const& decay3bodys, aod::BCsWithTimestamps const&) { + // for (const auto& collision : collisions) { + LOG(debug) << "Start of processRun3withKFParticle."; auto bc = collision.bc_as(); initCCDB(bc); registry.fill(HIST("hEventCounter"), 0.5); diff --git a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx index 8e2733a8f24..291dc148631 100644 --- a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx +++ b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx @@ -41,18 +41,22 @@ #include "PWGLF/DataModel/LFEbyeTables.h" #include "TDatabasePDG.h" +#include "TFormula.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using TracksFull = soa::Join; +using TracksFullPID = soa::Join; using TracksFullIU = soa::Join; using BCsWithRun2Info = soa::Join; namespace { constexpr int kNpart = 2; +constexpr float trackSels[10]{/* 60, */ 80, 100, 2, 3, /* 4, */ 0.05, 0.1, /* 0.15, */ 0.5, 1, /* 1.5, */ 2, 3 /* , 4 */}; +constexpr float dcaSels[3]{10., 10., 10.}; constexpr double betheBlochDefault[kNpart][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; constexpr double estimatorsCorrelationCoef[2]{-0.669108, 1.04489}; constexpr double estimatorsSigmaPars[4]{0.933321, 0.0416976, -0.000936344, 8.92179e-06}; @@ -60,7 +64,10 @@ constexpr double deltaEstimatorNsigma[2]{5.5, 5.}; constexpr double partMass[kNpart]{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}; constexpr double partPdg[kNpart]{2212, o2::constants::physics::kDeuteron}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; -static const std::vector particleNamesBB{"p", "d"}; +static const std::vector particleNamesPar{"p", "d"}; +static const std::vector trackSelsNames{"tpcClsMid", "tpcClsTight", "chi2TpcTight", "chi2TpcMid", "dcaxyTight", "dcaxyMid", "dcazTight", "dcazMid", "tpcNsigmaTight", "tpcNsigmaMid"}; +static const std::vector dcaSelsNames{"dcaxy", "dcaz", "dca"}; +static const std::vector particleName{"p"}; std::array, kNpart> tofMass; void momTotXYZ(std::array& momA, std::array const& momB, std::array const& momC) { @@ -136,9 +143,14 @@ struct CandidateTrack { float eta = -999.f; uint8_t mass = 100; float dcapv = 0; + float dcaxypv = 0; + float dcazpv = 0; uint8_t tpcncls = 0; + float tpcchi2 = 0; float tpcnsigma = -999.f; + float itsnsigma = -999.f; float tofmass = -999.f; + float outerPID = -999.f; float genpt = -999.f; float geneta = -999.f; int pdgcode = -999; @@ -147,12 +159,39 @@ struct CandidateTrack { int64_t globalIndex = -999; }; +enum selBits { + kTPCclsTight = BIT(0), + kTPCclsMid = BIT(1), + kChi2TPCTight = BIT(2), + kChi2TPCMid = BIT(3), + kDCAxyTight = BIT(4), + kDCAxyMid = BIT(5), + kDCAzTight = BIT(6), + kDCAzMid = BIT(7), + kITSPIDTight = BIT(8), + kITSPIDMid = BIT(9), + kTPCPIDTight = BIT(10), + kTPCPIDMid = BIT(11) +}; + +struct tagRun2V0MCalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorrV0A = nullptr; + TH1* mhVtxAmpCorrV0C = nullptr; + TH1* mhMultSelCalib = nullptr; + float mMCScalePars[6] = {0.0}; + TFormula* mMCScale = nullptr; +} Run2V0MInfo; + struct ebyeMaker { Produces collisionEbyeTable; + Produces miniCollTable; Produces nucleiEbyeTable; Produces lambdaEbyeTable; + Produces miniTrkTable; Produces mcNucleiEbyeTable; Produces mcLambdaEbyeTable; + Produces mcMiniTrkTable; std::mt19937 gen32; std::vector candidateV0s; std::array, 2> candidateTracks; @@ -161,10 +200,11 @@ struct ebyeMaker { int mRunNumber; float d_bz; + uint8_t nTrackletsColl; // o2::base::MatLayerCylSet* lut = nullptr; Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 2, 6, particleNamesBB, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 2, 6, particleNamesPar, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; @@ -184,6 +224,7 @@ struct ebyeMaker { Configurable etaMaxV0dau{"etaMaxV0dau", 0.8f, "maximum eta V0 daughters"}; Configurable fillOnlySignal{"fillOnlySignal", false, "fill histograms only for true signal candidates (MC)"}; + Configurable genName{"genname", "", "Genearator name: HIJING, PYTHIA8, ... Default: \"\""}; Configurable kINT7Intervals{"kINT7Intervals", false, "toggle kINT7 trigger selection in the 10-30% and 50-90% centrality intervals (2018 Pb-Pb)"}; Configurable kUseTPCPileUpCut{"kUseTPCPileUpCut", false, "toggle strong correlation cuts (Run 2)"}; @@ -203,7 +244,8 @@ struct ebyeMaker { Configurable trackNcrossedRows{"trackNcrossedRows", 70, "Minimum number of crossed TPC rows"}; Configurable trackNclusItsCut{"trackNclusITScut", 2, "Minimum number of ITS clusters"}; Configurable trackNclusTpcCut{"trackNclusTPCcut", 60, "Minimum number of TPC clusters"}; - Configurable trackDcaCut{"trackDcaCut", 0.1f, "DCA antid to PV"}; + Configurable trackChi2Cut{"trackChi2Cut", 4.f, "Maximum chi2/ncls in TPC"}; + Configurable> cfgDcaSels{"cfgDcaSels", {dcaSels, 1, 3, particleName, dcaSelsNames}, "DCA selections"}; Configurable v0trackNcrossedRows{"v0trackNcrossedRows", 100, "Minimum number of crossed TPC rows for V0 daughter"}; Configurable v0trackNclusItsCut{"v0trackNclusITScut", 0, "Minimum number of ITS clusters for V0 daughter"}; @@ -236,6 +278,8 @@ struct ebyeMaker { Configurable antidItsClsSizeCut{"antidItsClsSizeCut", 1.e-10f, "cluster size cut for antideuterons"}; Configurable antidPtItsClsSizeCut{"antidPtItsClsSizeCut", 10.f, "pt for cluster size cut for antideuterons"}; + Configurable> cfgTrackSels{"cfgTrackSels", {trackSels, 1, 10, particleName, trackSelsNames}, "Track selections"}; + std::array ptMin; std::array ptTof; std::array ptMax; @@ -247,6 +291,7 @@ struct ebyeMaker { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Preslice perCollisionTracksFull = o2::aod::track::collisionId; + Preslice perCollisionTracksFullPID = o2::aod::track::collisionId; Preslice perCollisionTracksFullIU = o2::aod::track::collisionId; Preslice perCollisionV0 = o2::aod::v0::collisionId; Preslice perCollisionMcParts = o2::aod::mcparticle::mcCollisionId; @@ -264,7 +309,7 @@ struct ebyeMaker { track.tpcNClsShared() > v0trackNsharedClusTpc) { return false; } - if (doprocessRun2 || doprocessMcRun2) { + if (doprocessRun2 || doprocessMiniRun2 || doprocessMcRun2 || doprocessMiniMcRun2) { if (!(track.trackType() & o2::aod::track::Run2Track) || !(track.flags() & o2::aod::track::TPCrefit)) { return false; @@ -289,11 +334,11 @@ struct ebyeMaker { track.tpcNClsFound() < trackNclusTpcCut || track.tpcNClsCrossedRows() < trackNcrossedRows || track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || - track.tpcChi2NCl() > 4.f || + track.tpcChi2NCl() > trackChi2Cut || track.itsChi2NCl() > 36.f) { return false; } - if (doprocessRun2 || doprocessMcRun2) { + if (doprocessRun2 || doprocessMiniRun2 || doprocessMcRun2 || doprocessMiniMcRun2) { if (!(track.trackType() & o2::aod::track::Run2Track) || !(track.flags() & o2::aod::track::TPCrefit) || !(track.flags() & o2::aod::track::ITSrefit)) { @@ -323,13 +368,40 @@ struct ebyeMaker { auto timestamp = bc.timestamp(); o2::parameters::GRPObject* grpo = 0x0; o2::parameters::GRPMagField* grpmag = 0x0; - if (doprocessRun2 || doprocessMcRun2) { + if (doprocessRun2 || doprocessMcRun2 || doprocessMiniRun2 || doprocessMiniMcRun2) { auto grpPath{"GLO/GRP/GRP"}; grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); if (!grpo) { LOG(fatal) << "Got nullptr from CCDB for path " << grpPath << " of object GRPObject for timestamp " << timestamp; } o2::base::Propagator::initFieldFromGRP(grpo); + TList* callst = ccdb->getForTimeStamp("Centrality/Estimators", bc.timestamp()); + auto getccdb = [callst](const char* ccdbhname) { + TH1* h = reinterpret_cast(callst->FindObject(ccdbhname)); + return h; + }; + auto getformulaccdb = [callst](const char* ccdbhname) { + TFormula* f = reinterpret_cast(callst->FindObject(ccdbhname)); + return f; + }; + Run2V0MInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); + Run2V0MInfo.mhVtxAmpCorrV0C = getccdb("hVtx_fAmplitude_V0C_Normalized"); + Run2V0MInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0M"); + Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", genName->c_str()).Data()); + if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) && (Run2V0MInfo.mhMultSelCalib != nullptr)) { + if (genName->length() != 0) { + if (Run2V0MInfo.mMCScale != nullptr) { + for (int ixpar = 0; ixpar < 6; ++ixpar) { + Run2V0MInfo.mMCScalePars[ixpar] = Run2V0MInfo.mMCScale->GetParameter(ixpar); + } + } else { + LOGF(fatal, "MC Scale information from V0M for run %d not available", bc.runNumber()); + } + } + Run2V0MInfo.mCalibrationStored = true; + } else { + LOGF(fatal, "Calibration information from V0M for run %d corrupted", bc.runNumber()); + } } else { auto grpmagPath{"GLO/Config/GRPMagField"}; grpmag = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); @@ -347,6 +419,80 @@ struct ebyeMaker { // o2::base::Propagator::Instance()->setMatLUT(lut); } + template + float getOuterPID(T const& track) + { + if (doprocessMiniRun2 || doprocessMiniMcRun2) { + if (track.hasTOF() && track.pt() > antipPtTof) + return track.tofNSigmaPr(); + // else if (track.pt() < antipPtTof && track.pt() > antipPtMin) { + // return track.tpcNSigmaPr() > -4.f ? track.tpcNSigmaPr() : -999.f; + // } + else + return -999.f; + } + return -999.f; + } + + float getV0M(int64_t const id, float const zvtx, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs) + { + auto fv0a = fv0as.rawIteratorAt(id); + auto fv0c = fv0cs.rawIteratorAt(id); + float multFV0A = 0; + float multFV0C = 0; + for (float amplitude : fv0a.amplitude()) { + multFV0A += amplitude; + } + + for (float amplitude : fv0c.amplitude()) { + multFV0C += amplitude; + } + + float v0m = -1; + auto scaleMC = [](float x, float pars[6]) { + return pow(((pars[0] + pars[1] * pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); + }; + + if (Run2V0MInfo.mMCScale != nullptr) { + float multFV0M = multFV0A + multFV0C; + v0m = scaleMC(multFV0M, Run2V0MInfo.mMCScalePars); + LOGF(debug, "Unscaled v0m: %f, scaled v0m: %f", multFV0M, v0m); + } else { + v0m = multFV0A * Run2V0MInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0A->FindFixBin(zvtx)) + + multFV0C * Run2V0MInfo.mhVtxAmpCorrV0C->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0C->FindFixBin(zvtx)); + } + return v0m; + } + + template + int getTrackSelMask(T const& track) + { + int mask = 0x0; + if (track.tpcncls > cfgTrackSels->get("tpcClsTight")) + mask |= kTPCclsTight; + else if (track.tpcncls > cfgTrackSels->get("tpcClsMid")) + mask |= kTPCclsMid; + if (track.tpcchi2 < cfgTrackSels->get("chi2TpcTight")) + mask |= kChi2TPCTight; + else if (track.tpcchi2 < cfgTrackSels->get("chi2TpcMid")) + mask |= kChi2TPCMid; + if (std::abs(track.dcaxypv) < cfgTrackSels->get("dcaxyTight")) + mask |= kDCAxyTight; + else if (std::abs(track.dcaxypv) < cfgTrackSels->get("dcaxyMid")) + mask |= kDCAxyMid; + if (std::abs(track.dcazpv) < cfgTrackSels->get("dcazTight")) + mask |= kDCAzTight; + else if (std::abs(track.dcazpv) < cfgTrackSels->get("dcazMid")) + mask |= kDCAzMid; + if (std::abs(track.tpcnsigma) < cfgTrackSels->get("tpcNsigmaTight")) + mask |= kTPCPIDTight; + else if (std::abs(track.tpcnsigma) < cfgTrackSels->get("tpcNsigmaMid")) + mask |= kTPCPIDMid; + // if (track.itsnsigma < 2) mask |= kITSPIDTight; + // else if (track.itsnsigma < 3) mask |= kITSPIDMid; + return mask; + } + void init(o2::framework::InitContext&) { @@ -376,9 +522,11 @@ struct ebyeMaker { if (doprocessRun3) { histos.add("QA/PvMultVsCent", ";Centrality T0C (%);#it{N}_{PV contributors};", HistType::kTH2F, {centAxis, multAxis}); histos.add("QA/MultVsCent", ";Centrality T0C (%);Multiplicity T0C;", HistType::kTH2F, {centAxis, multFt0Axis}); - } else if (doprocessRun2) { + } else if (doprocessRun2 || doprocessMiniRun2 || doprocessMcRun2 || doprocessMiniMcRun2) { histos.add("QA/V0MvsCL0", ";Centrality CL0 (%);Centrality V0M (%)", HistType::kTH2F, {centAxis, centAxis}); histos.add("QA/trackletsVsV0M", ";Centrality CL0 (%);Centrality V0M (%)", HistType::kTH2F, {centAxis, multAxis}); + histos.add("QA/nTrklCorrelation", ";Tracklets |#eta| > 0.6; Tracklets |#eta| < 0.6", HistType::kTH2D, {{201, -0.5, 200.5}, {201, -0.5, 200.5}}); + histos.add("QA/TrklEta", ";Tracklets #eta; Entries", HistType::kTH1D, {{100, -3., 3.}}); } // v0 QA @@ -386,6 +534,7 @@ struct ebyeMaker { // antid and antip QA histos.add("QA/tpcSignal", ";#it{p}_{TPC} (GeV/#it{c});d#it{E}/d#it{x}_{TPC} (a.u.)", HistType::kTH2F, {momAxis, tpcAxis}); + histos.add("QA/tpcSignalPr", ";#it{p}_{TPC} (GeV/#it{c});d#it{E}/d#it{x}_{TPC} (a.u.)", HistType::kTH2F, {momAxis, tpcAxis}); tofMass[0] = histos.add("QA/tofMass_p", ";Centrality (%);#it{p}_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, tofMassAxis}); tofMass[1] = histos.add("QA/tofMass_d", ";Centrality (%);#it{p}_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, tofMassAxis}); @@ -399,17 +548,33 @@ struct ebyeMaker { tofMassMax = std::array{antipTofMassMax, antidTofMassMax}; } + template + auto tracksSlice(T const& tracksAll, uint64_t const& collId) + { + if (doprocessRun3 || doprocessMcRun3) + return tracksAll.sliceBy(perCollisionTracksFullIU, collId); + else if (doprocessRun2 || doprocessMcRun2) + return tracksAll.sliceBy(perCollisionTracksFull, collId); + else + return tracksAll.sliceBy(perCollisionTracksFullPID, collId); + } + template void fillRecoEvent(C const& collision, T const& tracksAll, aod::V0s const& V0s, float const& centrality) { - auto tracks = (doprocessRun3 || doprocessMcRun3) ? tracksAll.sliceBy(perCollisionTracksFullIU, collision.globalIndex()) : tracksAll.sliceBy(perCollisionTracksFull, collision.globalIndex()); + auto tracks = tracksSlice(tracksAll, collision.globalIndex()); candidateTracks[0].clear(); candidateTracks[1].clear(); candidateV0s.clear(); gpu::gpustd::array dcaInfo; + int nTracklets[2]{0, 0}; for (const auto& track : tracks) { + if (track.trackType() == 255 && std::abs(track.eta()) < 1.2) { // tracklet + nTracklets[std::abs(track.eta()) < 0.6]++; + } + if (!selectTrack(track)) { continue; } @@ -419,7 +584,10 @@ struct ebyeMaker { auto dca = std::hypot(dcaInfo[0], dcaInfo[1]); auto trackPt = trackParCov.getPt(); auto trackEta = trackParCov.getEta(); - if (dca > trackDcaCut) { + if (dca > cfgDcaSels->get("dca")) { // dca + continue; + } + if (std::abs(dcaInfo[0]) > cfgDcaSels->get("dcaxy") || std::abs(dcaInfo[1]) > cfgDcaSels->get("dcaz")) { // dcaxy and dcaz continue; } histos.fill(HIST("QA/tpcSignal"), track.tpcInnerParam(), track.tpcSignal()); @@ -469,157 +637,170 @@ struct ebyeMaker { candTrack.eta = trackEta; candTrack.mass = iP; candTrack.dcapv = dca; + candTrack.dcaxypv = dcaInfo[0]; + candTrack.dcazpv = dcaInfo[1]; + candTrack.tpcchi2 = track.tpcChi2NCl(); candTrack.tpcncls = track.tpcNClsFound(); candTrack.tpcnsigma = nSigmaTPC; candTrack.tofmass = hasTof ? mass : -999.f; candTrack.globalIndex = track.globalIndex(); + candTrack.outerPID = nSigmaTPC; candidateTracks[iP].push_back(candTrack); } } } + if (doprocessRun2 || doprocessMcRun2 || doprocessMiniRun2 || doprocessMiniMcRun2) { + histos.fill(HIST("QA/nTrklCorrelation"), nTracklets[0], nTracklets[1]); + nTrackletsColl = nTracklets[1]; + } - std::vector trkId; - for (const auto& v0 : V0s) { - auto posTrack = v0.posTrack_as(); - auto negTrack = v0.negTrack_as(); + if (lambdaPtMax > lambdaPtMin) { + std::vector trkId; + for (const auto& v0 : V0s) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); - bool posSelect = selectV0Daughter(posTrack); - bool negSelect = selectV0Daughter(negTrack); - if (!posSelect || !negSelect) - continue; + bool posSelect = selectV0Daughter(posTrack); + bool negSelect = selectV0Daughter(negTrack); + if (!posSelect || !negSelect) + continue; + + if (doprocessRun2 || doprocessMiniRun2 || doprocessMcRun2 || doprocessMiniMcRun2) { + bool checkPosPileUp = posTrack.hasTOF() || (posTrack.flags() & o2::aod::track::ITSrefit); + bool checkNegPileUp = negTrack.hasTOF() || (negTrack.flags() & o2::aod::track::ITSrefit); + if (!checkPosPileUp && !checkNegPileUp) { + continue; + } + } + + auto posTrackCov = getTrackParCov(posTrack); + auto negTrackCov = getTrackParCov(negTrack); - if (doprocessRun2 || doprocessMcRun2) { - bool checkPosPileUp = posTrack.hasTOF() || (posTrack.flags() & o2::aod::track::ITSrefit); - bool checkNegPileUp = negTrack.hasTOF() || (negTrack.flags() & o2::aod::track::ITSrefit); - if (!checkPosPileUp && !checkNegPileUp) { + int nCand = 0; + try { + nCand = fitter.process(posTrackCov, negTrackCov); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + continue; + } + if (nCand == 0) { continue; } - } - auto posTrackCov = getTrackParCov(posTrack); - auto negTrackCov = getTrackParCov(negTrack); + auto& posPropTrack = fitter.getTrack(0); + auto& negPropTrack = fitter.getTrack(1); - int nCand = 0; - try { - nCand = fitter.process(posTrackCov, negTrackCov); - } catch (...) { - LOG(error) << "Exception caught in DCA fitter process call!"; - continue; - } - if (nCand == 0) { - continue; - } + std::array momPos; + std::array momNeg; + std::array momV0; + posPropTrack.getPxPyPzGlo(momPos); + negPropTrack.getPxPyPzGlo(momNeg); + momTotXYZ(momV0, momPos, momNeg); - auto& posPropTrack = fitter.getTrack(0); - auto& negPropTrack = fitter.getTrack(1); + auto ptV0 = std::hypot(momV0[0], momV0[1]); + if (ptV0 < lambdaPtMin || ptV0 > lambdaPtMax) { + continue; + } - std::array momPos; - std::array momNeg; - std::array momV0; - posPropTrack.getPxPyPzGlo(momPos); - negPropTrack.getPxPyPzGlo(momNeg); - momTotXYZ(momV0, momPos, momNeg); + auto etaV0 = etaFromMom(momPos, momNeg); + if (std::abs(etaV0) > etaMax) { + continue; + } - auto ptV0 = std::hypot(momV0[0], momV0[1]); - if (ptV0 < lambdaPtMin || ptV0 > lambdaPtMax) { - continue; - } + auto alpha = alphaAP(momV0, momPos, momNeg); + bool matter = alpha > 0; + auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; + auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; + auto mLambda = invMass2Body(momV0, momPos, momNeg, massPos, massNeg); + auto mK0Short = invMass2Body(momV0, momPos, momNeg, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged); + + // pid selections + double expBethePos{tpc::BetheBlochAleph(static_cast(posTrack.tpcInnerParam() / massPos), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; + double expSigmaPos{expBethePos * cfgBetheBlochParams->get("resolution")}; + auto nSigmaTPCPos = static_cast((posTrack.tpcSignal() - expBethePos) / expSigmaPos); + double expBetheNeg{tpc::BetheBlochAleph(static_cast(negTrack.tpcInnerParam() / massNeg), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; + double expSigmaNeg{expBetheNeg * cfgBetheBlochParams->get("resolution")}; + auto nSigmaTPCNeg = static_cast((negTrack.tpcSignal() - expBetheNeg) / expSigmaNeg); + float tpcSigPr = matter ? posTrack.tpcSignal() : negTrack.tpcSignal(); + + if (std::abs(nSigmaTPCPos) > v0setting_nsigmatpc || std::abs(nSigmaTPCNeg) > v0setting_nsigmatpc) { + continue; + } - auto etaV0 = etaFromMom(momPos, momNeg); - if (std::abs(etaV0) > etaMax) { - continue; - } + // veto on K0s mass + if (std::abs(mK0Short - o2::constants::physics::MassK0Short) < vetoMassK0Short) { + continue; + } - auto alpha = alphaAP(momV0, momPos, momNeg); - bool matter = alpha > 0; - auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; - auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; - auto mLambda = invMass2Body(momV0, momPos, momNeg, massPos, massNeg); - auto mK0Short = invMass2Body(momV0, momPos, momNeg, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged); - - // pid selections - double expBethePos{tpc::BetheBlochAleph(static_cast(posTrack.tpcInnerParam() / massPos), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; - double expSigmaPos{expBethePos * cfgBetheBlochParams->get("resolution")}; - auto nSigmaTPCPos = static_cast((posTrack.tpcSignal() - expBethePos) / expSigmaPos); - double expBetheNeg{tpc::BetheBlochAleph(static_cast(negTrack.tpcInnerParam() / massNeg), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; - double expSigmaNeg{expBetheNeg * cfgBetheBlochParams->get("resolution")}; - auto nSigmaTPCNeg = static_cast((negTrack.tpcSignal() - expBetheNeg) / expSigmaNeg); - - if (std::abs(nSigmaTPCPos) > v0setting_nsigmatpc || std::abs(nSigmaTPCNeg) > v0setting_nsigmatpc) { - continue; - } + float dcaV0dau = std::sqrt(fitter.getChi2AtPCACandidate()); + if (dcaV0dau > v0setting_dcav0dau) { + continue; + } - // veto on K0s mass - if (std::abs(mK0Short - o2::constants::physics::MassK0Short) < vetoMassK0Short) { - continue; - } + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; + const auto& vtx = fitter.getPCACandidate(); - float dcaV0dau = std::sqrt(fitter.getChi2AtPCACandidate()); - if (dcaV0dau > v0setting_dcav0dau) { - continue; - } + float radiusV0 = std::hypot(vtx[0], vtx[1]); + if (radiusV0 < v0setting_radius || radiusV0 > v0radiusMax) { + continue; + } - std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; - const auto& vtx = fitter.getPCACandidate(); + float dcaV0Pv = CalculateDCAStraightToPV( + vtx[0], vtx[1], vtx[2], + momPos[0] + momNeg[0], + momPos[1] + momNeg[1], + momPos[2] + momNeg[2], + collision.posX(), collision.posY(), collision.posZ()); + if (std::abs(dcaV0Pv) > v0setting_dcav0pv) { + continue; + } - float radiusV0 = std::hypot(vtx[0], vtx[1]); - if (radiusV0 < v0setting_radius || radiusV0 > v0radiusMax) { - continue; - } + double cosPA = RecoDecay::cpa(primVtx, vtx, momV0); + if (cosPA < v0setting_cospa) { + continue; + } - float dcaV0Pv = CalculateDCAStraightToPV( - vtx[0], vtx[1], vtx[2], - momPos[0] + momNeg[0], - momPos[1] + momNeg[1], - momPos[2] + momNeg[2], - collision.posX(), collision.posY(), collision.posZ()); - if (std::abs(dcaV0Pv) > v0setting_dcav0pv) { - continue; - } + auto ptotal = RecoDecay::sqrtSumOfSquares(momV0[0], momV0[1], momV0[2]); + auto lengthTraveled = RecoDecay::sqrtSumOfSquares(vtx[0] - primVtx[0], vtx[1] - primVtx[1], vtx[2] - primVtx[2]); + float ML2P_Lambda = o2::constants::physics::MassLambda * lengthTraveled / ptotal; + if (ML2P_Lambda > v0setting_lifetime) { + continue; + } - double cosPA = RecoDecay::cpa(primVtx, vtx, momV0); - if (cosPA < v0setting_cospa) { - continue; - } + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); + auto posDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); + if (posDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { + continue; + } - auto ptotal = RecoDecay::sqrtSumOfSquares(momV0[0], momV0[1], momV0[2]); - auto lengthTraveled = RecoDecay::sqrtSumOfSquares(vtx[0] - primVtx[0], vtx[1] - primVtx[1], vtx[2] - primVtx[2]); - float ML2P_Lambda = o2::constants::physics::MassLambda * lengthTraveled / ptotal; - if (ML2P_Lambda > v0setting_lifetime) { - continue; - } + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); + auto negDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); + if (negDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { + continue; + } - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); - auto posDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (posDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { - continue; - } + if (std::abs(mLambda - o2::constants::physics::MassLambda0) > lambdaMassCut) { // for QA histograms + continue; + } + histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); - auto negDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (negDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { - continue; - } + histos.fill(HIST("QA/tpcSignalPr"), matter > 0. ? posTrack.tpcInnerParam() : negTrack.tpcInnerParam(), tpcSigPr); - if (std::abs(mLambda - o2::constants::physics::MassLambda0) > lambdaMassCut) { // for QA histograms - continue; + CandidateV0 candV0; + candV0.pt = matter > 0. ? ptV0 : -ptV0; + candV0.eta = etaV0; + candV0.mass = mLambda; + candV0.cpa = cosPA; + candV0.dcav0daugh = dcaV0dau; + candV0.dcav0pv = dcaV0Pv; + candV0.dcanegpv = negDcaToPv; + candV0.dcapospv = posDcaToPv; + candV0.tpcnsigmaneg = nSigmaTPCNeg; + candV0.tpcnsigmapos = nSigmaTPCPos; + candV0.globalIndexPos = posTrack.globalIndex(); + candV0.globalIndexNeg = negTrack.globalIndex(); + candidateV0s.push_back(candV0); } - histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); - - CandidateV0 candV0; - candV0.pt = matter > 0. ? ptV0 : -ptV0; - candV0.eta = etaV0; - candV0.mass = mLambda; - candV0.cpa = cosPA; - candV0.dcav0daugh = dcaV0dau; - candV0.dcav0pv = dcaV0Pv; - candV0.dcanegpv = negDcaToPv; - candV0.dcapospv = posDcaToPv; - candV0.tpcnsigmaneg = nSigmaTPCNeg; - candV0.tpcnsigmapos = nSigmaTPCPos; - candV0.globalIndexPos = posTrack.globalIndex(); - candV0.globalIndexNeg = negTrack.globalIndex(); - candidateV0s.push_back(candV0); } } @@ -637,7 +818,7 @@ struct ebyeMaker { auto mcTrack = mcLab.template mcParticle_as(); if (std::abs(mcTrack.pdgCode()) != partPdg[iP]) continue; - if (((mcTrack.flags() & 0x8) && doprocessMcRun2) || (mcTrack.flags() & 0x2) || (mcTrack.flags() & 0x1)) + if (((mcTrack.flags() & 0x8) && (doprocessMcRun2 || doprocessMiniMcRun2)) || (mcTrack.flags() & 0x2) || (mcTrack.flags() & 0x1)) continue; if (!mcTrack.isPhysicalPrimary()) continue; @@ -670,7 +851,7 @@ struct ebyeMaker { } if (!posMother.isPhysicalPrimary() && !posMother.has_mothers()) continue; - if (((posMother.flags() & 0x8) && doprocessMcRun2) || (posMother.flags() & 0x2) || (posMother.flags() & 0x1)) + if (((posMother.flags() & 0x8) && (doprocessMcRun2 || doprocessMiniMcRun2)) || (posMother.flags() & 0x2) || (posMother.flags() & 0x1)) continue; auto genPt = std::hypot(posMother.px(), posMother.py()); @@ -693,7 +874,7 @@ struct ebyeMaker { if (std::abs(genEta) > etaMax) { continue; } - if (((mcPart.flags() & 0x8) && doprocessMcRun2) || (mcPart.flags() & 0x2) || (mcPart.flags() & 0x1)) + if (((mcPart.flags() & 0x8) && (doprocessMcRun2 || doprocessMiniMcRun2)) || (mcPart.flags() & 0x2) || (mcPart.flags() & 0x1)) continue; auto pdgCode = mcPart.pdgCode(); if (std::abs(pdgCode) == 3122) { @@ -718,7 +899,7 @@ struct ebyeMaker { if (it != candidateV0s.end()) { continue; } else { - LOGF(info, "not found!"); + LOGF(debug, "not found!"); candidateV0s.emplace_back(candV0); } } else if (std::abs(pdgCode) == partPdg[0] || std::abs(pdgCode) == partPdg[1]) { @@ -805,7 +986,7 @@ struct ebyeMaker { } PROCESS_SWITCH(ebyeMaker, processRun3, "process (Run 3)", false); - void processRun2(soa::Join const& collisions, TracksFull const& tracks, aod::V0s const& V0s, BCsWithRun2Info const&) + void processRun2(soa::Join const& collisions, TracksFull const& tracks, aod::V0s const& V0s, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, BCsWithRun2Info const&) { for (const auto& collision : collisions) { auto bc = collision.bc_as(); @@ -820,8 +1001,9 @@ struct ebyeMaker { if (kUseTPCPileUpCut && !(bc.eventCuts() & BIT(aod::Run2EventCuts::kTPCPileUp))) continue; - auto centrality = collision.centRun2V0M(); - if (!(collision.sel7() && collision.alias_bit(kINT7)) && (!kINT7Intervals || (kINT7Intervals && ((centrality >= 10 && centrality < 30) || centrality > 50)))) + float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); + float cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); + if (!(collision.sel7() && collision.alias_bit(kINT7)) && (!kINT7Intervals || (kINT7Intervals && ((cV0M >= 10 && cV0M < 30) || cV0M > 50)))) continue; auto centralityCl0 = collision.centRun2CL0(); @@ -829,7 +1011,7 @@ struct ebyeMaker { const auto& x = centralityCl0; const double center = estimatorsCorrelationCoef[0] + estimatorsCorrelationCoef[1] * x; const double sigma = estimatorsSigmaPars[0] + estimatorsSigmaPars[1] * x + estimatorsSigmaPars[2] * std::pow(x, 2) + estimatorsSigmaPars[3] * std::pow(x, 3); - if (centrality < center - deltaEstimatorNsigma[0] * sigma || centrality > center + deltaEstimatorNsigma[1] * sigma) { + if (cV0M < center - deltaEstimatorNsigma[0] * sigma || cV0M > center + deltaEstimatorNsigma[1] * sigma) { continue; } } @@ -841,12 +1023,12 @@ struct ebyeMaker { V0Table_thisCollision.bindExternalIndices(&tracks); auto multTracklets = collision.multTracklets(); - fillRecoEvent(collision, tracks, V0Table_thisCollision, centrality); + fillRecoEvent(collision, tracks, V0Table_thisCollision, cV0M); - histos.fill(HIST("QA/V0MvsCL0"), centralityCl0, centrality); - histos.fill(HIST("QA/trackletsVsV0M"), centrality, multTracklets); + histos.fill(HIST("QA/V0MvsCL0"), centralityCl0, cV0M); + histos.fill(HIST("QA/trackletsVsV0M"), cV0M, multTracklets); - collisionEbyeTable(centrality, collision.posZ()); + collisionEbyeTable(cV0M, collision.posZ()); for (auto& candidateV0 : candidateV0s) { lambdaEbyeTable( @@ -880,6 +1062,54 @@ struct ebyeMaker { } PROCESS_SWITCH(ebyeMaker, processRun2, "process (Run 2)", false); + void processMiniRun2(soa::Join const& collisions, TracksFullPID const& tracks, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::V0s const& V0s, BCsWithRun2Info const&) + { + + for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (std::abs(collision.posZ()) > zVtxMax) + continue; + + if (!collision.alias_bit(kINT7)) + continue; + + if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) + continue; + + float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); + float cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); + + histos.fill(HIST("QA/zVtx"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); + V0Table_thisCollision.bindExternalIndices(&tracks); + + fillRecoEvent(collision, tracks, V0Table_thisCollision, cV0M); + + uint8_t trigger = collision.alias_bit(kINT7) ? 0x1 : 0x0; + miniCollTable(std::abs(collision.posZ()), trigger, nTrackletsColl, cV0M); + + for (auto& candidateTrack : candidateTracks[0]) { // protons + auto tk = tracks.rawIteratorAt(candidateTrack.globalIndex); + float outerPID = getOuterPID(tk); + candidateTrack.outerPID = tk.pt() < antipPtTof ? candidateTrack.outerPID : outerPID; + int selMask = getTrackSelMask(candidateTrack); + if (candidateTrack.outerPID < -4) + continue; + miniTrkTable( + miniCollTable.lastIndex(), + candidateTrack.pt, + std::abs(candidateTrack.eta) * 10., + selMask, + candidateTrack.outerPID); + } + } + } + PROCESS_SWITCH(ebyeMaker, processMiniRun2, "process mini tables(Run 2)", false); + void processMcRun3(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullIU const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, aod::BCsWithTimestamps const&) { for (auto& collision : collisions) { @@ -948,7 +1178,7 @@ struct ebyeMaker { } PROCESS_SWITCH(ebyeMaker, processMcRun3, "process MC (Run 3)", false); - void processMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFull const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) + void processMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFull const& tracks, aod::V0s const& V0s, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) { for (auto& collision : collisions) { auto bc = collision.bc_as(); @@ -960,7 +1190,8 @@ struct ebyeMaker { if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) continue; - auto centrality = collision.centRun2V0M(); + float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); + float cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); histos.fill(HIST("QA/zVtx"), collision.posZ()); @@ -968,10 +1199,10 @@ struct ebyeMaker { auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); V0Table_thisCollision.bindExternalIndices(&tracks); - fillMcEvent(collision, tracks, V0Table_thisCollision, centrality, mcParticles, mcLab); + fillMcEvent(collision, tracks, V0Table_thisCollision, cV0M, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - collisionEbyeTable(centrality, collision.posZ()); + collisionEbyeTable(cV0M, collision.posZ()); for (auto& candidateV0 : candidateV0s) { mcLambdaEbyeTable( @@ -1012,6 +1243,57 @@ struct ebyeMaker { } } PROCESS_SWITCH(ebyeMaker, processMcRun2, "process MC (Run 2)", false); + + void processMiniMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullPID const& tracks, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) + { + + for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (std::abs(collision.posZ()) > zVtxMax) + continue; + + if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) + continue; + + float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); + float cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); + + histos.fill(HIST("QA/zVtx"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); + V0Table_thisCollision.bindExternalIndices(&tracks); + + fillMcEvent(collision, tracks, V0Table_thisCollision, cV0M, mcParticles, mcLab); + fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); + + miniCollTable(std::abs(collision.posZ()), 0x0, nTrackletsColl, cV0M); + + for (auto& candidateTrack : candidateTracks[0]) { // protons + int selMask = -1; + if (candidateTrack.isreco) { + auto tk = tracks.rawIteratorAt(candidateTrack.globalIndex); + float outerPID = getOuterPID(tk); + candidateTrack.outerPID = tk.pt() < antipPtTof ? candidateTrack.outerPID : outerPID; + selMask = getTrackSelMask(candidateTrack); + // if (candidateTrack.outerPID < -4) + // continue; + } + mcMiniTrkTable( + miniCollTable.lastIndex(), + candidateTrack.pt, + std::abs(candidateTrack.eta) * 10., + selMask, + candidateTrack.outerPID, + candidateTrack.pdgcode > 0 ? candidateTrack.genpt : -candidateTrack.genpt, + candidateTrack.geneta, + candidateTrack.isreco); + } + } + } + PROCESS_SWITCH(ebyeMaker, processMiniMcRun2, "process mini tables for mc(Run 2)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/TableProducer/Nuspex/hyperKinkRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperKinkRecoTask.cxx index d1fa0730ba4..658ab180d67 100644 --- a/PWGLF/TableProducer/Nuspex/hyperKinkRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperKinkRecoTask.cxx @@ -369,7 +369,6 @@ struct hyperKinkRecoTask { continue; int pdgHypo = isHyp ? hyperPdg : tritDauPdg; - svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); } auto& kinkPool = svCreator.getSVCandPool(collisions, !unlikeSignBkg); @@ -382,7 +381,7 @@ struct hyperKinkRecoTask { auto trackHyper = tracks.rawIteratorAt(svCand.tr0Idx); auto trackTrit = tracks.rawIteratorAt(svCand.tr1Idx); - auto const& collision = trackHyper.template collision_as(); + auto const& collision = trackHyper.template collision_as(); o2::dataformats::VertexBase primaryVertex; primaryVertex.setPos({collision.posX(), collision.posY(), collision.posZ()}); primaryVertex.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index e39df06c810..b3eec29372b 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -30,6 +30,9 @@ #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + #include "Common/Core/PID/TPCPIDResponse.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DCAFitter/DCAFitterN.h" @@ -99,6 +102,7 @@ struct hyperCandidate { std::array gDecVtx; uint16_t tpcSignalHe3 = 0u; uint16_t tpcSignalPi = 0u; + float tpcChi2He3 = 0.f; uint8_t nTPCClustersHe3 = 0u; uint8_t nTPCClustersPi = 0u; uint32_t clusterSizeITSHe3 = 0u; @@ -122,6 +126,8 @@ struct hyperRecoTask { Produces outputDataTableWithFlow; Produces outputMCTable; Service ccdb; + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; // PDG codes Configurable hyperPdg{"hyperPDG", 1010010030, "PDG code of the hyper-mother (could be 3LamH or 4LamH)"}; @@ -139,6 +145,7 @@ struct hyperRecoTask { Configurable nTPCClusMinHe{"nTPCClusMinHe", 70, "helium NTPC clusters cut"}; Configurable nTPCClusMinPi{"nTPCClusMinPi", -1., "pion NTPC clusters cut"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; // Define o2 fitter, 2-prong, active memory (no need to redefine per event) o2::vertexing::DCAFitterN<2> fitter; @@ -180,7 +187,7 @@ struct hyperRecoTask { std::vector recoCollisionIds; std::vector isSurvEvSelCollision; std::vector goodCollision; - std::vector isTracked; + std::vector trackedClSize; Preslice perCollision = o2::aod::v0::collisionId; @@ -193,6 +200,8 @@ struct hyperRecoTask { void init(InitContext const&) { + zorroSummary.setObject(zorro.getZorroSummary()); + mRunNumber = 0; d_bz = 0; @@ -230,9 +239,10 @@ struct hyperRecoTask { hH4LMassBefSel = qaRegistry.add("hH4LMassBefSel", ";M (GeV/#it{c}^{2}); ", HistType::kTH1D, {{60, 3.76, 3.84}}); hH4LMassTracked = qaRegistry.add("hH4LMassTracked", ";M (GeV/#it{c}^{2}); ", HistType::kTH1D, {{60, 3.76, 3.84}}); - hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{2, -0.5, 1.5}}); + hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{3, -0.5, 2.5}}); hEvents->GetXaxis()->SetBinLabel(1, "All"); hEvents->GetXaxis()->SetBinLabel(2, "Selected"); + hEvents->GetXaxis()->SetBinLabel(3, "Zorro He events"); if (doprocessMC) { hDecayChannel = qaRegistry.add("hDecayChannel", ";Decay channel; ", HistType::kTH1D, {{2, -0.5, 1.5}}); hDecayChannel->GetXaxis()->SetBinLabel(1, "2-body"); @@ -255,6 +265,10 @@ struct hyperRecoTask { if (mRunNumber == bc.runNumber()) { return; } + if (cfgSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fHe"); + zorro.populateHistRegistry(qaRegistry, bc.runNumber()); + } auto run3grp_timestamp = bc.timestamp(); o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); @@ -317,6 +331,13 @@ struct hyperRecoTask { continue; } + if (cfgSkimmedProcessing) { + bool zorroSelected = zorro.isSelected(collision.template bc_as().globalBC()); /// Just let Zorro do the accounting + if (zorroSelected) { + hEvents->Fill(2.); + } + } + goodCollision[collision.globalIndex()] = true; hEvents->Fill(1.); hZvtx->Fill(collision.posZ()); @@ -362,9 +383,12 @@ struct hyperRecoTask { hypCand.clusterSizeITSHe3 = heTrack.itsClusterSizes(); hypCand.nTPCClustersPi = piTrack.tpcNClsFound(); hypCand.tpcSignalPi = piTrack.tpcSignal(); + hypCand.tpcChi2He3 = heTrack.tpcChi2NCl(); hypCand.clusterSizeITSPi = piTrack.itsClusterSizes(); bool heliumPID = heTrack.pidForTracking() == o2::track::PID::Helium3 || heTrack.pidForTracking() == o2::track::PID::Alpha; hypCand.momHe3TPC = (heliumPID && cfgCompensatePIDinTracking) ? heTrack.tpcInnerParam() / 2 : heTrack.tpcInnerParam(); + if (hypCand.momHe3TPC < TPCRigidityMinHe) + return; hypCand.momPiTPC = piTrack.tpcInnerParam(); hDeDxTot->Fill(hypCand.momHe3TPC * heTrack.sign(), heTrack.tpcSignal()); hDeDxTot->Fill(hypCand.momPiTPC * piTrack.sign(), piTrack.tpcSignal()); @@ -420,7 +444,7 @@ struct hyperRecoTask { hH3LMassBefSel->Fill(massH3L); hH4LMassBefSel->Fill(massH4L); - if (!isTracked.empty() && isTracked[hypCand.v0ID]) { + if (!trackedClSize.empty() && trackedClSize[hypCand.v0ID] > 0) { hH3LMassTracked->Fill(massH3L); hH4LMassTracked->Fill(massH4L); } @@ -476,7 +500,7 @@ struct hyperRecoTask { hypCand.collisionID = collision.globalIndex(); hDeDx3HeSel->Fill(heTrack.sign() * hypCand.momHe3TPC, heTrack.tpcSignal()); - hNsigma3HeSel->Fill(hypCand.momPiTPC * hypCand.momHe3TPC, hypCand.nSigmaHe3); + hNsigma3HeSel->Fill(heTrack.sign() * hypCand.momHe3TPC, hypCand.nSigmaHe3); hyperCandidates.push_back(hypCand); } @@ -598,10 +622,10 @@ struct hyperRecoTask { void processDataTracked(CollisionsFull const& collisions, aod::V0s const& V0s, aod::TrackedV0s const& tV0s, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const& bcs) { - isTracked.clear(); - isTracked.resize(V0s.size(), false); + trackedClSize.clear(); + trackedClSize.resize(V0s.size(), 0); for (const auto& tV0 : tV0s) { - isTracked[tV0.v0Id()] = true; + trackedClSize[tV0.v0Id()] = tV0.itsClsSize(); } processData(collisions, V0s, tracks, ambiTracks, bcs); } @@ -618,6 +642,7 @@ struct hyperRecoTask { for (auto& hypCand : hyperCandidates) { auto collision = collisions.rawIteratorAt(hypCand.collisionID); + float trackedHypClSize = !trackedClSize.empty() ? trackedClSize[hypCand.v0ID] : 0; outputDataTable(collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ(), hypCand.isMatter, @@ -626,8 +651,8 @@ struct hyperRecoTask { hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, - hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, - hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, !isTracked.empty() && isTracked[hypCand.v0ID]); + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, + hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); } } PROCESS_SWITCH(hyperRecoTask, processData, "Data analysis", true); @@ -644,6 +669,7 @@ struct hyperRecoTask { for (auto& hypCand : hyperCandidates) { auto collision = collisions.rawIteratorAt(hypCand.collisionID); + float trackedHypClSize = !trackedClSize.empty() ? trackedClSize[hypCand.v0ID] : 0; outputDataTableWithFlow(collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.psiFT0A(), collision.multFT0A(), collision.psiFT0C(), collision.multFT0C(), @@ -655,8 +681,8 @@ struct hyperRecoTask { hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, - hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, - hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, !isTracked.empty() && isTracked[hypCand.v0ID]); + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, + hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); } } PROCESS_SWITCH(hyperRecoTask, processDataWithFlow, "Data analysis with flow", false); @@ -680,6 +706,7 @@ struct hyperRecoTask { if (!hypCand.isSignal && mcSignalOnly) continue; int chargeFactor = -1 + 2 * (hypCand.pdgCode > 0); + float trackedHypClSize = !trackedClSize.empty() ? trackedClSize[hypCand.v0ID] : 0; outputMCTable(collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ(), hypCand.isMatter, @@ -688,8 +715,8 @@ struct hyperRecoTask { hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, - hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, - hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, !isTracked.empty() && isTracked[hypCand.v0ID], + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, + hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize, chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), hypCand.gDecVtx[0], hypCand.gDecVtx[1], hypCand.gDecVtx[2], hypCand.isReco, hypCand.isSignal, hypCand.isRecoMCCollision, hypCand.isSurvEvSelection); @@ -761,7 +788,7 @@ struct hyperRecoTask { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, false, chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), hypCand.gDecVtx[0], hypCand.gDecVtx[1], hypCand.gDecVtx[2], @@ -772,10 +799,10 @@ struct hyperRecoTask { void processMCTracked(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, aod::V0s const& V0s, aod::TrackedV0s const& tV0s, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const& bcs, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC) { - isTracked.clear(); - isTracked.resize(V0s.size(), false); + trackedClSize.clear(); + trackedClSize.resize(V0s.size(), 0); for (const auto& tV0 : tV0s) { - isTracked[tV0.v0Id()] = true; + trackedClSize[tV0.v0Id()] = tV0.itsClsSize(); } processMC(collisions, mcCollisions, V0s, tracks, ambiTracks, bcs, trackLabelsMC, particlesMC); } diff --git a/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx b/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx index 52f038356dc..b4445a5619a 100644 --- a/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx +++ b/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx @@ -687,14 +687,17 @@ struct hypertriton3bodyFinder { auto Track0Par = getTrackPar(dPtrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track0Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); auto Track0dcaXY = dcaInfo[0]; + auto Track0dca = std::sqrt(Track0dcaXY * Track0dcaXY + dcaInfo[1] * dcaInfo[1]); auto Track1Par = getTrackPar(dNtrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track1Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); auto Track1dcaXY = dcaInfo[0]; + auto Track1dca = std::sqrt(Track1dcaXY * Track1dcaXY + dcaInfo[1] * dcaInfo[1]); auto Track2Par = getTrackPar(dBachtrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track2Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); auto Track2dcaXY = dcaInfo[0]; + auto Track2dca = std::sqrt(Track2dcaXY * Track2dcaXY + dcaInfo[1] * dcaInfo[1]); // H3L DCA Check // auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, fitter3body.calcPCACovMatrixFlat(), t2.sign()); @@ -712,6 +715,7 @@ struct hypertriton3bodyFinder { p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], fitter3body.getChi2AtPCACandidate(), Track0dcaXY, Track1dcaXY, Track2dcaXY, + Track0dca, Track1dca, Track2dca, 0); // To be fixed } //------------------------------------------------------------------ diff --git a/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx b/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx index 20e717836a1..6ad6afd931a 100644 --- a/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx +++ b/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx @@ -32,22 +32,33 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +// #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Framework/HistogramRegistry.h" +#include "Common/DataModel/Multiplicity.h" #include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Framework/ASoAHelpers.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "CCDB/BasicCCDBManager.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" + +#include "Common/Core/PID/TPCPIDResponse.h" #include "PWGLF/DataModel/LFLithium4Tables.h" +#include "PWGLF/Utils/svPoolCreator.h" using namespace o2; using namespace o2::framework; @@ -61,13 +72,12 @@ static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", constexpr float he3Mass = o2::constants::physics::MassHelium3; constexpr float protonMass = o2::constants::physics::MassProton; -constexpr int lithium4PDG = 1000030040; -constexpr int protonPDG = 2212; -constexpr int he3PDG = 1000020030; +constexpr int li4PDG = 1000030040; +constexpr int prPDG = 2212; +constexpr int hePDG = 1000020030; enum Selections { kNoCuts = 0, - kGlobalTrack, kTrackCuts, kPID, kAll @@ -75,9 +85,11 @@ enum Selections { } // namespace -struct lithium4Candidate { +struct Lithium4Candidate { float sign = 0.f; + std::array momHe3 = {99.f, 99.f, 99.f}; + std::array momPr = {99.f, 99.f, 99.f}; float recoPtHe3() const { return sign * std::hypot(momHe3[0], momHe3[1]); } float recoPhiHe3() const { return std::atan2(momHe3[1], momHe3[0]); } @@ -86,100 +98,179 @@ struct lithium4Candidate { float recoPhiPr() const { return std::atan2(momPr[1], momPr[0]); } float recoEtaPr() const { return std::asinh(momPr[2] / recoPtPr()); } - std::array momHe3 = {99.f, 99.f, 99.f}; - std::array momPr = {99.f, 99.f, 99.f}; - - uint32_t PIDtrkHe3 = 0xFFFFF; // PID in tracking - uint32_t PIDtrkPr = 0xFFFFF; - - float nSigmaHe3 = -10; - float nSigmaPr = -10; - float massTOFHe3 = -10; - float massTOFPr = -10; + float DCAxyHe3 = -10.f; + float DCAzHe3 = -10.f; + float DCAxyPr = -10.f; + float DCAzPr = -10.f; - float DCAxyHe3 = -10; - float DCAzHe3 = -10; - float DCAxyPr = -10; - float DCAzPr = -10; uint16_t tpcSignalHe3 = 0u; float momHe3TPC = -99.f; uint16_t tpcSignalPr = 0u; float momPrTPC = -99.f; - float invMass = -10.f; - uint32_t itsClSizeHe3 = 0u; - uint32_t itsClSizePr = 0u; uint8_t nTPCClustersHe3 = 0u; + float nSigmaHe3 = -10.f; + float nSigmaPr = -10.f; + float chi2TPCHe3 = -10.f; + float chi2TPCPr = -10.f; + float massTOFHe3 = -10; + float massTOFPr = -10; - float momHe3MC = -99.f; - float momPrMC = -99.f; + uint32_t PIDtrkHe3 = 0xFFFFF; // PID in tracking + uint32_t PIDtrkPr = 0xFFFFF; + uint32_t itsClSizeHe3 = 0u; + uint32_t itsClSizePr = 0u; uint8_t sharedClustersHe3 = 0u; uint8_t sharedClustersPr = 0u; bool isBkgUS = false; bool isBkgEM = false; + int trackIDHe3 = -1; + int trackIDPr = -1; + + float momHe3MC = -99.f; + float etaHe3MC = -99.f; + float phiHe3MC = -99.f; + float momPrMC = -99.f; + float etaPrMC = -99.f; + float phiPrMC = -99.f; + float l4PtMC = -99.f; float l4MassMC = -10.f; + + float invMass = -10.f; }; struct lithium4analysis { - Produces outputDataTable; - Produces outputMCTable; - - std::vector l4Candidates; + Produces m_outputDataTable; + Produces m_outputMCTable; + + // Selections + Configurable setting_cutVertex{"setting_cutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable setting_cutPT{"setting_cutPT", 0.2, "PT cut on daughter track"}; + Configurable setting_cutMaxPrPT{"setting_cutMaxPrPT", 1.8, "Max PT cut on proton"}; + Configurable setting_cutEta{"setting_cutEta", 0.8, "Eta cut on daughter track"}; + Configurable setting_cutDCAxy{"setting_cutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable setting_cutDCAz{"setting_cutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable setting_nsigmaCutTPC{"setting_nsigmaCutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable setting_nsigmaCutTOF{"setting_nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; + Configurable setting_noMixedEvents{"setting_noMixedEvents", 5, "Number of mixed events per event"}; + Configurable setting_enableBkgUS{"setting_enableBkgUS", false, "Enable US background"}; + Configurable setting_isMC{"setting_isMC", false, "Run MC"}; + Configurable setting_skimmedProcessing{"setting_skimmedProcessing", false, "Skimmed dataset processing"}; + + // CCDB options + Configurable setting_ccdburl{"setting_ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable setting_grpPath{"setting_grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable setting_grpmagPath{"setting_grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable setting_lutPath{"setting_lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable setting_geoPath{"setting_geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable setting_pidPath{"setting_pidPath", "", "Path to the PID response object"}; + + Configurable> setting_BetheBlochParams{"setting_BetheBlochParams", {betheBlochDefault[0], 1, 6, {"He3"}, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; + Configurable setting_compensatePIDinTracking{"setting_compensatePIDinTracking", false, "If true, divide tpcInnerParam by the electric charge"}; + Configurable setting_materialCorrection{"setting_materialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Material correction type"}; + + using McIter = aod::McParticles::iterator; + using CollBracket = o2::math_utils::Bracket; + Filter collZfilter = nabs(aod::collision::posZ) < setting_cutVertex; + using CollisionsFull = soa::Filtered>; //, aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms>>; + using CollisionsFullMC = soa::Filtered>; //, aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms>>; + using TrackCandidates = soa::Join; + using TrackCandidatesMC = soa::Join; + + o2::pid::tof::Beta m_responseBeta; + o2::pid::tof::Beta m_responseBetaMC; + + Preslice m_perCol = aod::track::collisionId; + Preslice m_perColMC = aod::track::collisionId; + // binning for EM background + ConfigurableAxis axisVertex{"axisVertex", {30, -10, 10}, "vertex axis for bin"}; + using BinningType = ColumnBinningPolicy; + BinningType binningOnPositions{{axisVertex}, true}; SliceCache cache; - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", false, "If true, divide tpcInnerParam by the electric charge"}; - // events - Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - // track - Configurable cfgCutPT{"cfgCutPT", 0.2, "PT cut on daughter track"}; - Configurable cfgCutMaxPrPT{"cfgCutMaxPrPT", 1.8, "Max PT cut on proton"}; - Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; - Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; - Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; - Configurable nsigmaCutTOF{"nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; - Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; - Configurable cfgEnableBkgUS{"cfgEnableBkgUS", false, "Enable US background"}; - - // bethe bloch parameters - std::array mBBparamsHe; - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, {"He3"}, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; - // MC - Configurable isMC{"isMC", false, "Run MC"}; + SameKindPair m_pair{binningOnPositions, setting_noMixedEvents, -1, &cache}; + + std::array m_BBparamsHe; + + std::vector m_recoCollisionIDs; + std::vector m_goodCollisions; + std::vector m_trackPairs; + + int m_runNumber; + Service m_ccdb; + Zorro m_zorro; + OutputObj m_zorroSummary{"zorroSummary"}; + + HistogramRegistry m_qaRegistry{ + "QA", + { + {"hVtxZ", "Vertex distribution in Z;Z (cm)", {HistType::kTH1F, {{400, -20.0, 20.0}}}}, + {"hNcontributor", "Number of primary vertex contributor", {HistType::kTH1F, {{2000, 0.0f, 2000.0f}}}}, + {"hTrackSel", "Accepted tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, + {"hEvents", "; Events;", {HistType::kTH1F, {{3, -0.5, 2.5}}}}, + {"hEmptyPool", "svPoolCreator did not find track pairs false/true", {HistType::kTH1F, {{2, -0.5, 1.5}}}}, + {"hDCAxyHe3", ";DCA_{xy} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hDCAzHe3", ";DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hLitInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", {HistType::kTH1F, {{50, 3.74f, 3.85f}}}}, + {"hHe3Pt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{200, -6.0f, 6.0f}}}}, + {"hProtonPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{200, -3.0f, 3.0f}}}}, + {"h2dEdxHe3candidates", "dEdx distribution; Signed #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, + {"h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}({}^{3}He)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaProtonTPC", "NsigmaProton TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaProtonTOF", "NsigmaProton TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + }, + OutputObjHandlingPolicy::AnalysisObject, + false, + true}; + void init(o2::framework::InitContext&) { + m_zorroSummary.setObject(m_zorro.getZorroSummary()); + m_runNumber = 0; - histos.add("hCentrality", "Centrality distribution", kTH1F, {{2001, -0.5, 2000.5}}); - histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 2000.0f}}); - histos.add("hDCAxyHe3", ";DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDCAzHe3", ";DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hLitInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", kTH1F, {{50, 3.74f, 3.85f}}); - histos.add("hHe3Pt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", kTH1F, {{200, 0.0f, 6.0f}}); - histos.add("hProtonPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", kTH1F, {{200, 0.0f, 3.0f}}); - histos.add("h2dEdxHe3candidates", "dEdx distribution; Signed #it{p} (GeV/#it{c}); dE/dx (a.u.)", kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}); - histos.add("h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}({}^{3}He)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); - histos.add("h2NsigmaProtonTPC", "NsigmaProton TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}(p)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); - histos.add("h2NsigmaProtonTOF", "NsigmaProton TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); - histos.add("hTrackSel", "Accepted tracks", kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}); + m_ccdb->setURL(setting_ccdburl); + m_ccdb->setCaching(true); + m_ccdb->setLocalObjectValidityChecking(); + m_ccdb->setFatalWhenNull(false); for (int i = 0; i < 5; i++) { - mBBparamsHe[i] = cfgBetheBlochParams->get("He3", Form("p%i", i)); + m_BBparamsHe[i] = setting_BetheBlochParams->get("He3", Form("p%i", i)); + } + m_BBparamsHe[5] = setting_BetheBlochParams->get("He3", "resolution"); + + std::vector selection_labels = {"All", "Track selection", "PID {}^{3}He"}; + for (int i = 0; i < Selections::kAll; i++) { + m_qaRegistry.get(HIST("hTrackSel"))->GetXaxis()->SetBinLabel(i + 1, selection_labels[i].c_str()); } - mBBparamsHe[5] = cfgBetheBlochParams->get("He3", "resolution"); - std::vector labels = {"All", "Global track", "Track selection", "PID {}^{3}He"}; + std::vector events_labels = {"All", "Selected", "Zorro He events"}; for (int i = 0; i < Selections::kAll; i++) { - histos.get(HIST("hTrackSel"))->GetXaxis()->SetBinLabel(i + 1, labels[i].c_str()); + m_qaRegistry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(i + 1, events_labels[i].c_str()); + } + } + + void initCCDB(const aod::BCsWithTimestamps::iterator& bc) + { + + if (m_runNumber == bc.runNumber()) { + return; + } + + if (setting_skimmedProcessing) { + m_zorro.initCCDB(m_ccdb.service, bc.runNumber(), bc.timestamp(), "fHe"); + m_zorro.populateHistRegistry(m_qaRegistry, bc.runNumber()); } + + m_runNumber = bc.runNumber(); } + // ================================================================================================================== + template bool selectionTrack(const T& candidate) { @@ -200,13 +291,13 @@ struct lithium4analysis { bool selectionPIDProton(const T& candidate) { if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaPr()) < nsigmaCutTOF && std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPC) { - histos.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); - histos.fill(HIST("h2NsigmaProtonTOF"), candidate.p(), candidate.tofNSigmaPr()); + if (std::abs(candidate.tofNSigmaPr()) < setting_nsigmaCutTOF && std::abs(candidate.tpcNSigmaPr()) < setting_nsigmaCutTPC) { + m_qaRegistry.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); + m_qaRegistry.fill(HIST("h2NsigmaProtonTOF"), candidate.p(), candidate.tofNSigmaPr()); return true; } - } else if (std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPC) { - histos.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); + } else if (std::abs(candidate.tpcNSigmaPr()) < setting_nsigmaCutTPC) { + m_qaRegistry.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); return true; } return false; @@ -216,11 +307,10 @@ struct lithium4analysis { float computeNSigmaHe3(const T& candidate) { bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParam = (heliumPID && setting_compensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); + float expTPCSignal = o2::tpc::BetheBlochAleph(static_cast(correctedTPCinnerParam * 2.f / constants::physics::MassHelium3), m_BBparamsHe[0], m_BBparamsHe[1], m_BBparamsHe[2], m_BBparamsHe[3], m_BBparamsHe[4]); - float correctedTPCinnerParam = (heliumPID && cfgCompensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); - float expTPCSignal = o2::tpc::BetheBlochAleph(static_cast(correctedTPCinnerParam * 2.f / constants::physics::MassHelium3), mBBparamsHe[0], mBBparamsHe[1], mBBparamsHe[2], mBBparamsHe[3], mBBparamsHe[4]); - - double resoTPC{expTPCSignal * mBBparamsHe[5]}; + double resoTPC{expTPCSignal * m_BBparamsHe[5]}; return static_cast((candidate.tpcSignal() - expTPCSignal) / resoTPC); } @@ -228,386 +318,389 @@ struct lithium4analysis { bool selectionPIDHe3(const T& candidate) { auto nSigmaHe3 = computeNSigmaHe3(candidate); - if (std::abs(nSigmaHe3) < nsigmaCutTPC) { + bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParam = (heliumPID && setting_compensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); + if (std::abs(nSigmaHe3) < setting_nsigmaCutTPC) { + m_qaRegistry.fill(HIST("h2NsigmaHe3TPC"), candidate.sign() * correctedTPCinnerParam, nSigmaHe3); return true; } return false; } - template - bool FillCandidateInfo(const T1& candidateHe3, const T2& candidatePr, bool mix, bool /*isMC*/ = false) - { - lithium4Candidate l4Cand; - - l4Cand.momHe3 = array{2 * candidateHe3.px(), 2 * candidateHe3.py(), 2 * candidateHe3.pz()}; - l4Cand.momPr = array{candidatePr.px(), candidatePr.py(), candidatePr.pz()}; - - float invMass = RecoDecay::m(array{l4Cand.momHe3, l4Cand.momPr}, array{he3Mass, protonMass}); + // ================================================================================================================== - if (invMass < 3.74 || invMass > 3.85 || candidatePr.pt() > cfgCutMaxPrPT) { - return false; + template + bool fillCandidateInfo(const T& trackHe3, const T& trackPr, Lithium4Candidate& li4cand, bool mix) + { + li4cand.momHe3 = std::array{trackHe3.px(), trackHe3.py(), trackHe3.pz()}; + li4cand.momPr = std::array{trackPr.px(), trackPr.py(), trackPr.pz()}; + float invMass = RecoDecay::m(array{li4cand.momHe3, li4cand.momPr}, std::array{o2::constants::physics::MassHelium3, o2::constants::physics::MassProton}); + + li4cand.sign = trackHe3.sign(); + + li4cand.DCAxyHe3 = trackHe3.dcaXY(); + li4cand.DCAzHe3 = trackHe3.dcaZ(); + li4cand.DCAxyPr = trackPr.dcaXY(); + li4cand.DCAzPr = trackPr.dcaZ(); + + li4cand.tpcSignalHe3 = trackHe3.tpcSignal(); + bool heliumPID = trackHe3.pidForTracking() == o2::track::PID::Helium3 || trackHe3.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParamHe3 = (heliumPID && setting_compensatePIDinTracking) ? trackHe3.tpcInnerParam() / 2.f : trackHe3.tpcInnerParam(); + li4cand.momHe3TPC = correctedTPCinnerParamHe3; + li4cand.tpcSignalPr = trackPr.tpcSignal(); + li4cand.momPrTPC = trackPr.tpcInnerParam(); + + li4cand.nTPCClustersHe3 = trackHe3.tpcNClsFound(); + li4cand.nSigmaHe3 = computeNSigmaHe3(trackHe3); + li4cand.nSigmaPr = trackPr.tpcNSigmaPr(); + li4cand.chi2TPCHe3 = trackHe3.tpcChi2NCl(); + li4cand.chi2TPCPr = trackPr.tpcChi2NCl(); + + li4cand.PIDtrkHe3 = trackHe3.pidForTracking(); + li4cand.PIDtrkPr = trackPr.pidForTracking(); + + li4cand.itsClSizeHe3 = trackHe3.itsClusterSizes(); + li4cand.itsClSizePr = trackPr.itsClusterSizes(); + + li4cand.sharedClustersHe3 = trackHe3.tpcNClsShared(); + li4cand.sharedClustersPr = trackPr.tpcNClsShared(); + + li4cand.isBkgUS = trackHe3.sign() * trackPr.sign() < 0; + li4cand.isBkgEM = mix; + + li4cand.invMass = invMass; + + li4cand.trackIDHe3 = trackHe3.globalIndex(); + li4cand.trackIDPr = trackPr.globalIndex(); + + if constexpr (isMC) { + if (trackHe3.hasTOF()) { + float beta = m_responseBetaMC.GetBeta(trackHe3); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + bool heliumPID = trackHe3.pidForTracking() == o2::track::PID::Helium3 || trackHe3.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParamHe3 = (heliumPID && setting_compensatePIDinTracking) ? trackHe3.tpcInnerParam() / 2.f : trackHe3.tpcInnerParam(); + li4cand.massTOFHe3 = correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + } + if (trackPr.hasTOF()) { + float beta = m_responseBetaMC.GetBeta(trackPr); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + li4cand.massTOFPr = trackPr.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); + } + } else { + if (trackHe3.hasTOF()) { + float beta = m_responseBeta.GetBeta(trackHe3); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + bool heliumPID = trackHe3.pidForTracking() == o2::track::PID::Helium3 || trackHe3.pidForTracking() == o2::track::PID::Alpha; + float correctedTPCinnerParamHe3 = (heliumPID && setting_compensatePIDinTracking) ? trackHe3.tpcInnerParam() / 2.f : trackHe3.tpcInnerParam(); + li4cand.massTOFHe3 = correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + } + if (trackPr.hasTOF()) { + float beta = m_responseBeta.GetBeta(trackPr); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + li4cand.massTOFPr = trackPr.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); + } } - l4Cand.PIDtrkHe3 = candidateHe3.pidForTracking(); - l4Cand.PIDtrkPr = candidatePr.pidForTracking(); - - l4Cand.sign = candidateHe3.sign(); - - l4Cand.isBkgUS = candidateHe3.sign() * candidatePr.sign() < 0; - l4Cand.isBkgEM = mix; - - l4Cand.DCAxyHe3 = candidateHe3.dcaXY(); - l4Cand.DCAzHe3 = candidateHe3.dcaZ(); - l4Cand.DCAxyPr = candidatePr.dcaXY(); - l4Cand.DCAzPr = candidatePr.dcaZ(); - - bool heliumPID = candidateHe3.pidForTracking() == o2::track::PID::Helium3 || candidateHe3.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParamHe3 = (heliumPID && cfgCompensatePIDinTracking) ? candidateHe3.tpcInnerParam() / 2.f : candidateHe3.tpcInnerParam(); - - l4Cand.tpcSignalHe3 = candidateHe3.tpcSignal(); - l4Cand.momHe3TPC = correctedTPCinnerParamHe3; - l4Cand.tpcSignalPr = candidatePr.tpcSignal(); - l4Cand.momPrTPC = candidatePr.tpcInnerParam(); - l4Cand.invMass = invMass; - - l4Cand.itsClSizeHe3 = candidateHe3.itsClusterSizes(); - l4Cand.itsClSizePr = candidatePr.itsClusterSizes(); - - l4Cand.nTPCClustersHe3 = candidateHe3.tpcNClsFound(); - - l4Cand.nSigmaHe3 = computeNSigmaHe3(candidateHe3); - l4Cand.nSigmaPr = candidatePr.tpcNSigmaPr(); - - l4Cand.sharedClustersHe3 = candidateHe3.tpcNClsShared(); - l4Cand.sharedClustersPr = candidatePr.tpcNClsShared(); - - l4Candidates.push_back(l4Cand); return true; } - template - void fillHistograms(const T& l4cand) + template + void fillCandidateInfoMC(const Mc& mctrackHe3, const Mc& mctrackPr, const Mc& mctrackMother, Lithium4Candidate& li4cand) { - int candSign = l4cand.sign; - histos.fill(HIST("hHe3Pt"), l4cand.recoPtHe3()); - histos.fill(HIST("hProtonPt"), l4cand.recoPtPr()); - histos.fill(HIST("hLitInvMass"), l4cand.invMass); - histos.fill(HIST("hDCAxyHe3"), l4cand.DCAxyHe3); - histos.fill(HIST("hDCAzHe3"), l4cand.DCAzHe3); - histos.fill(HIST("h2NsigmaHe3TPC"), candSign * l4cand.momHe3TPC, l4cand.nSigmaHe3); - histos.fill(HIST("h2NsigmaProtonTPC"), candSign * l4cand.momPrTPC, l4cand.nSigmaPr); - histos.fill(HIST("h2NsigmaProtonTOF"), l4cand.recoPtPr(), l4cand.nSigmaPr); + li4cand.momHe3MC = mctrackHe3.pt() * (mctrackHe3.pdgCode() > 0 ? 1 : -1); + li4cand.etaHe3MC = mctrackHe3.eta(); + li4cand.phiHe3MC = mctrackHe3.phi(); + li4cand.momPrMC = mctrackPr.pt() * (mctrackPr.pdgCode() > 0 ? 1 : -1); + li4cand.etaPrMC = mctrackPr.eta(); + li4cand.phiPrMC = mctrackPr.phi(); + li4cand.l4PtMC = mctrackMother.pt() * (mctrackMother.pdgCode() > 0 ? 1 : -1); + const double eLit = mctrackHe3.e() + mctrackPr.e(); + li4cand.l4MassMC = std::sqrt(eLit * eLit - mctrackMother.p() * mctrackMother.p()); } - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); - Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + template + void pairTracksSameEvent(const T& tracks) + { + for (auto track0 : tracks) { - using EventCandidates = soa::Filtered>; - using TrackCandidates = soa::Filtered>; - using TrackCandidatesMC = soa::Filtered>; - o2::pid::tof::Beta responseBeta; - o2::pid::tof::Beta responseBetaMC; + m_qaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); + bool heliumPID = track0.pidForTracking() == o2::track::PID::Helium3 || track0.pidForTracking() == o2::track::PID::Alpha; - Preslice perCol = aod::track::collisionId; - Preslice perColMC = aod::track::collisionId; + float correctedTPCinnerParam = (heliumPID && setting_compensatePIDinTracking) ? track0.tpcInnerParam() / 2.f : track0.tpcInnerParam(); + m_qaRegistry.fill(HIST("h2dEdxHe3candidates"), correctedTPCinnerParam * 2.f, track0.tpcSignal()); - // binning for EM background - ConfigurableAxis axisVertex{"axisVertex", {30, -10, 10}, "vertex axis for bin"}; - using BinningType = ColumnBinningPolicy; - BinningType binningOnPositions{{axisVertex}, true}; - SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; - - void processSameEvent(soa::Join const& collisions, TrackCandidates const& tracks, aod::BCs const&) - { - l4Candidates.clear(); - - for (auto& collision : collisions) { - if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { + if (!selectionTrack(track0)) { continue; } - histos.fill(HIST("hNcontributor"), collision.numContrib()); - histos.fill(HIST("hVtxZ"), collision.posZ()); + m_qaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); - const uint64_t collIdx = collision.globalIndex(); - auto TrackTable_thisCollision = tracks.sliceBy(perCol, collIdx); - TrackTable_thisCollision.bindExternalIndices(&tracks); - - for (auto track1 : TrackTable_thisCollision) { - - histos.fill(HIST("hTrackSel"), Selections::kNoCuts); - bool heliumPID = track1.pidForTracking() == o2::track::PID::Helium3 || track1.pidForTracking() == o2::track::PID::Alpha; + if (!selectionPIDHe3(track0)) { + continue; + } + m_qaRegistry.fill(HIST("hTrackSel"), Selections::kPID); - float correctedTPCinnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track1.tpcInnerParam() / 2.f : track1.tpcInnerParam(); - histos.fill(HIST("h2dEdxHe3candidates"), correctedTPCinnerParam * 2.f, track1.tpcSignal()); + for (auto track1 : tracks) { - if (!track1.isGlobalTrackWoDCA()) { + if (track0 == track1) { continue; } - histos.fill(HIST("hTrackSel"), Selections::kGlobalTrack); - if (!selectionTrack(track1)) { - continue; + if (!setting_enableBkgUS) { + if (track0.sign() * track1.sign() < 0) { + continue; + } } - histos.fill(HIST("hTrackSel"), Selections::kTrackCuts); - if (!selectionPIDHe3(track1)) { + if (!selectionTrack(track1) || !selectionPIDProton(track1)) { continue; } - histos.fill(HIST("hTrackSel"), Selections::kPID); - - for (auto track2 : TrackTable_thisCollision) { - - if (track1 == track2) { - continue; - } - if (!cfgEnableBkgUS) { - if (track1.sign() * track2.sign() < 0) { - continue; - } - } - - if (!track2.isGlobalTrackWoDCA()) { - continue; - } - - if (!selectionTrack(track2)) { - continue; - } - - if (!selectionPIDProton(track2)) { - continue; - } - - if (!FillCandidateInfo(track1, track2, false)) { - continue; - } - // fill TOF info outside to avoide responseBeta crash - auto& cand = l4Candidates.back(); - if (track1.hasTOF()) { - float beta = responseBeta.GetBeta(track1); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - bool heliumPID = track1.pidForTracking() == o2::track::PID::Helium3 || track1.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParamHe3 = (heliumPID && cfgCompensatePIDinTracking) ? track1.tpcInnerParam() / 2.f : track1.tpcInnerParam(); - cand.massTOFHe3 = correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); - } - if (track2.hasTOF()) { - float beta = responseBeta.GetBeta(track2); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - cand.massTOFPr = track2.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); - } - fillHistograms(cand); - } + SVCand trackPair; + trackPair.tr0Idx = track0.globalIndex(); + trackPair.tr1Idx = track1.globalIndex(); + m_trackPairs.push_back(trackPair); } } - - for (auto& l4Cand : l4Candidates) { - outputDataTable(l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), - l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), - l4Cand.DCAxyHe3, l4Cand.DCAzHe3, l4Cand.DCAxyPr, l4Cand.DCAzPr, - l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.tpcSignalPr, l4Cand.momPrTPC, - l4Cand.nTPCClustersHe3, - l4Cand.nSigmaHe3, l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, - l4Cand.PIDtrkHe3, l4Cand.PIDtrkPr, l4Cand.itsClSizeHe3, l4Cand.itsClSizePr, - l4Cand.sharedClustersHe3, l4Cand.sharedClustersPr, - l4Cand.isBkgUS, l4Cand.isBkgEM); - } } - PROCESS_SWITCH(lithium4analysis, processSameEvent, "Process Same event", false); - void processMixedEvent(EventCandidates& /*collisions*/, TrackCandidates const& /*tracks*/) + void pairTracksEventMixing() { - l4Candidates.clear(); - for (auto& [c1, tracks1, c2, tracks2] : pair) { - if (!c1.sel8()) { - continue; - } - if (!c2.sel8()) { + for (auto& [c1, tracks1, c2, tracks2] : m_pair) { + if (!c1.sel8() || !c2.sel8()) { continue; } - histos.fill(HIST("hNcontributor"), c1.numContrib()); - histos.fill(HIST("hVtxZ"), c1.posZ()); + m_qaRegistry.fill(HIST("hNcontributor"), c1.numContrib()); + m_qaRegistry.fill(HIST("hVtxZ"), c1.posZ()); for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (!t1.isGlobalTrackWoDCA()) { - continue; - } - - if (!selectionTrack(t1)) { - continue; - } - - if (!t2.isGlobalTrackWoDCA()) { - continue; - } - - if (!selectionTrack(t2)) { + if (!selectionTrack(t1) || !selectionTrack(t2)) { continue; } TrackCandidates::iterator he3Cand, protonCand; - bool passPID = false; if (selectionPIDHe3(t1) && selectionPIDProton(t2)) { he3Cand = t1, protonCand = t2; - passPID = true; - } - if (selectionPIDHe3(t2) && selectionPIDProton(t1)) { + } else if (selectionPIDHe3(t2) && selectionPIDProton(t1)) { he3Cand = t2, protonCand = t1; - passPID = true; - } - if (!passPID) { + } else { continue; } bool heliumPID = he3Cand.pidForTracking() == o2::track::PID::Helium3 || he3Cand.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParam = (heliumPID && cfgCompensatePIDinTracking) ? he3Cand.tpcInnerParam() / 2.f : he3Cand.tpcInnerParam(); - histos.fill(HIST("h2dEdxHe3candidates"), correctedTPCinnerParam * 2.f, he3Cand.tpcSignal()); + float correctedTPCinnerParam = (heliumPID && setting_compensatePIDinTracking) ? he3Cand.tpcInnerParam() / 2.f : he3Cand.tpcInnerParam(); + m_qaRegistry.fill(HIST("h2dEdxHe3candidates"), correctedTPCinnerParam * 2.f, he3Cand.tpcSignal()); - if (!FillCandidateInfo(he3Cand, protonCand, true)) { - continue; - } - // fill TOF info outside to avoide responseBeta crash - auto& cand = l4Candidates.back(); - if (he3Cand.hasTOF()) { - float beta = responseBeta.GetBeta(he3Cand); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - - bool heliumPID = t1.pidForTracking() == o2::track::PID::Helium3 || he3Cand.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParamHe3 = (heliumPID && cfgCompensatePIDinTracking) ? he3Cand.tpcInnerParam() / 2.f : he3Cand.tpcInnerParam(); - cand.massTOFHe3 = correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + SVCand trackPair; + trackPair.tr0Idx = he3Cand.globalIndex(); + trackPair.tr1Idx = protonCand.globalIndex(); + m_trackPairs.push_back(trackPair); + } + } + } + + void fillTable(const Lithium4Candidate& li4cand, bool isMC = false) + { + if (!isMC) { + m_outputDataTable( + li4cand.recoPtHe3(), + li4cand.recoEtaHe3(), + li4cand.recoPhiHe3(), + li4cand.recoPtPr(), + li4cand.recoEtaPr(), + li4cand.recoPhiPr(), + li4cand.DCAxyHe3, + li4cand.DCAzHe3, + li4cand.DCAxyPr, + li4cand.DCAzPr, + li4cand.tpcSignalHe3, + li4cand.momHe3TPC, + li4cand.tpcSignalPr, + li4cand.momPrTPC, + li4cand.nTPCClustersHe3, + li4cand.nSigmaHe3, + li4cand.nSigmaPr, + li4cand.chi2TPCHe3, + li4cand.chi2TPCPr, + li4cand.massTOFHe3, + li4cand.massTOFPr, + li4cand.PIDtrkHe3, + li4cand.PIDtrkPr, + li4cand.itsClSizeHe3, + li4cand.itsClSizePr, + li4cand.sharedClustersHe3, + li4cand.sharedClustersPr, + li4cand.isBkgUS, + li4cand.isBkgEM); + } else { + m_outputMCTable( + li4cand.recoPtHe3(), + li4cand.recoEtaHe3(), + li4cand.recoPhiHe3(), + li4cand.recoPtPr(), + li4cand.recoEtaPr(), + li4cand.recoPhiPr(), + li4cand.DCAxyHe3, + li4cand.DCAzHe3, + li4cand.DCAxyPr, + li4cand.DCAzPr, + li4cand.tpcSignalHe3, + li4cand.momHe3TPC, + li4cand.tpcSignalPr, + li4cand.momPrTPC, + li4cand.nTPCClustersHe3, + li4cand.nSigmaHe3, + li4cand.nSigmaPr, + li4cand.chi2TPCHe3, + li4cand.chi2TPCPr, + li4cand.massTOFHe3, + li4cand.massTOFPr, + li4cand.PIDtrkHe3, + li4cand.PIDtrkPr, + li4cand.itsClSizeHe3, + li4cand.itsClSizePr, + li4cand.sharedClustersHe3, + li4cand.sharedClustersPr, + li4cand.isBkgUS, + li4cand.isBkgEM, + li4cand.momHe3MC, + li4cand.etaHe3MC, + li4cand.phiHe3MC, + li4cand.momPrMC, + li4cand.etaPrMC, + li4cand.phiPrMC, + li4cand.l4PtMC, + li4cand.l4MassMC); + } + } + + void fillHistograms(const Lithium4Candidate& li4cand) + { + m_qaRegistry.fill(HIST("hHe3Pt"), li4cand.recoPtHe3()); + m_qaRegistry.fill(HIST("hProtonPt"), li4cand.recoPtPr()); + m_qaRegistry.fill(HIST("hLitInvMass"), li4cand.invMass); + m_qaRegistry.fill(HIST("hDCAxyHe3"), li4cand.DCAxyHe3); + m_qaRegistry.fill(HIST("hDCAzHe3"), li4cand.DCAzHe3); + } + + // ================================================================================================================== + + void processSameEvent(const CollisionsFull& collisions, const TrackCandidates& tracks, const aod::BCsWithTimestamps&) + { + for (auto& collision : collisions) { + + m_trackPairs.clear(); + m_qaRegistry.fill(HIST("hEvents"), 0); + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!collision.sel8() || std::abs(collision.posZ()) > setting_cutVertex) { + continue; + } + if (setting_skimmedProcessing) { + bool zorroSelected = m_zorro.isSelected(collision.template bc_as().globalBC()); + if (zorroSelected) { + m_qaRegistry.fill(HIST("hEvents"), 2); } - if (protonCand.hasTOF()) { - float beta = responseBeta.GetBeta(protonCand); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - cand.massTOFPr = protonCand.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); + } + m_qaRegistry.fill(HIST("hEvents"), 1); + m_qaRegistry.fill(HIST("hNcontributor"), collision.numContrib()); + m_qaRegistry.fill(HIST("hVtxZ"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto TrackTable_thisCollision = tracks.sliceBy(m_perCol, collIdx); + TrackTable_thisCollision.bindExternalIndices(&tracks); + + pairTracksSameEvent(TrackTable_thisCollision); + + for (auto& trackPair : m_trackPairs) { + + auto heTrack = tracks.rawIteratorAt(trackPair.tr0Idx); + auto prTrack = tracks.rawIteratorAt(trackPair.tr1Idx); + + Lithium4Candidate li4cand; + if (!fillCandidateInfo(heTrack, prTrack, li4cand, /*mix*/ false)) { + continue; } - fillHistograms(cand); + fillHistograms(li4cand); + fillTable(li4cand, false); } } + } + PROCESS_SWITCH(lithium4analysis, processSameEvent, "Process Same event", false); + + void processMixedEvent(const CollisionsFull& /*collisions*/, const TrackCandidates& tracks) + { + m_trackPairs.clear(); + pairTracksEventMixing(); + + for (auto& trackPair : m_trackPairs) { + auto heTrack = tracks.rawIteratorAt(trackPair.tr0Idx); + auto prTrack = tracks.rawIteratorAt(trackPair.tr1Idx); - for (auto& l4Cand : l4Candidates) { - outputDataTable(l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), - l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), - l4Cand.DCAxyHe3, l4Cand.DCAzHe3, l4Cand.DCAxyPr, l4Cand.DCAzPr, - l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.tpcSignalPr, l4Cand.momPrTPC, - l4Cand.nTPCClustersHe3, - l4Cand.nSigmaHe3, l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, - l4Cand.PIDtrkHe3, l4Cand.PIDtrkPr, l4Cand.itsClSizeHe3, l4Cand.itsClSizePr, - l4Cand.sharedClustersHe3, l4Cand.sharedClustersPr, - l4Cand.isBkgUS, l4Cand.isBkgEM); + Lithium4Candidate li4cand; + if (!fillCandidateInfo(heTrack, prTrack, li4cand, /*mix*/ true)) { + continue; + } + fillHistograms(li4cand); + fillTable(li4cand, false); } } PROCESS_SWITCH(lithium4analysis, processMixedEvent, "Process Mixed event", false); - void processMC(soa::Join const& collisions, aod::BCs const&, TrackCandidatesMC const& tracks, aod::McParticles const& mcParticles) + void processMC(const CollisionsFullMC& collisions, const aod::BCsWithTimestamps&, const TrackCandidatesMC& tracks, const aod::McParticles& mcParticles) { std::vector filledMothers; - l4Candidates.clear(); for (auto& collision : collisions) { - if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { + m_trackPairs.clear(); + m_qaRegistry.fill(HIST("hEvents"), 0); + if (/*!collision.sel8() ||*/ std::abs(collision.posZ()) > setting_cutVertex) { continue; } - histos.fill(HIST("hNcontributor"), collision.numContrib()); - histos.fill(HIST("hVtxZ"), collision.posZ()); + m_qaRegistry.fill(HIST("hEvents"), 1); + m_qaRegistry.fill(HIST("hNcontributor"), collision.numContrib()); + m_qaRegistry.fill(HIST("hVtxZ"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto TrackTable_thisCollision = tracks.sliceBy(perColMC, collIdx); + auto TrackTable_thisCollision = tracks.sliceBy(m_perColMC, collIdx); TrackTable_thisCollision.bindExternalIndices(&tracks); - for (auto track1 : TrackTable_thisCollision) { + pairTracksSameEvent(TrackTable_thisCollision); - if (!track1.has_mcParticle()) { - continue; - } + for (auto& trackPair : m_trackPairs) { - histos.fill(HIST("hTrackSel"), Selections::kNoCuts); + auto heTrack = tracks.rawIteratorAt(trackPair.tr0Idx); + auto prTrack = tracks.rawIteratorAt(trackPair.tr1Idx); - if (!track1.isGlobalTrackWoDCA()) { + if (!heTrack.has_mcParticle() || !prTrack.has_mcParticle()) { continue; } - histos.fill(HIST("hTrackSel"), Selections::kGlobalTrack); - if (!selectionTrack(track1)) { - continue; - } - histos.fill(HIST("hTrackSel"), Selections::kTrackCuts); + auto mctrackHe3 = heTrack.mcParticle(); + auto mctrackPr = prTrack.mcParticle(); - if (!selectionPIDHe3(track1)) { + if (std::abs(mctrackHe3.pdgCode()) != hePDG || std::abs(mctrackPr.pdgCode()) != prPDG) { continue; } - histos.fill(HIST("hTrackSel"), Selections::kPID); - for (auto track2 : TrackTable_thisCollision) { - if (!track2.has_mcParticle()) { - continue; - } - - if (!track2.isGlobalTrackWoDCA()) { - continue; - } - - if (!selectionTrack(track2)) { - continue; - } - - if (!selectionPIDProton(track2)) { - continue; - } - - if (track1.sign() * track2.sign() < 0) { - continue; - } - - const auto mctrackHe3 = track1.mcParticle(); - const auto mctrackPr = track2.mcParticle(); + for (auto& mothertrack : mctrackHe3.mothers_as()) { + for (auto& mothertrackPr : mctrackPr.mothers_as()) { - if (std::abs(mctrackHe3.pdgCode()) != he3PDG || std::abs(mctrackPr.pdgCode()) != protonPDG) { - continue; - } + if (mothertrack != mothertrackPr || std::abs(mothertrack.pdgCode()) != li4PDG || std::abs(mothertrack.y()) > 1) { + continue; + } - for (auto& mothertrack : mctrackHe3.mothers_as()) { - for (auto& mothertrackPr : mctrackPr.mothers_as()) { - - if (mothertrack != mothertrackPr || std::abs(mothertrack.pdgCode()) != lithium4PDG) { - continue; - } - - if (std::abs(mothertrack.y()) > 1) { - continue; - } - - if (!FillCandidateInfo(track1, track2, false, true)) { - continue; - } - - // fill TOF info outside to avoide responseBeta crash - auto& cand = l4Candidates.back(); - if (track1.hasTOF()) { - float beta = responseBetaMC.GetBeta(track1); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - bool heliumPID = track1.pidForTracking() == o2::track::PID::Helium3 || track1.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParamHe3 = (heliumPID && cfgCompensatePIDinTracking) ? track1.tpcInnerParam() / 2.f : track1.tpcInnerParam(); - cand.massTOFHe3 = correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); - } - if (track2.hasTOF()) { - float beta = responseBetaMC.GetBeta(track2); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - cand.massTOFPr = track2.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); - } - - cand.momHe3MC = mctrackHe3.pt() * (mctrackHe3.pdgCode() > 0 ? 1 : -1); - cand.momPrMC = mctrackPr.pt() * (mctrackPr.pdgCode() > 0 ? 1 : -1); - cand.l4PtMC = mothertrack.pt() * (mothertrack.pdgCode() > 0 ? 1 : -1); - double eLit = mctrackHe3.e() + mctrackPr.e(); - cand.l4MassMC = std::sqrt(eLit * eLit - mothertrack.p() * mothertrack.p()); - filledMothers.push_back(mothertrack.globalIndex()); - fillHistograms(cand); + Lithium4Candidate li4cand; + if (!fillCandidateInfo(heTrack, prTrack, li4cand, /*mix*/ false)) { + continue; } + fillCandidateInfoMC(mctrackHe3, mctrackPr, mothertrack, li4cand); + fillHistograms(li4cand); + fillTable(li4cand, true); + filledMothers.push_back(mothertrack.globalIndex()); } } } @@ -615,11 +708,7 @@ struct lithium4analysis { for (auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.pdgCode()) != lithium4PDG) { - continue; - } - - if (std::abs(mcParticle.y()) > 1 || mcParticle.isPhysicalPrimary() == false) { + if (std::abs(mcParticle.pdgCode()) != li4PDG || std::abs(mcParticle.y()) > 1 || mcParticle.isPhysicalPrimary() == false) { continue; } @@ -628,53 +717,28 @@ struct lithium4analysis { } auto kDaughters = mcParticle.daughters_as(); - auto daughtHe3 = false; - auto daughtPr = false; - double eLit = 0; - int signHe3 = 0, signPr = 0; - double ptHe3 = 0, ptPr = 0; + bool daughtHe3(false), daughtPr(false); + McIter mcHe3, mcPr; for (auto kCurrentDaughter : kDaughters) { - if (std::abs(kCurrentDaughter.pdgCode()) == he3PDG) { + if (std::abs(kCurrentDaughter.pdgCode()) == hePDG) { daughtHe3 = true; - signHe3 = kCurrentDaughter.pdgCode() > 0 ? 1 : -1; - ptHe3 = kCurrentDaughter.pt(); - eLit += kCurrentDaughter.e(); - } else if (std::abs(kCurrentDaughter.pdgCode()) == protonPDG) { + mcHe3 = kCurrentDaughter; + } else if (std::abs(kCurrentDaughter.pdgCode()) == prPDG) { daughtPr = true; - signPr = kCurrentDaughter.pdgCode() > 0 ? 1 : -1; - ptPr = kCurrentDaughter.pt(); - eLit += kCurrentDaughter.e(); + mcPr = kCurrentDaughter; } } if (daughtHe3 && daughtPr) { - lithium4Candidate l4Candidate; - int signLi = mcParticle.pdgCode() > 0 ? 1 : -1; - l4Candidate.l4PtMC = mcParticle.pt() * signLi; - l4Candidate.momHe3MC = ptHe3 * signHe3; - l4Candidate.momPrMC = ptPr * signPr; - l4Candidate.l4MassMC = std::sqrt(eLit * eLit - mcParticle.p() * mcParticle.p()); - l4Candidates.push_back(l4Candidate); + Lithium4Candidate li4cand; + fillCandidateInfoMC(mcHe3, mcPr, mcParticle, li4cand); + fillTable(li4cand, true); } } - - for (auto& l4Cand : l4Candidates) { - outputMCTable(l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), - l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), - l4Cand.DCAxyHe3, l4Cand.DCAzHe3, l4Cand.DCAxyPr, l4Cand.DCAzPr, - l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.tpcSignalPr, l4Cand.momPrTPC, - l4Cand.nTPCClustersHe3, - l4Cand.nSigmaHe3, l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, - l4Cand.PIDtrkHe3, l4Cand.PIDtrkPr, l4Cand.itsClSizeHe3, l4Cand.itsClSizePr, - l4Cand.sharedClustersHe3, l4Cand.sharedClustersPr, - l4Cand.isBkgUS, l4Cand.isBkgEM, - l4Cand.momHe3MC, l4Cand.momPrMC, - l4Cand.l4PtMC, l4Cand.l4MassMC); - } } PROCESS_SWITCH(lithium4analysis, processMC, "Process MC", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +WorkflowSpec defineDataProcessing(const ConfigContext& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"lithium4analysis"})}; diff --git a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx index b60db27433d..ecea4722a3c 100644 --- a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx @@ -12,6 +12,7 @@ // Build \Lambda-n-n candidates from V0s and tracks // ============================================================================== #include +#include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -30,17 +31,25 @@ #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "Common/DataModel/PIDResponse.h" + #include "Common/Core/PID/TPCPIDResponse.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DCAFitter/DCAFitterN.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + #include "PWGLF/DataModel/LFLnnTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using TracksFull = soa::Join; +using TracksFull = soa::Join; +using TracksFullMC = soa::Join; using CollisionsFull = soa::Join; using CollisionsFullMC = soa::Join; @@ -48,8 +57,7 @@ namespace { constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; -static const std::vector particleNames{"3H"}; - +static const std::vector NucleiName{"3H"}; std::shared_ptr hEvents; std::shared_ptr hZvtx; std::shared_ptr hCentFT0A; @@ -57,8 +65,12 @@ std::shared_ptr hCentFT0C; std::shared_ptr hCentFT0M; std::shared_ptr hCentFV0A; std::shared_ptr hNsigma3HSel; +std::shared_ptr hNsigma3HSelTOF; std::shared_ptr hdEdx3HSel; +std::shared_ptr hdEdx3HPosTrack; std::shared_ptr hdEdxTot; +std::shared_ptr h3HMassPtTOF; +std::shared_ptr h3HSignalPtTOF; std::shared_ptr hDecayChannel; std::shared_ptr hIsMatterGen; std::shared_ptr hIsMatterGenTwoBody; @@ -86,6 +98,8 @@ struct lnnCandidate { float piDCAXY = -10; float mom3HTPC = -10.f; float momPiTPC = -10.f; + float mass2TrTOF = 10.f; + float beta = 10.f; std::array mom3H; std::array momPi; std::array decVtx; @@ -114,13 +128,17 @@ struct lnnRecoTask { // Selection criteria Configurable v0cospa{"lnncospa", 0.95, "V0 CosPA"}; - Configurable masswidth{"lnnmasswidth", 0.06, "Mass width (GeV/c^2)"}; - Configurable dcav0dau{"lnndcaDau", 1.0, "DCA V0 Daughters"}; + Configurable masswidth{"lnnmasswidth", 0.006, "Mass width (GeV/c^2)"}; + Configurable dcav0dau{"lnndcaDau", 0.5, "DCA V0 Daughters"}; + Configurable Chi2nClusTPC{"Chi2NClusTPC", 4., "Chi2 / nClusTPC for triton track"}; + Configurable Chi2nClusITS{"Chi2NClusITS", 36., "Chi2 / nClusITS for triton track"}; Configurable ptMin{"ptMin", 0.5, "Minimum pT of the lnncandidate"}; + Configurable etaMax{"eta", 0.8, "eta daughter"}; Configurable TPCRigidityMin3H{"TPCRigidityMin3H", 0.5, "Minimum rigidity of the triton candidate"}; - Configurable etaMax{"eta", 1., "eta daughter"}; - Configurable nSigmaMax3H{"nSigmaMax3H", 5, "triton dEdx cut (n sigma)"}; - Configurable nTPCClusMin3H{"nTPCClusMin3H", 80, "triton NTPC clusters cut"}; + Configurable nSigmaCutTPC{"nSigmaCutTPC", 2.5, "triton dEdx cut (n sigma)"}; + Configurable nSigmaCutTOF{"nSigmaCutITS", 4., "triton dEdx cut (n sigma)"}; + Configurable nTPCClusMin3H{"nTPCClusMin3H", 100, "triton NTPC clusters cut"}; + Configurable nClusITS{"nClusITSMin3H", 3.0, "triton NITS clusters cut"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; // Define o2 fitter, 2-prong, active memory (no need to redefine per event) @@ -131,7 +149,7 @@ struct lnnRecoTask { float piMass = o2::constants::physics::MassPionCharged; // bethe bloch parameters - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for 3H"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, NucleiName, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for 3H"}; Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; // CCDB options @@ -149,10 +167,14 @@ struct lnnRecoTask { // histogram axes ConfigurableAxis rigidityBins{"rigidityBins", {200, -10.f, 10.f}, "Binning for rigidity #it{p}^{TPC}/#it{z}"}; - ConfigurableAxis dEdxBins{"dEdxBins", {1000, 0.f, 1000.f}, "Binning for dE/dx"}; + ConfigurableAxis dEdxBins{"dEdxBins", {5000, 0.f, 1000.f}, "Binning for dE/dx"}; ConfigurableAxis nSigmaBins{"nSigmaBins", {200, -5.f, 5.f}, "Binning for n sigma"}; ConfigurableAxis zVtxBins{"zVtxBins", {100, -20.f, 20.f}, "Binning for n sigma"}; ConfigurableAxis centBins{"centBins", {100, 0.f, 100.f}, "Binning for centrality"}; + ConfigurableAxis TritMomBins{"TritMom", {100, 0.f, 10.f}, "Binning for Triton TPC momentum"}; + ConfigurableAxis MassTOFBins{"MassTOFTr", {400, 0.f, 10.f}, "Binning for Triton Mass TOF"}; + ConfigurableAxis MomTritonBins{"MomTritonBins", {200, -6.f, 6.f}, "Binning for Triton Mom positive values"}; + ConfigurableAxis BetaBins{"BetaBins", {550, 0.f, 1.1f}, "BInning for Beta"}; // std vector of candidates std::vector lnnCandidates; @@ -160,6 +182,7 @@ struct lnnRecoTask { std::vector filledMothers; // vector to keep track of the collisions passing the event selection in the MC std::vector isGoodCollision; + // vector to armazenade h3Track Preslice perCollision = o2::aod::v0::collisionId; @@ -195,10 +218,18 @@ struct lnnRecoTask { const AxisSpec nSigma3HAxis{nSigmaBins, "n_{#sigma}({}^{3}H)"}; const AxisSpec zVtxAxis{zVtxBins, "z_{vtx} (cm)"}; const AxisSpec centAxis{centBins, "Centrality"}; - - hNsigma3HSel = qaRegistry.add("hNsigma3HSel", "; p_{TPC}/z (GeV/#it{c}); n_{#sigma} ({}^{3}H)", HistType::kTH2F, {rigidityAxis, nSigma3HAxis}); - hdEdx3HSel = qaRegistry.add("hdEdx3HSel", ";p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dEdxAxis}); + const AxisSpec TritMomAxis{TritMomBins, "#it{p}^{TPC}({}^{3}H)"}; + const AxisSpec MassTOFAxis{MassTOFBins, "{m}^{2}/{z}^{2}"}; + const AxisSpec MomTrAxis{MomTritonBins, "#it{p_T}^{TOF}({}^{3}H)"}; + const AxisSpec BetaAxis{BetaBins, "#beta (TOF)"}; + + hNsigma3HSel = qaRegistry.add("hNsigma3HSel", "; #it{p}_{TPC}/z (GeV/#it{c}); n_{#sigma} ({}^{3}H)", HistType::kTH2F, {rigidityAxis, nSigma3HAxis}); + hNsigma3HSelTOF = qaRegistry.add("hNsigma3HSelTOF", "; Signed p_{TOF} (GeV/#it{c}); n#sigma_{TOF} ({}^{3}H)", HistType::kTH2F, {TritMomAxis, nSigma3HAxis}); + hdEdx3HSel = qaRegistry.add("hdEdx3HSel", ";#it{p}_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dEdxAxis}); + hdEdx3HPosTrack = qaRegistry.add("hdEdx3HPosTrack", "; #it{p}^{TPC}({}^{3}H); dE/dx", HistType::kTH2F, {TritMomAxis, dEdxAxis}); hdEdxTot = qaRegistry.add("hdEdxTot", ";p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dEdxAxis}); + h3HMassPtTOF = qaRegistry.add("hTrMassPtTOF", "; #it{p}_{T}({}^{3}H) (#it{GeV}^2/#it{c}^4); m^{2}/z", HistType::kTH2F, {MomTrAxis, MassTOFAxis}); + h3HSignalPtTOF = qaRegistry.add("h3HSignalPtTOF", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta (TOF)", HistType::kTH2F, {MomTrAxis, BetaAxis}); hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{2, -0.5, 1.5}}); hEvents->GetXaxis()->SetBinLabel(1, "All"); @@ -273,6 +304,7 @@ struct lnnRecoTask { if (mBBparams3H[5] < 0) { LOG(fatal) << "Bethe-Bloch parameters for 3H not set, please check your CCDB and configuration"; } + for (auto& v0 : V0s) { auto posTrack = v0.posTrack_as(); @@ -285,9 +317,6 @@ struct lnnRecoTask { float posRigidity = posTrack.tpcInnerParam(); float negRigidity = negTrack.tpcInnerParam(); - hdEdxTot->Fill(posRigidity, posTrack.tpcSignal()); - hdEdxTot->Fill(-negRigidity, negTrack.tpcSignal()); - // Bethe-Bloch calcution for 3H & nSigma calculation double expBethePos{tpc::BetheBlochAleph(static_cast(posRigidity / constants::physics::MassTriton), mBBparams3H[0], mBBparams3H[1], mBBparams3H[2], mBBparams3H[3], mBBparams3H[4])}; double expBetheNeg{tpc::BetheBlochAleph(static_cast(negRigidity / constants::physics::MassTriton), mBBparams3H[0], mBBparams3H[1], mBBparams3H[2], mBBparams3H[3], mBBparams3H[4])}; @@ -297,8 +326,8 @@ struct lnnRecoTask { auto nSigmaTPCneg = static_cast((negTrack.tpcSignal() - expBetheNeg) / expSigmaNeg); // ITS only tracks do not have TPC information. TPCnSigma: only lower cut to allow for triton reconstruction - bool is3H = posTrack.hasTPC() && nSigmaTPCpos > -1 * nSigmaMax3H; - bool isAnti3H = negTrack.hasTPC() && nSigmaTPCneg > -1 * nSigmaMax3H; + bool is3H = posTrack.hasTPC() && nSigmaTPCpos > -1 * nSigmaCutTPC; + bool isAnti3H = negTrack.hasTPC() && nSigmaTPCneg > -1 * nSigmaCutTPC; if (!is3H && !isAnti3H) continue; @@ -308,17 +337,22 @@ struct lnnRecoTask { lnnCand.isMatter = is3H && isAnti3H ? std::abs(nSigmaTPCpos) < std::abs(nSigmaTPCneg) : is3H; auto& h3track = lnnCand.isMatter ? posTrack : negTrack; auto& h3Rigidity = lnnCand.isMatter ? posRigidity : negRigidity; - if (h3track.tpcNClsFound() < nTPCClusMin3H || h3Rigidity < TPCRigidityMin3H) { + + if (h3Rigidity < TPCRigidityMin3H || + h3track.tpcNClsFound() < nTPCClusMin3H || + h3track.tpcChi2NCl() > Chi2nClusTPC || + h3track.itsChi2NCl() > Chi2nClusITS || + h3track.itsNCls() < nClusITS) { continue; } lnnCand.nSigma3H = lnnCand.isMatter ? nSigmaTPCpos : nSigmaTPCneg; - lnnCand.nTPCClusters3H = lnnCand.isMatter ? posTrack.tpcNClsFound() : negTrack.tpcNClsFound(); - lnnCand.tpcSignal3H = lnnCand.isMatter ? posTrack.tpcSignal() : negTrack.tpcSignal(); - lnnCand.clusterSizeITS3H = lnnCand.isMatter ? posTrack.itsClusterSizes() : negTrack.itsClusterSizes(); - lnnCand.nTPCClustersPi = !lnnCand.isMatter ? posTrack.tpcNClsFound() : negTrack.tpcNClsFound(); - lnnCand.tpcSignalPi = !lnnCand.isMatter ? posTrack.tpcSignal() : negTrack.tpcSignal(); - lnnCand.clusterSizeITSPi = !lnnCand.isMatter ? posTrack.itsClusterSizes() : negTrack.itsClusterSizes(); + lnnCand.nTPCClusters3H = lnnCand.isMatter ? h3track.tpcNClsFound() : negTrack.tpcNClsFound(); + lnnCand.tpcSignal3H = lnnCand.isMatter ? h3track.tpcSignal() : negTrack.tpcSignal(); + lnnCand.clusterSizeITS3H = lnnCand.isMatter ? h3track.itsClusterSizes() : negTrack.itsClusterSizes(); + lnnCand.nTPCClustersPi = !lnnCand.isMatter ? h3track.tpcNClsFound() : negTrack.tpcNClsFound(); + lnnCand.tpcSignalPi = !lnnCand.isMatter ? h3track.tpcSignal() : negTrack.tpcSignal(); + lnnCand.clusterSizeITSPi = !lnnCand.isMatter ? h3track.itsClusterSizes() : negTrack.itsClusterSizes(); lnnCand.mom3HTPC = lnnCand.isMatter ? posRigidity : negRigidity; lnnCand.momPiTPC = !lnnCand.isMatter ? posRigidity : negRigidity; @@ -365,8 +399,28 @@ struct lnnRecoTask { continue; } + hdEdxTot->Fill(posRigidity, posTrack.tpcSignal()); + hdEdxTot->Fill(-negRigidity, negTrack.tpcSignal()); + int chargeFactor = -1 + 2 * lnnCand.isMatter; + hdEdx3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, h3track.tpcSignal()); + hNsigma3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, lnnCand.nSigma3H); + + if (is3H) { + hdEdx3HPosTrack->Fill(lnnCand.mom3HTPC, h3track.tpcSignal()); + } + + if (h3track.hasTOF()) { + float beta = h3track.beta(); + lnnCand.mass2TrTOF = h3track.mass() * h3track.mass(); + h3HMassPtTOF->Fill(h3track.pt(), lnnCand.mass2TrTOF); + h3HSignalPtTOF->Fill(h3track.pt(), beta); + if (h3track.pt() >= 0.5) { + hNsigma3HSelTOF->Fill(h3track.pt(), h3track.tofNSigmaTr()); + } + } + // Definition of lnn mass - float mLNN_HypHI = 2.99; // 2993.7 MeV/c**2 + float mLNN_HypHI = 2.994; // value in GeV, but 2993.7 MeV/c**2 float massLNNL = std::sqrt(h3lE * h3lE - lnnMom[0] * lnnMom[0] - lnnMom[1] * lnnMom[1] - lnnMom[2] * lnnMom[2]); bool isLNNMass = false; if (massLNNL > mLNN_HypHI - masswidth && massLNNL < mLNN_HypHI + masswidth) { @@ -407,9 +461,6 @@ struct lnnRecoTask { lnnCand.posTrackID = posTrack.globalIndex(); lnnCand.negTrackID = negTrack.globalIndex(); - int chargeFactor = -1 + 2 * lnnCand.isMatter; - hdEdx3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, h3track.tpcSignal()); - hNsigma3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, lnnCand.nSigma3H); lnnCandidates.push_back(lnnCand); } } @@ -450,7 +501,6 @@ struct lnnRecoTask { lnnCand.isSignal = true; lnnCand.pdgCode = posMother.pdgCode(); lnnCand.survEvSelection = isGoodCollision[posMother.mcCollisionId()]; - filledMothers.push_back(posMother.globalIndex()); } } @@ -468,7 +518,7 @@ struct lnnRecoTask { initCCDB(bc); hEvents->Fill(0.); - if (!collision.sel8() || std::abs(collision.posZ()) > 10) { + if ((!collision.sel8()) || std::abs(collision.posZ()) > 10) { continue; } hEvents->Fill(1.); @@ -494,6 +544,7 @@ struct lnnRecoTask { lnnCand.dcaV0dau, lnnCand.h3DCAXY, lnnCand.piDCAXY, lnnCand.nSigma3H, lnnCand.nTPCClusters3H, lnnCand.nTPCClustersPi, lnnCand.mom3HTPC, lnnCand.momPiTPC, lnnCand.tpcSignal3H, lnnCand.tpcSignalPi, + lnnCand.mass2TrTOF, lnnCand.clusterSizeITS3H, lnnCand.clusterSizeITSPi, lnnCand.flags); } } @@ -501,9 +552,11 @@ struct lnnRecoTask { PROCESS_SWITCH(lnnRecoTask, processData, "Data analysis", true); // MC process - void processMC(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, aod::V0s const& V0s, TracksFull const& tracks, aod::BCsWithTimestamps const&, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC) + void processMC(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, aod::V0s const& V0s, aod::BCsWithTimestamps const&, TracksFull const& tracks, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC) { filledMothers.clear(); + + isGoodCollision.clear(); isGoodCollision.resize(mcCollisions.size(), false); for (const auto& collision : collisions) { @@ -548,6 +601,7 @@ struct lnnRecoTask { lnnCand.dcaV0dau, lnnCand.h3DCAXY, lnnCand.piDCAXY, lnnCand.nSigma3H, lnnCand.nTPCClusters3H, lnnCand.nTPCClustersPi, lnnCand.mom3HTPC, lnnCand.momPiTPC, lnnCand.tpcSignal3H, lnnCand.tpcSignalPi, + lnnCand.mass2TrTOF, lnnCand.clusterSizeITS3H, lnnCand.clusterSizeITSPi, lnnCand.flags, chargeFactor * lnnCand.genPt(), lnnCand.genPhi(), lnnCand.genEta(), lnnCand.genPt3H(), lnnCand.gDecVtx[0], lnnCand.gDecVtx[1], lnnCand.gDecVtx[2], lnnCand.isReco, lnnCand.isSignal, lnnCand.survEvSelection); @@ -617,6 +671,7 @@ struct lnnRecoTask { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, chargeFactor * lnnCand.genPt(), lnnCand.genPhi(), lnnCand.genEta(), lnnCand.genPt3H(), lnnCand.gDecVtx[0], lnnCand.gDecVtx[1], lnnCand.gDecVtx[2], lnnCand.isReco, lnnCand.isSignal, lnnCand.survEvSelection); diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index f76b97e0465..09b2e909ec1 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -36,6 +36,7 @@ #include "Common/TableProducer/PID/pidTOFBase.h" #include "Common/Core/EventPlaneHelper.h" #include "Common/DataModel/Qvectors.h" +#include "Common/Tools/TrackTuner.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" @@ -44,6 +45,7 @@ #include "DetectorsBase/Propagator.h" #include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -65,6 +67,7 @@ using namespace o2::constants::physics; struct NucleusCandidate { int globalIndex; + int collTrackIndex; float pt; float eta; float phi; @@ -76,11 +79,20 @@ struct NucleusCandidate { float TPCsignal; float ITSchi2; float TPCchi2; + std::array nSigmaTPC; + std::array tofMasses; + bool fillTree; + bool fillDCAHist; + bool correctPV; + bool isSecondary; + bool fromWeakDecay; uint16_t flags; uint8_t TPCfindableCls; uint8_t TPCcrossedRows; uint8_t ITSclsMap; uint8_t TPCnCls; + uint8_t TPCnClsShared; + uint8_t ITSnCls; uint32_t clusterSizesITS; }; @@ -143,12 +155,12 @@ constexpr int FlowHistDefault[5][1]{ {0}, {0}, {0}}; -constexpr int DCAHistDefault[5][1]{ - {0}, - {0}, - {0}, - {0}, - {0}}; +constexpr int DCAHistDefault[5][2]{ + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}; constexpr double DownscalingDefault[5][1]{ {1.}, {1.}, @@ -165,7 +177,7 @@ static const std::vector pidName{"TPC", "TOF"}; static const std::vector names{"proton", "deuteron", "triton", "He3", "alpha"}; static const std::vector treeConfigNames{"Filter trees", "Use TOF selection"}; static const std::vector flowConfigNames{"Save flow hists"}; -static const std::vector DCAConfigNames{"Save DCA hists"}; +static const std::vector DCAConfigNames{"Save DCA hist", "Matter/Antimatter"}; static const std::vector nSigmaConfigName{"nsigma_min", "nsigma_max"}; static const std::vector nDCAConfigName{"max DCAxy", "max DCAz"}; static const std::vector DownscalingConfigName{"Fraction of kept candidates"}; @@ -222,6 +234,8 @@ struct nucleiSpectra { Produces nucleiTableFlow; Service ccdb; Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + TrackTuner trackTunerObj; Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", false, "If true, divide tpcInnerParam by the electric charge"}; @@ -242,8 +256,8 @@ struct nucleiSpectra { Configurable> cfgDCAcut{"cfgDCAcut", {nuclei::DCAcutDefault[0], 5, 2, nuclei::names, nuclei::nDCAConfigName}, "Max DCAxy and DCAz for light nuclei"}; Configurable> cfgDownscaling{"cfgDownscaling", {nuclei::DownscalingDefault[0], 5, 1, nuclei::names, nuclei::DownscalingConfigName}, "Fraction of kept candidates for light nuclei"}; Configurable> cfgTreeConfig{"cfgTreeConfig", {nuclei::TreeConfigDefault[0], 5, 2, nuclei::names, nuclei::treeConfigNames}, "Filtered trees configuration"}; + Configurable> cfgDCAHists{"cfgDCAHists", {nuclei::DCAHistDefault[0], 5, 2, nuclei::names, nuclei::DCAConfigNames}, "DCA hist configuration"}; Configurable> cfgFlowHist{"cfgFlowHist", {nuclei::FlowHistDefault[0], 5, 1, nuclei::names, nuclei::flowConfigNames}, "Flow hist configuration"}; - Configurable> cfgDCAHist{"cfgDCAHist", {nuclei::DCAHistDefault[0], 5, 1, nuclei::names, nuclei::DCAConfigNames}, "DCA hist configuration"}; ConfigurableAxis cfgDCAxyBinsProtons{"cfgDCAxyBinsProtons", {1500, -1.5f, 1.5f}, "DCAxy binning for Protons"}; ConfigurableAxis cfgDCAxyBinsDeuterons{"cfgDCAxyBinsDeuterons", {1500, -1.5f, 1.5f}, "DCAxy binning for Deuterons"}; @@ -268,6 +282,14 @@ struct nucleiSpectra { Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + // configurables for track tuner + Configurable cfgUseTrackTuner{"cfgUseTrackTuner", false, "Apply track tuner corrections to MC tracks"}; + Configurable cfgTrackTunerParams{"cfgTrackTunerParams", "debugInfo=0|updateTrackDCAs=1|updateTrackCovMat=1|updateCurvature=0|updateCurvatureIU=0|updatePulls=1|isInputFileFromCCDB=1|pathInputFile=Users/m/mfaggin/test/inputsTrackTuner/pp2023/smoothHighPtMC|nameInputFile=trackTuner_DataLHC23fPass1_McLHC23k4b_run535085.root|pathFileQoverPt=Users/h/hsharma/qOverPtGraphs|nameFileQoverPt=D0sigma_Data_removal_itstps_MC_LHC22b1b.root|usePvRefitCorrections=0|qOverPtMC=-1.|qOverPtData=-1.", "TrackTuner parameter initialization (format: =|=)"}; + // running variables for track tuner + o2::dataformats::DCA mDcaInfoCov; + o2::track::TrackParametrizationWithError mTrackParCov; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + // CCDB options Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; Configurable cfgCCDBurl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -287,7 +309,6 @@ struct nucleiSpectra { using CollWithQvec = soa::Join::iterator; HistogramRegistry spectra{"spectra", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - o2::pid::tof::Beta responseBeta; double getPhiInRange(double phi) { @@ -337,19 +358,22 @@ struct nucleiSpectra { return; } if (cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fHe3"); + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fHe"); + zorro.populateHistRegistry(spectra, bc.runNumber()); } auto timestamp = bc.timestamp(); mRunNumber = bc.runNumber(); o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(nuclei::lut); mBz = static_cast(grpmag->getNominalL3Field()); LOGF(info, "Retrieved GRP for timestamp %ull (%i) with magnetic field of %1.2f kZG", timestamp, mRunNumber, mBz); } void init(o2::framework::InitContext&) { + zorroSummary.setObject(zorro.getZorroSummary()); ccdb->setURL(cfgCCDBurl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -363,6 +387,9 @@ struct nucleiSpectra { const AxisSpec nITSClusAxis{cfgNITSClusBins, "N ITS clusters"}; const AxisSpec nTPCClusAxis{cfgNTPCClusBins, "N TPC clusters"}; const AxisSpec hasTRDAxis{2, -0.5, 1.5, "Has TRD"}; + const AxisSpec correctPVAxis{2, -0.5, 1.5, "Correct PV"}; + const AxisSpec isSecondaryAxis{2, -0.5, 1.5, "Is secondary"}; + const AxisSpec fromWeakDecayAxis{2, -0.5, 1.5, "From weak decay"}; const AxisSpec ptAxes[5]{ {cfgPtBinsProtons, "#it{p}_{T} (GeV/#it{c})"}, @@ -409,13 +436,15 @@ struct nucleiSpectra { if (doprocessMC) { nuclei::hMomRes[iS][iC] = spectra.add(fmt::format("h{}MomRes{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("Momentum resolution {}", nuclei::names[iS]).data(), HistType::kTH3D, {centAxis, ptAxes[iS], ptResAxis}); nuclei::hGenNuclei[iS][iC] = spectra.add(fmt::format("h{}Gen{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("Generated {}", nuclei::names[iS]).data(), HistType::kTH2D, {centAxis, ptAxes[iS]}); - } - if (doprocessDataFlow) { - if (cfgFlowHist->get(iS)) { - nuclei::hFlowHists[iC][iS] = spectra.add(fmt::format("hFlowHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("Flow histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {centAxis, ptAxes[iS], nSigmaAxes[0], tofMassAxis, v2Axis, nITSClusAxis, nTPCClusAxis}); + nuclei::hDCAHists[iC][iS] = spectra.add(fmt::format("hDCAHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCA histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {ptAxes[iS], dcaxyAxes[iS], dcazAxes[iS], nSigmaAxes[0], tofMassAxis, nITSClusAxis, nTPCClusAxis, correctPVAxis, isSecondaryAxis, fromWeakDecayAxis}); + } else { + if (doprocessDataFlow) { + if (cfgFlowHist->get(iS)) { + nuclei::hFlowHists[iC][iS] = spectra.add(fmt::format("hFlowHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("Flow histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {centAxis, ptAxes[iS], nSigmaAxes[0], tofMassAxis, v2Axis, nITSClusAxis, nTPCClusAxis}); + } } + nuclei::hDCAHists[iC][iS] = spectra.add(fmt::format("hDCAHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCA histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {ptAxes[iS], dcaxyAxes[iS], dcazAxes[iS], nSigmaAxes[0], tofMassAxis, nITSClusAxis, nTPCClusAxis}); } - nuclei::hDCAHists[iC][iS] = spectra.add(fmt::format("hDCAHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCA histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {ptAxes[iS], dcaxyAxes[iS], dcazAxes[iS], nSigmaAxes[0], tofMassAxis, nITSClusAxis, nTPCClusAxis}); } } @@ -426,7 +455,12 @@ struct nucleiSpectra { } nuclei::lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); - o2::base::Propagator::Instance(true)->setMatLUT(nuclei::lut); + // TrackTuner initialization + if (cfgUseTrackTuner) { + std::string outputStringParams = trackTunerObj.configParams(cfgTrackTunerParams); + spectra.add("hTrackTunedTracks", outputStringParams.c_str(), HistType::kTH1F, {{1, 0.5, 1.5, ""}}); + trackTunerObj.getDcaGraphs(); + } } template @@ -452,6 +486,7 @@ struct nucleiSpectra { template void fillDataInfo(Tcoll const& collision, Ttrks const& tracks) { + o2::pid::tof::Beta responseBeta; auto bc = collision.template bc_as(); initCCDB(bc); gRandom->SetSeed(bc.timestamp()); @@ -501,10 +536,12 @@ struct nucleiSpectra { } bool selectedTPC[5]{false}, goodToAnalyse{false}; + std::array nSigmaTPC; for (int iS{0}; iS < nuclei::species; ++iS) { double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScalings[iS][iC]), cfgBetheBlochParams->get(iS, 0u), cfgBetheBlochParams->get(iS, 1u), cfgBetheBlochParams->get(iS, 2u), cfgBetheBlochParams->get(iS, 3u), cfgBetheBlochParams->get(iS, 4u))}; double expSigma{expBethe * cfgBetheBlochParams->get(iS, 5u)}; nSigma[0][iS] = static_cast((track.tpcSignal() - expBethe) / expSigma); + nSigmaTPC[iS] = nSigma[0][iS]; selectedTPC[iS] = (nSigma[0][iS] > nuclei::pidCuts[0][iS][0] && nSigma[0][iS] < nuclei::pidCuts[0][iS][1]); goodToAnalyse = goodToAnalyse || selectedTPC[iS]; if (selectedTPC[iS] && track.p() > 0.2) { @@ -515,15 +552,38 @@ struct nucleiSpectra { continue; } - auto trackParCov = getTrackParCov(track); // should we set the charge according to the nucleus? + mDcaInfoCov.set(999, 999, 999, 999, 999); + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + if constexpr ( + requires { + track.has_mcParticle(); + }) { + if (cfgUseTrackTuner) { + bool hasMcParticle = track.has_mcParticle(); + if (hasMcParticle) { + spectra.get(HIST("hTrackTunedTracks"))->Fill(1); // all tracks + auto mcParticle = track.mcParticle(); + trackTunerObj.tuneTrackParams(mcParticle, mTrackParCov, matCorr, &mDcaInfoCov, spectra.get(HIST("hTrackTunedTracks"))); + } + } + } + gpu::gpustd::array dcaInfo; - o2::base::Propagator::Instance()->propagateToDCA(collVtx, trackParCov, mBz, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfo); + o2::base::Propagator::Instance()->propagateToDCA(collVtx, mTrackParCov, mBz, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfo); float beta{responseBeta.GetBeta(track)}; spectra.fill(HIST("hTpcSignalDataSelected"), correctedTpcInnerParam * track.sign(), track.tpcSignal()); spectra.fill(HIST("hTofSignalData"), correctedTpcInnerParam, beta); beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked uint16_t flag = static_cast((track.pidForTracking() & 0xF) << 12); + std::array tofMasses{-3.f, -3.f, -3.f, -3.f, -3.f}; + bool fillTree{false}; + bool fillDCAHist{false}; + bool correctPV{false}; + bool isSecondary{false}; + bool fromWeakDecay{false}; + if (track.hasTOF()) { flag |= kHasTOF; } @@ -538,9 +598,8 @@ struct nucleiSpectra { if (std::abs(dcaInfo[1]) > cfgDCAcut->get(iS, 1)) { continue; } - ROOT::Math::LorentzVector> fvector{trackParCov.getPt() * nuclei::charges[iS], trackParCov.getEta(), trackParCov.getPhi(), nuclei::masses[iS]}; + ROOT::Math::LorentzVector> fvector{mTrackParCov.getPt() * nuclei::charges[iS], mTrackParCov.getEta(), mTrackParCov.getPhi(), nuclei::masses[iS]}; float y{fvector.Rapidity() + cfgCMrapidity}; - for (int iPID{0}; iPID < 2; ++iPID) { if (selectedTPC[iS]) { if (iPID && !track.hasTOF()) { @@ -552,46 +611,49 @@ struct nucleiSpectra { nuclei::hDCAxy[iPID][iS][iC]->Fill(centrality, fvector.pt(), dcaInfo[0]); nuclei::hDCAz[iPID][iS][iC]->Fill(centrality, fvector.pt(), dcaInfo[1]); if (std::abs(dcaInfo[0]) < cfgDCAcut->get(iS, 0u)) { - float tofMass = -10.f; if (!iPID) { /// temporary exclusion of the TOF nsigma PID for the He3 and Alpha nuclei::hNsigma[iPID][iS][iC]->Fill(centrality, fvector.pt(), nSigma[iPID][iS]); nuclei::hNsigmaEta[iPID][iS][iC]->Fill(fvector.eta(), fvector.pt(), nSigma[iPID][iS]); } if (iPID) { - tofMass = correctedTpcInnerParam * std::sqrt(1.f / (beta * beta) - 1.f) - nuclei::masses[iS]; - nuclei::hTOFmass[iS][iC]->Fill(centrality, fvector.pt(), tofMass); - nuclei::hTOFmassEta[iS][iC]->Fill(fvector.eta(), fvector.pt(), tofMass); + float charge{1}; + if (iS == 3 || iS == 4) + charge = 2; + tofMasses[iS] = correctedTpcInnerParam * charge * std::sqrt(1.f / (beta * beta) - 1.f) - nuclei::masses[iS]; + nuclei::hTOFmass[iS][iC]->Fill(centrality, fvector.pt(), tofMasses[iS]); + nuclei::hTOFmassEta[iS][iC]->Fill(fvector.eta(), fvector.pt(), tofMasses[iS]); } if (cfgFlowHist->get(iS) && doprocessDataFlow) { if constexpr (std::is_same::value) { auto deltaPhiInRange = getPhiInRange(fvector.phi() - collision.psiFT0C()); auto v2 = std::cos(2.0 * deltaPhiInRange); - nuclei::hFlowHists[iC][iS]->Fill(collision.centFT0C(), fvector.pt(), nSigma[0][iS], tofMass, v2, track.itsNCls(), track.tpcNClsFound()); + nuclei::hFlowHists[iC][iS]->Fill(collision.centFT0C(), fvector.pt(), nSigma[0][iS], tofMasses[iS], v2, track.itsNCls(), track.tpcNClsFound()); } } else if (cfgFlowHist->get(iS) && doprocessDataFlowAlternative) { if constexpr (std::is_same::value) { auto deltaPhiInRange = getPhiInRange(fvector.phi() - computeEventPlane(collision.qvecFT0CIm(), collision.qvecFT0CRe())); auto v2 = std::cos(2.0 * deltaPhiInRange); - nuclei::hFlowHists[iC][iS]->Fill(collision.centFT0C(), fvector.pt(), nSigma[0][iS], tofMass, v2, track.itsNCls(), track.tpcNClsFound()); + nuclei::hFlowHists[iC][iS]->Fill(collision.centFT0C(), fvector.pt(), nSigma[0][iS], tofMasses[iS], v2, track.itsNCls(), track.tpcNClsFound()); } } - if (cfgDCAHist->get(iS)) { - nuclei::hDCAHists[iC][iS]->Fill(fvector.pt(), dcaInfo[0], dcaInfo[1], nSigma[0][iS], tofMass, track.itsNCls(), track.tpcNClsFound()); - } } } } } - - if (cfgTreeConfig->get(iS, 0u) && selectedTPC[iS]) { + if (selectedTPC[iS]) { if (cfgTreeConfig->get(iS, 1u) && !selectedTOF) { continue; } - if (cfgDownscaling->get(iS) < 1. && gRandom->Rndm() > cfgDownscaling->get(iS)) { - continue; + !fillTree && cfgTreeConfig->get(iS, 0u) ? fillTree = true : fillTree; + !fillDCAHist && cfgDCAHists->get(iS, iC) ? fillDCAHist = true : fillDCAHist; + bool setPartFlag = cfgTreeConfig->get(iS, 0u) || cfgDCAHists->get(iS, iC); + if (setPartFlag) { + if (cfgDownscaling->get(iS) < 1. && gRandom->Rndm() > cfgDownscaling->get(iS)) { + continue; + } + flag |= BIT(iS); } - flag |= BIT(iS); } } if (flag & (kProton | kDeuteron | kTriton | kHe3 | kHe4) || doprocessMC) { /// ignore PID pre-selections for the MC @@ -624,7 +686,11 @@ struct nucleiSpectra { computeEventPlane(collision.qvecBPosIm(), collision.qvecBPosRe()), collision.multTPC()}); } - nuclei::candidates.emplace_back(NucleusCandidate{static_cast(track.globalIndex()), (1 - 2 * iC) * trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), correctedTpcInnerParam, beta, collision.posZ(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), flag, track.tpcNClsFindable(), static_cast(track.tpcNClsCrossedRows()), track.itsClusterMap(), static_cast(track.tpcNClsFound()), static_cast(track.itsClusterSizes())}); + nuclei::candidates.emplace_back(NucleusCandidate{ + static_cast(track.globalIndex()), static_cast(track.collisionId()), (1 - 2 * iC) * mTrackParCov.getPt(), mTrackParCov.getEta(), mTrackParCov.getPhi(), + correctedTpcInnerParam, beta, collision.posZ(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), + nSigmaTPC, tofMasses, fillTree, fillDCAHist, correctPV, isSecondary, fromWeakDecay, flag, track.tpcNClsFindable(), static_cast(track.tpcNClsCrossedRows()), track.itsClusterMap(), + static_cast(track.tpcNClsFound()), static_cast(track.tpcNClsShared()), static_cast(track.itsNCls()), static_cast(track.itsClusterSizes())}); } } // end loop over tracks @@ -644,7 +710,16 @@ struct nucleiSpectra { fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.clusterSizesITS); + if (c.fillTree) { + nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + } + if (c.fillDCAHist) { + for (int iS{0}; iS < nuclei::species; ++iS) { + if (c.flags & BIT(iS)) { + nuclei::hDCAHists[c.pt < 0][iS]->Fill(std::abs(c.pt), c.DCAxy, c.DCAz, c.nSigmaTPC[iS], c.tofMasses[iS], c.ITSnCls, c.TPCnCls); + } + } + } } } PROCESS_SWITCH(nucleiSpectra, processData, "Data analysis", true); @@ -661,7 +736,16 @@ struct nucleiSpectra { } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.clusterSizesITS); + if (c.fillTree) { + nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + } + if (c.fillDCAHist) { + for (int iS{0}; iS < nuclei::species; ++iS) { + if (c.flags & BIT(iS)) { + nuclei::hDCAHists[c.pt < 0][iS]->Fill(std::abs(c.pt), c.DCAxy, c.DCAz, c.nSigmaTPC[iS], c.tofMasses[iS], c.ITSnCls, c.TPCnCls); + } + } + } } for (auto& c : nuclei::candidates_flow) { nucleiTableFlow(c.centFV0A, c.centFT0M, c.centFT0A, c.centFT0C, c.psiFT0A, c.multFT0A, c.psiFT0C, c.multFT0C, c.psiTPC, c.psiTPCl, c.psiTPCr, c.multTPC); @@ -681,7 +765,16 @@ struct nucleiSpectra { } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.clusterSizesITS); + if (c.fillTree) { + nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + } + if (c.fillDCAHist) { + for (int iS{0}; iS < nuclei::species; ++iS) { + if (c.flags & BIT(iS)) { + nuclei::hDCAHists[c.pt < 0][iS]->Fill(std::abs(c.pt), c.DCAxy, c.DCAz, c.nSigmaTPC[iS], c.tofMasses[iS], c.ITSnCls, c.TPCnCls); + } + } + } } for (auto& c : nuclei::candidates_flow) { nucleiTableFlow(c.centFV0A, c.centFT0M, c.centFT0A, c.centFT0C, c.psiFT0A, c.multFT0A, c.psiFT0C, c.multFT0C, c.psiTPC, c.psiTPCl, c.psiTPCr, c.multTPC); @@ -690,7 +783,7 @@ struct nucleiSpectra { PROCESS_SWITCH(nucleiSpectra, processDataFlowAlternative, "Data analysis with flow - alternative framework", false); Preslice tracksPerCollisions = aod::track::collisionId; - void processMC(soa::Join const& collisions, aod::McCollisions const& mcCollisions, TrackCandidates const& tracks, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, aod::BCsWithTimestamps const&) + void processMC(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& tracks, aod::McParticles const& particlesMC, aod::BCsWithTimestamps const&) { nuclei::candidates.clear(); for (auto& c : mcCollisions) { @@ -707,7 +800,7 @@ struct nucleiSpectra { } std::vector isReconstructed(particlesMC.size(), false); for (auto& c : nuclei::candidates) { - auto label = trackLabelsMC.iteratorAt(c.globalIndex); + auto label = tracks.iteratorAt(c.globalIndex); if (label.mcParticleId() < -1 || label.mcParticleId() >= particlesMC.size()) { continue; } @@ -715,9 +808,24 @@ struct nucleiSpectra { bool storeIt{false}; for (int iS{0}; iS < nuclei::species; ++iS) { if (std::abs(particle.pdgCode()) == nuclei::codes[iS]) { - nuclei::hMomRes[iS][particle.pdgCode() < 0]->Fill(1., std::abs(c.pt * nuclei::charges[iS]), 1. - std::abs(c.pt * nuclei::charges[iS]) / particle.pt()); - storeIt = cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u); /// store only the particles of interest - break; + if (c.fillTree && !storeIt) { + nuclei::hMomRes[iS][particle.pdgCode() < 0]->Fill(1., std::abs(c.pt * nuclei::charges[iS]), 1. - std::abs(c.pt * nuclei::charges[iS]) / particle.pt()); + storeIt = cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u); /// store only the particles of interest + } + auto coll = collisions.iteratorAt(c.collTrackIndex); + int collMCGlobId = coll.mcCollisionId(); + if (particle.mcCollisionId() == collMCGlobId) { + c.correctPV = true; + } + if (!particle.isPhysicalPrimary()) { + c.isSecondary = true; + if (particle.getProcess() == 4) { + c.fromWeakDecay = true; + } + } + if (c.fillDCAHist && cfgDCAHists->get(iS, c.pt < 0)) { + nuclei::hDCAHists[c.pt < 0][iS]->Fill(std::abs(c.pt), c.DCAxy, c.DCAz, c.nSigmaTPC[iS], c.tofMasses[iS], c.ITSnCls, c.TPCnCls, c.correctPV, c.isSecondary, c.fromWeakDecay); + } } } if (!storeIt) { @@ -732,7 +840,7 @@ struct nucleiSpectra { c.flags |= kIsSecondaryFromMaterial; } float absoDecL = computeAbsoDecL(particle); - nucleiTableMC(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.clusterSizesITS, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), goodCollisions[particle.mcCollisionId()], absoDecL); + nucleiTableMC(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), goodCollisions[particle.mcCollisionId()], absoDecL); } int index{0}; @@ -753,7 +861,7 @@ struct nucleiSpectra { if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { float absDecL = computeAbsoDecL(particle); - nucleiTableMC(999., 999., 999., 0., 0., 999., 999., 999., -1, -1, -1, flags, 0, 0, 0, 0, 0, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), goodCollisions[particle.mcCollisionId()], absDecL); + nucleiTableMC(999., 999., 999., 0., 0., 999., 999., 999., -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), goodCollisions[particle.mcCollisionId()], absDecL); } break; } diff --git a/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx b/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx new file mode 100644 index 00000000000..88b4fb04499 --- /dev/null +++ b/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx @@ -0,0 +1,410 @@ +// Copyright 2019-2020 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. + +/// +/// \file pidTOFGeneric.cxx +/// \origin Based on pidTOFBase.cxx +/// \brief Task to produce event Time obtained from TOF and FT0. +/// In order to redo TOF PID for tracks which are linked to wrong collisions +/// + +#include +#include +#include + +// O2 includes +#include "CCDB/BasicCCDBManager.h" +#include "TOFBase/EventTimeMaker.h" +#include "Framework/AnalysisTask.h" +#include "ReconstructionDataFormats/Track.h" + +// O2Physics includes +#include "Common/Core/TableHelper.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "PID/ParamBase.h" +#include "PID/PIDTOF.h" +#include "PWGLF/DataModel/pidTOFGeneric.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::pid; +using namespace o2::framework::expressions; +using namespace o2::track; + +/// Selection criteria for tracks used for TOF event time +float trackSampleMinMomentum = 0.5f; +float trackSampleMaxMomentum = 2.f; +template +bool filterForTOFEventTime(const trackType& tr) +{ + return (tr.hasTOF() && tr.p() > trackSampleMinMomentum && tr.p() < trackSampleMaxMomentum && (tr.trackType() == o2::aod::track::TrackTypeEnum::Track || tr.trackType() == o2::aod::track::TrackTypeEnum::TrackIU)); +} // accept all + +/// Specialization of TOF event time maker +template typename response, + typename trackTypeContainer, + typename responseParametersType> +o2::tof::eventTimeContainer evTimeMakerForTracks(const trackTypeContainer& tracks, + const responseParametersType& responseParameters, + const float& diamond = 6.0, + bool isFast = false) +{ + return o2::tof::evTimeMakerFromParam(tracks, responseParameters, diamond, isFast); +} + +/// Task to produce the event time tables for generic TOF PID +struct pidTOFGeneric { + // Tables to produce + Produces tableEvTime; // Table for global event time + Produces tableEvTimeForTrack; // Table for event time after removing bias from the track + static constexpr float diamond = 6.0; // Collision diamond used in the estimation of the TOF event time + static constexpr float errDiamond = diamond * 33.356409f; + static constexpr float weightDiamond = 1.f / (errDiamond * errDiamond); + + bool enableTable = false; + // Detector response and input parameters + o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + Service ccdb; + Configurable inheritFromBaseTask{"inheritFromBaseTask", true, "Flag to iherit all common configurables from the TOF base task"}; + Configurable fastTOFPID{"fastTOFPID", false, "Flag to enable computeEvTimeFast for evTimeMaker"}; + // CCDB configuration (inherited from TOF signal task) + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + // Event time configurations + Configurable minMomentum{"minMomentum", 0.5f, "Minimum momentum to select track sample for TOF event time"}; + Configurable maxMomentum{"maxMomentum", 2.0f, "Maximum momentum to select track sample for TOF event time"}; + Configurable maxEvTimeTOF{"maxEvTimeTOF", 100000.0f, "Maximum value of the TOF event time"}; + Configurable sel8TOFEvTime{"sel8TOFEvTime", false, "Flag to compute the ev. time only for events that pass the sel8 ev. selection"}; + Configurable maxNtracksInSet{"maxNtracksInSet", 10, "Size of the set to consider for the TOF ev. time computation"}; + // TOF Calib configuration + Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; + Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; + Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; + Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; + Configurable enableTimeDependentResponse{"enableTimeDependentResponse", false, "Flag to use the collision timestamp to fetch the PID Response"}; + Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; + + void init(o2::framework::InitContext& initContext) + { + if (inheritFromBaseTask.value) { + if (!getTaskOptionValue(initContext, "tof-signal", "ccdb-url", url.value, true)) { + LOG(fatal) << "Could not get ccdb-url from tof-signal task"; + } + if (!getTaskOptionValue(initContext, "tof-signal", "ccdb-timestamp", timestamp.value, true)) { + LOG(fatal) << "Could not get ccdb-timestamp from tof-signal task"; + } + } + + trackSampleMinMomentum = minMomentum; + trackSampleMaxMomentum = maxMomentum; + LOG(info) << "Configuring track sample for TOF ev. time: " << trackSampleMinMomentum << " < p < " << trackSampleMaxMomentum; + // Check that both processes are not enabled + int nEnabled = 0; + if (doprocessNoFT0 == true) { + LOGF(info, "Enabling process function: processNoFT0"); + nEnabled++; + } + if (doprocessFT0 == true) { + LOGF(info, "Enabling process function: processFT0"); + nEnabled++; + } + if (doprocessOnlyFT0 == true) { + LOGF(info, "Enabling process function: processOnlyFT0"); + nEnabled++; + } + if (nEnabled > 1) { + LOGF(fatal, "Cannot enable more process functions at the same time. Please choose one."); + } + // Checking that the table is requested in the workflow and enabling it + enableTable = isTableRequiredInWorkflow(initContext, "EvTimeTOFFT0"); + if (!enableTable) { + LOG(info) << "Table for global Event time is not required, disabling it"; + return; + } + LOG(info) << "Table EvTimeTOFFT0 enabled!"; + + if (sel8TOFEvTime.value == true) { + LOG(info) << "TOF event time will be computed for collisions that pass the event selection only!"; + } + // Getting the parametrization parameters + ccdb->setURL(url.value); + ccdb->setTimestamp(timestamp.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + // + + // TODO: implement the automatic pass name detection from metadata + if (passName.value == "") { + passName.value = "unanchored"; // temporary default + LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; + } + LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; + + const std::string fname = paramFileName.value; + if (!fname.empty()) { // Loading the parametrization from file + LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; + if (1) { + o2::tof::ParameterCollection paramCollection; + paramCollection.loadParamFromFile(fname, parametrizationPath.value); + LOG(info) << "+++ Loaded parameter collection from file +++"; + if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { + if (fatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } + } else { + mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); + mRespParamsV2.printShiftParameters(); + } + } else { + mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); + } + } else if (loadResponseFromCCDB) { // Loading it from CCDB + LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; + + o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); + paramCollection->print(); + if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { + if (fatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } + } else { + mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); + mRespParamsV2.printShiftParameters(); + } + } + mRespParamsV2.print(); + o2::tof::eventTimeContainer::setMaxNtracksInSet(maxNtracksInSet.value); + o2::tof::eventTimeContainer::printConfig(); + } + + /// + /// Process function to prepare the event time on Run 3 data without the FT0 + using TrksEvTime = soa::Join; + // Define slice per collision + Preslice perCollision = aod::track::collisionId; + template + using ResponseImplementationEvTime = o2::pid::tof::ExpTimes; + using EvTimeCollisions = soa::Join; + void processNoFT0(TrksEvTime& tracks, + EvTimeCollisions const& collisions) + { + if (!enableTable) { + return; + } + tableEvTime.reserve(collisions.size()); + tableEvTimeForTrack.reserve(tracks.size()); + + // for tracks not assigned to a collision + for (auto track : tracks) { + if (!track.has_collision()) { + tableEvTimeForTrack(0.f, 999.f); + } + } + + for (auto const& collision : collisions) { // Loop on collisions + const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); + if ((sel8TOFEvTime.value == true) && !collision.sel8()) { + tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); + for (int i = 0; i < tracksInCollision.size(); i++) { + tableEvTimeForTrack(0.f, 999.f); + } + continue; + } + + // First make table for event time + const auto evTimeTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV2, diamond, fastTOFPID); + int nGoodTracksForTOF = 0; // count for ntrackIndex for removeBias() + float et = evTimeTOF.mEventTime; + float erret = evTimeTOF.mEventTimeError; + + if (erret < errDiamond && (maxEvTimeTOF <= 0.f || abs(et) < maxEvTimeTOF)) { + } else { + et = 0.f; + erret = errDiamond; + } + tableEvTime(et, erret, et, erret, 0.f, 999.f); + for (auto const& track : tracksInCollision) { + evTimeTOF.removeBias(track, nGoodTracksForTOF, et, erret, 2); + if (erret < errDiamond && (maxEvTimeTOF <= 0.f || abs(et) < maxEvTimeTOF)) { + } else { + et = 0.f; + erret = errDiamond; + } + tableEvTimeForTrack(et, erret); + } + } + } + PROCESS_SWITCH(pidTOFGeneric, processNoFT0, "Process without FT0", false); + + /// + /// Process function to prepare the event for each track on Run 3 data with the FT0 + using EvTimeCollisionsFT0 = soa::Join; + void processFT0(TrksEvTime& tracks, + aod::FT0s const&, + EvTimeCollisionsFT0 const& collisions) + { + if (!enableTable) { + return; + } + tableEvTime.reserve(collisions.size()); + tableEvTimeForTrack.reserve(tracks.size()); + std::vector tEvTimeForTrack; + std::vector tEvTimeErrForTrack; + tEvTimeForTrack.resize(tracks.size()); + tEvTimeErrForTrack.resize(tracks.size()); + + // for tracks not assigned to a collision + for (auto track : tracks) { + if (!track.has_collision()) { + tEvTimeForTrack[track.globalIndex()] = 0.f; + tEvTimeErrForTrack[track.globalIndex()] = 999.f; + } + } + + for (auto const& collision : collisions) { // Loop on collisions + const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); + if ((sel8TOFEvTime.value == true) && !collision.sel8()) { + tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); + for (auto track : tracksInCollision) { + tEvTimeForTrack[track.globalIndex()] = 0.f; + tEvTimeErrForTrack[track.globalIndex()] = 999.f; + } + continue; + } + + // Compute the TOF event time + const auto evTimeTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV2, diamond, fastTOFPID); + + float t0TOF[2] = {static_cast(evTimeTOF.mEventTime), static_cast(evTimeTOF.mEventTimeError)}; // Value and error of TOF + float t0AC[2] = {.0f, 999.f}; // Value and error of T0A or T0C or T0AC + + float eventTime = 0.f; + float sumOfWeights = 0.f; + float weight = 0.f; + + if (t0TOF[1] < errDiamond && (maxEvTimeTOF <= 0 || abs(t0TOF[0]) < maxEvTimeTOF)) { + weight = 1.f / (t0TOF[1] * t0TOF[1]); + eventTime += t0TOF[0] * weight; + sumOfWeights += weight; + } + + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + t0AC[0] = collision.t0AC() * 1000.f; + t0AC[1] = collision.t0resolution() * 1000.f; + } + + weight = 1.f / (t0AC[1] * t0AC[1]); + eventTime += t0AC[0] * weight; + sumOfWeights += weight; + } + + if (sumOfWeights < weightDiamond) { // avoiding sumOfWeights = 0 or worse that diamond + eventTime = 0; + sumOfWeights = weightDiamond; + } + tableEvTime(eventTime / sumOfWeights, sqrt(1. / sumOfWeights), t0TOF[0], t0TOF[1], t0AC[0], t0AC[1]); + + int nGoodTracksForTOF = 0; // count for ntrackIndex for removeBias() + for (auto const& track : tracksInCollision) { + // Reset the event time + eventTime = 0.f; + sumOfWeights = 0.f; + weight = 0.f; + // Remove the bias on TOF ev. time + evTimeTOF.removeBias(track, nGoodTracksForTOF, t0TOF[0], t0TOF[1], 2); + if (t0TOF[1] < errDiamond && (maxEvTimeTOF <= 0 || abs(t0TOF[0]) < maxEvTimeTOF)) { + weight = 1.f / (t0TOF[1] * t0TOF[1]); + eventTime += t0TOF[0] * weight; + sumOfWeights += weight; + } + + // Add the contribution from FT0 if it is available, t0AC is already calculated + if (collision.has_foundFT0()) { + weight = 1.f / (t0AC[1] * t0AC[1]); + eventTime += t0AC[0] * weight; + sumOfWeights += weight; + } + + if (sumOfWeights < weightDiamond) { // avoiding sumOfWeights = 0 or worse that diamond + eventTime = 0; + sumOfWeights = weightDiamond; + } + tEvTimeForTrack[track.globalIndex()] = eventTime / sumOfWeights; + tEvTimeErrForTrack[track.globalIndex()] = sqrt(1. / sumOfWeights); + } + } + for (int i = 0; i < tracks.size(); i++) { + tableEvTimeForTrack(tEvTimeForTrack[i], tEvTimeErrForTrack[i]); + } + } + PROCESS_SWITCH(pidTOFGeneric, processFT0, "Process with FT0", true); + + /// + /// Process function to prepare the event time on Run 3 data with only the FT0 + void processOnlyFT0(EvTimeCollisionsFT0 const& collisions, + TrksEvTime& tracks, + aod::FT0s const&) + { + if (!enableTable) { + return; + } + tableEvTime.reserve(collisions.size()); + tableEvTimeForTrack.reserve(tracks.size()); + + // for tracks not assigned to a collision + for (auto track : tracks) { + if (!track.has_collision()) { + tableEvTimeForTrack(0.f, 999.f); + } + } + + for (auto const& collision : collisions) { + const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + tableEvTime(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f, 0.f, 999.f, collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + for (int i = 0; i < tracks.size(); i++) { + tableEvTimeForTrack(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + } + return; + } + } + tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); + for (int i = 0; i < tracksInCollision.size(); i++) { + tableEvTimeForTrack(0.f, 999.f); + } + } + } + PROCESS_SWITCH(pidTOFGeneric, processOnlyFT0, "Process only with FT0", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx b/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx index 337d87223ad..857a02e1cf2 100644 --- a/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx @@ -54,6 +54,7 @@ struct Candidate3body { // 0 - proton, 1 - pion, 2 - bachelor uint8_t dautpcNclusters[3]; uint8_t dauitsclussize[3]; + uint8_t daudcaxytopv[3]; uint8_t daudcatopv[3]; float dautpcNsigma[3]; bool isMatter; @@ -65,6 +66,7 @@ struct Candidate3body { float bachelortofNsigma; TLorentzVector lgencand = {0, 0, 0, 0}; float genct = -1; + float genrapidity = -999; bool isSignal = false; bool isReco = false; int pdgCode = -1; @@ -112,6 +114,7 @@ struct threebodyRecoTask { "registry", { {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, + {"hCentFT0C", "hCentFT0C", {HistType::kTH1F, {{100, 0.0f, 100.0f, "FT0C Centrality"}}}}, {"hCandidatesCounter", "hCandidatesCounter", {HistType::kTH1F, {{12, 0.0f, 12.0f}}}}, {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f}}}}, {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f}}}}, @@ -122,6 +125,9 @@ struct threebodyRecoTask { {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, @@ -351,6 +357,8 @@ struct threebodyRecoTask { registry.fill(HIST("hPtProton"), trackProton.pt()); registry.fill(HIST("hPtPionMinus"), trackPion.pt()); registry.fill(HIST("hPtDeuteron"), trackDeuteron.pt()); + registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack0topv()); + registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack1topv()); registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack0topv()); registry.fill(HIST("hDCAPionToPV"), candData.dcatrack1topv()); @@ -379,6 +387,8 @@ struct threebodyRecoTask { registry.fill(HIST("hPtAntiProton"), trackProton.pt()); registry.fill(HIST("hPtPionPlus"), trackPion.pt()); registry.fill(HIST("hPtAntiDeuteron"), trackDeuteron.pt()); + registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack1topv()); + registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack0topv()); registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack1topv()); registry.fill(HIST("hDCAPionToPV"), candData.dcatrack0topv()); @@ -409,10 +419,15 @@ struct threebodyRecoTask { cand3body.dautpcNclusters[0] = trackProton.tpcNClsFound(); cand3body.dautpcNclusters[1] = trackPion.tpcNClsFound(); cand3body.dautpcNclusters[2] = trackDeuteron.tpcNClsFound(); - cand3body.dauitsclussize[0] = trackPion.itsClusterSizes(); + cand3body.dauitsclussize[0] = trackProton.itsClusterSizes(); + cand3body.dauitsclussize[1] = trackPion.itsClusterSizes(); + cand3body.dauitsclussize[2] = trackDeuteron.itsClusterSizes(); cand3body.dautpcNsigma[0] = trackProton.tpcNSigmaPr(); cand3body.dautpcNsigma[1] = trackPion.tpcNSigmaPi(); cand3body.dautpcNsigma[2] = trackDeuteron.tpcNSigmaDe(); + cand3body.daudcaxytopv[0] = cand3body.isMatter ? candData.dcaXYtrack0topv() : candData.dcaXYtrack1topv(); + cand3body.daudcaxytopv[1] = cand3body.isMatter ? candData.dcaXYtrack1topv() : candData.dcaXYtrack0topv(); + cand3body.daudcaxytopv[2] = candData.dcaXYtrack2topv(); cand3body.daudcatopv[0] = cand3body.isMatter ? candData.dcatrack0topv() : candData.dcatrack1topv(); cand3body.daudcatopv[1] = cand3body.isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); cand3body.daudcatopv[2] = candData.dcatrack2topv(); @@ -426,6 +441,7 @@ struct threebodyRecoTask { cand3body.mcmotherId = lLabel; cand3body.lgencand = lmother; cand3body.genct = MClifetime; + cand3body.genrapidity = lmother.Rapidity(); cand3body.isSignal = true; cand3body.isReco = true; cand3body.pdgCode = cand3body.isMatter ? motherPdgCode : -motherPdgCode; @@ -514,6 +530,7 @@ struct threebodyRecoTask { return; } registry.fill(HIST("hEventCounter"), 2.5); + registry.fill(HIST("hCentFT0C"), collision.centFT0C()); bool if_hasvtx = false; @@ -537,6 +554,7 @@ struct threebodyRecoTask { cand3body.dautpcNclusters[0], cand3body.dautpcNclusters[1], cand3body.dautpcNclusters[2], cand3body.dauitsclussize[0], cand3body.dauitsclussize[1], cand3body.dauitsclussize[2], cand3body.dautpcNsigma[0], cand3body.dautpcNsigma[1], cand3body.dautpcNsigma[2], cand3body.bachelortofNsigma, + cand3body.daudcaxytopv[0], cand3body.daudcaxytopv[1], cand3body.daudcaxytopv[2], cand3body.daudcatopv[0], cand3body.daudcatopv[1], cand3body.daudcatopv[2]); } } @@ -587,7 +605,7 @@ struct threebodyRecoTask { for (auto& lMother2 : lMCTrack2.mothers_as()) { if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { lLabel = lMother0.globalIndex(); - lPDG = lMother1.pdgCode(); + lPDG = lMother0.pdgCode(); if ((lPDG == motherPdgCode && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == bachelorPdgCode) || (lPDG == -motherPdgCode && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -bachelorPdgCode)) { isTrueCand = true; @@ -620,8 +638,9 @@ struct threebodyRecoTask { cand3body.dautpcNclusters[0], cand3body.dautpcNclusters[1], cand3body.dautpcNclusters[2], cand3body.dauitsclussize[0], cand3body.dauitsclussize[1], cand3body.dauitsclussize[2], cand3body.dautpcNsigma[0], cand3body.dautpcNsigma[1], cand3body.dautpcNsigma[2], cand3body.bachelortofNsigma, + cand3body.daudcaxytopv[0], cand3body.daudcaxytopv[1], cand3body.daudcaxytopv[2], cand3body.daudcatopv[0], cand3body.daudcatopv[1], cand3body.daudcatopv[2], - cand3body.lgencand.P(), cand3body.lgencand.Pt(), cand3body.genct, cand3body.lgencand.Phi(), cand3body.lgencand.Eta(), + cand3body.lgencand.P(), cand3body.lgencand.Pt(), cand3body.genct, cand3body.lgencand.Phi(), cand3body.lgencand.Eta(), cand3body.lgencand.Rapidity(), cand3body.isSignal, cand3body.isReco, cand3body.pdgCode, cand3body.SurvivedEventSelection); } } @@ -653,7 +672,8 @@ struct threebodyRecoTask { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - mcparticle.p(), mcparticle.pt(), MClifetime, mcparticle.phi(), mcparticle.eta(), + -1, -1, -1, + mcparticle.p(), mcparticle.pt(), MClifetime, mcparticle.phi(), mcparticle.eta(), mcparticle.y(), true, false, mcparticle.pdgCode(), isSurEvSelection); } } diff --git a/PWGLF/TableProducer/Resonances/LFResonanceInitializer.cxx b/PWGLF/TableProducer/Resonances/LFResonanceInitializer.cxx index de8d26cc611..a453b6edeb5 100644 --- a/PWGLF/TableProducer/Resonances/LFResonanceInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/LFResonanceInitializer.cxx @@ -89,6 +89,7 @@ struct reso2initializer { /// Event cuts o2::analysis::CollisonCuts colCuts; Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable ConfEvtOccupancyInTimeRange{"ConfEvtOccupancyInTimeRange", -1, "Evt sel: maximum track occupancy"}; Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", false, "Evt sel: check for trigger"}; Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", 8, "Evt sel: trigger"}; Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", true, "Evt sel: check for offline selection"}; @@ -837,7 +838,7 @@ struct reso2initializer { } template - void fillMCCollision(MCCol const& mccol, MCPart const& mcparts) + void fillMCCollision(MCCol const& mccol, MCPart const& mcparts, float impactpar = -999.0) { auto centrality = 0.0; if constexpr (!isRun2) @@ -849,7 +850,7 @@ struct reso2initializer { bool isTriggerTVX = mccol.selection_bit(aod::evsel::kIsTriggerTVX); bool isSel8 = mccol.sel8(); bool isSelected = colCuts.isSelected(mccol); - resoMCCollisions(inVtx10, isTrueINELgt0, isTriggerTVX, isSel8, isSelected); + resoMCCollisions(inVtx10, isTrueINELgt0, isTriggerTVX, isSel8, isSelected, impactpar); // QA for Trigger efficiency qaRegistry.fill(HIST("Event/hMCEventIndices"), centrality, aod::resocollision::kINEL); @@ -923,7 +924,7 @@ struct reso2initializer { if (doprocessTrackDataRun2 || doprocessTrackV0DataRun2 || doprocessTrackV0CascDataRun2 || doprocessTrackMCRun2 || doprocessTrackV0MCRun2 || doprocessTrackV0CascMCRun2) { colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, false); } else if (doprocessTrackData || doprocessTrackV0Data || doprocessTrackV0CascData || doprocessTrackMC || doprocessTrackV0MC || doprocessTrackV0CascMC || doprocessTrackEPData) { - colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, true); + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, true, false, ConfEvtOccupancyInTimeRange); } colCuts.init(&qaRegistry); colCuts.setTriggerTVX(ConfEvtTriggerTVXSel); @@ -1144,7 +1145,10 @@ struct reso2initializer { colCuts.fillQA(collision); resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), 0., 0., 0., 0., d_bz, bc.timestamp()); - fillMCCollision(collision, mcParticles); + + auto mccollision = collision.mcCollision_as(); + float impactpar = mccollision.impactParameter(); + fillMCCollision(collision, mcParticles, impactpar); // Loop over tracks fillTracks(collision, tracks); diff --git a/PWGLF/TableProducer/Resonances/LFResonanceMergeDF.cxx b/PWGLF/TableProducer/Resonances/LFResonanceMergeDF.cxx index 56949d1d503..9668afc3e01 100644 --- a/PWGLF/TableProducer/Resonances/LFResonanceMergeDF.cxx +++ b/PWGLF/TableProducer/Resonances/LFResonanceMergeDF.cxx @@ -65,7 +65,8 @@ struct reso2dfmerged { Configurable cpidCut{"cpidCut", 0, "pid cut"}; Configurable crejtpc{"crejtpc", 0, "reject electron pion"}; Configurable crejtof{"crejtof", 0, "reject electron pion tof"}; - + Configurable isPrimary{"isPrimary", 0, "is Primary only"}; + Configurable isGlobal{"isGlobal", 0, "Global tracks only"}; Configurable cDCAXY{"cDCAXY", 1., "value of dcaxy"}; Configurable cDCAZ{"cDCAZ", 1., "value of dcaz"}; Configurable nsigmaPr{"nsigmaPr", 6., "nsigma value for proton"}; @@ -92,7 +93,7 @@ struct reso2dfmerged { std::vector>> @@ -105,7 +106,7 @@ struct reso2dfmerged { std::vector> @@ -116,14 +117,14 @@ struct reso2dfmerged { if (std::abs(track.tpcNSigmaPr()) > nsigmaPr && std::abs(track.tpcNSigmaKa()) > nsigmaKa) continue; - if (crejtpc && ((track.tpcNSigmaPr() > track.tpcNSigmaEl() && track.tpcNSigmaKa() > track.tpcNSigmaEl()) || (track.tpcNSigmaPr() > track.tpcNSigmaPi() && track.tpcNSigmaKa() > track.tpcNSigmaPi()))) + if (crejtpc && ((std::abs(track.tpcNSigmaPr()) > std::abs(track.tpcNSigmaEl()) && std::abs(track.tpcNSigmaKa()) > std::abs(track.tpcNSigmaEl())) || (std::abs(track.tpcNSigmaPr()) > std::abs(track.tpcNSigmaPi()) && std::abs(track.tpcNSigmaKa()) > std::abs(track.tpcNSigmaPi())))) continue; } else { if (std::abs(track.tofNSigmaPr()) > nsigmatofPr && std::abs(track.tofNSigmaKa()) > nsigmatofKa) continue; - if (crejtof && ((track.tofNSigmaPr() > track.tofNSigmaEl() && track.tofNSigmaKa() > track.tofNSigmaEl()) || (track.tofNSigmaPr() > track.tofNSigmaPi() && track.tofNSigmaKa() > track.tofNSigmaPi()))) + if (crejtof && ((std::abs(track.tofNSigmaPr()) > std::abs(track.tofNSigmaEl()) && std::abs(track.tofNSigmaKa()) > std::abs(track.tofNSigmaEl())) || (std::abs(track.tofNSigmaPr()) > std::abs(track.tofNSigmaPi()) && std::abs(track.tofNSigmaKa()) > std::abs(track.tofNSigmaPi())))) continue; } @@ -148,6 +149,8 @@ struct reso2dfmerged { track.dcaZ(), track.x(), track.alpha(), + track.hasITS(), + track.hasTPC(), track.hasTOF(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), @@ -218,7 +221,9 @@ struct reso2dfmerged { std::get<29>(tuple), std::get<30>(tuple), std::get<31>(tuple), - std::get<32>(tuple)); + std::get<32>(tuple), + std::get<33>(tuple), + std::get<34>(tuple)); } } @@ -239,19 +244,22 @@ struct reso2dfmerged { resoCollisionsdf(collision.posX(), collision.posY(), collision.posZ(), collision.cent(), collision.spherocity(), collision.evtPl(), 0., 0., 0., 0., 0); for (auto& track : tracks) { - + if (isPrimary && !track.isPrimaryTrack()) + continue; + if (isGlobal && !track.isGlobalTrack()) + continue; if (!track.hasTOF()) { if (std::abs(track.tpcNSigmaPr()) > nsigmaPr && std::abs(track.tpcNSigmaKa()) > nsigmaKa) continue; - if (crejtpc && ((track.tpcNSigmaPr() > track.tpcNSigmaEl() && track.tpcNSigmaKa() > track.tpcNSigmaEl()) || (track.tpcNSigmaPr() > track.tpcNSigmaPi() && track.tpcNSigmaKa() > track.tpcNSigmaPi()))) + if (crejtpc && ((std::abs(track.tpcNSigmaPr()) > std::abs(track.tpcNSigmaEl()) && std::abs(track.tpcNSigmaKa()) > std::abs(track.tpcNSigmaEl())) || (std::abs(track.tpcNSigmaPr()) > std::abs(track.tpcNSigmaPi()) && std::abs(track.tpcNSigmaKa()) > std::abs(track.tpcNSigmaPi())))) continue; } else { if (std::abs(track.tofNSigmaPr()) > nsigmatofPr && std::abs(track.tofNSigmaKa()) > nsigmatofKa) continue; - if (crejtof && ((track.tofNSigmaPr() > track.tofNSigmaEl() && track.tofNSigmaKa() > track.tofNSigmaEl()) || (track.tofNSigmaPr() > track.tofNSigmaPi() && track.tofNSigmaKa() > track.tofNSigmaPi()))) + if (crejtof && ((std::abs(track.tofNSigmaPr()) > std::abs(track.tofNSigmaEl()) && std::abs(track.tofNSigmaKa()) > std::abs(track.tofNSigmaEl())) || (std::abs(track.tofNSigmaPr()) > std::abs(track.tofNSigmaPi()) && std::abs(track.tofNSigmaKa()) > std::abs(track.tofNSigmaPi())))) continue; } @@ -275,6 +283,8 @@ struct reso2dfmerged { track.dcaZ(), track.x(), track.alpha(), + track.hasITS(), + track.hasTPC(), track.hasTOF(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index a4f8061f68d..27aec6b4e62 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -56,6 +56,12 @@ o2physics_add_dpl_workflow(hstrangecorrelationfilter PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(double-casc-tree-creator + SOURCES doubleCascTreeCreator.cxx + PUBLIC_LINK_LIBRARIES O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(lambdakzerobuilder SOURCES lambdakzerobuilder.cxx PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2Physics::MLCore diff --git a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt index 660365da5ac..035c4ca6581 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt @@ -24,7 +24,17 @@ o2physics_add_dpl_workflow(strarawcentsconverter2v4 PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(straevselsconverter + SOURCES straevselsconverter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(v0coresconverter SOURCES v0coresconverter.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(v0coresconverter2 + SOURCES v0coresconverter2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx new file mode 100644 index 00000000000..9806e15abfc --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx @@ -0,0 +1,62 @@ +// Copyright 2019-2020 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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +using namespace o2; +using namespace o2::framework; + +// Converts Stra Event selections from 000 to 001 +struct straevselsconverter { + Produces straEvSels_001; + + void process(soa::Join const& straEvSels_000_RawCents_004) + { + for (auto& values : straEvSels_000_RawCents_004) { + straEvSels_001(values.sel8(), + values.selection_raw(), + values.multFT0A(), + values.multFT0C(), + values.multFT0A(), + 0 /*dummy FDDA value*/, + 0 /*dummy FDDC value*/, + values.multNTracksPVeta1(), + values.multPVTotalContributors(), + values.multNTracksGlobal(), + values.multNTracksITSTPC(), + values.multAllTracksTPCOnly(), + values.multAllTracksITSTPC(), + values.multZNA(), + values.multZNC(), + values.multZEM1(), + values.multZEM2(), + values.multZPA(), + values.multZPC(), + values.trackOccupancyInTimeRange(), + -1 /*dummy gap side value*/, + -999. /*dummy FT0-A value*/, + -999. /*dummy FT0-C value*/, + -999. /*dummy FV0-A value*/, + -999. /*dummy FDD-A value*/, + -999. /*dummy FDD-C value*/, + -999. /*dummy ZN-A value*/, + -999. /*dummy ZN-C value*/); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx new file mode 100644 index 00000000000..c918f227525 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx @@ -0,0 +1,52 @@ +// Copyright 2019-2020 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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +using namespace o2; +using namespace o2::framework; + +// Converts V0 version 001 to 002 +struct v0coresconverter2 { + Produces v0MCCores_002; + + void process(aod::V0MCCores_001 const& v0MCCores_001) + { + for (auto& values : v0MCCores_001) { + v0MCCores_002(0, + values.pdgCode(), + values.pdgCodeMother(), + values.pdgCodePositive(), + values.pdgCodeNegative(), + values.isPhysicalPrimary(), + values.xMC(), + values.yMC(), + values.zMC(), + values.pxPosMC(), + values.pyPosMC(), + values.pzPosMC(), + values.pxNegMC(), + values.pyNegMC(), + values.pzNegMC(), + values.pxPosMC() + values.pxNegMC(), + values.pyPosMC() + values.pyNegMC(), + values.pzPosMC() + values.pzNegMC()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx index fad38e38b67..fd5f225ea99 100644 --- a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx @@ -119,6 +119,8 @@ struct CandidateV0 { o2::track::TrackParCov trackv0; std::array mompos; std::array momneg; + std::array momposMC; + std::array momnegMC; float dcav0daugh = -999.f; float dcanegpv = -999.f; float dcapospv = -999.f; @@ -132,8 +134,11 @@ struct CandidateV0 { int pdgcode = -999; int pdgcodemother = -999; int pdgposdau = -999; + int pdgcodemotherdaupos = -999; int pdgnegdau = -999; + int pdgcodemotherdauneg = -999; bool isreco = 0; + int64_t pdgmatchmothersecondmother = -999; int64_t mcIndex = -999; int64_t globalIndex = -999; int64_t globalIndexPos = -999; @@ -157,8 +162,6 @@ struct LFStrangeTreeCreator { ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; - ConfigurableAxis multAxis{"multAxis", {100, 0, 10000}, "Binning for the multiplicity axis"}; - ConfigurableAxis multFt0Axis{"multFt0Axis", {100, 0, 100000}, "Binning for the ft0 multiplicity axis"}; // binning of (anti)lambda mass QA histograms ConfigurableAxis massLambdaAxis{"massLambdaAxis", {400, o2::constants::physics::MassLambda0 - 0.03f, o2::constants::physics::MassLambda0 + 0.03f}, "binning for the lambda invariant-mass"}; @@ -195,6 +198,7 @@ struct LFStrangeTreeCreator { Configurable cascsetting_vetoOm{"cascsetting_vetoOm", 0.01f, "vetoOm"}; Configurable cascsetting_mXi{"cascsetting_mXi", 0.02f, "mXi"}; Configurable lambdaMassCut{"lambdaMassCut", 0.02f, "maximum deviation from PDG mass (for QA histograms)"}; + Configurable k0short{"k0short", false, "process for k0short (true) or lambda (false)"}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -273,8 +277,6 @@ struct LFStrangeTreeCreator { // event QA histos.add("QA/zVtx", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); - histos.add("QA/PvMultVsCent", ";Centrality T0C (%);#it{N}_{PV contributors};", HistType::kTH2F, {centAxis, multAxis}); - histos.add("QA/MultVsCent", ";Centrality T0C (%);Multiplicity T0C;", HistType::kTH2F, {centAxis, multFt0Axis}); // v0 QA histos.add("QA/massLambda", ";Centrality (%);#it{p}_{T} (GeV/#it{c});#it{M}(p + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, massLambdaAxis}); @@ -314,9 +316,9 @@ struct LFStrangeTreeCreator { auto& posPropTrack = fitter.getTrack(0); auto& negPropTrack = fitter.getTrack(1); - std::array momPos; - std::array momNeg; - std::array momV0; + std::array momPos = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; + std::array momNeg = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; + std::array momV0 = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; posPropTrack.getPxPyPzGlo(momPos); negPropTrack.getPxPyPzGlo(momNeg); momTotXYZ(momV0, momPos, momNeg); @@ -341,13 +343,18 @@ struct LFStrangeTreeCreator { // pid selections auto nSigmaTPCPos = matter ? posTrack.tpcNSigmaPr() : posTrack.tpcNSigmaPi(); auto nSigmaTPCNeg = matter ? negTrack.tpcNSigmaPi() : negTrack.tpcNSigmaPr(); + // change for k0 + if (k0short) { + nSigmaTPCPos = posTrack.tpcNSigmaPi(); + nSigmaTPCNeg = negTrack.tpcNSigmaPi(); + } if (std::abs(nSigmaTPCPos) > v0setting_nsigmatpc || std::abs(nSigmaTPCNeg) > v0setting_nsigmatpc) { continue; } - // veto on K0s mass - if (std::abs(mK0Short - o2::constants::physics::MassK0Short) < vetoMassK0Short) { + // veto on K0s mass (only for lambda) + if (!k0short && (std::abs(mK0Short - o2::constants::physics::MassK0Short) < vetoMassK0Short)) { continue; } @@ -381,8 +388,15 @@ struct LFStrangeTreeCreator { auto ptotal = RecoDecay::sqrtSumOfSquares(momV0[0], momV0[1], momV0[2]); auto lengthTraveled = RecoDecay::sqrtSumOfSquares(vtx[0] - primVtx[0], vtx[1] - primVtx[1], vtx[2] - primVtx[2]); - float ML2P_Lambda = o2::constants::physics::MassLambda * lengthTraveled / ptotal; - if (ML2P_Lambda > v0setting_lifetime) { + // change calculation of ML2P for k0 and lambda + float particlemass; + if (k0short) { + particlemass = o2::constants::physics::MassK0; + } else { + particlemass = o2::constants::physics::MassLambda; + } + float ML2P = particlemass * lengthTraveled / ptotal; + if (ML2P > v0setting_lifetime) { continue; } @@ -406,7 +420,7 @@ struct LFStrangeTreeCreator { CandidateV0 candV0; candV0.pt = matter > 0. ? ptV0 : -ptV0; candV0.eta = etaV0; - candV0.ct = ML2P_Lambda; + candV0.ct = ML2P; candV0.len = lengthTraveled; candV0.mass = mLambda; candV0.radius = radiusV0; @@ -501,45 +515,114 @@ struct LFStrangeTreeCreator { auto mcTrackNeg = mcLabNeg.template mcParticle_as(); candidateV0.pdgposdau = mcTrackPos.pdgCode(); candidateV0.pdgnegdau = mcTrackNeg.pdgCode(); + auto pdgCodeMotherDauPos = -999; + auto pdgCodeMotherDauNeg = -999; + auto pdgMatchMotherSecondMother = -999; if (mcTrackPos.has_mothers() && mcTrackNeg.has_mothers()) { for (auto& negMother : mcTrackNeg.template mothers_as()) { for (auto& posMother : mcTrackPos.template mothers_as()) { - if (posMother.globalIndex() != negMother.globalIndex()) - continue; - candidateV0.pdgcode = posMother.pdgCode(); - if (!((mcTrackPos.pdgCode() == 2212 && mcTrackNeg.pdgCode() == -211) || (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -2212))) - continue; - if (std::abs(posMother.pdgCode()) != 3122) { - continue; - } - if (!posMother.isPhysicalPrimary() && !posMother.has_mothers()) - continue; - - auto pdgCodeMother = -999; - if (posMother.isPhysicalPrimary()) { - pdgCodeMother = 0; - } else if (posMother.has_mothers()) { - for (auto& mcMother : posMother.mothers_as()) { - if (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334) { - pdgCodeMother = mcMother.pdgCode(); - break; + if (posMother.globalIndex() != negMother.globalIndex()) { + pdgCodeMotherDauPos = posMother.pdgCode(); + pdgCodeMotherDauNeg = negMother.pdgCode(); + if (negMother.pdgCode() == -211) { + if (negMother.has_mothers()) { + for (auto& negSecondMother : negMother.template mothers_as()) { + if (negSecondMother.globalIndex() == posMother.globalIndex()) { + pdgMatchMotherSecondMother = negSecondMother.pdgCode(); + } + } } } + if (posMother.pdgCode() == 211) { + if (posMother.has_mothers()) { + for (auto& posSecondMother : posMother.template mothers_as()) { + if (posSecondMother.globalIndex() == negMother.globalIndex()) { + pdgMatchMotherSecondMother = posSecondMother.pdgCode(); + } + } + } + } + } else { + candidateV0.pdgcode = posMother.pdgCode(); + pdgCodeMotherDauPos = posMother.pdgCode(); + pdgCodeMotherDauNeg = negMother.pdgCode(); + // build conditions for mother/daughter for k0short or lambda + bool mother; + bool daughter; + if (k0short) { + // mother is k0short (310) and daughters are pions (211/-211) + mother = posMother.pdgCode() == 310; + daughter = (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -211); + } else { + // mother is lambda (3122) and daughters are proton (2212) and pion(211) + mother = posMother.pdgCode() == 3122; + daughter = ((mcTrackPos.pdgCode() == 2212 && mcTrackNeg.pdgCode() == -211) || (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -2212)); + } + // check conditions + if (!mother || !daughter) { + continue; + } + + if (!posMother.isPhysicalPrimary() && !posMother.has_mothers()) + continue; + + auto pdgCodeMother = -999; + if (posMother.isPhysicalPrimary()) { + pdgCodeMother = 0; + } else if (posMother.has_mothers()) { + for (auto& mcMother : posMother.mothers_as()) { + // feed-down: xi and omega decaying to lambda, ignore for k0 + if (!k0short && (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334)) { + pdgCodeMother = mcMother.pdgCode(); + break; + } + } + } + auto genPt = std::hypot(posMother.px(), posMother.py()); + auto posPrimVtx = std::array{posMother.vx(), posMother.vy(), posMother.vz()}; + auto secVtx = std::array{mcTrackPos.vx(), mcTrackPos.vy(), mcTrackPos.vz()}; + auto mom = std::sqrt(std::pow(posMother.px(), 2) + std::pow(posMother.py(), 2) + std::pow(posMother.pz(), 2)); + auto len = std::sqrt(std::pow(secVtx[0] - posPrimVtx[0], 2) + std::pow(secVtx[1] - posPrimVtx[1], 2) + std::pow(secVtx[2] - posPrimVtx[2], 2)); + candidateV0.genpt = genPt; + candidateV0.genlen = len; + candidateV0.genct = len / (mom + 1e-10) * o2::constants::physics::MassLambda0; + candidateV0.pdgcodemother = pdgCodeMother; + candidateV0.geneta = posMother.eta(); + candidateV0.mcIndex = posMother.globalIndex(); } - auto genPt = std::hypot(posMother.px(), posMother.py()); - auto posPrimVtx = std::array{posMother.vx(), posMother.vy(), posMother.vz()}; - auto secVtx = std::array{mcTrackPos.vx(), mcTrackPos.vy(), mcTrackPos.vz()}; - auto mom = std::sqrt(std::pow(posMother.px(), 2) + std::pow(posMother.py(), 2) + std::pow(posMother.pz(), 2)); - auto len = std::sqrt(std::pow(secVtx[0] - posPrimVtx[0], 2) + std::pow(secVtx[1] - posPrimVtx[1], 2) + std::pow(secVtx[2] - posPrimVtx[2], 2)); - candidateV0.genpt = genPt; - candidateV0.genlen = len; - candidateV0.genct = len / (mom + 1e-10) * o2::constants::physics::MassLambda0; - candidateV0.pdgcodemother = pdgCodeMother; - candidateV0.geneta = posMother.eta(); - candidateV0.mcIndex = posMother.globalIndex(); } } } + if ((!mcTrackPos.has_mothers()) && mcTrackNeg.has_mothers()) { + pdgCodeMotherDauPos = -999; + for (auto& negMother : mcTrackNeg.template mothers_as()) { + pdgCodeMotherDauNeg = negMother.pdgCode(); + } + } + if ((!mcTrackNeg.has_mothers()) && mcTrackPos.has_mothers()) { + pdgCodeMotherDauNeg = -999; + for (auto& posMother : mcTrackPos.template mothers_as()) { + pdgCodeMotherDauPos = posMother.pdgCode(); + } + } + if ((!mcTrackNeg.has_mothers()) && (!mcTrackPos.has_mothers())) { + pdgCodeMotherDauNeg = -999; + pdgCodeMotherDauPos = -999; + } + candidateV0.pdgcodemotherdauneg = pdgCodeMotherDauNeg; + candidateV0.pdgcodemotherdaupos = pdgCodeMotherDauPos; + candidateV0.pdgmatchmothersecondmother = pdgMatchMotherSecondMother; + // momentum of daughters + std::array momPosMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; + std::array momNegMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; + momPosMC[0] = mcTrackPos.px(); + momPosMC[1] = mcTrackPos.py(); + momPosMC[2] = mcTrackPos.pz(); + momNegMC[0] = mcTrackNeg.px(); + momNegMC[1] = mcTrackNeg.py(); + momNegMC[2] = mcTrackNeg.pz(); + candidateV0.momposMC = std::array{momPosMC[0], momPosMC[1], momPosMC[2]}; + candidateV0.momnegMC = std::array{momNegMC[0], momNegMC[1], momNegMC[2]}; } } } @@ -555,18 +638,45 @@ struct LFStrangeTreeCreator { auto pdgCode = mcPart.pdgCode(); std::array secVtx; - if (std::abs(pdgCode) == 3122) { + std::array momPosMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; + std::array momNegMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; + + // look for lambda (3122) or k0short (310) + int pdg_test = 3122; + if (k0short) + pdg_test = 310; + + if (std::abs(pdgCode) == pdg_test) { if (!mcPart.isPhysicalPrimary() && !mcPart.has_mothers()) continue; - bool foundPr = false; + // check if its the right decay containing proton (2122) for lambda and charged pion (211) for k0short + int pdg_particle; + if (k0short) { + pdg_particle = 211; + } else { + pdg_particle = 2212; + } + bool foundParticle = false; for (auto& mcDaught : mcPart.daughters_as()) { - if (std::abs(mcDaught.pdgCode()) == 2212) { - foundPr = true; + if (std::abs(mcDaught.pdgCode()) == pdg_particle) { + foundParticle = true; secVtx = std::array{mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; break; } } - if (!foundPr) { + // momentum of daughters + for (auto& mcDaught : mcPart.daughters_as()) { + if (mcDaught.pdgCode() < 0) { + momNegMC[0] = mcDaught.px(); + momNegMC[1] = mcDaught.py(); + momNegMC[2] = mcDaught.pz(); + } else { + momPosMC[0] = mcDaught.px(); + momPosMC[1] = mcDaught.py(); + momPosMC[2] = mcDaught.pz(); + } + } + if (!foundParticle) { continue; } auto pdgCodeMother = -999; @@ -574,7 +684,8 @@ struct LFStrangeTreeCreator { pdgCodeMother = 0; } else if (mcPart.has_mothers()) { for (auto& mcMother : mcPart.mothers_as()) { - if (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334) { + // feed-down: xi and omega decaying to lambda, ignore for k0 + if (!k0short && (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334)) { pdgCodeMother = mcMother.pdgCode(); break; } @@ -592,6 +703,8 @@ struct LFStrangeTreeCreator { candV0.geneta = mcPart.eta(); candV0.pdgcode = pdgCode; candV0.pdgcodemother = pdgCodeMother; + candV0.momposMC = std::array{momPosMC[0], momPosMC[1], momPosMC[2]}; + candV0.momnegMC = std::array{momNegMC[0], momNegMC[1], momNegMC[2]}; auto it = find_if(candidateV0s.begin(), candidateV0s.end(), [&](CandidateV0 v0) { return v0.mcIndex == mcPart.globalIndex(); }); if (it == candidateV0s.end()) { candidateV0s.emplace_back(candV0); @@ -633,13 +746,9 @@ struct LFStrangeTreeCreator { CascTable_thisCollision.bindExternalIndices(&tracks); CascTable_thisCollision.bindExternalIndices(&V0s); - auto multiplicity = collision.multFT0C(); auto centrality = collision.centFT0C(); fillRecoEvent(collision, tracks, V0Table_thisCollision, V0s, CascTable_thisCollision, centrality); - histos.fill(HIST("QA/PvMultVsCent"), centrality, collision.numContrib()); - histos.fill(HIST("QA/MultVsCent"), centrality, multiplicity); - for (auto& candidateV0 : candidateV0s) { lambdaTableML( candidateV0.pt, @@ -727,10 +836,13 @@ struct LFStrangeTreeCreator { candidateV0.geneta, candidateV0.genct, candidateV0.pdgposdau, + candidateV0.pdgcodemotherdaupos, candidateV0.pdgnegdau, + candidateV0.pdgcodemotherdauneg, candidateV0.pdgcode, candidateV0.pdgcodemother, - candidateV0.isreco); + candidateV0.isreco, + candidateV0.pdgmatchmothersecondmother); mcV0TableAP( candidateV0.eta, @@ -741,6 +853,12 @@ struct LFStrangeTreeCreator { candidateV0.momneg[0], candidateV0.momneg[1], candidateV0.momneg[2], + candidateV0.momposMC[0], + candidateV0.momposMC[1], + candidateV0.momposMC[2], + candidateV0.momnegMC[0], + candidateV0.momnegMC[1], + candidateV0.momnegMC[2], candidateV0.radius, candidateV0.dcav0pv, candidateV0.dcapospv, diff --git a/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx b/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx index c06c054fef3..30a0b178454 100644 --- a/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx @@ -53,6 +53,7 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -125,6 +126,10 @@ struct cascadeBuilder { Produces casccovs; // if requested by someone Produces kfcasccovs; // if requested by someone + // produces calls for machine-learning selections + Produces xiMLSelections; // Xi scores + Produces omegaMLSelections; // Omega scores + o2::ccdb::CcdbApi ccdbApi; Service ccdb; @@ -194,6 +199,8 @@ struct cascadeBuilder { Configurable kfDoDCAFitterPreMinimV0{"kfDoDCAFitterPreMinimV0", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections for V0"}; Configurable kfDoDCAFitterPreMinimCasc{"kfDoDCAFitterPreMinimCasc", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections for Xi"}; + // for using cascade momentum at prim. vtx + Configurable useCascadeMomentumAtPrimVtx{"useCascadeMomentumAtPrimVtx", false, "if enabled, store cascade momentum at prim. vtx instead of decay point (= default)"}; // for topo var QA struct : ConfigurableGroup { ConfigurableAxis axisTopoVarPointingAngle{"axisConfigurations.axisTopoVarPointingAngle", {50, 0.0, 1.0}, "pointing angle"}; @@ -1118,6 +1125,14 @@ struct cascadeBuilder { cascadecandidate.v0dcapostopv = v0.dcapostopv(); cascadecandidate.v0dcanegtopv = v0.dcanegtopv(); + if (useCascadeMomentumAtPrimVtx) { + lCascadeTrack.getPxPyPzGlo(cascadecandidate.cascademom); + } else { + cascadecandidate.cascademom[0] = cascadecandidate.bachP[0] + cascadecandidate.v0mompos[0] + cascadecandidate.v0momneg[0]; + cascadecandidate.cascademom[1] = cascadecandidate.bachP[1] + cascadecandidate.v0mompos[1] + cascadecandidate.v0momneg[1]; + cascadecandidate.cascademom[2] = cascadecandidate.bachP[2] + cascadecandidate.v0mompos[2] + cascadecandidate.v0momneg[2]; + } + if (d_doTrackQA) { if (posTrack.itsNCls() < 10) statisticsRegistry.posITSclu[posTrack.itsNCls()]++; @@ -1555,9 +1570,7 @@ struct cascadeBuilder { cascadecandidate.v0mompos[0], cascadecandidate.v0mompos[1], cascadecandidate.v0mompos[2], cascadecandidate.v0momneg[0], cascadecandidate.v0momneg[1], cascadecandidate.v0momneg[2], cascadecandidate.bachP[0], cascadecandidate.bachP[1], cascadecandidate.bachP[2], - cascadecandidate.bachP[0] + cascadecandidate.v0mompos[0] + cascadecandidate.v0momneg[0], // <--- redundant but ok - cascadecandidate.bachP[1] + cascadecandidate.v0mompos[1] + cascadecandidate.v0momneg[1], // <--- redundant but ok - cascadecandidate.bachP[2] + cascadecandidate.v0mompos[2] + cascadecandidate.v0momneg[2], // <--- redundant but ok + cascadecandidate.cascademom[0], cascadecandidate.cascademom[1], cascadecandidate.cascademom[2], cascadecandidate.v0dcadau, cascadecandidate.dcacascdau, cascadecandidate.v0dcapostopv, cascadecandidate.v0dcanegtopv, cascadecandidate.bachDCAxy, cascadecandidate.cascDCAxy, cascadecandidate.cascDCAz); // <--- no corresponding stratrack information available @@ -1565,6 +1578,13 @@ struct cascadeBuilder { cascTrackXs(cascadecandidate.positiveX, cascadecandidate.negativeX, cascadecandidate.bachelorX); } cascbb(cascadecandidate.bachBaryonCosPA, cascadecandidate.bachBaryonDCAxyToPV); + if (cascadecandidate.charge < 0) { + xiMLSelections(cascadecandidate.mlXiMinusScore); + omegaMLSelections(cascadecandidate.mlOmegaMinusScore); + } else { + xiMLSelections(cascadecandidate.mlXiPlusScore); + omegaMLSelections(cascadecandidate.mlOmegaPlusScore); + } // populate cascade covariance matrices if required by any other task if (createCascCovMats) { @@ -1735,6 +1755,13 @@ struct cascadeBuilder { cascTrackXs(cascadecandidate.positiveX, cascadecandidate.negativeX, cascadecandidate.bachelorX); } cascbb(cascadecandidate.bachBaryonCosPA, cascadecandidate.bachBaryonDCAxyToPV); + if (cascadecandidate.charge < 0) { + xiMLSelections(cascadecandidate.mlXiMinusScore); + omegaMLSelections(cascadecandidate.mlOmegaMinusScore); + } else { + xiMLSelections(cascadecandidate.mlXiPlusScore); + omegaMLSelections(cascadecandidate.mlOmegaPlusScore); + } // populate cascade covariance matrices if required by any other task if (createCascCovMats) { @@ -1999,6 +2026,7 @@ struct cascadePreselector { bitTrueXiMinus, bitTrueXiPlus, bitTrueOmegaMinus, + bitPhysicalPrimary, bitTrueOmegaPlus, bitdEdxXiMinus, bitdEdxXiPlus, @@ -2098,6 +2126,7 @@ struct cascadePreselector { void checkPDG(TCascadeObject const& lCascadeCandidate, uint16_t& maskElement) { int lPDG = -1; + bool physicalPrimary = false; // Acquire all three daughter tracks, please auto lBachTrack = lCascadeCandidate.template bachelor_as(); @@ -2123,6 +2152,7 @@ struct cascadePreselector { for (auto& lBachMother : lMCBachTrack.template mothers_as()) { if (lV0Mother == lBachMother) { lPDG = lV0Mother.pdgCode(); + physicalPrimary = lV0Mother.isPhysicalPrimary(); // additionally check PDG of the mother particle if requested if (dIfMCselectV0MotherPDG != 0) { @@ -2152,6 +2182,8 @@ struct cascadePreselector { bitset(maskElement, bitTrueOmegaMinus); if (lPDG == -3334) bitset(maskElement, bitTrueOmegaPlus); + if (physicalPrimary) + bitset(maskElement, bitPhysicalPrimary); } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* /// function to check early dE/dx selection @@ -2232,6 +2264,7 @@ struct cascadePreselector { casctags(validCascade, bitcheck(selectionMask[ii], bitTrueXiMinus), bitcheck(selectionMask[ii], bitTrueXiPlus), bitcheck(selectionMask[ii], bitTrueOmegaMinus), bitcheck(selectionMask[ii], bitTrueOmegaPlus), + bitcheck(selectionMask[ii], bitPhysicalPrimary), bitcheck(selectionMask[ii], bitdEdxXiMinus), bitcheck(selectionMask[ii], bitdEdxXiPlus), bitcheck(selectionMask[ii], bitdEdxOmegaMinus), bitcheck(selectionMask[ii], bitdEdxOmegaPlus)); } diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index 434f27f284f..c3a1060f3cf 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -298,6 +298,25 @@ struct cascadeFlow { template void fillAnalysedTable(collision_t coll, cascade_t casc, float v2CSP, float v2CEP, float PsiT0C, float BDTresponseXi, float BDTresponseOmega) { + double masses[2]{o2::constants::physics::MassXiMinus, o2::constants::physics::MassOmegaMinus}; + ROOT::Math::PxPyPzMVector cascadeVector[2], lambdaVector, protonVector; + float cosThetaStarLambda[2], cosThetaStarProton; + lambdaVector.SetCoordinates(casc.pxlambda(), casc.pylambda(), casc.pzlambda(), o2::constants::physics::MassLambda); + ROOT::Math::Boost lambdaBoost{lambdaVector.BoostToCM()}; + if (casc.sign() < 0) { + protonVector.SetCoordinates(casc.pxneg(), casc.pyneg(), casc.pzneg(), o2::constants::physics::MassProton); + } else { + protonVector.SetCoordinates(casc.pxpos(), casc.pypos(), casc.pzpos(), o2::constants::physics::MassProton); + } + auto boostedProton{lambdaBoost(protonVector)}; + cosThetaStarProton = boostedProton.Pz() / boostedProton.P(); + for (int i{0}; i < 2; ++i) { + cascadeVector[i].SetCoordinates(casc.px(), casc.py(), casc.pz(), masses[i]); + ROOT::Math::Boost cascadeBoost{cascadeVector[i].BoostToCM()}; + auto boostedLambda{cascadeBoost(lambdaVector)}; + cosThetaStarLambda[i] = boostedLambda.Pz() / boostedLambda.P(); + } + analysisSample(coll.centFT0C(), casc.sign(), casc.pt(), @@ -309,7 +328,10 @@ struct cascadeFlow { v2CEP, PsiT0C, BDTresponseXi, - BDTresponseOmega); + BDTresponseOmega, + cosThetaStarLambda[0], + cosThetaStarLambda[1], + cosThetaStarProton); } void init(InitContext const&) diff --git a/PWGLF/TableProducer/Strangeness/cascademcbuilder.cxx b/PWGLF/TableProducer/Strangeness/cascademcbuilder.cxx index 4084afdcae4..729ac3e27da 100644 --- a/PWGLF/TableProducer/Strangeness/cascademcbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/cascademcbuilder.cxx @@ -76,6 +76,9 @@ struct cascademcbuilder { int pdgCodeNegative; int pdgCodeBachelor; bool isPhysicalPrimary; + int processPositive = -1; + int processNegative = -1; + int processBachelor = -1; std::array xyz; std::array lxyz; std::array posP; @@ -89,8 +92,6 @@ struct cascademcbuilder { mcCascinfo thisInfo; //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void init(InitContext const&) {} - template void generateCascadeMCinfo(TCascadeTable cascTable, TMCParticleTable mcParticles) { @@ -142,6 +143,9 @@ struct cascademcbuilder { thisInfo.bachP[0] = lMCBachTrack.px(); thisInfo.bachP[1] = lMCBachTrack.py(); thisInfo.bachP[2] = lMCBachTrack.pz(); + thisInfo.processPositive = lMCPosTrack.getProcess(); + thisInfo.processNegative = lMCNegTrack.getProcess(); + thisInfo.processBachelor = lMCBachTrack.getProcess(); // Step 1: check if the mother is the same, go up a level if (lMCNegTrack.has_mothers() && lMCPosTrack.has_mothers()) { @@ -194,8 +198,8 @@ struct cascademcbuilder { thisInfo.label, thisInfo.motherLabel); // Mark mcParticle as recoed (no searching necessary afterwards) - if (thisInfo.motherLabel > -1) { - mcParticleIsReco[thisInfo.motherLabel] = true; + if (thisInfo.label > -1) { + mcParticleIsReco[thisInfo.label] = true; } if (populateCascMCCoresSymmetric) { @@ -216,10 +220,7 @@ struct cascademcbuilder { // step 1: check if this element is already provided in the table // using the packedIndices variable calculated above for (uint32_t ii = 0; ii < mcCascinfos.size(); ii++) { - if ( - thisInfo.mcParticlePositive == mcCascinfos[ii].mcParticlePositive && mcCascinfos[ii].mcParticlePositive > 0 && - thisInfo.mcParticleNegative == mcCascinfos[ii].mcParticleNegative && mcCascinfos[ii].mcParticleNegative > 0 && - thisInfo.mcParticleBachelor == mcCascinfos[ii].mcParticleBachelor && mcCascinfos[ii].mcParticleBachelor > 0) { + if (thisInfo.label == mcCascinfos[ii].label && mcCascinfos[ii].label > -1) { thisCascMCCoreIndex = ii; break; // this exists already in list } @@ -272,6 +273,54 @@ struct cascademcbuilder { thisInfo.momentum[0] = mcParticle.px(); thisInfo.momentum[1] = mcParticle.py(); thisInfo.momentum[2] = mcParticle.pz(); + thisInfo.label = mcParticle.globalIndex(); + + if (mcParticle.has_daughters()) { + auto const& daughters = mcParticle.template daughters_as(); + for (auto& dau : daughters) { + if (dau.getProcess() != 4) // check whether the daughter comes from a decay + continue; + + if (TMath::Abs(dau.pdgCode()) == 211 || TMath::Abs(dau.pdgCode()) == 321) { + thisInfo.pdgCodeBachelor = dau.pdgCode(); + thisInfo.bachP[0] = dau.px(); + thisInfo.bachP[1] = dau.py(); + thisInfo.bachP[2] = dau.pz(); + thisInfo.xyz[0] = dau.vx(); + thisInfo.xyz[1] = dau.vy(); + thisInfo.xyz[2] = dau.vz(); + thisInfo.mcParticleBachelor = dau.globalIndex(); + } + if (TMath::Abs(dau.pdgCode()) == 2212) { + thisInfo.pdgCodeV0 = dau.pdgCode(); + + for (auto& v0Dau : dau.template daughters_as()) { + if (v0Dau.getProcess() != 4) + continue; + + if (v0Dau.pdgCode() > 0) { + thisInfo.pdgCodePositive = v0Dau.pdgCode(); + thisInfo.processPositive = v0Dau.getProcess(); + thisInfo.posP[0] = v0Dau.px(); + thisInfo.posP[1] = v0Dau.py(); + thisInfo.posP[2] = v0Dau.pz(); + thisInfo.lxyz[0] = v0Dau.vx(); + thisInfo.lxyz[1] = v0Dau.vy(); + thisInfo.lxyz[2] = v0Dau.vz(); + thisInfo.mcParticlePositive = v0Dau.globalIndex(); + } + if (v0Dau.pdgCode() < 0) { + thisInfo.pdgCodeNegative = v0Dau.pdgCode(); + thisInfo.processNegative = v0Dau.getProcess(); + thisInfo.negP[0] = v0Dau.px(); + thisInfo.negP[1] = v0Dau.py(); + thisInfo.negP[2] = v0Dau.pz(); + thisInfo.mcParticleNegative = v0Dau.globalIndex(); + } + } + } + } + } // if I got here, it means this MC particle was not recoed and is of interest. Add it please mcCascinfos.push_back(thisInfo); diff --git a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx index 44b9f784447..0f8659fac38 100644 --- a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx @@ -28,6 +28,7 @@ #include "TRandom2.h" #include "Framework/O2DatabasePDGPlugin.h" #include "PWGLF/Utils/inelGt.h" +#include "PWGLF/DataModel/mcCentrality.h" using namespace o2; using namespace o2::framework; @@ -48,9 +49,10 @@ struct cascqaanalysis { // Event selection criteria Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable isVertexITSTPCCut{"isVertexITSTPCCut", 0, "Select collisions with at least one ITS-TPC track"}; - Configurable isNoSameBunchPileupCut{"isNoSameBunchPileupCut", 0, "Same found-by-T0 bunch crossing rejection"}; - Configurable isGoodZvtxFT0vsPVCut{"isGoodZvtxFT0vsPVCut", 0, "z of PV by tracks and z of PV from FT0 A-C time difference cut"}; + Configurable isVertexITSTPC{"isVertexITSTPC", 0, "Select collisions with at least one ITS-TPC track"}; + Configurable isNoSameBunchPileup{"isNoSameBunchPileup", 0, "Same found-by-T0 bunch crossing rejection"}; + Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", 0, "z of PV by tracks and z of PV from FT0 A-C time difference cut"}; + Configurable isVertexTOFmatched{"isVertexTOFmatched", 0, "Is Vertex TOF matched"}; Configurable isTriggerTVX{"isTriggerTVX", 1, "TVX trigger"}; Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", 1, "TF border cut"}; @@ -75,6 +77,9 @@ struct cascqaanalysis { // QA histograms for the multiplicity estimation Configurable multQA{"multQA", 0, "0 - not to do QA, 1 - do the QA"}; + // QA histograms for cascade rec. + Configurable candidateQA{"candidateQA", 1, "0 - not to do QA, 1 - do the QA"}; + // Necessary for particle charges Service pdgDB; @@ -106,23 +111,26 @@ struct cascqaanalysis { AxisSpec multNTracksAxis = {500, 0, 500, "N_{tracks}"}; AxisSpec signalFT0MAxis = {10000, 0, 40000, "FT0M amplitude"}; AxisSpec signalFV0AAxis = {10000, 0, 40000, "FV0A amplitude"}; + AxisSpec nCandidates = {30, -0.5, 29.5, "N_{cand.}"}; - TString hCandidateCounterLabels[5] = {"All candidates", "v0data exists", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; + TString hCandidateCounterLabels[4] = {"All candidates", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; TString hNEventsMCLabels[6] = {"All", "z vrtx", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; - TString hNEventsLabels[11] = {"All", "kIsTriggerTVX", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kIsVertexITSTPC", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "z vrtx", "INEL", "INEL>0", "INEL>1"}; + TString hNEventsLabels[12] = {"All", "kIsTriggerTVX", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kIsVertexITSTPC", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "isVertexTOFmatched", "z vrtx", "INEL", "INEL>0", "INEL>1"}; + + registry.add("hNEvents", "hNEvents", {HistType::kTH1F, {{12, 0.f, 12.f}}}); - registry.add("hNEvents", "hNEvents", {HistType::kTH1F, {{11, 0.f, 11.f}}}); for (Int_t n = 1; n <= registry.get(HIST("hNEvents"))->GetNbinsX(); n++) { registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(n, hNEventsLabels[n - 1]); } registry.add("hZCollision", "hZCollision", {HistType::kTH1F, {{200, -20.f, 20.f}}}); - registry.add("hCandidateCounter", "hCandidateCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}); + registry.add("hCandidateCounter", "hCandidateCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}); for (Int_t n = 1; n <= registry.get(HIST("hCandidateCounter"))->GetNbinsX(); n++) { registry.get(HIST("hCandidateCounter"))->GetXaxis()->SetBinLabel(n, hCandidateCounterLabels[n - 1]); } if (isMC) { // Rec. lvl + registry.add("fakeEvents", "fakeEvents", {HistType::kTH1F, {{1, -0.5f, 0.5f}}}); registry.add("hNchFT0MPVContr", "hNchFT0MPVContr", {HistType::kTH3F, {nChargedFT0MGenAxis, multNTracksAxis, eventTypeAxis}}); registry.add("hNchFV0APVContr", "hNchFV0APVContr", {HistType::kTH3F, {nChargedFV0AGenAxis, multNTracksAxis, eventTypeAxis}}); // Gen. lvl @@ -136,19 +144,24 @@ struct cascqaanalysis { registry.add("hNContributorsCorrelation", "hNContributorsCorrelation", {HistType::kTH2F, {{250, -0.5f, 249.5f, "Secondary Contributor"}, {250, -0.5f, 249.5f, "Main Contributor"}}}); registry.add("hNchFT0MGenEvType", "hNchFT0MGenEvType", {HistType::kTH2F, {nChargedFT0MGenAxis, eventTypeAxis}}); registry.add("hNchFV0AGenEvType", "hNchFV0AGenEvType", {HistType::kTH2F, {nChargedFV0AGenAxis, eventTypeAxis}}); - } else { - registry.add("hFT0MpvContr", "hFT0MpvContr", {HistType::kTH3F, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); - registry.add("hFV0ApvContr", "hFV0ApvContr", {HistType::kTH3F, {centFV0AAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hCentFT0M_genMC", "hCentFT0M_genMC", {HistType::kTH2F, {centFT0MAxis, eventTypeAxis}}); + } + + registry.add("hCentFT0M_rec", "hCentFT0M_rec", {HistType::kTH2F, {centFT0MAxis, eventTypeAxis}}); + + if (candidateQA) { + registry.add("hNcandidates", "hNcandidates", {HistType::kTH3F, {nCandidates, centFT0MAxis, {2, -0.5f, 1.5f}}}); } if (multQA) { if (isMC) { // Rec. lvl registry.add("hNchFT0Mglobal", "hNchFT0Mglobal", {HistType::kTH3F, {nChargedFT0MGenAxis, multNTracksAxis, eventTypeAxis}}); - } else { - registry.add("hFT0Mglobal", "hFT0Mglobal", {HistType::kTH3F, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); - registry.add("hFV0AFT0M", "hFV0AFT0M", {HistType::kTH3F, {centFV0AAxis, centFT0MAxis, eventTypeAxis}}); } + registry.add("hFT0MpvContr", "hFT0MpvContr", {HistType::kTH3F, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hFV0ApvContr", "hFV0ApvContr", {HistType::kTH3F, {centFV0AAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hFT0Mglobal", "hFT0Mglobal", {HistType::kTH3F, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hFV0AFT0M", "hFV0AFT0M", {HistType::kTH3F, {centFV0AAxis, centFT0MAxis, eventTypeAxis}}); registry.add("hFT0MFV0Asignal", "hFT0MFV0Asignal", {HistType::kTH2F, {signalFT0MAxis, signalFV0AAxis}}); registry.add("hFT0MsignalPVContr", "hFT0MsignalPVContr", {HistType::kTH3F, {signalFT0MAxis, multNTracksAxis, eventTypeAxis}}); } @@ -239,14 +252,14 @@ struct cascqaanalysis { { // 0 - INEL, 1 - INEL>0, 2 - INEL>1 int evFlag = 0; - registry.fill(HIST("hNEvents"), 8.5); // INEL + registry.fill(HIST("hNEvents"), 9.5); // INEL if (collision.isInelGt0()) { evFlag += 1; - registry.fill(HIST("hNEvents"), 9.5); // INEL>0 + registry.fill(HIST("hNEvents"), 10.5); // INEL>0 } if (collision.isInelGt1()) { evFlag += 1; - registry.fill(HIST("hNEvents"), 10.5); // INEL>1 + registry.fill(HIST("hNEvents"), 11.5); // INEL>1 } return evFlag; } @@ -286,33 +299,40 @@ struct cascqaanalysis { } // kIsVertexITSTPC selection - if (isVertexITSTPCCut && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { + if (isVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { return false; } if (isFillEventSelectionQA) { registry.fill(HIST("hNEvents"), 4.5); } // kNoSameBunchPileup selection - if (isNoSameBunchPileupCut && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (isNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } if (isFillEventSelectionQA) { registry.fill(HIST("hNEvents"), 5.5); } // kIsGoodZvtxFT0vsPV selection - if (isGoodZvtxFT0vsPVCut && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } if (isFillEventSelectionQA) { registry.fill(HIST("hNEvents"), 6.5); } + // isVertexTOFmatched selection + if (isVertexTOFmatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if (isFillEventSelectionQA) { + registry.fill(HIST("hNEvents"), 7.5); + } // Z vertex selection if (TMath::Abs(collision.posZ()) > cutzvertex) { return false; } if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 7.5); + registry.fill(HIST("hNEvents"), 8.5); registry.fill(HIST("hZCollision"), collision.posZ()); } @@ -338,10 +358,11 @@ struct cascqaanalysis { auto tracksGroupedGlobal = globalTracksIUEta05->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); int nTracksGlobal = tracksGroupedGlobal.size(); - registry.fill(HIST("hFT0MpvContr"), collision.centFT0M(), nTracksPVcontr, evType); - registry.fill(HIST("hFV0ApvContr"), collision.centFV0A(), nTracksPVcontr, evType); + registry.fill(HIST("hCentFT0M_rec"), collision.centFT0M(), evType); if (multQA) { + registry.fill(HIST("hFT0MpvContr"), collision.centFT0M(), nTracksPVcontr, evType); + registry.fill(HIST("hFV0ApvContr"), collision.centFV0A(), nTracksPVcontr, evType); registry.fill(HIST("hFT0Mglobal"), collision.centFT0M(), nTracksGlobal, evType); registry.fill(HIST("hFV0AFT0M"), collision.centFV0A(), collision.centFT0M(), evType); registry.fill(HIST("hFT0MFV0Asignal"), collision.multFT0A() + collision.multFT0C(), collision.multFV0A()); @@ -349,13 +370,15 @@ struct cascqaanalysis { } float lEventScale = scalefactor; + int nCandSel = 0; + int nCandAll = 0; for (const auto& casc : Cascades) { // loop over Cascades registry.fill(HIST("hCandidateCounter"), 0.5); // all candidates - registry.fill(HIST("hCandidateCounter"), 1.5); // v0data exists, deprecated - + nCandAll++; if (AcceptCascCandidate(casc, collision.posX(), collision.posY(), collision.posZ())) { - registry.fill(HIST("hCandidateCounter"), 2.5); // passed topo cuts + registry.fill(HIST("hCandidateCounter"), 1.5); // passed topo cuts + nCandSel++; // Fill table if (fRand->Rndm() < lEventScale) { auto posdau = casc.posTrack_as(); @@ -391,7 +414,10 @@ struct cascqaanalysis { float ctauXi = pdgDB->Mass(3312) * cascpos / (cascptotmom + 1e-13); float ctauOmega = pdgDB->Mass(3334) * cascpos / (cascptotmom + 1e-13); - mycascades(collision.posZ(), collision.centFT0M(), collision.centFV0A(), casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), + mycascades(collision.posZ(), + collision.centFT0M(), collision.centFV0A(), + collision.multFT0M(), collision.multFV0A(), + casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), casc.mXi(), casc.mOmega(), casc.mLambda(), casc.cascradius(), casc.v0radius(), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.dcapostopv(), casc.dcanegtopv(), casc.dcabachtopv(), casc.dcacascdaughters(), casc.dcaV0daughters(), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), @@ -405,6 +431,11 @@ struct cascqaanalysis { } } } + + if (candidateQA) { + registry.fill(HIST("hNcandidates"), nCandAll, collision.centFT0M(), 0); + registry.fill(HIST("hNcandidates"), nCandSel, collision.centFT0M(), 1); + } } Preslice perMcCollision = aod::mcparticle::mcCollisionId; @@ -415,13 +446,20 @@ struct cascqaanalysis { aod::V0Datas const&, soa::Filtered const& Cascades, DauTracks const&, - aod::McCollisions const&, + soa::Join const&, // aod::McCentFV0As to be added aod::McParticles const& mcParticles) { if (!AcceptEvent(collision, 1)) { return; } + if (!collision.has_mcCollision()) { + registry.fill(HIST("fakeEvents"), 0); // no assoc. MC collisions + return; + } + + const auto& mcCollision = collision.mcCollision_as>(); // aod::McCentFV0As to be added + auto tracksGroupedPVcontr = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); int nTracksPVcontr = tracksGroupedPVcontr.size(); @@ -429,48 +467,55 @@ struct cascqaanalysis { int nTracksGlobal = tracksGroupedGlobal.size(); // N charged in FT0M region in corresponding gen. MC collision - auto mcPartSlice = mcParticles.sliceBy(perMcCollision, collision.mcCollision_as().globalIndex()); + auto mcPartSlice = mcParticles.sliceBy(perMcCollision, collision.mcCollision_as>().globalIndex()); // mcCollision.centFV0A() to be added uint16_t nchFT0 = GetGenNchInFT0Mregion(mcPartSlice); uint16_t nchFV0 = GetGenNchInFV0Aregion(mcPartSlice); int evType = 0; - registry.fill(HIST("hNEvents"), 8.5); // INEL + registry.fill(HIST("hNEvents"), 9.5); // INEL // Rec. collision associated with INEL>0 gen. one if (pwglf::isINELgtNmc(mcPartSlice, 0, pdgDB)) { - registry.fill(HIST("hNEvents"), 9.5); // INEL + registry.fill(HIST("hNEvents"), 10.5); // INEL evType++; } // Rec. collision associated with INEL>1 gen. one if (pwglf::isINELgtNmc(mcPartSlice, 1, pdgDB)) { - registry.fill(HIST("hNEvents"), 10.5); // INEL + registry.fill(HIST("hNEvents"), 11.5); // INEL evType++; } - registry.fill(HIST("hNchFT0MPVContr"), nchFT0, nTracksPVcontr, evType); - registry.fill(HIST("hNchFV0APVContr"), nchFV0, nTracksPVcontr, evType); + registry.fill(HIST("hCentFT0M_rec"), mcCollision.centFT0M(), evType); if (multQA) { + registry.fill(HIST("hNchFT0MPVContr"), nchFT0, nTracksPVcontr, evType); + registry.fill(HIST("hNchFV0APVContr"), nchFV0, nTracksPVcontr, evType); + registry.fill(HIST("hFT0MpvContr"), mcCollision.centFT0M(), nTracksPVcontr, evType); + registry.fill(HIST("hFV0ApvContr"), 0, nTracksPVcontr, evType); // mcCollision.centFV0A() to be added + registry.fill(HIST("hFT0Mglobal"), mcCollision.centFT0M(), nTracksGlobal, evType); + registry.fill(HIST("hFV0AFT0M"), 0, mcCollision.centFT0M(), evType); // mcCollision.centFV0A() to be added registry.fill(HIST("hNchFT0Mglobal"), nchFT0, nTracksGlobal, evType); registry.fill(HIST("hFT0MFV0Asignal"), collision.multFT0A() + collision.multFT0C(), collision.multFV0A()); registry.fill(HIST("hFT0MsignalPVContr"), collision.multFT0A() + collision.multFT0C(), nTracksPVcontr, evType); } float lEventScale = scalefactor; + int nCandSel = 0; + int nCandAll = 0; for (const auto& casc : Cascades) { // loop over Cascades registry.fill(HIST("hCandidateCounter"), 0.5); // all candidates - registry.fill(HIST("hCandidateCounter"), 1.5); // v0data exists - deprecated - + nCandAll++; if (AcceptCascCandidate(casc, collision.posX(), collision.posY(), collision.posZ())) { - registry.fill(HIST("hCandidateCounter"), 2.5); // passed topo cuts + registry.fill(HIST("hCandidateCounter"), 1.5); // passed topo cuts + nCandSel++; // Check mc association float lPDG = -1; float isPrimary = -1; if (casc.has_mcParticle()) { - registry.fill(HIST("hCandidateCounter"), 3.5); // has associated MC particle + registry.fill(HIST("hCandidateCounter"), 2.5); // has associated MC particle auto cascmc = casc.mcParticle(); if (TMath::Abs(cascmc.pdgCode()) == 3312 || TMath::Abs(cascmc.pdgCode()) == 3334) { - registry.fill(HIST("hCandidateCounter"), 4.5); // associated with Xi or Omega + registry.fill(HIST("hCandidateCounter"), 3.5); // associated with Xi or Omega lPDG = cascmc.pdgCode(); isPrimary = cascmc.isPhysicalPrimary() ? 1 : 0; } @@ -511,7 +556,10 @@ struct cascqaanalysis { float ctauXi = pdgDB->Mass(3312) * cascpos / (cascptotmom + 1e-13); float ctauOmega = pdgDB->Mass(3334) * cascpos / (cascptotmom + 1e-13); - mycascades(collision.posZ(), nchFT0, collision.multFV0A(), casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), + mycascades(collision.posZ(), + mcCollision.centFT0M(), 0, // mcCollision.centFV0A() to be added + collision.multFT0M(), collision.multFV0A(), + casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), casc.mXi(), casc.mOmega(), casc.mLambda(), casc.cascradius(), casc.v0radius(), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.dcapostopv(), casc.dcanegtopv(), casc.dcabachtopv(), casc.dcacascdaughters(), casc.dcaV0daughters(), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), @@ -525,9 +573,14 @@ struct cascqaanalysis { } } } + + if (candidateQA) { + registry.fill(HIST("hNcandidates"), nCandAll, mcCollision.centFT0M(), 0); + registry.fill(HIST("hNcandidates"), nCandSel, mcCollision.centFT0M(), 1); + } } - void processMCgen(aod::McCollision const& mcCollision, + void processMCgen(soa::Join::iterator const& mcCollision, // mcCollision.centFV0A() to be added aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions, DauTracks const&) @@ -560,6 +613,8 @@ struct cascqaanalysis { registry.fill(HIST("hNEventsMC"), 4.5); } + registry.fill(HIST("hCentFT0M_genMC"), mcCollision.centFT0M(), evType); + uint16_t nchFT0 = GetGenNchInFT0Mregion(mcParticles); uint16_t nchFV0 = GetGenNchInFV0Aregion(mcParticles); registry.fill(HIST("hNchFT0MGenEvType"), nchFT0, evType); @@ -574,7 +629,7 @@ struct cascqaanalysis { if (!AcceptEvent(collision, 0)) { continue; } - collWithType.index = collision.mcCollision_as().globalIndex(); + collWithType.index = collision.mcCollision_as>().globalIndex(); // mcCollision.centFV0A() to be added collWithType.typeFlag |= o2::aod::myMCcascades::EvFlags::EvINEL; if (collision.isInelGt0()) { @@ -585,7 +640,7 @@ struct cascqaanalysis { } SelectedEvents[nevts++] = collWithType; - if (collision.mcCollision_as().globalIndex() == mcCollision.globalIndex()) { + if (collision.mcCollision_as>().globalIndex() == mcCollision.globalIndex()) { // mcCollision.centFV0A() to be added nAssocColl++; NumberOfContributors.push_back(collision.numContrib()); } @@ -650,7 +705,9 @@ struct cascqaanalysis { } myMCcascades(mcCollision.posZ(), sign, mcParticle.pdgCode(), mcParticle.y(), mcParticle.eta(), mcParticle.phi(), mcParticle.pt(), - mcParticle.isPhysicalPrimary(), nAssocColl, nchFT0, + mcParticle.isPhysicalPrimary(), nAssocColl, + nchFT0, nchFV0, + mcCollision.centFT0M(), 0, // mcCollision.centFV0A() to be added flagsAssoc, flagsGen); } diff --git a/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx new file mode 100644 index 00000000000..5ecffca742f --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx @@ -0,0 +1,334 @@ +// Copyright 2019-2020 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. + +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/DataModel/PIDResponse.h" +#include "DCAFitter/DCAFitterN.h" + +#include "PWGLF/DataModel/LFDoubleCascTables.h" +#include "TDatabasePDG.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using Collisions = soa::Join::iterator; +using FullCascades = aod::CascDataExt; +using TracksFull = soa::Join; + +struct doubleCascCand { + float ptCasc1 = -999.f; // signed pt of the cascade + float etaCasc1 = -999.f; + float phiCasc1 = -999.f; + float cascDecLength1 = -999.f; + float omegaMassCasc1 = -999.f; + float xiMassCasc1 = -999.f; + float cosPACasc1 = -999.f; + float dcaBachPVCasc1 = -999.f; + float dcaV0BachCasc1 = -999.f; + float nSigmaKBach1 = -999.f; + + float ptCasc2 = -999.f; + float etaCasc2 = -999.f; + float phiCasc2 = -999.f; + float cascDecLength2 = -999.f; + float omegaMassCasc2 = -999.f; + float xiMassCasc2 = -999.f; + float cosPACasc2 = -999.f; + float dcaBachPVCasc2 = -999.f; + float dcaV0BachCasc2 = -999.f; + float nSigmaKBach2 = -999.f; + float doubleOmegaMass = -999.f; +}; + +struct doubleCascTreeCreator { + Produces doubleCascTable; + std::vector doubleCascCands; + Service ccdb; + o2::vertexing::DCAFitterN<2> fitter; + + int mRunNumber; + + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; + ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; + + // binning of (anti)lambda mass QA histograms + ConfigurableAxis massOmegaAxis{"massLambdaAxis", {400, o2::constants::physics::MassOmegaMinus - 0.05f, o2::constants::physics::MassOmegaMinus + 0.035}, "binning for the Omega invariant-mass"}; + ConfigurableAxis massXiAxis{"massXiAxis", {400, o2::constants::physics::MassXiMinus - 0.05f, o2::constants::physics::MassXiMinus + 0.05f}, "binning for the Xi invariant-mass"}; + + Configurable zVtxMax{"zVtxMax", 10.0f, "maximum z position of the primary vertex"}; + Configurable etaMax{"etaMax", 0.9f, "maximum eta"}; + ConfigurableAxis momAxis{"momAxisFine", {5.e2, 0.f, 5.f}, "momentum axis binning"}; + + Configurable cascPtMin{"cascPtMin", 1.f, "minimum (anti)casc pT (GeV/c)"}; + Configurable cascPtMax{"cascPtMax", 4.f, "maximum (anti)casc pT (GeV/c)"}; + + Configurable minNCrossedRows{"minNCrossedRows", 100, "Minimum number of crossed TPC rows"}; + Configurable minNITSClus{"minNITSClus", 0., "Minimum number of ITS clusters"}; + Configurable minNTPCClus{"minNTPCClus", 100, "Minimum number of TPC clusters"}; + Configurable maxNSharedTPCClus{"maxNSharedTPCClus", 5, "Maximum number of shared TPC clusters"}; + + Configurable minCascCosPA{"minCascCosPA", 0.99f, "Minimum cosine of the pointing angle of the cascade"}; + Configurable nSigmaTPCCut{"nSigmaTPCCut", 3.f, "Number of sigmas for the TPC PID"}; + Configurable dcaBachToPV{"dcaBachToPV", 0.05f, "DCA of the bachelor to the primary vertex"}; + Configurable dcaV0Bach{"dcaV0Bach", 1.f, "DCA between the V0 daughters"}; + Configurable mXiWindow{"mXiWindow", 0.02f, "mXiWindow"}; + Configurable mOmegaWindow{"mOmegaWindow", 0.01f, "mOmegaWindow"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + template + bool selectTrack(T const& track) + { + if (std::abs(track.eta()) > etaMax) { + return false; + } + if (track.itsNCls() < minNITSClus || + track.tpcNClsFound() < minNTPCClus || + track.tpcNClsCrossedRows() < minNCrossedRows || + track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || + track.tpcNClsShared() > maxNSharedTPCClus) { + return false; + } + return true; + } + + template + void initCCDB(Bc const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + auto timestamp = bc.timestamp(); + LOG(info) << "Retrieved GRP for timestamp " << timestamp; + mRunNumber = bc.runNumber(); + if (cfgSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fDoubleOmega,fOmegaXi"); + zorro.populateHistRegistry(histos, bc.runNumber()); + } + } + + void init(o2::framework::InitContext&) + { + mRunNumber = 0; + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + zorroSummary.setObject(zorro.getZorroSummary()); + + // event QA + histos.add("QA/zVtx", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); + histos.add("QA/massXi", ";#it{p}_{T} (GeV/#it{c});#it{M}(#Lambda + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH2F, {momAxis, massXiAxis}); + histos.add("QA/massOmega", ";#it{p}_{T} (GeV/#it{c});#it{M}(#Omega + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH2F, {momAxis, massOmegaAxis}); + } + + template + bool isSelectedCasc(C const& collision, T const&, FullCascades::iterator const& casc) + { + + auto bachelor = casc.bachelor_as(); + auto posDau = casc.posTrack_as(); + auto negDau = casc.negTrack_as(); + + if (!selectTrack(bachelor) || !selectTrack(posDau) || !selectTrack(negDau)) { + return false; + } + if (casc.sign() > 0) { + if (TMath::Abs(posDau.tpcNSigmaPi()) > nSigmaTPCCut || TMath::Abs(negDau.tpcNSigmaPr()) > nSigmaTPCCut) { + return false; + } + } else if (casc.sign() < 0) { + if (TMath::Abs(negDau.tpcNSigmaPi()) > nSigmaTPCCut || TMath::Abs(posDau.tpcNSigmaPr()) > nSigmaTPCCut) { + return false; + } + } + if (TMath::Abs(casc.dcabachtopv()) < dcaBachToPV) { + return false; + } + if (TMath::Abs(casc.dcacascdaughters()) > dcaV0Bach) { + return false; + } + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < minCascCosPA) { + return false; + } + if (TMath::Abs(casc.eta()) > etaMax) { + return false; + } + // mass cuts + bool massInWindow = false; + if (casc.mOmega() > o2::constants::physics::MassOmegaMinus - mOmegaWindow && casc.mOmega() < o2::constants::physics::MassOmegaMinus + mOmegaWindow) { + massInWindow = true; + } + if (casc.mXi() > o2::constants::physics::MassXiMinus - mXiWindow && casc.mXi() < o2::constants::physics::MassXiMinus + mXiWindow) { + massInWindow = true; + } + if (!massInWindow) { + return false; + } + return true; + }; + + template + bool doubleOmegaMass(T const&, FullCascades::iterator const& casc1, FullCascades::iterator const& casc2) + { + // the fake omega decay is the one with the smaller radius + auto& fakeOmega = casc1.cascradius() < casc2.cascradius() ? casc1 : casc2; + auto& realOmega = casc1.cascradius() < casc2.cascradius() ? casc2 : casc1; + auto kaon = fakeOmega.bachelor_as(); + float momKaon[3] = {kaon.px(), kaon.py(), kaon.pz()}; + float momLambda[3] = {fakeOmega.pxlambda(), fakeOmega.pylambda(), fakeOmega.pzlambda()}; + // now compute real Omega-lambda-kaon mass + float momTot[3] = {momKaon[0] + momLambda[0] + realOmega.px(), momKaon[1] + momLambda[1] + realOmega.py(), momKaon[2] + momLambda[2] + realOmega.pz()}; + float eK = std::sqrt(o2::constants::physics::MassKaonCharged * o2::constants::physics::MassKaonCharged + momKaon[0] * momKaon[0] + momKaon[1] * momKaon[1] + momKaon[2] * momKaon[2]); + float eL = std::sqrt(o2::constants::physics::MassLambda0 * o2::constants::physics::MassLambda0 + momLambda[0] * momLambda[0] + momLambda[1] * momLambda[1] + momLambda[2] * momLambda[2]); + float eO = std::sqrt(o2::constants::physics::MassOmegaMinus * o2::constants::physics::MassOmegaMinus + momTot[0] * momTot[0] + momTot[1] * momTot[1] + momTot[2] * momTot[2]); + float eTot = eK + eL + eO; + float mass = std::sqrt(eTot * eTot - momTot[0] * momTot[0] - momTot[1] * momTot[1] - momTot[2] * momTot[2]); + return mass; + } + + template + void fillDoubleCasc(C const& collision, T const& tracks, FullCascades const& cascades) + { + doubleCascCands.clear(); + + for (auto& casc1 : cascades) { + if (!isSelectedCasc(collision, tracks, casc1)) { + continue; + } + for (auto& casc2 : cascades) { + if (!isSelectedCasc(collision, tracks, casc2)) { + continue; + } + + if (casc1.posTrackId() == casc2.posTrackId() || casc1.posTrackId() == casc2.negTrackId() || casc1.bachelorId() == casc2.bachelorId()) { + continue; + } + + auto bach1 = casc1.bachelor_as(); + auto bach2 = casc2.bachelor_as(); + + doubleCascCand cand; + cand.ptCasc1 = casc1.pt(); + cand.etaCasc1 = casc1.eta(); + cand.phiCasc1 = casc1.phi(); + cand.cascDecLength1 = std::hypot(casc1.x() - collision.posX(), casc1.y() - collision.posY(), casc1.z() - collision.posZ()); + cand.omegaMassCasc1 = casc1.mOmega(); + cand.xiMassCasc1 = casc1.mXi(); + cand.cosPACasc1 = casc1.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + cand.dcaBachPVCasc1 = casc1.dcabachtopv(); + cand.dcaV0BachCasc1 = casc1.dcacascdaughters(); + cand.nSigmaKBach1 = bach1.tpcNSigmaKa(); + + cand.ptCasc2 = casc2.pt(); + cand.etaCasc2 = casc2.eta(); + cand.phiCasc2 = casc2.phi(); + cand.cascDecLength2 = std::hypot(casc2.x() - collision.posX(), casc2.y() - collision.posY(), casc2.z() - collision.posZ()); + cand.omegaMassCasc2 = casc2.mOmega(); + cand.xiMassCasc2 = casc2.mXi(); + cand.cosPACasc2 = casc2.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + cand.dcaBachPVCasc2 = casc2.dcabachtopv(); + cand.dcaV0BachCasc2 = casc2.dcacascdaughters(); + cand.nSigmaKBach2 = bach2.tpcNSigmaKa(); + + cand.doubleOmegaMass = doubleOmegaMass(tracks, casc1, casc2); + + doubleCascCands.push_back(cand); + } + } + }; + + void processData(Collisions const& collision, TracksFull const& tracks, FullCascades const& cascades, aod::BCsWithTimestamps const&) + { + auto bc = collision.bc_as(); + initCCDB(bc); + + if (!collision.sel8()) + return; + + if (std::abs(collision.posZ()) > zVtxMax) + return; + + if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return; + + if (cfgSkimmedProcessing) { + zorro.isSelected(collision.bc_as().globalBC()); /// Just let Zorro do the accounting + } + histos.fill(HIST("QA/zVtx"), collision.posZ()); + fillDoubleCasc(collision, tracks, cascades); + + for (auto& cand : doubleCascCands) { + doubleCascTable( + cand.ptCasc1, + cand.etaCasc1, + cand.phiCasc1, + cand.cascDecLength1, + cand.omegaMassCasc1, + cand.xiMassCasc1, + cand.cosPACasc1, + cand.dcaBachPVCasc1, + cand.dcaV0BachCasc1, + cand.nSigmaKBach1, + cand.ptCasc2, + cand.etaCasc2, + cand.phiCasc2, + cand.cascDecLength2, + cand.omegaMassCasc2, + cand.xiMassCasc2, + cand.cosPACasc2, + cand.dcaBachPVCasc2, + cand.dcaV0BachCasc2, + cand.nSigmaKBach2, + cand.doubleOmegaMass); + } + } + PROCESS_SWITCH(doubleCascTreeCreator, processData, "process (Run 3)", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx b/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx index 4c84b1d3279..3bed2ca7e8e 100644 --- a/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx +++ b/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx @@ -33,6 +33,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +#define bitset(var, nbit) ((var) |= (1 << (nbit))) #define bitcheck(var, nbit) ((var) & (1 << (nbit))) struct hstrangecorrelationfilter { @@ -40,7 +41,9 @@ struct hstrangecorrelationfilter { // Operational Configurable fillTableOnlyWithCompatible{"fillTableOnlyWithCompatible", true, "pre-apply dE/dx, broad mass window in table filling"}; - Configurable strangedEdxNSigma{"strangedEdxNSigma", 5, "Nsigmas for strange decay daughters"}; + Configurable strangedEdxNSigmaLoose{"strangedEdxNSigmaLoose", 5, "Nsigmas for strange decay daughters"}; + Configurable strangedEdxNSigma{"strangedEdxNSigma", 4, "Nsigmas for strange decay daughters"}; + Configurable strangedEdxNSigmaTight{"strangedEdxNSigmaTight", 3, "Nsigmas for strange decay daughters"}; // Trigger particle selections in phase space Configurable triggerEtaMin{"triggerEtaCutMin", -0.8, "triggeretamin"}; @@ -102,9 +105,8 @@ struct hstrangecorrelationfilter { Configurable> massParsOmegaMean{"massParsOmegaMean", {1.67, 0.000298, 0.0, 0.0}, "pars in [0]+[1]*x+[2]*TMath::Exp(-[3]*x)"}; Configurable> massParsOmegaWidth{"massParsOmegaWidth", {0.00189, 0.000325, 0.00606, 1.77}, "pars in [0]+[1]*x+[2]*TMath::Exp(-[3]*x)"}; - // definitions of peak and background - Configurable peakNsigma{"peakNsigma", 3.0f, "peak region is +/- this many sigmas away"}; - Configurable backgroundNsigma{"backgroundNsigma", 6.0f, "bg region is +/- this many sigmas away (minus peak)"}; + // must include windows for background and peak + Configurable maxMassNSigma{"maxMassNSigma", 12.0f, "max mass region to be considered for further analysis"}; // For extracting strangeness mass QA plots ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; @@ -114,6 +116,8 @@ struct hstrangecorrelationfilter { ConfigurableAxis axisOmegaMass{"axisOmegaMass", {200, 1.57f, 1.77f}, "Inv. Mass (GeV/c^{2})"}; ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0.0f, 0.01f, 1.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 100.0f}, "Centrality percentile bins"}; + // QA + Configurable doTrueSelectionInMass{"doTrueSelectionInMass", false, "Fill mass histograms only with true primary Particles for MC"}; // Do declarative selections for DCAs, if possible Filter preFilterTracks = nabs(aod::track::dcaXY) < dcaXYconstant + dcaXYpTdep * nabs(aod::track::signed1Pt); Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > dcaPostopv&& @@ -128,6 +132,7 @@ struct hstrangecorrelationfilter { using V0LinkedTagged = soa::Join; using CascadesLinkedTagged = soa::Join; using DauTracks = soa::Join; + using DauTracksMC = soa::Join; // using IDTracks= soa::Join; // prepared for Bayesian PID using IDTracks = soa::Join; using V0DatasWithoutTrackX = soa::Join; @@ -166,6 +171,33 @@ struct hstrangecorrelationfilter { histos.add("h3dMassOmegaPlus", "h3dMassOmegaPlus", kTH3F, {axisPtQA, axisOmegaMass, axisMult}); } + // reco-level trigger quality checks (N.B.: DCA is filtered, not selected) + template + bool isValidTrigger(TTrack track) + { + if (track.eta() > triggerEtaMax || track.eta() < triggerEtaMin) { + return false; + } + // if (track.sign()= 1 ) {continue;} + if (track.pt() > triggerPtCutMax || track.pt() < triggerPtCutMin) { + return false; + } + if (track.tpcNClsCrossedRows() < minTPCNCrossedRows) { + return false; // crossed rows + } + if (!track.hasITS() && triggerRequireITS) { + return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) + } + if (track.tpcNClsShared() > triggerMaxTPCSharedClusters) { + return false; // skip, has shared clusters + } + if (!(bitcheck(track.itsClusterMap(), 0)) && triggerRequireL0) { + return false; // skip, doesn't have cluster in ITS L0 + } + return true; + } + + // for real data processing void processTriggers(soa::Join::iterator const& collision, soa::Filtered const& tracks) { // Perform basic event selection @@ -180,30 +212,44 @@ struct hstrangecorrelationfilter { /// _________________________________________________ /// Step 1: Populate table with trigger tracks for (auto const& track : tracks) { - if (track.eta() > triggerEtaMax || track.eta() < triggerEtaMin) { + if (!isValidTrigger(track)) continue; - } - // if (track.sign()= 1 ) {continue;} - if (track.pt() > triggerPtCutMax || track.pt() < triggerPtCutMin) { + triggerTrack( + track.collisionId(), + false, // if you decide to check real data for primaries, you'll have a hard time + track.globalIndex()); + } + } + + // for MC processing + void processTriggersMC(soa::Join::iterator const& collision, soa::Filtered const& tracks, aod::McParticles const&) + { + // Perform basic event selection + if (!collision.sel8()) { + return; + } + // No need to correlate stuff that's in far collisions + if (TMath::Abs(collision.posZ()) > 10.0) { + return; + } + + /// _________________________________________________ + /// Step 1: Populate table with trigger tracks + for (auto const& track : tracks) { + if (!isValidTrigger(track)) continue; - } - if (track.tpcNClsCrossedRows() < minTPCNCrossedRows) { - continue; // crossed rows - } - if (!track.hasITS() && triggerRequireITS) { - continue; // skip, doesn't have ITS signal (skips lots of TPC-only!) - } - if (track.tpcNClsShared() > triggerMaxTPCSharedClusters) { - continue; // skip, has shared clusters - } - if (!(bitcheck(track.itsClusterMap(), 0)) && triggerRequireL0) { - continue; // skip, doesn't have cluster in ITS L0 + bool physicalPrimary = false; + if (track.has_mcParticle()) { + auto mcParticle = track.mcParticle(); + physicalPrimary = mcParticle.isPhysicalPrimary(); } triggerTrack( track.collisionId(), + physicalPrimary, track.globalIndex()); } } + void processAssocPions(soa::Join::iterator const& collision, soa::Filtered const& tracks) { // Perform basic event selection @@ -287,9 +333,9 @@ struct hstrangecorrelationfilter { continue; } // check dE/dx compatibility - bool compatibleK0Short = false; - bool compatibleLambda = false; - bool compatibleAntiLambda = false; + int compatibleK0Short = 0; + int compatibleLambda = 0; + int compatibleAntiLambda = 0; auto posdau = v0.posTrack_as(); auto negdau = v0.negTrack_as(); @@ -300,88 +346,55 @@ struct hstrangecorrelationfilter { if (posdau.tpcNClsCrossedRows() < minTPCNCrossedRows) continue; - if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - compatibleK0Short = true; - } - if (TMath::Abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (v0.v0cosPA() > lambdaCospa) { - compatibleLambda = true; - } - } - if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { - if (v0.v0cosPA() > lambdaCospa) { - compatibleAntiLambda = true; - } - } - // check whether V0s are in the regin - int massRegK0Short = -1; - if (TMath::Abs(v0.mK0Short() - fK0Mean->Eval(v0.pt()) < peakNsigma * fK0Width->Eval(v0.pt()))) { - massRegK0Short = 2; - } - if (v0.mK0Short() > fK0Mean->Eval(v0.pt()) + peakNsigma * fK0Width->Eval(v0.pt()) && v0.mK0Short() < fK0Mean->Eval(v0.pt()) + backgroundNsigma * fK0Width->Eval(v0.pt())) { - massRegK0Short = 3; - } - if (v0.mK0Short() < fK0Mean->Eval(v0.pt()) - peakNsigma * fK0Width->Eval(v0.pt()) && v0.mK0Short() > fK0Mean->Eval(v0.pt()) - backgroundNsigma * fK0Width->Eval(v0.pt())) { - massRegK0Short = 1; - } - if (v0.mK0Short() > fK0Mean->Eval(v0.pt()) + backgroundNsigma * fK0Width->Eval(v0.pt())) { - massRegK0Short = 4; - } - if (v0.mK0Short() < fK0Mean->Eval(v0.pt()) - backgroundNsigma * fK0Width->Eval(v0.pt())) { - massRegK0Short = 0; - } - - int massRegLambda = -1; - if (TMath::Abs(v0.mLambda() - fLambdaMean->Eval(v0.pt()) < peakNsigma * fLambdaWidth->Eval(v0.pt()))) { - massRegLambda = 2; - } - if (v0.mLambda() > fLambdaMean->Eval(v0.pt()) + peakNsigma * fLambdaWidth->Eval(v0.pt()) && v0.mLambda() < fLambdaMean->Eval(v0.pt()) + backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegLambda = 3; - } - if (v0.mLambda() < fLambdaMean->Eval(v0.pt()) - peakNsigma * fLambdaWidth->Eval(v0.pt()) && v0.mLambda() > fLambdaMean->Eval(v0.pt()) - backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegLambda = 1; - } - if (v0.mLambda() > fLambdaMean->Eval(v0.pt()) + backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegLambda = 4; - } - if (v0.mLambda() < fLambdaMean->Eval(v0.pt()) - backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegLambda = 0; - } - - int massRegAntiLambda = -1; - if (TMath::Abs(v0.mAntiLambda() - fLambdaMean->Eval(v0.pt()) < peakNsigma * fLambdaWidth->Eval(v0.pt()))) { - massRegAntiLambda = 2; - } - if (v0.mAntiLambda() > fLambdaMean->Eval(v0.pt()) + peakNsigma * fLambdaWidth->Eval(v0.pt()) && v0.mAntiLambda() < fLambdaMean->Eval(v0.pt()) + backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegAntiLambda = 3; - } - if (v0.mAntiLambda() < fLambdaMean->Eval(v0.pt()) - peakNsigma * fLambdaWidth->Eval(v0.pt()) && v0.mAntiLambda() > fLambdaMean->Eval(v0.pt()) - backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegAntiLambda = 1; - } - if (v0.mAntiLambda() > fLambdaMean->Eval(v0.pt()) + backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegAntiLambda = 4; - } - if (v0.mAntiLambda() < fLambdaMean->Eval(v0.pt()) - backgroundNsigma * fLambdaWidth->Eval(v0.pt())) { - massRegAntiLambda = 0; - } - - if (compatibleK0Short) + if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) + bitset(compatibleK0Short, 0); + if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) + bitset(compatibleK0Short, 1); + if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) + bitset(compatibleK0Short, 2); + + if (TMath::Abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) + if (v0.v0cosPA() > lambdaCospa) + bitset(compatibleLambda, 0); + if (TMath::Abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) + if (v0.v0cosPA() > lambdaCospa) + bitset(compatibleLambda, 1); + if (TMath::Abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) + if (v0.v0cosPA() > lambdaCospa) + bitset(compatibleLambda, 2); + + if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && TMath::Abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) + if (v0.v0cosPA() > lambdaCospa) + bitset(compatibleAntiLambda, 0); + if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) + if (v0.v0cosPA() > lambdaCospa) + bitset(compatibleAntiLambda, 1); + if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && TMath::Abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) + if (v0.v0cosPA() > lambdaCospa) + bitset(compatibleAntiLambda, 2); + + // simplified handling: calculate NSigma in mass here + float massNSigmaK0Short = (v0.mK0Short() - fK0Mean->Eval(v0.pt())) / (fK0Width->Eval(v0.pt()) + 1e-6); + float massNSigmaLambda = (v0.mLambda() - fLambdaMean->Eval(v0.pt())) / (fLambdaWidth->Eval(v0.pt()) + 1e-6); + float massNSigmaAntiLambda = (v0.mAntiLambda() - fLambdaMean->Eval(v0.pt())) / (fLambdaWidth->Eval(v0.pt()) + 1e-6); + + if (compatibleK0Short && (!doTrueSelectionInMass || (origV0entry.isTrueK0Short() && origV0entry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassK0Short"), v0.pt(), v0.mK0Short(), collision.centFT0M()); - if (compatibleLambda) + if (compatibleLambda && (!doTrueSelectionInMass || (origV0entry.isTrueLambda() && origV0entry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassLambda"), v0.pt(), v0.mLambda(), collision.centFT0M()); - if (compatibleAntiLambda) + if (compatibleAntiLambda && (!doTrueSelectionInMass || (origV0entry.isTrueAntiLambda() && origV0entry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassAntiLambda"), v0.pt(), v0.mAntiLambda(), collision.centFT0M()); if (!fillTableOnlyWithCompatible || ( // start major condition check - (compatibleK0Short && massRegK0Short > 0 && massRegK0Short < 4) || - (compatibleLambda && massRegLambda > 0 && massRegLambda < 4) || - (compatibleAntiLambda && massRegAntiLambda > 0 && massRegAntiLambda < 4)) // end major condition check + (compatibleK0Short > 0 && std::abs(massNSigmaK0Short) < maxMassNSigma) || + (compatibleLambda > 0 && std::abs(massNSigmaLambda) < maxMassNSigma) || + (compatibleAntiLambda > 0 && std::abs(massNSigmaAntiLambda) < maxMassNSigma)) // end major condition check ) { assocV0(v0.collisionId(), v0.globalIndex(), compatibleK0Short, compatibleLambda, compatibleAntiLambda, - origV0entry.isTrueK0Short(), origV0entry.isTrueLambda(), origV0entry.isTrueAntiLambda(), - massRegK0Short, massRegLambda, massRegAntiLambda); + origV0entry.isTrueK0Short(), origV0entry.isTrueLambda(), origV0entry.isTrueAntiLambda(), origV0entry.isPhysicalPrimary(), + massNSigmaK0Short, massNSigmaLambda, massNSigmaAntiLambda); } } } @@ -412,82 +425,68 @@ struct hstrangecorrelationfilter { continue; // check dE/dx compatibility - bool compatibleXiMinus = false; - bool compatibleXiPlus = false; - bool compatibleOmegaMinus = false; - bool compatibleOmegaPlus = false; - - if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() < 0) { - compatibleXiMinus = true; - } - if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() > 0) { - compatibleXiPlus = true; - } - if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() < 0) { - compatibleOmegaMinus = true; - } - if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() > 0) { - compatibleOmegaPlus = true; - } - - int massRegXi = -1; - if (TMath::Abs(casc.mXi() - fXiMean->Eval(casc.pt()) < peakNsigma * fXiWidth->Eval(casc.pt()))) { - massRegXi = 2; - } - if (casc.mXi() > fXiMean->Eval(casc.pt()) + peakNsigma * fXiWidth->Eval(casc.pt()) && casc.mXi() < fXiMean->Eval(casc.pt()) + backgroundNsigma * fXiWidth->Eval(casc.pt())) { - massRegXi = 3; - } - if (casc.mXi() < fXiMean->Eval(casc.pt()) - peakNsigma * fXiWidth->Eval(casc.pt()) && casc.mXi() > fXiMean->Eval(casc.pt()) - backgroundNsigma * fXiWidth->Eval(casc.pt())) { - massRegXi = 1; - } - if (casc.mXi() > fXiMean->Eval(casc.pt()) + backgroundNsigma * fXiWidth->Eval(casc.pt())) { - massRegXi = 4; - } - if (casc.mXi() < fXiMean->Eval(casc.pt()) - backgroundNsigma * fXiWidth->Eval(casc.pt())) { - massRegXi = 0; - } - - int massRegOmega = -1; - if (TMath::Abs(casc.mOmega() - fOmegaMean->Eval(casc.pt()) < peakNsigma * fOmegaWidth->Eval(casc.pt()))) { - massRegOmega = 2; - } - if (casc.mOmega() > fOmegaMean->Eval(casc.pt()) + peakNsigma * fOmegaWidth->Eval(casc.pt()) && casc.mOmega() < fOmegaMean->Eval(casc.pt()) + backgroundNsigma * fOmegaWidth->Eval(casc.pt())) { - massRegOmega = 3; - } - if (casc.mOmega() < fOmegaMean->Eval(casc.pt()) - peakNsigma * fOmegaWidth->Eval(casc.pt()) && casc.mOmega() > fOmegaMean->Eval(casc.pt()) - backgroundNsigma * fOmegaWidth->Eval(casc.pt())) { - massRegOmega = 1; - } - if (casc.mOmega() > fOmegaMean->Eval(casc.pt()) + backgroundNsigma * fOmegaWidth->Eval(casc.pt())) { - massRegOmega = 4; - } - if (casc.mOmega() < fOmegaMean->Eval(casc.pt()) - backgroundNsigma * fOmegaWidth->Eval(casc.pt())) { - massRegOmega = 0; - } - - if (compatibleXiMinus) + int compatibleXiMinus = 0; + int compatibleXiPlus = 0; + int compatibleOmegaMinus = 0; + int compatibleOmegaPlus = 0; + + if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() < 0) + bitset(compatibleXiMinus, 0); + if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() < 0) + bitset(compatibleXiMinus, 1); + if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() < 0) + bitset(compatibleXiMinus, 2); + + if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() > 0) + bitset(compatibleXiPlus, 0); + if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() > 0) + bitset(compatibleXiPlus, 1); + if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && TMath::Abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() > 0) + bitset(compatibleXiPlus, 2); + + if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() < 0) + bitset(compatibleOmegaMinus, 0); + if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() < 0) + bitset(compatibleOmegaMinus, 1); + if (TMath::Abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && TMath::Abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() < 0) + bitset(compatibleOmegaMinus, 2); + + if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() > 0) + bitset(compatibleOmegaPlus, 0); + if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() > 0) + bitset(compatibleOmegaPlus, 1); + if (TMath::Abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && TMath::Abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && TMath::Abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() > 0) + bitset(compatibleOmegaPlus, 2); + + float massNSigmaXi = (casc.mXi() - fXiMean->Eval(casc.pt())) / (fXiWidth->Eval(casc.pt()) + 1e-6); + float massNSigmaOmega = (casc.mOmega() - fOmegaMean->Eval(casc.pt())) / (fOmegaWidth->Eval(casc.pt()) + 1e-6); + + if (compatibleXiMinus && (!doTrueSelectionInMass || (origCascadeEntry.isTrueXiMinus() && origCascadeEntry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassXiMinus"), casc.pt(), casc.mXi(), collision.centFT0M()); - if (compatibleXiPlus) + if (compatibleXiPlus && (!doTrueSelectionInMass || (origCascadeEntry.isTrueXiPlus() && origCascadeEntry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassXiPlus"), casc.pt(), casc.mXi(), collision.centFT0M()); - if (compatibleOmegaMinus) + if (compatibleOmegaMinus && (!doTrueSelectionInMass || (origCascadeEntry.isTrueOmegaMinus() && origCascadeEntry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassOmegaMinus"), casc.pt(), casc.mOmega(), collision.centFT0M()); - if (compatibleOmegaPlus) + if (compatibleOmegaPlus && (!doTrueSelectionInMass || (origCascadeEntry.isTrueOmegaPlus() && origCascadeEntry.isPhysicalPrimary()))) histos.fill(HIST("h3dMassOmegaPlus"), casc.pt(), casc.mOmega(), collision.centFT0M()); if (!fillTableOnlyWithCompatible || ( // start major condition check - ((compatibleXiMinus || compatibleXiPlus) && massRegXi > 0 && massRegXi < 4) || - ((compatibleOmegaMinus || compatibleOmegaPlus) && massRegOmega > 0 && massRegOmega < 4)) // end major condition check + ((compatibleXiMinus > 0 || compatibleXiPlus > 0) && std::abs(massNSigmaXi) < maxMassNSigma) || + ((compatibleOmegaMinus > 0 || compatibleOmegaPlus > 0) && std::abs(massNSigmaOmega) < maxMassNSigma)) // end major condition check ) { assocCascades(casc.collisionId(), casc.globalIndex(), compatibleXiMinus, compatibleXiPlus, compatibleOmegaMinus, compatibleOmegaPlus, origCascadeEntry.isTrueXiMinus(), origCascadeEntry.isTrueXiPlus(), origCascadeEntry.isTrueOmegaMinus(), origCascadeEntry.isTrueOmegaPlus(), - massRegXi, massRegOmega); + origCascadeEntry.isPhysicalPrimary(), + massNSigmaXi, massNSigmaOmega); } } } PROCESS_SWITCH(hstrangecorrelationfilter, processTriggers, "Produce trigger tables", true); + PROCESS_SWITCH(hstrangecorrelationfilter, processTriggersMC, "Produce trigger tables for MC", false); PROCESS_SWITCH(hstrangecorrelationfilter, processV0s, "Produce associated V0 tables", true); PROCESS_SWITCH(hstrangecorrelationfilter, processAssocPions, "Produce associated Pion tables", true); PROCESS_SWITCH(hstrangecorrelationfilter, processCascades, "Produce associated cascade tables", true); diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx index 18d854aa1f6..2e1fb20f689 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx @@ -1182,16 +1182,11 @@ struct lambdakzeroBuilder { if (V0.v0Type() > 1 && !storePhotonCandidates) continue; - if (mlConfigurations.calculateK0ShortScores || - mlConfigurations.calculateLambdaScores || - mlConfigurations.calculateAntiLambdaScores || - mlConfigurations.calculateGammaScores) { - // at this stage, the candidate is interesting -> populate table - gammaMLSelections(gammaScore); - lambdaMLSelections(lambdaScore); - antiLambdaMLSelections(antiLambdaScore); - k0ShortMLSelections(k0ShortScore); - } + // at this stage, the candidate is interesting -> populate table + gammaMLSelections(gammaScore); + lambdaMLSelections(lambdaScore); + antiLambdaMLSelections(antiLambdaScore); + k0ShortMLSelections(k0ShortScore); // populates the various tables for analysis statisticsRegistry.v0stats[kCountStandardV0]++; @@ -1377,7 +1372,7 @@ struct lambdakzeroPreselector { Configurable minITSCluITSOnly{"minITSCluITSOnly", 0, "minimum number of ITS clusters to ask for if daughter track does not have TPC"}; // for bit-packed maps - std::vector selectionMask; + std::vector selectionMask; enum v0bit { bitInteresting = 0, bitTrackQuality, bitTrueGamma, @@ -1386,6 +1381,7 @@ struct lambdakzeroPreselector { bitTrueAntiLambda, bitTrueHypertriton, bitTrueAntiHypertriton, + bitPhysicalPrimary, bitdEdxGamma, bitdEdxK0Short, bitdEdxLambda, @@ -1419,7 +1415,7 @@ struct lambdakzeroPreselector { //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* /// function to check track quality template - void checkTrackQuality(TV0Object const& lV0Candidate, uint16_t& maskElement, bool passdEdx = false) + void checkTrackQuality(TV0Object const& lV0Candidate, uint32_t& maskElement, bool passdEdx = false) { auto lNegTrack = lV0Candidate.template negTrack_as(); auto lPosTrack = lV0Candidate.template posTrack_as(); @@ -1462,9 +1458,10 @@ struct lambdakzeroPreselector { //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* /// function to check PDG association template - void checkPDG(TV0Object const& lV0Candidate, uint16_t& maskElement) + void checkPDG(TV0Object const& lV0Candidate, uint32_t& maskElement) { int lPDG = -1; + bool physicalPrimary = false; auto lNegTrack = lV0Candidate.template negTrack_as(); auto lPosTrack = lV0Candidate.template posTrack_as(); @@ -1478,6 +1475,7 @@ struct lambdakzeroPreselector { for (auto& lPosMother : lMCPosTrack.template mothers_as()) { if (lNegMother.globalIndex() == lPosMother.globalIndex() && (!dIfMCselectPhysicalPrimary || lNegMother.isPhysicalPrimary())) { lPDG = lNegMother.pdgCode(); + physicalPrimary = lNegMother.isPhysicalPrimary(); // additionally check PDG of the mother particle if requested if (dIfMCselectV0MotherPDG != 0) { @@ -1507,10 +1505,12 @@ struct lambdakzeroPreselector { bitset(maskElement, bitTrueHypertriton); if (lPDG == -1010010030) bitset(maskElement, bitTrueAntiHypertriton); + if (physicalPrimary) + bitset(maskElement, bitPhysicalPrimary); } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* template - void checkdEdx(TV0Object const& lV0Candidate, uint16_t& maskElement) + void checkdEdx(TV0Object const& lV0Candidate, uint32_t& maskElement) { auto lNegTrack = lV0Candidate.template negTrack_as(); auto lPosTrack = lV0Candidate.template posTrack_as(); @@ -1593,7 +1593,8 @@ struct lambdakzeroPreselector { } v0tags(validV0, bitcheck(selectionMask[ii], bitTrueGamma), bitcheck(selectionMask[ii], bitTrueK0Short), bitcheck(selectionMask[ii], bitTrueLambda), - bitcheck(selectionMask[ii], bitTrueAntiLambda), bitcheck(selectionMask[ii], bitTrueHypertriton), bitcheck(selectionMask[ii], bitTrueAntiHypertriton), + bitcheck(selectionMask[ii], bitTrueAntiLambda), + bitcheck(selectionMask[ii], bitTrueHypertriton), bitcheck(selectionMask[ii], bitTrueAntiHypertriton), bitcheck(selectionMask[ii], bitPhysicalPrimary), bitcheck(selectionMask[ii], bitdEdxGamma), bitcheck(selectionMask[ii], bitdEdxK0Short), bitcheck(selectionMask[ii], bitdEdxLambda), bitcheck(selectionMask[ii], bitdEdxAntiLambda), bitcheck(selectionMask[ii], bitdEdxHypertriton), bitcheck(selectionMask[ii], bitdEdxAntiHypertriton), bitcheck(selectionMask[ii], bitUsedInCascade), bitcheck(selectionMask[ii], bitUsedInTrackedCascade)); diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx index c1085762b6f..60d331ea61d 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx @@ -270,11 +270,11 @@ struct lambdakzerofinder { int collisionIndex = -1; // float getDCAtoPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ){ for (auto const& collision : collisions) { - float thisDCA = TMath::Abs(getDCAtoPV(vtx[0], vtx[1], vtx[2], pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2], collision.posX(), collision.posY(), collision.posY())); + float thisDCA = TMath::Abs(getDCAtoPV(vtx[0], vtx[1], vtx[2], pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2], collision.posX(), collision.posY(), collision.posZ())); if (thisDCA < smallestDCA) { collisionIndex = collision.globalIndex(); smallestDCA = thisDCA; - cosPA = RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posY()}, array{vtx[0], vtx[1], vtx[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); + cosPA = RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, array{vtx[0], vtx[1], vtx[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); } } if (smallestDCA > maxV0DCAtoPV) diff --git a/PWGLF/TableProducer/Strangeness/lambdakzeromcbuilder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzeromcbuilder.cxx index 8fe57bc144f..a2324681040 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzeromcbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzeromcbuilder.cxx @@ -77,22 +77,40 @@ struct lambdakzeromcbuilder { h->GetXaxis()->SetBinLabel(2, "V0MCCores population"); h->GetXaxis()->SetBinLabel(3, "x check: duplicates"); h->GetXaxis()->SetBinLabel(4, "x check: unique"); + + auto hK0s = histos.add("hStatisticsK0s", "hBuildingStatisticsK0s", kTH1F, {{3, -0.5, 2.5f}}); + hK0s->GetXaxis()->SetBinLabel(1, "MC associated to reco."); + hK0s->GetXaxis()->SetBinLabel(2, "Not originating from decay"); + hK0s->GetXaxis()->SetBinLabel(3, "MC with un-recoed V0"); + + auto hLambda = histos.add("hStatisticsLambda", "hBuildingStatisticsLambda", kTH1F, {{3, -0.5, 2.5f}}); + hLambda->GetXaxis()->SetBinLabel(1, "MC associated to reco."); + hLambda->GetXaxis()->SetBinLabel(2, "Not originating from decay"); + hLambda->GetXaxis()->SetBinLabel(3, "MC with un-recoed V0"); + + auto hAlambda = histos.add("hStatisticsAlambda", "hBuildingStatisticsAlambda", kTH1F, {{3, -0.5, 2.5f}}); + hAlambda->GetXaxis()->SetBinLabel(1, "MC associated to reco."); + hAlambda->GetXaxis()->SetBinLabel(2, "Not originating from decay"); + hAlambda->GetXaxis()->SetBinLabel(3, "MC with un-recoed V0"); } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* // Helper struct to contain V0MCCore information prior to filling struct mcV0info { - int label; - int motherLabel; - int pdgCode; - int pdgCodeMother; - int pdgCodePositive; - int pdgCodeNegative; - int mcCollision; - bool isPhysicalPrimary; + int label = -1; + int motherLabel = -1; + int pdgCode = 0; + int pdgCodeMother = 0; + int pdgCodePositive = 0; + int pdgCodeNegative = 0; + int mcCollision = -1; + bool isPhysicalPrimary = false; + int processPositive = -1; + int processNegative = -1; std::array xyz; std::array posP; std::array negP; + std::array momentum; uint64_t packedMcParticleIndices; }; mcV0info thisInfo; @@ -124,17 +142,21 @@ struct lambdakzeromcbuilder { thisInfo.xyz[0] = thisInfo.xyz[1] = thisInfo.xyz[2] = 0.0f; thisInfo.posP[0] = thisInfo.posP[1] = thisInfo.posP[2] = 0.0f; thisInfo.negP[0] = thisInfo.negP[1] = thisInfo.negP[2] = 0.0f; + thisInfo.momentum[0] = thisInfo.momentum[1] = thisInfo.momentum[2] = 0.0f; auto lNegTrack = v0.negTrack_as(); auto lPosTrack = v0.posTrack_as(); // Association check // There might be smarter ways of doing this in the future if (lNegTrack.has_mcParticle() && lPosTrack.has_mcParticle()) { - thisInfo.packedMcParticleIndices = combineProngIndices(lPosTrack.mcParticleId(), lNegTrack.mcParticleId()); auto lMCNegTrack = lNegTrack.mcParticle_as(); auto lMCPosTrack = lPosTrack.mcParticle_as(); + + thisInfo.packedMcParticleIndices = combineProngIndices(lPosTrack.mcParticleId(), lNegTrack.mcParticleId()); thisInfo.pdgCodePositive = lMCPosTrack.pdgCode(); thisInfo.pdgCodeNegative = lMCNegTrack.pdgCode(); + thisInfo.processPositive = lMCPosTrack.getProcess(); + thisInfo.processNegative = lMCNegTrack.getProcess(); thisInfo.posP[0] = lMCPosTrack.px(); thisInfo.posP[1] = lMCPosTrack.py(); thisInfo.posP[2] = lMCPosTrack.pz(); @@ -146,17 +168,50 @@ struct lambdakzeromcbuilder { for (auto& lPosMother : lMCPosTrack.mothers_as()) { if (lNegMother.globalIndex() == lPosMother.globalIndex()) { thisInfo.label = lNegMother.globalIndex(); + thisInfo.xyz[0] = lMCPosTrack.vx(); + thisInfo.xyz[1] = lMCPosTrack.vy(); + thisInfo.xyz[2] = lMCPosTrack.vz(); + + // MC pos. and neg. daughters are the same! Looking for replacement... + if (lMCPosTrack.globalIndex() == lMCNegTrack.globalIndex()) { + auto const& daughters = lNegMother.daughters_as(); + for (auto& ldau : daughters) { + // check if the candidate originate from a decay + // if not, this is not a suitable candidate for one of the decay daughters + if (ldau.getProcess() != 4) // see TMCProcess.h + continue; + + if (lMCPosTrack.pdgCode() < 0 && ldau.pdgCode() > 0) { // the positive track needs to be changed + thisInfo.pdgCodePositive = ldau.pdgCode(); + thisInfo.processPositive = ldau.getProcess(); + thisInfo.posP[0] = ldau.px(); + thisInfo.posP[1] = ldau.py(); + thisInfo.posP[2] = ldau.pz(); + thisInfo.xyz[0] = ldau.vx(); + thisInfo.xyz[1] = ldau.vy(); + thisInfo.xyz[2] = ldau.vz(); + } + if (lMCNegTrack.pdgCode() > 0 && ldau.pdgCode() < 0) { // the negative track needs to be changed + thisInfo.pdgCodeNegative = ldau.pdgCode(); + thisInfo.processNegative = ldau.getProcess(); + thisInfo.negP[0] = ldau.px(); + thisInfo.negP[1] = ldau.py(); + thisInfo.negP[2] = ldau.pz(); + } + } + } if (lNegMother.has_mcCollision()) { thisInfo.mcCollision = lNegMother.mcCollisionId(); // save this reference, please } // acquire information - thisInfo.xyz[0] = lMCPosTrack.vx(); - thisInfo.xyz[1] = lMCPosTrack.vy(); - thisInfo.xyz[2] = lMCPosTrack.vz(); thisInfo.pdgCode = lNegMother.pdgCode(); thisInfo.isPhysicalPrimary = lNegMother.isPhysicalPrimary(); + thisInfo.momentum[0] = lNegMother.px(); + thisInfo.momentum[1] = lNegMother.py(); + thisInfo.momentum[2] = lNegMother.pz(); + if (lNegMother.has_mothers()) { for (auto& lNegGrandMother : lNegMother.mothers_as()) { thisInfo.pdgCodeMother = lNegGrandMother.pdgCode(); @@ -173,8 +228,8 @@ struct lambdakzeromcbuilder { thisInfo.label, thisInfo.motherLabel); // Mark mcParticle as recoed (no searching necessary afterwards) - if (thisInfo.motherLabel > -1) { - mcParticleIsReco[thisInfo.motherLabel] = true; + if (thisInfo.label > -1) { + mcParticleIsReco[thisInfo.label] = true; } // ---] Symmetric populate [--- @@ -187,7 +242,8 @@ struct lambdakzeromcbuilder { thisInfo.pdgCodeMother, thisInfo.pdgCodePositive, thisInfo.pdgCodeNegative, thisInfo.isPhysicalPrimary, thisInfo.xyz[0], thisInfo.xyz[1], thisInfo.xyz[2], thisInfo.posP[0], thisInfo.posP[1], thisInfo.posP[2], - thisInfo.negP[0], thisInfo.negP[1], thisInfo.negP[2]); + thisInfo.negP[0], thisInfo.negP[1], thisInfo.negP[2], + thisInfo.momentum[0], thisInfo.momentum[1], thisInfo.momentum[2]); v0mccollref(thisInfo.mcCollision); // n.b. placing the interlink index here allows for the writing of @@ -204,17 +260,45 @@ struct lambdakzeromcbuilder { // step 1: check if this element is already provided in the table // using the packedIndices variable calculated above for (uint32_t ii = 0; ii < mcV0infos.size(); ii++) { - if (thisInfo.packedMcParticleIndices == mcV0infos[ii].packedMcParticleIndices && mcV0infos[ii].packedMcParticleIndices > 0) { + if (thisInfo.label == mcV0infos[ii].label && mcV0infos[ii].label > -1) { thisV0MCCoreIndex = ii; histos.fill(HIST("hBuildingStatistics"), 2.0f); // found break; // this exists already in list } } - if (thisV0MCCoreIndex < 0) { + if (thisV0MCCoreIndex < 0 && thisInfo.label > -1) { // this V0MCCore does not exist yet. Create it and reference it histos.fill(HIST("hBuildingStatistics"), 3.0f); // new thisV0MCCoreIndex = mcV0infos.size(); mcV0infos.push_back(thisInfo); + + // For bookkeeping + if (thisInfo.label > -1 && thisInfo.isPhysicalPrimary) { + float ymc = 1e3; + if (thisInfo.pdgCode == 310) + ymc = RecoDecay::y(std::array{thisInfo.posP[0] + thisInfo.negP[0], thisInfo.posP[1] + thisInfo.negP[1], thisInfo.posP[2] + thisInfo.negP[2]}, o2::constants::physics::MassKaonNeutral); + else if (TMath::Abs(thisInfo.pdgCode) == 3122) + ymc = RecoDecay::y(std::array{thisInfo.posP[0] + thisInfo.negP[0], thisInfo.posP[1] + thisInfo.negP[1], thisInfo.posP[2] + thisInfo.negP[2]}, o2::constants::physics::MassLambda); + + if (thisInfo.pdgCode == 310 && TMath::Abs(ymc) < rapidityWindow) { + histos.fill(HIST("hStatisticsK0s"), 0.0f); // found + if (thisInfo.processPositive != 4 || thisInfo.processNegative != 4) { + histos.fill(HIST("hStatisticsK0s"), 1.0f); // Not originating from decay + } + } + if (thisInfo.pdgCode == 3122 && TMath::Abs(ymc) < rapidityWindow) { + histos.fill(HIST("hStatisticsLambda"), 0.0f); // found + if (thisInfo.processPositive != 4 || thisInfo.processNegative != 4) { + histos.fill(HIST("hStatisticsLambda"), 1.0f); // Not originating from decay + } + } + if (thisInfo.pdgCode == -3122 && TMath::Abs(ymc) < rapidityWindow) { + histos.fill(HIST("hStatisticsAlambda"), 0.0f); // found + if (thisInfo.processPositive != 4 || thisInfo.processNegative != 4) { + histos.fill(HIST("hStatisticsAlambda"), 1.0f); // Not originating from decay + } + } + } } v0CoreMCLabels(thisV0MCCoreIndex); // interlink index } @@ -228,13 +312,14 @@ struct lambdakzeromcbuilder { thisInfo.label = -1; thisInfo.motherLabel = -1; thisInfo.pdgCode = 0; - thisInfo.pdgCodeMother = 0; - thisInfo.pdgCodePositive = 0; - thisInfo.pdgCodeNegative = 0; + thisInfo.pdgCodeMother = -1; + thisInfo.pdgCodePositive = -1; + thisInfo.pdgCodeNegative = -1; thisInfo.mcCollision = -1; thisInfo.xyz[0] = thisInfo.xyz[1] = thisInfo.xyz[2] = 0.0f; thisInfo.posP[0] = thisInfo.posP[1] = thisInfo.posP[2] = 0.0f; thisInfo.negP[0] = thisInfo.negP[1] = thisInfo.negP[2] = 0.0f; + thisInfo.momentum[0] = thisInfo.momentum[1] = thisInfo.momentum[2] = 0.0f; if (mcParticleIsReco[mcParticle.globalIndex()] == true) continue; // skip if already created in list @@ -249,16 +334,65 @@ struct lambdakzeromcbuilder { (addGeneratedGamma && mcParticle.pdgCode() == 22)) { thisInfo.pdgCode = mcParticle.pdgCode(); thisInfo.isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + thisInfo.label = mcParticle.globalIndex(); if (mcParticle.has_mcCollision()) { thisInfo.mcCollision = mcParticle.mcCollisionId(); // save this reference, please } - // guarantee compressibility: keep momentum entirely in the positive prong - // WARNING: THIS IS AS ARBITRARY AS IT GETS but should be ok - thisInfo.posP[0] = mcParticle.px(); - thisInfo.posP[1] = mcParticle.py(); - thisInfo.posP[2] = mcParticle.pz(); + // + thisInfo.momentum[0] = mcParticle.px(); + thisInfo.momentum[1] = mcParticle.py(); + thisInfo.momentum[2] = mcParticle.pz(); + + if (mcParticle.has_mothers()) { + auto const& mother = mcParticle.mothers_first_as(); + thisInfo.pdgCodeMother = mother.pdgCode(); + thisInfo.motherLabel = mother.globalIndex(); + } + if (mcParticle.has_daughters()) { + auto const& daughters = mcParticle.daughters_as(); + + for (auto& dau : daughters) { + if (dau.getProcess() != 4) + continue; + + if (dau.pdgCode() > 0) { + thisInfo.pdgCodePositive = dau.pdgCode(); + thisInfo.processPositive = dau.getProcess(); + thisInfo.posP[0] = dau.px(); + thisInfo.posP[1] = dau.py(); + thisInfo.posP[2] = dau.pz(); + thisInfo.xyz[0] = dau.vx(); + thisInfo.xyz[1] = dau.vy(); + thisInfo.xyz[2] = dau.vz(); + } + if (dau.pdgCode() < 0) { + thisInfo.pdgCodeNegative = dau.pdgCode(); + thisInfo.processNegative = dau.getProcess(); + thisInfo.negP[0] = dau.px(); + thisInfo.negP[1] = dau.py(); + thisInfo.negP[2] = dau.pz(); + } + } + } + + // For bookkeeping + float ymc = 1e3; + if (mcParticle.pdgCode() == 310) + ymc = RecoDecay::y(std::array{thisInfo.posP[0] + thisInfo.negP[0], thisInfo.posP[1] + thisInfo.negP[0], thisInfo.posP[2] + thisInfo.negP[2]}, o2::constants::physics::MassKaonNeutral); + else if (TMath::Abs(mcParticle.pdgCode()) == 3122) + ymc = RecoDecay::y(std::array{thisInfo.posP[0] + thisInfo.negP[0], thisInfo.posP[1] + thisInfo.negP[0], thisInfo.posP[2] + thisInfo.negP[2]}, o2::constants::physics::MassLambda); + + if (mcParticle.pdgCode() == 310 && mcParticle.isPhysicalPrimary() && TMath::Abs(ymc) < rapidityWindow) { + histos.fill(HIST("hStatisticsK0s"), 2.0f); // found + } + if (mcParticle.pdgCode() == 3122 && mcParticle.isPhysicalPrimary() && TMath::Abs(ymc) < rapidityWindow) { + histos.fill(HIST("hStatisticsLambda"), 2.0f); // found + } + if (mcParticle.pdgCode() == -3122 && mcParticle.isPhysicalPrimary() && TMath::Abs(ymc) < rapidityWindow) { + histos.fill(HIST("hStatisticsAlambda"), 2.0f); // found + } // if I got here, it means this MC particle was not recoed and is of interest. Add it please mcV0infos.push_back(thisInfo); @@ -271,8 +405,9 @@ struct lambdakzeromcbuilder { info.pdgCodeMother, info.pdgCodePositive, info.pdgCodeNegative, info.isPhysicalPrimary, info.xyz[0], info.xyz[1], info.xyz[2], info.posP[0], info.posP[1], info.posP[2], - info.negP[0], info.negP[1], info.negP[2]); - v0mccollref(thisInfo.mcCollision); + info.negP[0], info.negP[1], info.negP[2], + info.momentum[0], info.momentum[1], info.momentum[2]); + v0mccollref(info.mcCollision); } } diff --git a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx index 351eac60497..c651eb31007 100644 --- a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx @@ -58,6 +58,7 @@ using TracksWithExtra = soa::Join; using FullTracksExtIUTOF = soa::Join; using FullCollisions = soa::Join; +using UDCollisionsFull = soa::Join; // simple bit checkers #define bitset(var, nbit) ((var) |= (1 << (nbit))) @@ -73,8 +74,7 @@ struct strangederivedbuilder { Produces strangeMCColl; // characterises collisions / MC Produces strangeMCMults; // characterises collisions / MC mults Produces strangeCents; // characterises collisions / centrality - Produces strangeRawCents; // characterises collisions / centrality - Produces strangeEvSels; // characterises collisions / sel8 selection + Produces strangeEvSels; // characterises collisions / centrality / sel8 selection Produces strangeStamps; // provides timestamps, run numbers Produces v0collref; // references collisions from V0s Produces casccollref; // references collisions from cascades @@ -167,12 +167,23 @@ struct strangederivedbuilder { Configurable fillRawFT0A{"fillRawFT0A", false, "Fill raw FT0A information for debug"}; Configurable fillRawFT0C{"fillRawFT0C", true, "Fill raw FT0C information for debug"}; Configurable fillRawFV0A{"fillRawFV0A", false, "Fill raw FV0A information for debug"}; + Configurable fillRawFDDA{"fillRawFDDA", false, "Fill raw FDDA information for debug"}; + Configurable fillRawFDDC{"fillRawFDDC", false, "Fill raw FDDC information for debug"}; Configurable fillRawZDC{"fillRawZDC", false, "Fill raw ZDC information for debug"}; Configurable fillRawNTracksEta1{"fillRawNTracksEta1", true, "Fill raw NTracks |eta|<1 information for debug"}; Configurable fillRawNTracksForCorrelation{"fillRawNTracksForCorrelation", true, "Fill raw NTracks for correlation cuts"}; Configurable fillTOFInformation{"fillTOFInformation", true, "Fill Daughter Track TOF information"}; Configurable qaCentrality{"qaCentrality", false, "qa centrality flag: check base raw values"}; + struct : ConfigurableGroup { + ConfigurableAxis axisFT0A{"FT0Aamplitude", {100, 0.0f, 2000.0f}, "FT0Aamplitude"}; + ConfigurableAxis axisFT0C{"FT0Camplitude", {100, 0.0f, 2000.0f}, "FT0Camplitude"}; + ConfigurableAxis axisFV0A{"FV0Aamplitude", {100, 0.0f, 2000.0f}, "FV0Aamplitude"}; + ConfigurableAxis axisFDDA{"FDDAamplitude", {100, 0.0f, 2000.0f}, "FDDAamplitude"}; + ConfigurableAxis axisFDDC{"FDDCamplitude", {100, 0.0f, 2000.0f}, "FDDCamplitude"}; + ConfigurableAxis axisZNA{"ZNAamplitude", {100, 0.0f, 250.0f}, "ZNAamplitude"}; + ConfigurableAxis axisZNC{"ZNCamplitude", {100, 0.0f, 250.0f}, "ZNCamplitude"}; + } axisDetectors; // For manual sliceBy Preslice V0perCollision = o2::aod::v0data::collisionId; @@ -180,6 +191,7 @@ struct strangederivedbuilder { Preslice KFCascperCollision = o2::aod::cascdata::collisionId; Preslice TraCascperCollision = o2::aod::cascdata::collisionId; Preslice mcParticlePerMcCollision = o2::aod::mcparticle::mcCollisionId; + Preslice udCollisionsPerCollision = o2::aod::udcollision::collisionId; std::vector genK0Short; std::vector genLambda; @@ -211,8 +223,8 @@ struct strangederivedbuilder { // Creation of histograms: MC generated for (Int_t i = 0; i < nSpecies; i++) { - histos.add(Form("hGen%s", particleNames[i].data()), Form("hGen%s", particleNames[i].data()), kTH1D, {axisPt}); - histos.add(Form("h2dGen%s", particleNames[i].data()), Form("h2dGen%s", particleNames[i].data()), kTH2D, {axisCentrality, axisPt}); + histos.add(Form("hGenerated%s", particleNames[i].data()), Form("hGenerated%s", particleNames[i].data()), kTH1D, {axisPt}); + histos.add(Form("h2dGenerated%s", particleNames[i].data()), Form("h2dGenerated%s", particleNames[i].data()), kTH2D, {axisCentrality, axisPt}); } histos.add("h2dNVerticesVsCentrality", "h2dNVerticesVsCentrality", kTH2D, {axisCentrality, axisNVertices}); @@ -230,6 +242,14 @@ struct strangederivedbuilder { // for QA and test purposes auto hRawCentrality = histos.add("hRawCentrality", "hRawCentrality", kTH1F, {axisRawCentrality}); + auto hFT0AMultVsFT0AUD = histos.add("hFT0AMultVsFT0AUD", "hFT0AMultVsFT0AUD; FT0-A Mult; FT0-A UD", kTH2F, {axisDetectors.axisFT0A, axisDetectors.axisFT0A}); + auto hFT0CMultVsFT0CUD = histos.add("hFT0CMultVsFT0CUD", "hFT0CMultVsFT0CUD; FT0-C Mult; FT0-C UD", kTH2F, {axisDetectors.axisFT0C, axisDetectors.axisFT0C}); + auto hFV0AMultVsFV0AUD = histos.add("hFV0AMultVsFV0AUD", "hFV0AMultVsFV0AUD; FV0-A Mult; FV0-A UD", kTH2F, {axisDetectors.axisFV0A, axisDetectors.axisFV0A}); + auto hFDDAMultVsFDDAUD = histos.add("hFDDAMultVsFDDAUD", "hFDDAMultVsFDDAUD; FDD-A Mult; FDD-A UD", kTH2F, {axisDetectors.axisFDDA, axisDetectors.axisFDDA}); + auto hFDDCMultVsFDDCUD = histos.add("hFDDCMultVsFDDCUD", "hFDDCMultVsFDDCUD; FDD-C Mult; FDD-C UD", kTH2F, {axisDetectors.axisFDDC, axisDetectors.axisFDDC}); + auto hZNAMultVsZNAUD = histos.add("hZNAMultVsZNAUD", "hZNAMultVsZNAUD; ZNA Mult; ZNA UD", kTH2F, {axisDetectors.axisZNA, axisDetectors.axisZNA}); + auto hZNCMultVsZNCUD = histos.add("hZNCMultVsZNCUD", "hZNCMultVsZNCUD; ZNC Mult; ZNC UD", kTH2F, {axisDetectors.axisZNC, axisDetectors.axisZNC}); + for (int ii = 1; ii < 101; ii++) { float value = 100.5f - static_cast(ii); hRawCentrality->SetBinContent(ii, value); @@ -237,7 +257,7 @@ struct strangederivedbuilder { if (doprocessBinnedGenerated) { // reserve space for generated vectors if that process enabled - auto hBinFinder = histos.get(HIST("h2dGenK0Short")); + auto hBinFinder = histos.get(HIST("h2dGeneratedK0Short")); LOGF(info, "Binned generated processing enabled. Initialising with %i elements...", hBinFinder->GetNcells()); genK0Short.resize(hBinFinder->GetNcells(), 0); genLambda.resize(hBinFinder->GetNcells(), 0); @@ -250,46 +270,76 @@ struct strangederivedbuilder { } } - void processCollisionsV0sOnly(soa::Join const& collisions, aod::V0Datas const& V0s, aod::BCsWithTimestamps const&) + void processCollisionsV0sOnly(soa::Join const& collisions, aod::V0Datas const& V0s, aod::BCsWithTimestamps const& /*bcs*/, UDCollisionsFull const& udCollisions) { for (const auto& collision : collisions) { const uint64_t collIdx = collision.globalIndex(); auto V0Table_thisColl = V0s.sliceBy(V0perCollision, collIdx); bool strange = V0Table_thisColl.size() > 0; + + auto bc = collision.bc_as(); + + int gapSide = -1; + float totalFT0AmplitudeA = -999; + float totalFT0AmplitudeC = -999; + float totalFV0AmplitudeA = -999; + float totalFDDAmplitudeA = -999; + float totalFDDAmplitudeC = -999; + float energyCommonZNA = -999; + float energyCommonZNC = -999; + if (udCollisions.size() > 0) { // check that the UD collision table is not empty + auto udCollision = udCollisions.sliceBy(udCollisionsPerCollision, collIdx); + if (udCollision.size() == 1) { // check that the slicing provide a unique UD collision + for (auto& udColl : udCollision) { + gapSide = udColl.gapSide(); + totalFT0AmplitudeA = udColl.totalFT0AmplitudeA(); + totalFT0AmplitudeC = udColl.totalFT0AmplitudeC(); + totalFV0AmplitudeA = udColl.totalFV0AmplitudeA(); + totalFDDAmplitudeA = udColl.totalFDDAmplitudeA(); + totalFDDAmplitudeC = udColl.totalFDDAmplitudeC(); + energyCommonZNA = udColl.energyCommonZNA(); + energyCommonZNC = udColl.energyCommonZNC(); + } + } + } + // casc table sliced if (strange || fillEmptyCollisions) { strangeColl(collision.posX(), collision.posY(), collision.posZ()); strangeCents(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centFV0A()); - strangeEvSels(collision.sel8(), collision.selection_raw()); - auto bc = collision.bc_as(); + strangeEvSels(collision.sel8(), collision.selection_raw(), + collision.multFT0A() * static_cast(fillRawFT0A), + collision.multFT0C() * static_cast(fillRawFT0C), + collision.multFV0A() * static_cast(fillRawFV0A), + collision.multFDDA() * static_cast(fillRawFDDA), + collision.multFDDC() * static_cast(fillRawFDDC), + collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), + collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), + collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), + collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), + collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), + collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), + collision.multZNA() * static_cast(fillRawZDC), + collision.multZNC() * static_cast(fillRawZDC), + collision.multZEM1() * static_cast(fillRawZDC), + collision.multZEM2() * static_cast(fillRawZDC), + collision.multZPA() * static_cast(fillRawZDC), + collision.multZPC() * static_cast(fillRawZDC), + collision.trackOccupancyInTimeRange(), + // UPC info + gapSide, + totalFT0AmplitudeA, totalFT0AmplitudeC, totalFV0AmplitudeA, + totalFDDAmplitudeA, totalFDDAmplitudeC, + energyCommonZNA, energyCommonZNC); strangeStamps(bc.runNumber(), bc.timestamp()); - - if (fillRawFT0C || fillRawFT0C || fillRawFV0A || fillRawNTracksEta1 || fillRawZDC) { - strangeRawCents(collision.multFT0A() * static_cast(fillRawFT0A), - collision.multFT0C() * static_cast(fillRawFT0C), - collision.multFV0A() * static_cast(fillRawFV0A), - collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), - collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multZNA() * static_cast(fillRawZDC), - collision.multZNC() * static_cast(fillRawZDC), - collision.multZEM1() * static_cast(fillRawZDC), - collision.multZEM2() * static_cast(fillRawZDC), - collision.multZPA() * static_cast(fillRawZDC), - collision.multZPC() * static_cast(fillRawZDC), - collision.trackOccupancyInTimeRange()); - } } for (int i = 0; i < V0Table_thisColl.size(); i++) v0collref(strangeColl.lastIndex()); } } - void processCollisions(soa::Join const& collisions, aod::V0Datas const& V0s, aod::CascDatas const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, aod::BCsWithTimestamps const&) + void processCollisions(soa::Join const& collisions, aod::V0Datas const& V0s, aod::CascDatas const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, aod::BCsWithTimestamps const& /*bcs*/, UDCollisionsFull const& udCollisions) { // create collision indices beforehand std::vector V0CollIndices(V0s.size(), -1); // index -1: no collision @@ -314,33 +364,71 @@ struct strangederivedbuilder { CascTable_thisColl.size() > 0 || KFCascTable_thisColl.size() > 0 || TraCascTable_thisColl.size() > 0; + + auto bc = collision.bc_as(); + + int gapSide = -1; + float totalFT0AmplitudeA = -999; + float totalFT0AmplitudeC = -999; + float totalFV0AmplitudeA = -999; + float totalFDDAmplitudeA = -999; + float totalFDDAmplitudeC = -999; + float energyCommonZNA = -999; + float energyCommonZNC = -999; + if (udCollisions.size() > 0) { // check that the UD collision table is not empty + auto udCollision = udCollisions.sliceBy(udCollisionsPerCollision, collIdx); + if (udCollision.size() == 1) { // check that the slicing provide a unique UD collision + for (auto& udColl : udCollision) { + gapSide = udColl.gapSide(); + totalFT0AmplitudeA = udColl.totalFT0AmplitudeA(); + totalFT0AmplitudeC = udColl.totalFT0AmplitudeC(); + totalFV0AmplitudeA = udColl.totalFV0AmplitudeA(); + totalFDDAmplitudeA = udColl.totalFDDAmplitudeA(); + totalFDDAmplitudeC = udColl.totalFDDAmplitudeC(); + energyCommonZNA = udColl.energyCommonZNA(); + energyCommonZNC = udColl.energyCommonZNC(); + + histos.fill(HIST("hFT0AMultVsFT0AUD"), collision.multFT0A(), udColl.totalFT0AmplitudeA()); + histos.fill(HIST("hFT0CMultVsFT0CUD"), collision.multFT0C(), udColl.totalFT0AmplitudeC()); + histos.fill(HIST("hFV0AMultVsFV0AUD"), collision.multFV0A(), udColl.totalFV0AmplitudeA()); + histos.fill(HIST("hFDDAMultVsFDDAUD"), collision.multFDDA(), udColl.totalFDDAmplitudeA()); + histos.fill(HIST("hFDDCMultVsFDDCUD"), collision.multFDDC(), udColl.totalFDDAmplitudeC()); + histos.fill(HIST("hZNAMultVsZNAUD"), collision.multZNA(), udColl.energyCommonZNA()); + histos.fill(HIST("hZNCMultVsZNCUD"), collision.multZNC(), udColl.energyCommonZNC()); + } + } + } + // casc table sliced if (strange || fillEmptyCollisions) { strangeColl(collision.posX(), collision.posY(), collision.posZ()); strangeCents(collision.centFT0M(), collision.centFT0A(), centrality, collision.centFV0A()); - strangeEvSels(collision.sel8(), collision.selection_raw()); - auto bc = collision.bc_as(); + strangeEvSels(collision.sel8(), collision.selection_raw(), + collision.multFT0A() * static_cast(fillRawFT0A), + collision.multFT0C() * static_cast(fillRawFT0C), + collision.multFV0A() * static_cast(fillRawFV0A), + collision.multFDDA() * static_cast(fillRawFDDA), + collision.multFDDC() * static_cast(fillRawFDDC), + collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), + collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), + collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), + collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), + collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), + collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), + collision.multZNA() * static_cast(fillRawZDC), + collision.multZNC() * static_cast(fillRawZDC), + collision.multZEM1() * static_cast(fillRawZDC), + collision.multZEM2() * static_cast(fillRawZDC), + collision.multZPA() * static_cast(fillRawZDC), + collision.multZPC() * static_cast(fillRawZDC), + collision.trackOccupancyInTimeRange(), + // UPC info + gapSide, + totalFT0AmplitudeA, totalFT0AmplitudeC, totalFV0AmplitudeA, + totalFDDAmplitudeA, totalFDDAmplitudeC, + energyCommonZNA, energyCommonZNC); strangeStamps(bc.runNumber(), bc.timestamp()); - - if (fillRawFT0C || fillRawFT0C || fillRawFV0A || fillRawNTracksEta1 || fillRawZDC) { - strangeRawCents(collision.multFT0A() * static_cast(fillRawFT0A), - collision.multFT0C() * static_cast(fillRawFT0C), - collision.multFV0A() * static_cast(fillRawFV0A), - collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), - collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multZNA() * static_cast(fillRawZDC), - collision.multZNC() * static_cast(fillRawZDC), - collision.multZEM1() * static_cast(fillRawZDC), - collision.multZEM2() * static_cast(fillRawZDC), - collision.multZPA() * static_cast(fillRawZDC), - collision.multZPC() * static_cast(fillRawZDC), - collision.trackOccupancyInTimeRange()); - } } for (const auto& v0 : V0Table_thisColl) @@ -364,7 +452,7 @@ struct strangederivedbuilder { tracasccollref(TraCascadeCollIndices[casc.globalIndex()]); } - void processCollisionsMC(soa::Join const& collisions, soa::Join const& V0s, soa::Join const& V0MCCores, soa::Join const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, aod::BCsWithTimestamps const&, soa::Join const& mcCollisions, aod::McParticles const&) + void processCollisionsMC(soa::Join const& collisions, soa::Join const& V0s, soa::Join const& /*V0MCCores*/, soa::Join const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, aod::BCsWithTimestamps const& /*bcs*/, UDCollisionsFull const& udCollisions, soa::Join const& mcCollisions, aod::McParticles const&) { // create collision indices beforehand std::vector V0CollIndices(V0s.size(), -1); // index -1: no collision @@ -402,34 +490,72 @@ struct strangederivedbuilder { CascTable_thisColl.size() > 0 || KFCascTable_thisColl.size() > 0 || TraCascTable_thisColl.size() > 0; + + auto bc = collision.bc_as(); + + int gapSide = -1; + float totalFT0AmplitudeA = -999; + float totalFT0AmplitudeC = -999; + float totalFV0AmplitudeA = -999; + float totalFDDAmplitudeA = -999; + float totalFDDAmplitudeC = -999; + float energyCommonZNA = -999; + float energyCommonZNC = -999; + if (udCollisions.size() > 0) { // check that the UD collision table is not empty + auto udCollision = udCollisions.sliceBy(udCollisionsPerCollision, collIdx); + if (udCollision.size() == 1) { // check that the slicing provide a unique UD collision + for (auto& udColl : udCollision) { + gapSide = udColl.gapSide(); + totalFT0AmplitudeA = udColl.totalFT0AmplitudeA(); + totalFT0AmplitudeC = udColl.totalFT0AmplitudeC(); + totalFV0AmplitudeA = udColl.totalFV0AmplitudeA(); + totalFDDAmplitudeA = udColl.totalFDDAmplitudeA(); + totalFDDAmplitudeC = udColl.totalFDDAmplitudeC(); + energyCommonZNA = udColl.energyCommonZNA(); + energyCommonZNC = udColl.energyCommonZNC(); + + histos.fill(HIST("hFT0AMultVsFT0AUD"), collision.multFT0A(), udColl.totalFT0AmplitudeA()); + histos.fill(HIST("hFT0CMultVsFT0CUD"), collision.multFT0C(), udColl.totalFT0AmplitudeC()); + histos.fill(HIST("hFV0AMultVsFV0AUD"), collision.multFV0A(), udColl.totalFV0AmplitudeA()); + histos.fill(HIST("hFDDAMultVsFDDAUD"), collision.multFDDA(), udColl.totalFDDAmplitudeA()); + histos.fill(HIST("hFDDCMultVsFDDCUD"), collision.multFDDC(), udColl.totalFDDAmplitudeC()); + histos.fill(HIST("hZNAMultVsZNAUD"), collision.multZNA(), udColl.energyCommonZNA()); + histos.fill(HIST("hZNCMultVsZNCUD"), collision.multZNC(), udColl.energyCommonZNC()); + } + } + } + // casc table sliced if (strange || fillEmptyCollisions) { strangeColl(collision.posX(), collision.posY(), collision.posZ()); strangeCollLabels(collision.mcCollisionId()); strangeCents(collision.centFT0M(), collision.centFT0A(), centrality, collision.centFV0A()); - strangeEvSels(collision.sel8(), collision.selection_raw()); - auto bc = collision.bc_as(); + strangeEvSels(collision.sel8(), collision.selection_raw(), + collision.multFT0A() * static_cast(fillRawFT0A), + collision.multFT0C() * static_cast(fillRawFT0C), + collision.multFV0A() * static_cast(fillRawFV0A), + collision.multFDDA() * static_cast(fillRawFDDA), + collision.multFDDC() * static_cast(fillRawFDDC), + collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), + collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), + collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), + collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), + collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), + collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), + collision.multZNA() * static_cast(fillRawZDC), + collision.multZNC() * static_cast(fillRawZDC), + collision.multZEM1() * static_cast(fillRawZDC), + collision.multZEM2() * static_cast(fillRawZDC), + collision.multZPA() * static_cast(fillRawZDC), + collision.multZPC() * static_cast(fillRawZDC), + collision.trackOccupancyInTimeRange(), + // UPC info + gapSide, + totalFT0AmplitudeA, totalFT0AmplitudeC, totalFV0AmplitudeA, + totalFDDAmplitudeA, totalFDDAmplitudeC, + energyCommonZNA, energyCommonZNC); strangeStamps(bc.runNumber(), bc.timestamp()); - - if (fillRawFT0C || fillRawFT0C || fillRawFV0A || fillRawNTracksEta1 || fillRawZDC) { - strangeRawCents(collision.multFT0A() * static_cast(fillRawFT0A), - collision.multFT0C() * static_cast(fillRawFT0C), - collision.multFV0A() * static_cast(fillRawFV0A), - collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), - collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multZNA() * static_cast(fillRawZDC), - collision.multZNC() * static_cast(fillRawZDC), - collision.multZEM1() * static_cast(fillRawZDC), - collision.multZEM2() * static_cast(fillRawZDC), - collision.multZPA() * static_cast(fillRawZDC), - collision.multZPC() * static_cast(fillRawZDC), - collision.trackOccupancyInTimeRange()); - } } for (const auto& v0 : V0Table_thisColl) V0CollIndices[v0.globalIndex()] = strangeColl.lastIndex(); @@ -470,7 +596,7 @@ struct strangederivedbuilder { // Figure out the numbering of the new tracks table // assume filling per order int nTracks = 0; - for (int i = 0; i < trackMap.size(); i++) { + for (int i = 0; i < static_cast(trackMap.size()); i++) { if (trackMap[i] >= 0) { trackMap[i] = nTracks++; } @@ -545,7 +671,7 @@ struct strangederivedbuilder { // Figure out the numbering of the new tracks table // assume filling per order int nTracks = 0; - for (int i = 0; i < trackMap.size(); i++) { + for (int i = 0; i < static_cast(trackMap.size()); i++) { if (trackMap[i] >= 0) { trackMap[i] = nTracks++; } @@ -637,7 +763,7 @@ struct strangederivedbuilder { // Figure out the numbering of the new mcMother table // assume filling per order int nParticles = 0; - for (int i = 0; i < motherReference.size(); i++) { + for (int i = 0; i < static_cast(motherReference.size()); i++) { if (motherReference[i] >= 0) { motherReference[i] = nParticles++; // count particles of interest } @@ -710,7 +836,7 @@ struct strangederivedbuilder { static_for<0, nSpecies - 1>([&](auto i) { constexpr int index = i.value; if (mcp.pdgCode() == particlePDGCodes[index] && bitcheck(enabledBits, index)) { - histos.fill(HIST("hGen") + HIST(particleNamesConstExpr[index]), mcp.pt()); + histos.fill(HIST("hGenerated") + HIST(particleNamesConstExpr[index]), mcp.pt()); } }); } @@ -740,7 +866,7 @@ struct strangederivedbuilder { static_for<0, nSpecies - 1>([&](auto i) { constexpr int index = i.value; if (mcp.pdgCode() == particlePDGCodes[index] && bitcheck(enabledBits, index)) { - histos.fill(HIST("h2dGen") + HIST(particleNamesConstExpr[index]), bestCentrality, mcp.pt()); + histos.fill(HIST("h2dGenerated") + HIST(particleNamesConstExpr[index]), bestCentrality, mcp.pt()); } }); } @@ -763,7 +889,7 @@ struct strangederivedbuilder { const uint64_t mcCollIndex = mcCollision.globalIndex(); // use one of the generated histograms as the bin finder - auto hBinFinder = histos.get(HIST("h2dGenK0Short")); + auto hBinFinder = histos.get(HIST("h2dGeneratedK0Short")); auto mcParticles = mcParticlesEntireTable.sliceBy(mcParticlePerMcCollision, mcCollIndex); for (auto& mcp : mcParticles) { @@ -829,7 +955,7 @@ struct strangederivedbuilder { uint64_t combineProngIndices(uint32_t low, uint32_t high) { - return (((uint64_t)high) << 32) | ((uint64_t)low); + return ((static_cast(high)) << 32) | (static_cast(low)); } void processV0FoundTags(aod::V0s const& foundV0s, aod::V0Datas const& findableV0s, aod::FindableV0s const& /* added to avoid troubles */) @@ -851,7 +977,7 @@ struct strangederivedbuilder { using uint128_t = __uint128_t; uint128_t combineProngIndices128(uint32_t pos, uint32_t neg, uint32_t bach) { - return (((uint128_t)pos) << 64) | (((uint128_t)neg) << 32) | ((uint128_t)bach); + return ((static_cast(pos)) << 64) | ((static_cast(neg)) << 32) | (static_cast(bach)); } void processCascFoundTags(aod::Cascades const& foundCascades, aod::CascDatas const& findableCascades, aod::V0s const&, aod::FindableCascades const& /* added to avoid troubles */) diff --git a/PWGLF/TableProducer/Strangeness/v0qaanalysis.cxx b/PWGLF/TableProducer/Strangeness/v0qaanalysis.cxx index fdf2f68c96f..875d0f1c671 100644 --- a/PWGLF/TableProducer/Strangeness/v0qaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/v0qaanalysis.cxx @@ -66,14 +66,16 @@ struct LfV0qaanalysis { } LOG(info) << "Number of process functions enabled: " << nProc; - registry.add("hNEvents", "hNEvents", {HistType::kTH1I, {{8, 0.f, 8.f}}}); + registry.add("hNEvents", "hNEvents", {HistType::kTH1I, {{10, 0.f, 10.f}}}); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "all"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "sel8"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "TVX"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "zvertex"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "TFBorder"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "ITSROFBorder"); - registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "Applied selection"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "isTOFVertexMatched"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(8, "isGoodZvtxFT0vsPV"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(9, "Applied selection"); registry.add("hCentFT0M", "hCentFT0M", {HistType::kTH1F, {{1000, 0.f, 100.f}}}); registry.add("hCentFV0A", "hCentFV0A", {HistType::kTH1F, {{1000, 0.f, 100.f}}}); @@ -137,6 +139,8 @@ struct LfV0qaanalysis { Configurable isTriggerTVX{"isTriggerTVX", 1, "Is Trigger TVX"}; Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", 1, "Is No Time Frame Border"}; Configurable isNoITSROFrameBorder{"isNoITSROFrameBorder", 1, "Is No ITS Readout Frame Border"}; + Configurable isVertexTOFmatched{"isVertexTOFmatched", 0, "Is Vertex TOF matched"}; + Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", 0, "isGoodZvtxFT0vsPV"}; // V0 selection criteria Configurable v0cospa{"v0cospa", 0.97, "V0 CosPA"}; @@ -150,6 +154,7 @@ struct LfV0qaanalysis { template bool AcceptEvent(TCollision const& collision) { + registry.fill(HIST("hNEvents"), 0.5); if (sel8 && !collision.sel8()) { return false; } @@ -170,6 +175,14 @@ struct LfV0qaanalysis { return false; } registry.fill(HIST("hNEvents"), 5.5); + if (isVertexTOFmatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + registry.fill(HIST("hNEvents"), 6.5); + if (isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + registry.fill(HIST("hNEvents"), 7.5); return true; } @@ -183,11 +196,10 @@ struct LfV0qaanalysis { { // Apply event selection - registry.fill(HIST("hNEvents"), 0.5); if (!AcceptEvent(collision)) { return; } - registry.fill(HIST("hNEvents"), 6.5); + registry.fill(HIST("hNEvents"), 8.5); registry.fill(HIST("hCentFT0M"), collision.centFT0M()); registry.fill(HIST("hCentFV0A"), collision.centFV0A()); @@ -246,9 +258,6 @@ struct LfV0qaanalysis { Preslice perMCCol = aod::mcparticle::mcCollisionId; SliceCache cache1; - SliceCache cache2; - SliceCache cache3; - SliceCache cache4; Service pdgDB; @@ -391,8 +400,8 @@ struct LfV0qaanalysis { PROCESS_SWITCH(LfV0qaanalysis, processMCReco, "Process MC Reco", false); void processMCGen(soa::Join::iterator const& mcCollision, - soa::SmallGroups> const& collisions, - aod::McParticles const& mcParticles) + aod::McParticles const& mcParticles, + soa::SmallGroups> const& collisions) { //==================================== //===== Event Loss Denominator ======= @@ -406,11 +415,9 @@ struct LfV0qaanalysis { registry.fill(HIST("hNEventsMCGen"), 1.5); registry.fill(HIST("hCentFT0M_GenColl_MC"), mcCollision.centFT0M()); - const auto particlesInMCCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache3); - bool isINELgt0true = false; - if (pwglf::isINELgtNmc(particlesInMCCollision, 0, pdgDB)) { + if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { isINELgt0true = true; registry.fill(HIST("hNEventsMCGen"), 2.5); registry.fill(HIST("hCentFT0M_GenColl_MC_INELgt0"), mcCollision.centFT0M()); @@ -420,7 +427,7 @@ struct LfV0qaanalysis { //===== Signal Loss Denominator ======= //===================================== - for (auto& mcParticle : particlesInMCCollision) { + for (auto& mcParticle : mcParticles) { if (!mcParticle.isPhysicalPrimary()) { continue; @@ -457,12 +464,11 @@ struct LfV0qaanalysis { //====== Event Split Numerator ======== //===================================== - registry.fill(HIST("hNEvents"), 0.5); registry.fill(HIST("hNEventsMCReco"), 0.5); if (!AcceptEvent(collision)) { continue; } - registry.fill(HIST("hNEvents"), 6.5); + registry.fill(HIST("hNEvents"), 8.5); registry.fill(HIST("hNEventsMCReco"), 1.5); registry.fill(HIST("hCentFT0M_RecoColl_MC"), mcCollision.centFT0M()); @@ -479,7 +485,7 @@ struct LfV0qaanalysis { //======== Sgn Split Numerator ======== //===================================== - for (auto& mcParticle : particlesInMCCollision) { + for (auto& mcParticle : mcParticles) { if (!mcParticle.isPhysicalPrimary()) { continue; @@ -531,9 +537,7 @@ struct LfV0qaanalysis { //===== Signal Loss Numerator ========= //===================================== - const auto particlesInMCRecoCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache4); - - for (auto& mcParticle : particlesInMCRecoCollision) { + for (auto& mcParticle : mcParticles) { if (!mcParticle.isPhysicalPrimary()) { continue; diff --git a/PWGLF/Tasks/Nuspex/AngularCorrelationsInJets.cxx b/PWGLF/Tasks/Nuspex/AngularCorrelationsInJets.cxx index ac3a77a04c2..b9b26efd175 100644 --- a/PWGLF/Tasks/Nuspex/AngularCorrelationsInJets.cxx +++ b/PWGLF/Tasks/Nuspex/AngularCorrelationsInJets.cxx @@ -9,23 +9,21 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Authors: Lars Jörgensen -// Date: 29.05.2024 +// author: Lars Jörgensen -#include #include -#include -#include -#include "ReconstructionDataFormats/Track.h" +#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "CCDB/BasicCCDBManager.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "fastjet/PseudoJet.hh" #include "fastjet/AreaDefinition.hh" @@ -35,29 +33,155 @@ #include "fastjet/tools/Subtractor.hh" #include "fastjet/tools/JetMedianBackgroundEstimator.hh" #include "TVector2.h" +#include "TVector3.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// using SelectedCollisions = soa::Join; -using FullTracks = soa::Join; +struct AxisSpecs { + AxisSpec ptAxisPos = {1000, 0, 100, "#it{p}_{T} [GeV/#it{c}]"}; + AxisSpec ptAxisFull = {2000, -100, 100, "#it{p}_{T} [GeV/#it{c}]"}; + AxisSpec nsigmapTAxis = {1000, -50, 50, "#it{p}_{T} [GeV/#it{c}]"}; + AxisSpec nsigmaAxis = {1000, -15, 15, "n#sigma"}; + AxisSpec dcazAxis = {1000, -1, 1, "DCA_{z} [cm]"}; + AxisSpec dcaxyAxis = {1000, -0.5, 0.5, "DCA_{xy} [cm]"}; + AxisSpec angDistPhiAxis = {1000, -2, 5, "#Delta#varphi"}; + AxisSpec angDistEtaAxis = {1000, -2, 2, "#Delta#eta"}; +}; struct AngularCorrelationsInJets { + // Preliminary Cuts + Configurable fMinNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "min number of crossed rows TPC"}; + Configurable fMinReqClusterITS{"minReqClusterITS", 2, "min number of clusters required in ITS"}; + Configurable fMinReqClusterTPC{"minReqClusterTPC", 70, "min number of clusters required in TPC"}; + Configurable fMinRatioCrossedRowsTPC{"minRatioCrossedRowsTPC", 0.7, "min ratio of crossed rows over findable clusters TPC"}; + Configurable fMaxChi2ITS{"maxChi2ITS", 36.0, "max chi2 per cluster ITS"}; + Configurable fMaxChi2TPC{"maxChi2TPC", 4.0, "max chi2 per cluster TPC"}; + Configurable fMaxDCAxy{"maxDCA_xy", 0.5, "max DCA to vertex xy"}; + Configurable fMaxDCAz{"maxDCA_z", 1.0, "max DCA to vertex z"}; + Configurable fMaxEta{"maxEta", 0.8, "max pseudorapidity"}; // consider jet cone? + + // Jet Cuts + Configurable fJetR{"jetR", 0.4, "jet resolution parameter"}; + Configurable fMinJetPt{"minJetPt", 10.0, "minimum total pT to accept jet"}; + Configurable fMinJetParticlePt{"minJetParticlePt", 0.0, "minimum pT to accept jet particle"}; + Configurable fMinLeadingPt{"minLeadingPt", 5.0, "minimum pT for leading track"}; + + // Proton Cuts + Configurable fProtonDCAxyYield{"protonDCAxyYield", 0.05, "[proton] DCAxy cut for yield"}; + Configurable fProtonDCAzYield{"protonDCAzYield", 1.0, "[proton] DCAz cut for yield"}; + Configurable fProtonDCAxyCF{"protonDCAxyCF", 0.05, "[proton] DCAxy cut for CF"}; + Configurable fProtonDCAzCF{"protonDCAzCF", 1.0, "[proton] DCAz cut for CF"}; + Configurable fProtonTPCTOFpT{"protonTPCTOFswitchpT", 0.7, "[proton] pT for switch in TPC/TOF nsigma"}; + Configurable fProtonTPCnsigLowYield{"protonTPCnsigmaLowPtYield", 4.0, "[proton] max TPC nsigma with low pT for yield"}; + Configurable fProtonTPCnsigHighYield{"protonTPCnsigmaHighPtYield", 4.0, "[proton] max TPC nsigma with high pT for yield"}; + Configurable fProtonTPCnsigLowCF{"protonTPCnsigmaLowPtCF", 4.0, "[proton] max TPC nsigma with low pT for CF"}; + Configurable fProtonTPCnsigHighCF{"protonTPCnsigmaHighPtCF", 4.0, "[proton] max TPC nsigma with high pT for CF"}; + Configurable fProtonTOFnsigLowYield{"protonTOFnsigmaLowPtYield", 15.0, "[proton] max TOF nsigma with low pT for yield"}; + Configurable fProtonTOFnsigHighYield{"protonTOFnsigmaHighPtYield", 15.0, "[proton] max TOF nsigma with high pT yield"}; + Configurable fProtonTOFnsigLowCF{"protonTOFnsigmaLowPtCF", 15.0, "[proton] max TOF nsigma with low pT for CF"}; + Configurable fProtonTOFnsigHighCF{"protonTOFnsigmaHighPtCF", 15.0, "[proton] max TOF nsigma with high pT for CF"}; + + // Antiproton Cuts + Configurable fAntiprotonDCAxyYield{"antiprotonDCAxyYield", 0.05, "[antiproton] DCAxy cut for yield"}; + Configurable fAntiprotonDCAzYield{"antiprotonDCAzYield", 1.0, "[antiproton] DCAz cut for yield"}; + Configurable fAntiprotonDCAxyCF{"antiprotonDCAxyCF", 0.05, "[antiproton] DCAxy cut for CF"}; + Configurable fAntiprotonDCAzCF{"antiprotonDCAzCF", 1.0, "[antiproton] DCAz cut for CF"}; + Configurable fAntiprotonTPCTOFpT{"antiprotonTPCTOFswitchpT", 0.7, "[antiproton] pT for switch in TPC/TOF nsigma"}; + Configurable fAntiprotonTPCnsigLowYield{"antiprotonTPCnsigmaLowPtYield", 4.0, "[antiproton] max TPC nsigma with low pT for yield"}; + Configurable fAntiprotonTPCnsigHighYield{"antiprotonTPCnsigmaHighPtYield", 4.0, "[antiproton] max TPC nsigma with high pT for yield"}; + Configurable fAntiprotonTPCnsigLowCF{"antiprotonTPCnsigmaLowPtCF", 4.0, "[antiproton] max TPC nsigma with low pT for CF"}; + Configurable fAntiprotonTPCnsigHighCF{"antiprotonTPCnsigmaHighPtCF", 4.0, "[antiproton] max TPC nsigma with high pT for CF"}; + Configurable fAntiprotonTOFnsigLowYield{"antiprotonTOFnsigmaLowPtYield", 15.0, "[antiproton] min TOF nsigma with low pT for yield"}; + Configurable fAntiprotonTOFnsigHighYield{"antiprotonTOFnsigmaHighPtYield", 15.0, "[antiproton] min TOF nsigma with high pT for yield"}; + Configurable fAntiprotonTOFnsigLowCF{"antiprotonTOFnsigmaLowPtCF", 15.0, "[antiproton] max TOF nsigma with low pT for CF"}; + Configurable fAntiprotonTOFnsigHighCF{"antiprotonTOFnsigmaHighPtCF", 15.0, "[antiproton] max TOF nsigma with high pT for CF"}; - HistogramRegistry registryData{"jetOutput", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + // Deuteron Cuts + Configurable fDeuteronDCAxyYield{"deuteronDCAxyYield", 0.05, "[deuteron] DCAxy cut for yield"}; + Configurable fDeuteronDCAzYield{"deuteronDCAzYield", 1.0, "[deuteron] DCAz cut for yield"}; + Configurable fDeuteronDCAxyCF{"deuteronDCAxyCF", 0.05, "[deuteron] DCAxy cut for CF"}; + Configurable fDeuteronDCAzCF{"deuteronDCAzCF", 1.0, "[deuteron] DCAz cut for CF"}; + Configurable fDeuteronTPCTOFpT{"deuteronTPCTOFswitchpT", 0.7, "[deuteron] pT for switch in TPC/TOF nsigma"}; + Configurable fDeuteronTPCnsigLowYield{"deuteronTPCnsigmaLowPtYield", 4.0, "[deuteron] max TPC nsigma with low pT for yield"}; + Configurable fDeuteronTPCnsigHighYield{"deuteronTPCnsigmaHighPtYield", 4.0, "[deuteron] max TPC nsigma with high pT for yield"}; + Configurable fDeuteronTPCnsigLowCF{"deuteronTPCnsigmaLowPtCF", 4.0, "[deuteron] max TPC nsigma with low pT for CF"}; + Configurable fDeuteronTPCnsigHighCF{"deuteronTPCnsigmaHighPtCF", 4.0, "[deuteron] max TPC nsigma with high pT for CF"}; + Configurable fDeuteronTOFnsigLowYield{"deuteronTOFnsigmaLowPtYield", 15.0, "[deuteron] min TOF nsigma with low pT for yield"}; + Configurable fDeuteronTOFnsigHighYield{"deuteronTOFnsigmaHighPtYield", 15.0, "[deuteron] min TOF nsigma with high pT for yield"}; + Configurable fDeuteronTOFnsigLowCF{"deuteronTOFnsigmaLowPtCF", 15.0, "[deuteron] max TOF nsigma with low pT for CF"}; + Configurable fDeuteronTOFnsigHighCF{"deuteronTOFnsigmaHighPtCF", 15.0, "[deuteron] max TOF nsigma with high pT for CF"}; - void init(InitContext&) + // Antideuteron Cuts + Configurable fAntideuteronDCAxyYield{"antideuteronDCAxyYield", 0.05, "[antideuteron] DCAxy cut for yield"}; + Configurable fAntideuteronDCAzYield{"antideuteronDCAzYield", 1.0, "[antideuteron] DCAz cut for yield"}; + Configurable fAntideuteronDCAxyCF{"antideuteronDCAxyCF", 0.05, "[antideuteron] DCAxy cut for CF"}; + Configurable fAntideuteronDCAzCF{"antideuteronDCAzCF", 1.0, "[antideuteron] DCAz cut for CF"}; + Configurable fAntideuteronTPCTOFpT{"antideuteronTPCTOFswitchpT", 0.7, "[antideuteron] pT for switch in TPC/TOF nsigma"}; + Configurable fAntideuteronTPCnsigLowYield{"antideuteronTPCnsigmaLowPtYield", 4.0, "[antideuteron] max TPC nsigma with low pT for yield"}; + Configurable fAntideuteronTPCnsigHighYield{"antideuteronTPCnsigmaHighPtYield", 4.0, "[antideuteron] max TPC nsigma with high pT for yield"}; + Configurable fAntideuteronTPCnsigLowCF{"antideuteronTPCnsigmaLowPtCF", 4.0, "[antideuteron] max TPC nsigma with low pT for CF"}; + Configurable fAntideuteronTPCnsigHighCF{"antideuteronTPCnsigmaHighPtCF", 4.0, "[antideuteron] max TPC nsigma with high pT for CF"}; + Configurable fAntideuteronTOFnsigLowYield{"antideuteronTOFnsigmaLowPtYield", 15.0, "[antideuteron] min TOF nsigma with low pT for yield"}; + Configurable fAntideuteronTOFnsigHighYield{"antideuteronTOFnsigmaHighPtYield", 15.0, "[antideuteron] min TOF nsigma with high pT for yield"}; + Configurable fAntideuteronTOFnsigLowCF{"antideuteronTOFnsigmaLowPtCF", 15.0, "[antideuteron] max TOF nsigma with low pT for CF"}; + Configurable fAntideuteronTOFnsigHighCF{"antideuteronTOFnsigmaHighPtCF", 15.0, "[antideuteron] max TOF nsigma with high pT for CF"}; + + // Helium-3 Cuts + Configurable fHeliumDCAxy{"heliumDCAxy", 0.5, "[helium] DCAxy cut"}; + Configurable fHeliumDCAz{"heliumDCAz", 1.0, "[helium] DCAz cut"}; + Configurable fHeliumTPCTOFpT{"heliumTPCTOFswitchpT", 0.7, "[helium] pT for switch in TPC/TOF nsigma"}; + Configurable fHeliumTPCnsigLowYield{"heliumTPCnsigmaLowPtYield", 4.0, "[helium] max TPC nsigma with low pT for yield"}; + Configurable fHeliumTPCnsigHighYield{"heliumTPCnsigmaHighPtYield", 4.0, "[helium] max TPC nsigma with high pT for yield"}; + Configurable fHeliumTOFnsigLowYield{"heliumTOFnsigmaLowPtYield", 15.0, "[helium] min TOF nsigma with low pT for yield"}; + Configurable fHeliumTOFnsigHighYield{"heliumTOFnsigmaHighPtYield", 15.0, "[helium] min TOF nsigma with high pT for yield"}; + + // Antihelium-3 Cuts + Configurable fAntiheliumDCAxy{"antiheliumDCAxy", 0.5, "[antihelium] DCAxy cut"}; + Configurable fAntiheliumDCAz{"antiheliumDCAz", 1.0, "[antihelium] DCAz cut"}; + Configurable fAntiheliumTPCTOFpT{"antiheliumTPCTOFswitchpT", 0.7, "[antihelium] pT for switch in TPC/TOF nsigma"}; + Configurable fAntiheliumTPCnsigLowYield{"antiheliumTPCnsigmaLowPtYield", 4.0, "[antihelium] max TPC nsigma with low pT for yield"}; + Configurable fAntiheliumTPCnsigHighYield{"antiheliumTPCnsigmaHighPtYield", 4.0, "[antihelium] max TPC nsigma with high pT for yield"}; + Configurable fAntiheliumTOFnsigLowYield{"antiheliumTOFnsigmaLowPtYield", 15.0, "[antihelium] min TOF nsigma with low pT for yield"}; + Configurable fAntiheliumTOFnsigHighYield{"antiheliumTOFnsigmaHighPtYield", 15.0, "[antihelium] min TOF nsigma with high pT for yield"}; + + Configurable fBufferSize{"trackBufferSize", 2000, "Number of mixed-event tracks being stored"}; + + // QC Configurables + Configurable fZVtx{"zVtx", 9999, "max zVertex"}; + Configurable fRmax{"Rmax", 0.3, "Maximum radius for jet and UE regions"}; + + Service ccdb; + int mRunNumber; + + using FullTracksRun2 = soa::Join; + using FullTracksRun3 = soa::Join; + using BCsWithRun2Info = soa::Join; + + Filter prelimTrackCuts = (aod::track::itsChi2NCl < fMaxChi2ITS && + aod::track::tpcChi2NCl < fMaxChi2TPC && + nabs(aod::track::dcaXY) < fMaxDCAxy && + nabs(aod::track::dcaZ) < fMaxDCAz && + nabs(aod::track::eta) < fMaxEta); + + Preslice perCollisionFullTracksRun2 = o2::aod::track::collisionId; + Preslice perCollisionFullTracksRun3 = o2::aod::track::collisionId; + + AxisSpecs axisSpecs; + + HistogramRegistry registryData{"dataOutput", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryQA{"dataQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + void init(o2::framework::InitContext&) { - // AxisSpec specName = {binningInfo, "axisLabel"}; - AxisSpec ptAxis = {1000, 0, 100, "#it{p}_{T} [GeV/#it{c}]"}; - AxisSpec particleTypeAxis = {4, 1, 5, "[p, ap, d, ad]"}; - AxisSpec nsigmapTAxis = {1000, -50, 50, "#it{p}_{T} [GeV/#it{c}]"}; - AxisSpec nsigmaAxis = {1000, -5, 5, "n#sigma"}; - AxisSpec dcazAxis = {200, -3, 3, "DCA_{z} [cm]"}; - AxisSpec dcaxyAxis = {200, -2, 2, "DCA_{xy} [cm]"}; - AxisSpec angDistPhiAxis = {1000, -2, 5, "#Delta#varphi"}; - AxisSpec angDistEtaAxis = {1000, -2, 2, "#Delta#eta"}; + mRunNumber = 0; + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); // Counters registryData.add("hNumberOfEvents", "Number of events", HistType::kTH1I, {{1, 0, 1}}); @@ -67,169 +191,687 @@ struct AngularCorrelationsInJets { registryData.add("hNumPartInJet", "Number of particles in a jet", HistType::kTH1I, {{200, 0, 200}}); // (Pseudo)Rapidity - registryData.add("hEtaFullEvent", "Particle pseudorapidity;#eta", HistType::kTH1F, {{200, -1, 1}}); registryData.add("hJetRapidity", "Jet rapidity;#it{y}", HistType::kTH1F, {{200, -1, 1}}); // pT - registryData.add("hPtFullEvent", "p_{T} after basic cuts", HistType::kTH1F, {ptAxis}); - registryData.add("hPtJetParticle", "p_{T} of particles in jets", HistType::kTH1D, {ptAxis}); - registryData.add("hPtSubtractedJet", "Subtracted jet p_{T}", HistType::kTH1D, {ptAxis}); - registryData.add("hPtJetProtonDeuteron", "p_{T} of (anti)p, (anti)d", HistType::kTH2D, {particleTypeAxis, ptAxis}); + registryData.add("hPtJetParticle", "p_{T} of particles in jets", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtSubtractedJet", "Subtracted jet p_{T}", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtJetProton", "p_{T} of p", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtJetAntiproton", "p_{T} of antip", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtJetDeuteron", "p_{T} of d", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtJetAntideuteron", "p_{T} of antid", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtJetHelium", "p_{T} of He", HistType::kTH1D, {axisSpecs.ptAxisPos}); + registryData.add("hPtJetAntihelium", "p_{T} of anti-He", HistType::kTH1D, {axisSpecs.ptAxisPos}); registryData.add("hPtTotalJet", "p_{T} of entire jet;#it{p}_{T} [GeV/#it{c}]", HistType::kTH1F, {{2000, 0, 500}}); - registryData.add("hPtDiff", "pT difference PseudoJet/original track;#it{p}_{T} [GeV/#it{c}]", HistType::kTH1D, {{100, -0.0000005, 0.0000005}}); + registryData.add("hPtDiff", "pT difference PseudoJet/original track;#it{p}_{T} [GeV/#it{c}]", HistType::kTH1D, {{100, -5, 5}}); // nSigma - registryData.add("hTPCnsigma", "TPC n#sigma for full event", HistType::kTH2F, {nsigmapTAxis, nsigmaAxis}); - registryData.add("hTOFnsigma", "TOF n#sigma for full event", HistType::kTH2F, {nsigmapTAxis, nsigmaAxis}); - registryData.add("hTPCnsigmaProton", "TPC n#sigma for (anti)proton", HistType::kTH2F, {nsigmapTAxis, nsigmaAxis}); - registryData.add("hTOFnsigmaProton", "TOF n#sigma for (anti)proton", HistType::kTH2F, {nsigmapTAxis, nsigmaAxis}); - registryData.add("hTPCnsigmaDeuteron", "TPC n#sigma for (anti)deuteron", HistType::kTH2F, {nsigmapTAxis, nsigmaAxis}); - registryData.add("hTOFnsigmaDeuteron", "TOF n#sigma for (anti)deuteron", HistType::kTH2F, {nsigmapTAxis, nsigmaAxis}); + registryData.add("hTPCsignal", "TPC signal", HistType::kTH2F, {{1000, 0, 100, "#it{p} [GeV/#it{c}]"}, {5000, 0, 5000, "d#it{E}/d#it{X} (a.u.)"}}); + registryData.add("hTOFsignal", "TOF signal", HistType::kTH2F, {{1000, 0, 100, "#it{p} [GeV/#it{c}]"}, {550, 0, 1.1, "#beta (TOF)"}}); + registryData.add("hTPCnsigmaProton", "TPC n#sigma for (anti)proton", HistType::kTH2F, {axisSpecs.nsigmapTAxis, axisSpecs.nsigmaAxis}); + registryData.add("hTOFnsigmaProton", "TOF n#sigma for (anti)proton", HistType::kTH2F, {axisSpecs.nsigmapTAxis, axisSpecs.nsigmaAxis}); + registryData.add("hTPCnsigmaDeuteron", "TPC n#sigma for (anti)deuteron", HistType::kTH2F, {axisSpecs.nsigmapTAxis, axisSpecs.nsigmaAxis}); + registryData.add("hTOFnsigmaDeuteron", "TOF n#sigma for (anti)deuteron", HistType::kTH2F, {axisSpecs.nsigmapTAxis, axisSpecs.nsigmaAxis}); + registryData.add("hTPCnsigmaHelium", "TPC n#sigma for (anti)helium", HistType::kTH2F, {axisSpecs.nsigmapTAxis, axisSpecs.nsigmaAxis}); + registryData.add("hTOFnsigmaHelium", "TOF n#sigma for (anti)helium", HistType::kTH2F, {axisSpecs.nsigmapTAxis, axisSpecs.nsigmaAxis}); // DCA - registryData.add("hDCAxyFullJet", "DCA_{xy} of full jet", HistType::kTH2F, {ptAxis, dcaxyAxis}); - registryData.add("hDCAzFullJet", "DCA_{z} of full jet", HistType::kTH2F, {ptAxis, dcazAxis}); - registryData.add("hDCAzJetProton", "DCA_{z} of protons after TPC cut", HistType::kTH2F, {ptAxis, dcazAxis}); - registryData.add("hDCAzJetAntiproton", "DCA_{z} of antiprotons after TPC cut", HistType::kTH2F, {ptAxis, dcazAxis}); - registryData.add("hDCAzJetDeuteron", "DCA_{z} of deuterons after TPC cut", HistType::kTH2F, {ptAxis, dcazAxis}); - registryData.add("hDCAzJetAntideuteron", "DCA_{z} of antideuterons after TPC cut", HistType::kTH2F, {ptAxis, dcazAxis}); + registryData.add("hDCAxyFullJet", "DCA_{xy} of full jet", HistType::kTH2F, {axisSpecs.ptAxisFull, axisSpecs.dcaxyAxis}); + registryData.add("hDCAzFullJet", "DCA_{z} of full jet", HistType::kTH2F, {axisSpecs.ptAxisFull, axisSpecs.dcazAxis}); + registryData.add("hDCAzJetProton", "DCA_{z} of protons after TPC cut", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); + registryData.add("hDCAzJetAntiproton", "DCA_{z} of antiprotons after TPC cut", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); + registryData.add("hDCAzJetDeuteron", "DCA_{z} of deuterons after TPC cut", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); + registryData.add("hDCAzJetAntideuteron", "DCA_{z} of antideuterons after TPC cut", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); + registryData.add("hDCAzJetHelium", "DCA_{z} of helium after TPC cut", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); + registryData.add("hDCAzJetAntihelium", "DCA_{z} of antihelium after TPC cut", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); // Angular Distributions - registryData.add("hDeltaPhiSE", "#Delta#varphi of (anti)p, (anti)d in single event", HistType::kTH2D, {particleTypeAxis, angDistPhiAxis}); - registryData.add("hDeltaPhiME", "#Delta#varphi of (anti)p, (anti)d in mixed events", HistType::kTH2D, {particleTypeAxis, angDistPhiAxis}); - registryData.add("hDeltaPhiEtaSE", "#Delta#varphi vs #Delta#eta of (anti)p, (anti)d in single event", HistType::kTH3D, {particleTypeAxis, angDistPhiAxis, angDistEtaAxis}); - registryData.add("hDeltaPhiEtaME", "#Delta#varphi vs #Delta#eta of (anti)p, (anti)d in mixed events", HistType::kTH3D, {particleTypeAxis, angDistPhiAxis, angDistEtaAxis}); + registryData.add("hDeltaPhiSEFull", "#Delta#varphi of particles in single event", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiSEJet", "#Delta#varphi of jet particles in single event", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiSEProton", "#Delta#varphi of protons in single event", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiSEAntiproton", "#Delta#varphi of antiprotons in single event", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiSEDeuteron", "#Delta#varphi of deuterons in single event", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiSEAntideuteron", "#Delta#varphi of antideuterons in single event", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiMEFull", "#Delta#varphi of particles in mixed events", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiMEJet", "#Delta#varphi of jet particles in mixed events", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiMEProton", "#Delta#varphi of protons in mixed events", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiMEAntiproton", "#Delta#varphi of antiprotons in mixed events", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiMEDeuteron", "#Delta#varphi of deuterons in mixed events", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiMEAntideuteron", "#Delta#varphi of antideuterons in mixed events", HistType::kTH1D, {axisSpecs.angDistPhiAxis}); + registryData.add("hDeltaPhiEtaSEFull", "#Delta#varphi vs #Delta#eta of full particles in single event", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaSEJet", "#Delta#varphi vs #Delta#eta of jet particles in single event", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaSEProton", "#Delta#varphi vs #Delta#eta of protons in single event", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaSEAntiproton", "#Delta#varphi vs #Delta#eta of antiprotons in single event", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaSEDeuteron", "#Delta#varphi vs #Delta#eta of deuterons in single event", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaSEAntideuteron", "#Delta#varphi vs #Delta#eta of antideuterons in single event", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaMEFull", "#Delta#varphi vs #Delta#eta of particles in mixed events", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaMEJet", "#Delta#varphi vs #Delta#eta of jet particles in mixed events", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaMEProton", "#Delta#varphi vs #Delta#eta of protons in mixed events", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaMEAntiproton", "#Delta#varphi vs #Delta#eta of antiprotons in mixed events", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaMEDeuteron", "#Delta#varphi vs #Delta#eta of deuterons in mixed events", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); + registryData.add("hDeltaPhiEtaMEAntideuteron", "#Delta#varphi vs #Delta#eta of antideuterons in mixed events", HistType::kTH2D, {axisSpecs.angDistPhiAxis, axisSpecs.angDistEtaAxis}); registryData.add("hJetConeRadius", "Jet Radius;#it{R}", HistType::kTH1F, {{100, 0, 1}}); + + // QA + registryQA.add("hTOFmass", "TOF mass", HistType::kTH2F, {axisSpecs.ptAxisPos, {1000, 0, 5, "#it{m} [GeV/#it{c}^{2}]"}}); + registryQA.get(HIST("hTOFmass"))->Sumw2(); + registryQA.add("hPtFullEvent", "p_{T} after basic cuts", HistType::kTH1F, {axisSpecs.ptAxisPos}); + registryQA.add("hEtaFullEvent", "Particle pseudorapidity;#eta", HistType::kTH1F, {{200, -1, 1}}); + registryQA.add("hCrossedRowsTPC", "Crossed rows TPC", HistType::kTH2I, {axisSpecs.ptAxisPos, {135, 65, 200}}); + registryQA.add("hClusterITS", "ITS clusters", HistType::kTH2I, {axisSpecs.ptAxisPos, {10, 0, 10}}); + registryQA.add("hClusterTPC", "TPC clusters", HistType::kTH2I, {axisSpecs.ptAxisPos, {135, 65, 200}}); + registryQA.add("hRatioCrossedRowsTPC", "Ratio crossed rows/findable TPC", HistType::kTH2F, {axisSpecs.ptAxisPos, {100, 0.5, 1.5}}); + registryQA.add("hChi2ITS", "ITS #chi^{2}", HistType::kTH2F, {axisSpecs.ptAxisPos, {400, 0, 40}}); + registryQA.add("hChi2TPC", "TPC #chi^{2}", HistType::kTH2F, {axisSpecs.ptAxisPos, {50, 0, 5}}); + registryQA.add("hDCAxyFullEvent", "DCA_{xy} of full event", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcaxyAxis}); + registryQA.add("hDCAzFullEvent", "DCA_{z} of full event", HistType::kTH2F, {axisSpecs.ptAxisPos, axisSpecs.dcazAxis}); + registryQA.add("hJetPtVsNumPart", "Total jet p_{T} vs number of constituents", HistType::kTH2F, {axisSpecs.ptAxisPos, {100, 0, 100}}); + + // QA Histograms for Comparison with nuclei_in_jets.cxx + registryQA.add("hMultiplicityJetPlusUE", "hMultiplicityJetPlusUE", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); + registryQA.add("hMultiplicityJet", "hMultiplicityJet", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); + registryQA.add("hMultiplicityUE", "hMultiplicityUE", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); + registryQA.add("hPtLeading", "hPtLeading", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQA.add("hEtaLeading", "hEtaLeading", HistType::kTH1F, {{100, -0.8, 0.8, "#eta"}}); + registryQA.add("hPhiLeading", "hPhiLeading", HistType::kTH1F, {{100, 0, TMath::TwoPi(), "#phi"}}); + registryQA.add("hRJet", "hRJet", HistType::kTH1F, {{100, 0.0, 0.5, "#it{R}"}}); + registryQA.add("hRUE", "hRUE", HistType::kTH1F, {{100, 0.0, 0.5, "#it{R}"}}); + registryQA.add("hAngleJetLeadingTrack", "hAngleJetLeadingTrack", HistType::kTH1F, {{200, 0.0, 50.0, "#theta"}}); + registryQA.add("hPtJetPlusUE", "hPtJetPlusUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQA.add("hPtJet", "hPtJet", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQA.add("hPtUE", "hPtUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQA.add("hDeltaEtadeltaPhiJet", "hDeltaEtadeltaPhiJet", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); + registryQA.add("hDeltaEtadeltaPhiUE", "hDeltaEtadeltaPhiUE", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); + registryQA.add("hDeltaEtadeltaPhiLeadingJet", "hDeltaEtadeltaPhiLeadingJet", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); + registryQA.add("hDeltaJetPt", "hDeltaJetPt", HistType::kTH1F, {{200, -2, 2, "#Delta#it{p}_{T} (GeV/#it{c})"}}); + + // QC Histograms for ptJet < ptLeading + registryQA.add("hNParticlesClusteredInJet", "hNParticlesClusteredInJet", HistType::kTH1F, {{50, 0, 50, "#it{N}_{ch}"}}); + registryQA.add("hPtParticlesClusteredInJet", "hPtParticlesClusteredInJet", HistType::kTH1F, {{200, 0, 10, "#it{p}_{T} (GeV/#it{c})"}}); + registryQA.add("hDeltaEtaDeltaPhiJetAxis", "hDeltaEtaDeltaPhiJetAxis", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); + registryQA.add("hDeltaEtaDeltaPhiJetAxisLeading", "hDeltaEtaDeltaPhiJetAxisLeading", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); } - // Preliminary Cuts - // Configurable fTPCRefit{"TPCRefit", 0, "Require TPC refit"}; - Configurable fMinNCrossedRowsTPC{"minNCrossedRowsTPC", 70.0f, "min number of crossed rows TPC"}; - Configurable fMinReqClusterITS{"minReqClusterITS", 2.0, "min number of clusters required in ITS"}; - Configurable fMinRatioCrossedRowsTPC{"minRatioCrossedRowsTPC", 0.7f, "min ratio of crossed rows over findable clusters TPC"}; - Configurable fMaxChi2ITS{"maxChi2ITS", 36.0f, "max chi2 per cluster ITS"}; - Configurable fMaxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; - Configurable fMaxDCAxy{"maxDCA_xy", 0.5f, "max DCA to vertex xy"}; - Configurable fMaxDCAz{"maxDCA_z", 2.4f, "max DCA to vertex z"}; - Configurable fMaxEta{"maxEta", 0.8, "max pseudorapidity"}; + std::vector> fBufferProton; + std::vector> fBufferAntiproton; + std::vector> fBufferDeuteron; + std::vector> fBufferAntideuteron; + std::vector> fBufferJet; + std::vector> fBufferFull; - // Jet Cuts - Configurable fJetRadius{"jetRadius", 0.4, "jet radius R"}; - Configurable fMinJetPt{"minJetPt", 10.0, "minimum total pT to accept jet"}; - Configurable fMinJetParticlePt{"minJetParticlePt", 0.0, "minimum pT to accept jet particle"}; - Configurable fMinLeadingPt{"minLeadingPt", 5.0, "minimum pT for leading track"}; + template + void initCCDB(Bc const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + } - // Proton Cuts - Configurable fProtonDCAxy{"protonDCAxy", 0.5, "[proton] DCAxy cut"}; - Configurable fProtonDCAz{"protonDCAz", 1.0, "[proton] DCAz cut"}; - Configurable fProtonTPCTOFpT{"protonTPCTOFswitchpT", 0.7, "[proton] pT for switch in TPC/TOF nsigma"}; - Configurable fProtonTPCnsigLow{"protonTPCnsigmapTLow", 5.0, "[proton] max TPC nsigma with low pT"}; - Configurable fProtonTPCnsigHigh{"protonTPCnsigmapTHigh", 4.0, "[proton] max TPC nsigma with high pT"}; - Configurable fProtonTOFnsigLow{"protonTOFnsigmapTLow", 10.0, "[proton] max TOF nsigma with low pT"}; - Configurable fProtonTOFnsigHigh{"protonTOFnsigmapTHigh", 10.0, "[proton] max TOF nsigma with high pT"}; + template + bool selectTrack(T const& track) + { + if (track.tpcNClsCrossedRows() < fMinRatioCrossedRowsTPC * track.tpcNClsFindable() || + track.tpcNClsCrossedRows() < fMinNCrossedRowsTPC || + track.tpcNClsFound() < fMinReqClusterTPC || + track.itsNCls() < fMinReqClusterITS) { + return false; + } + if (doprocessRun2) { + if (!(track.trackType() & o2::aod::track::Run2Track) || + !(track.flags() & o2::aod::track::TPCrefit) || + !(track.flags() & o2::aod::track::ITSrefit)) { + return false; + } + } + return true; + } - // Antiproton Cuts - Configurable fAntiprotonDCAxy{"antiprotonDCAxy", 0.5, "[antiproton] DCAxy cut"}; - Configurable fAntiprotonDCAz{"antiprotonDCAz", 1.0, "[antiproton] DCAz cut"}; - Configurable fAntiprotonTPCTOFpT{"antiprotonTPCTOFswitchpT", 0.7, "[antiproton] pT for switch in TPC/TOF nsigma"}; - Configurable fAntiprotonTPCnsigLow{"antiprotonTPCnsigmapTLow", 5.0, "[antiproton] max TPC nsigma with low pT"}; - Configurable fAntiprotonTPCnsigHigh{"antiprotonTPCnsigmapTHigh", 4.0, "[antiproton] max TPC nsigma with high pT"}; - Configurable fAntiprotonTOFnsigLow{"antiprotonTOFnsigmapTLow", 10.0, "[antiproton] max TOF nsigma with low pT"}; - Configurable fAntiprotonTOFnsigHigh{"antiprotonTOFnsigmapTHigh", 10.0, "[antiproton] max TOF nsigma with high pT"}; + template + bool isProton(const T& track, bool tightCuts) + { + if (track.sign() < 0) + return false; - // Deuteron Cuts - Configurable fDeuteronDCAxy{"deuteronDCAxy", 0.5, "[deuteron] DCAxy cut"}; - Configurable fDeuteronDCAz{"deuteronDCAz", 1.0, "[deuteron] DCAz cut"}; - Configurable fDeuteronTPCTOFpT{"deuteronTPCTOFswitchpT", 0.7, "[deuteron] pT for switch in TPC/TOF nsigma"}; - Configurable fDeuteronTPCnsigLow{"deuteronTPCnsigmapTLow", 5.0, "[deuteron] max TPC nsigma with low pT"}; - Configurable fDeuteronTPCnsigHigh{"deuteronTPCnsigmapTHigh", 4.0, "[deuteron] max TPC nsigma with high pT"}; - Configurable fDeuteronTOFnsigLow{"deuteronTOFnsigmapTLow", 10.0, "[deuteron] max TOF nsigma with low pT"}; - Configurable fDeuteronTOFnsigHigh{"deuteronTOFnsigmapTHigh", 10.0, "[deuteron] max TOF nsigma with high pT"}; + if (tightCuts) { // for correlation function + // TPC + if (track.pt() < fProtonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fProtonTPCnsigLowCF) + return false; + if (track.pt() > fProtonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fProtonTPCnsigHighCF) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fProtonDCAxyCF) + return false; + if (TMath::Abs(track.dcaZ()) > fProtonDCAzCF) + return false; + + // TOF + if (track.pt() < fProtonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fProtonTOFnsigLowCF) + return false; // drop for low pt if no TOF + if (track.pt() > fProtonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fProtonTOFnsigHighCF) + return false; + } else { // for yields + // TPC + if (track.pt() < fProtonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fProtonTPCnsigLowYield) + return false; + if (track.pt() > fProtonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fProtonTPCnsigHighYield) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fProtonDCAxyYield) + return false; + if (TMath::Abs(track.dcaZ()) > fProtonDCAzYield) + return false; + + // TOF + if (track.pt() < fProtonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fProtonTOFnsigLowYield) + return false; + if (track.pt() > fProtonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fProtonTOFnsigHighYield) + return false; + } - // Antideuteron Cuts - Configurable fAntideuteronDCAxy{"antideuteronDCAxy", 0.5, "[antideuteron] DCAxy cut"}; - Configurable fAntideuteronDCAz{"antideuteronDCAz", 1.0, "[antideuteron] DCAz cut"}; - Configurable fAntideuteronTPCTOFpT{"antideuteronTPCTOFswitchpT", 0.7, "[antideuteron] pT for switch in TPC/TOF nsigma"}; - Configurable fAntideuteronTPCnsigLow{"antideuteronTPCnsigmapTLow", 5.0, "[antideuteron] max TPC nsigma with low pT"}; - Configurable fAntideuteronTPCnsigHigh{"antideuteronTPCnsigmapTHigh", 4.0, "[antideuteron] max TPC nsigma with high pT"}; - Configurable fAntideuteronTOFnsigLow{"antideuteronTOFnsigmapTLow", 10.0, "[antideuteron] max TOF nsigma with low pT"}; - Configurable fAntideuteronTOFnsigHigh{"antideuteronTOFnsigmapTHigh", 10.0, "[antideuteron] max TOF nsigma with high pT"}; + return true; + } - Configurable fTrackBufferSize{"trackBufferSize", 2000, "Number of mixed-event tracks being stored"}; + template + bool isAntiproton(const T& track, bool tightCuts) + { + if (track.sign() > 0) + return false; + + if (tightCuts) { // for correlation function + // TPC + if (track.pt() < fAntiprotonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fAntiprotonTPCnsigLowCF) + return false; + if (track.pt() > fAntiprotonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fAntiprotonTPCnsigHighCF) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fAntiprotonDCAxyCF) + return false; + if (TMath::Abs(track.dcaZ()) > fAntiprotonDCAzCF) + return false; + + // TOF + if (track.pt() < fAntiprotonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fAntiprotonTOFnsigLowCF) + return false; + if (track.pt() > fAntiprotonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fAntiprotonTOFnsigHighCF) + return false; + } else { // for yields + // TPC + if (track.pt() < fAntiprotonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fAntiprotonTPCnsigLowYield) + return false; + if (track.pt() > fAntiprotonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) > fAntiprotonTPCnsigHighYield) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fAntiprotonDCAxyYield) + return false; + if (TMath::Abs(track.dcaZ()) > fAntiprotonDCAzYield) + return false; + + // TOF + if (track.pt() < fAntiprotonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fAntiprotonTOFnsigLowYield) + return false; + if (track.pt() > fAntiprotonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) > fAntiprotonTOFnsigHighYield) + return false; + } + + return true; + } + + template + bool isDeuteron(const T& track, bool tightCuts) + { + if (track.sign() < 0) + return false; - std::vector fTrackBufferProton; - std::vector fTrackBufferAntiproton; - std::vector fTrackBufferDeuteron; - std::vector fTrackBufferAntideuteron; + if (tightCuts) { // for correlation function + // TPC + if (track.pt() < fDeuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fDeuteronTPCnsigLowCF) + return false; + if (track.pt() > fDeuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fDeuteronTPCnsigHighCF) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fDeuteronDCAxyCF) + return false; + if (TMath::Abs(track.dcaZ()) > fDeuteronDCAzCF) + return false; + + // TOF + if (track.pt() < fDeuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fDeuteronTOFnsigLowCF) + return false; + if (track.pt() > fDeuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fDeuteronTOFnsigHighCF) + return false; + } else { // for yields + // TPC + if (track.pt() < fDeuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fDeuteronTPCnsigLowYield) + return false; + if (track.pt() > fDeuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fDeuteronTPCnsigHighYield) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fDeuteronDCAxyYield) + return false; + if (TMath::Abs(track.dcaZ()) > fDeuteronDCAzYield) + return false; + + // TOF + if (track.pt() < fDeuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fDeuteronTOFnsigLowYield) + return false; + if (track.pt() > fDeuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fDeuteronTOFnsigHighYield) + return false; + } - //**************************************************************************************************** + return true; + } - template - void angCorrData(const CollisionType& /*collision*/, const TracksType& tracks) + template + bool isAntideuteron(const T& track, bool tightCuts) { - registryData.fill(HIST("hNumberOfEvents"), 0); - registryData.fill(HIST("hEventProtocol"), 0); + if (track.sign() > 0) + return false; + + if (tightCuts) { // for correlation function + // TPC + if (track.pt() < fAntideuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fAntideuteronTPCnsigLowCF) + return false; + if (track.pt() > fAntideuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fAntideuteronTPCnsigHighCF) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fAntideuteronDCAxyCF) + return false; + if (TMath::Abs(track.dcaZ()) > fAntideuteronDCAzCF) + return false; + + // TOF + if (track.pt() < fAntideuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fAntideuteronTOFnsigLowCF) + return false; + if (track.pt() > fAntideuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fAntideuteronTOFnsigHighCF) + return false; + } else { // for yields + // TPC + if (track.pt() < fAntideuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fAntideuteronTPCnsigLowYield) + return false; + if (track.pt() > fAntideuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) > fAntideuteronTPCnsigHighYield) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fAntideuteronDCAxyYield) + return false; + if (TMath::Abs(track.dcaZ()) > fAntideuteronDCAzYield) + return false; + + // TOF + if (track.pt() < fAntideuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fAntideuteronTOFnsigLowYield) + return false; + if (track.pt() > fAntideuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) > fAntideuteronTOFnsigHighYield) + return false; + } + + return true; + } + + template + bool isHelium(const T& track) + { + if (track.sign() < 0) + return false; + + // TPC + if (track.pt() < fHeliumTPCTOFpT && TMath::Abs(track.tpcNSigmaHe()) > fHeliumTPCnsigLowYield) + return false; + if (track.pt() > fHeliumTPCTOFpT && TMath::Abs(track.tpcNSigmaHe()) > fHeliumTPCnsigHighYield) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fHeliumDCAxy) + return false; + if (TMath::Abs(track.dcaZ()) > fHeliumDCAz) + return false; + + // TOF + if (track.pt() < fHeliumTPCTOFpT && TMath::Abs(track.tofNSigmaHe()) > fHeliumTOFnsigLowYield) + return false; + if (track.pt() > fHeliumTPCTOFpT && TMath::Abs(track.tofNSigmaHe()) > fHeliumTOFnsigHighYield) + return false; + + return true; + } + + template + bool isAntihelium(const T& track) + { + if (track.sign() > 0) + return false; + + // TPC + if (track.pt() < fAntiheliumTPCTOFpT && TMath::Abs(track.tpcNSigmaHe()) > fAntiheliumTPCnsigLowYield) + return false; + if (track.pt() > fAntiheliumTPCTOFpT && TMath::Abs(track.tpcNSigmaHe()) > fAntiheliumTPCnsigHighYield) + return false; + + // DCA + if (TMath::Abs(track.dcaXY()) > fAntiheliumDCAxy) + return false; + if (TMath::Abs(track.dcaZ()) > fAntiheliumDCAz) + return false; + + // TOF + if (track.pt() < fAntiheliumTPCTOFpT && TMath::Abs(track.tofNSigmaHe()) > fAntiheliumTOFnsigLowYield) + return false; + if (track.pt() > fAntiheliumTPCTOFpT && TMath::Abs(track.tofNSigmaHe()) > fAntiheliumTOFnsigHighYield) + return false; + + return true; + } + + void setTrackBuffer(const auto& tempBuffer, auto& buffer) + { + for (const auto& pair : tempBuffer) { + if (static_cast(buffer.size()) == fBufferSize) { + buffer.insert(buffer.begin(), pair); + buffer.resize(fBufferSize); + } else if (static_cast(buffer.size()) < fBufferSize) { + buffer.emplace_back(pair); + } + } + } + + void fillMixedEventDeltas(const auto& track, const auto& buffer, int particleType, const TVector3 jetAxis) + { + if (buffer.size() == 0) + return; + if (std::isnan(track.phi()) || std::isnan(jetAxis.Phi())) + return; + for (int i = 0; i < static_cast(buffer.size()); i++) { // loop over tracks in buffer + if (std::isnan(buffer.at(i).first)) + continue; + if (buffer.at(i).first > 2 * TMath::Pi() || buffer.at(i).first < -2 * TMath::Pi()) { + registryData.fill(HIST("hTrackProtocol"), 16); + continue; + } + + double phiToAxis = TVector2::Phi_0_2pi(track.phi() - jetAxis.Phi()); + double etaToAxis = track.eta() - jetAxis.Eta(); + double DeltaPhi = TVector2::Phi_0_2pi(phiToAxis - buffer.at(i).first); + if (DeltaPhi > (1.5 * TMath::Pi())) { // ensure range of [-pi/2, 3/2 pi] + DeltaPhi = DeltaPhi - 2 * TMath::Pi(); + } + double DeltaEta = etaToAxis - buffer.at(i).second; + + switch (particleType) { + case -1: + registryData.fill(HIST("hDeltaPhiMEFull"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaMEFull"), DeltaPhi, DeltaEta); + break; + case 0: + registryData.fill(HIST("hDeltaPhiMEJet"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaMEJet"), DeltaPhi, DeltaEta); + break; + case 1: + registryData.fill(HIST("hDeltaPhiMEProton"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaMEProton"), DeltaPhi, DeltaEta); + break; + case 2: + registryData.fill(HIST("hDeltaPhiMEAntiproton"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaMEAntiproton"), DeltaPhi, DeltaEta); + break; + case 3: + registryData.fill(HIST("hDeltaPhiMEDeuteron"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaMEDeuteron"), DeltaPhi, DeltaEta); + break; + case 4: + registryData.fill(HIST("hDeltaPhiMEAntideuteron"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaMEAntideuteron"), DeltaPhi, DeltaEta); + break; + } + } // for (int i = 0; i < static_cast(buffer.size()); i++) + } + + void doCorrelations(const auto& particleVector, const auto& buffer, auto& tempBuffer, int particleType, const TVector3 jetAxis) + { + if (std::isnan(jetAxis.Phi())) + return; + for (int i = 0; i < static_cast(particleVector.size()); i++) { + if (std::isnan(particleVector.at(i).phi())) + continue; + double phiToAxis = TVector2::Phi_0_2pi(particleVector.at(i).phi() - jetAxis.Phi()); + double etaToAxis = particleVector.at(i).eta() - jetAxis.Eta(); + if (TMath::Abs(particleVector.at(i).phi()) > 2 * TMath::Pi()) { + registryData.fill(HIST("hTrackProtocol"), 14); + continue; + } + for (int j = i + 1; j < static_cast(particleVector.size()); j++) { + if ((j == static_cast(particleVector.size())) || std::isnan(particleVector.at(j).phi())) + continue; + if (TMath::Abs(particleVector.at(j).phi()) > 2 * TMath::Pi()) { + registryData.fill(HIST("hTrackProtocol"), 15); + continue; + } + + double DeltaPhi = TVector2::Phi_0_2pi(particleVector.at(i).phi() - particleVector.at(j).phi()); + double DeltaEta = particleVector.at(i).eta() - particleVector[j].eta(); + if (DeltaPhi > (1.5 * TMath::Pi())) { + DeltaPhi = DeltaPhi - 2 * TMath::Pi(); + } + switch (particleType) { + case -1: + registryData.fill(HIST("hDeltaPhiSEFull"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaSEFull"), DeltaPhi, DeltaEta); + break; + case 0: + registryData.fill(HIST("hDeltaPhiSEJet"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaSEJet"), DeltaPhi, DeltaEta); + break; + case 1: + registryData.fill(HIST("hDeltaPhiSEProton"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaSEProton"), DeltaPhi, DeltaEta); + break; + case 2: + registryData.fill(HIST("hDeltaPhiSEAntiproton"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaSEAntiproton"), DeltaPhi, DeltaEta); + break; + case 3: + registryData.fill(HIST("hDeltaPhiSEDeuteron"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaSEDeuteron"), DeltaPhi, DeltaEta); + break; + case 4: + registryData.fill(HIST("hDeltaPhiSEAntideuteron"), DeltaPhi); + registryData.fill(HIST("hDeltaPhiEtaSEAntideuteron"), DeltaPhi, DeltaEta); + break; + } + } + fillMixedEventDeltas(particleVector.at(i), buffer, particleType, jetAxis); + tempBuffer.emplace_back(std::make_pair(phiToAxis, etaToAxis)); + } + } + + double getDeltaPhi(double a1, double a2) + { + if (std::isnan(a1) || std::isnan(a2) || a1 == -999 || a2 == -999) + return -999; + double deltaPhi(0); + double phi1 = TVector2::Phi_0_2pi(a1); + double phi2 = TVector2::Phi_0_2pi(a2); + double diff = TMath::Abs(phi1 - phi2); + + if (diff <= TMath::Pi()) + deltaPhi = diff; + if (diff > TMath::Pi()) + deltaPhi = TMath::TwoPi() - diff; + + return deltaPhi; + } + + void getPerpendicularAxis(TVector3 p, TVector3& u, double sign) + { + // Initialization + double ux(0), uy(0), uz(0); + + // Components of Vector p + double px = p.X(); + double py = p.Y(); + double pz = p.Z(); + // Protection 1 + if (px == 0 && py != 0) { + + uy = -(pz * pz) / py; + ux = sign * sqrt(py * py - (pz * pz * pz * pz) / (py * py)); + uz = pz; + u.SetXYZ(ux, uy, uz); + return; + } + + // Protection 2 + if (py == 0 && px != 0) { + + ux = -(pz * pz) / px; + uy = sign * sqrt(px * px - (pz * pz * pz * pz) / (px * px)); + uz = pz; + u.SetXYZ(ux, uy, uz); + return; + } + + // Equation Parameters + double a = px * px + py * py; + double b = 2.0 * px * pz * pz; + double c = pz * pz * pz * pz - py * py * py * py - px * px * py * py; + double delta = b * b - 4.0 * a * c; + + // Protection agains delta<0 + if (delta < 0) { + return; + } + + // Solutions + ux = (-b + sign * sqrt(delta)) / (2.0 * a); + uy = (-pz * pz - px * ux) / py; + uz = pz; + u.SetXYZ(ux, uy, uz); + return; + } + + template + void fillHistograms(U const& tracks) + { + std::vector> fTempBufferProton; + std::vector> fTempBufferAntiproton; + std::vector> fTempBufferDeuteron; + std::vector> fTempBufferAntideuteron; + std::vector> fTempBufferJet; + std::vector> fTempBufferFull; + fTempBufferProton.clear(); + fTempBufferAntiproton.clear(); + fTempBufferDeuteron.clear(); + fTempBufferAntideuteron.clear(); + fTempBufferJet.clear(); + fTempBufferFull.clear(); std::vector jetInput; - std::vector jets; - std::vector constituents; + std::map particles; + std::vector particlesForCF; + jetInput.clear(); + particles.clear(); + int index = 0; + int leadingID = 0; fastjet::PseudoJet hardestJet(0., 0., 0., 0.); fastjet::PseudoJet subtractedJet(0., 0., 0., 0.); - jetInput.clear(); + std::vector jets; + std::vector constituents; jets.clear(); constituents.clear(); for (const auto& track : tracks) { - registryData.fill(HIST("hTrackProtocol"), 0); - registryData.fill(HIST("hEtaFullEvent"), track.eta()); - registryData.fill(HIST("hPtFullEvent"), track.pt()); + if (!selectTrack(track)) + continue; + + double mass; + if (track.hasTOF()) { + mass = track.mass(); // check reliability, maybe use only pion mass + registryQA.fill(HIST("hTOFmass"), track.pt(), track.mass()); + registryData.fill(HIST("hTrackProtocol"), 1); + } else { + mass = 0.139; // pion mass as default, ~80% are pions + registryData.fill(HIST("hTrackProtocol"), 2); + } + + if (track.pt() > fMinLeadingPt) { + leadingID = track.globalIndex(); + } - fastjet::PseudoJet inputPseudoJet(track.px(), track.py(), track.pz(), track.energy(track.mass())); // is this fine? just TOF for invariant mass? - inputPseudoJet.set_user_index(track.globalIndex()); + if (track.tpcNClsFindable() != 0) { + registryQA.fill(HIST("hRatioCrossedRowsTPC"), track.pt(), track.tpcNClsCrossedRows() / track.tpcNClsFindable()); + } + registryQA.fill(HIST("hPtFullEvent"), track.pt()); + registryQA.fill(HIST("hEtaFullEvent"), track.eta()); + registryQA.fill(HIST("hCrossedRowsTPC"), track.pt(), track.tpcNClsCrossedRows()); + registryQA.fill(HIST("hClusterITS"), track.pt(), track.itsNCls()); + registryQA.fill(HIST("hClusterTPC"), track.pt(), track.tpcNClsFound()); + registryQA.fill(HIST("hChi2ITS"), track.pt(), track.itsChi2NCl()); + registryQA.fill(HIST("hChi2TPC"), track.pt(), track.tpcChi2NCl()); + registryQA.fill(HIST("hDCAxyFullEvent"), track.pt(), track.dcaXY()); + registryQA.fill(HIST("hDCAzFullEvent"), track.pt(), track.dcaZ()); + fastjet::PseudoJet inputPseudoJet(track.px(), track.py(), track.pz(), track.energy(mass)); + inputPseudoJet.set_user_index(index); + particles[index] = track; + particlesForCF.emplace_back(track); jetInput.emplace_back(inputPseudoJet); - } + + index++; + } // for (const auto& track : tracks) if (jetInput.size() < 2) return; - registryData.fill(HIST("hEventProtocol"), 1); + registryData.fill(HIST("hEventProtocol"), 2); + // Reconstruct Jets double ghost_maxrap = 1.0; double ghost_area = 0.005; int ghost_repeat = 1; - fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, fJetRadius); + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, fJetR); fastjet::JetDefinition jetDefBkg(fastjet::kt_algorithm, 0.5); fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(ghost_maxrap, ghost_repeat, ghost_area)); fastjet::AreaDefinition areaDefBkg(fastjet::active_area_explicit_ghosts, fastjet::GhostedAreaSpec(ghost_maxrap)); - fastjet::ClusterSequenceArea clusterSeq(jetInput, jetDef, areaDef); // or CSActiveArea? + fastjet::ClusterSequenceArea clusterSeq(jetInput, jetDef, areaDef); jets = sorted_by_pt(clusterSeq.inclusive_jets()); + if (jets.size() == 0) return; - registryData.fill(HIST("hEventProtocol"), 2); + + registryData.fill(HIST("hEventProtocol"), 3); hardestJet = jets[0]; if (hardestJet.pt() < fMinJetPt) return; - registryData.fill(HIST("hEventProtocol"), 3); - if (hardestJet.constituents().size() < 2) - return; + registryData.fill(HIST("hEventProtocol"), 4); + if (hardestJet.constituents().size() < 2) // unlikely but maybe yields before this point? + return; + + registryData.fill(HIST("hEventProtocol"), 5); registryData.fill(HIST("hNumberOfJets"), 0); registryData.fill(HIST("hPtTotalJet"), hardestJet.pt()); registryData.fill(HIST("hJetRapidity"), hardestJet.rap()); + registryData.fill(HIST("hNumPartInJet"), hardestJet.constituents().size()); + registryQA.fill(HIST("hJetPtVsNumPart"), hardestJet.pt(), hardestJet.constituents().size()); - constituents = hardestJet.constituents(); - - for (int i = 0; i < constituents.size(); i++) { - registryData.fill(HIST("hPtJetParticle"), constituents[i].pt()); - double DeltaPhi = TVector2::Phi_0_2pi(constituents[i].phi() - hardestJet.phi()); - double DeltaEta = constituents[i].eta() - hardestJet.eta(); - double Delta = TMath::Sqrt(DeltaPhi * DeltaPhi + DeltaEta * DeltaEta) / (constituents[i].pt() * constituents[i].pt()); // need 1/pT^2? + for (const auto& constituent : hardestJet.constituents()) { + registryData.fill(HIST("hPtJetParticle"), constituent.pt()); + if (std::isnan(constituent.phi()) || std::isnan(hardestJet.phi())) + continue; + double DeltaPhi = TVector2::Phi_0_2pi(constituent.phi() - hardestJet.phi()); + double DeltaEta = constituent.eta() - hardestJet.eta(); + double Delta = TMath::Sqrt(DeltaPhi * DeltaPhi + DeltaEta * DeltaEta); registryData.fill(HIST("hJetConeRadius"), Delta); } - fastjet::Selector selector = fastjet::SelectorAbsEtaMax(1.0) * (!fastjet::SelectorNHardest(2)); // fix! + fastjet::Selector selector = fastjet::SelectorAbsEtaMax(1.0) * (!fastjet::SelectorNHardest(2)); // TODO: fix subtraction -> check PWGJE fastjet::JetMedianBackgroundEstimator bkgEst(selector, jetDefBkg, areaDefBkg); fastjet::Subtractor subtractor(&bkgEst); subtractor.set_use_rho_m(true); @@ -237,338 +879,268 @@ struct AngularCorrelationsInJets { subtractedJet = subtractor(hardestJet); if (subtractedJet.has_constituents()) { - for (int i = 0; i < subtractedJet.constituents().size(); i++) { - registryData.fill(HIST("hPtSubtractedJet"), subtractedJet.constituents()[i].pt()); + for (const auto& subConstituent : subtractedJet.constituents()) { + registryData.fill(HIST("hPtSubtractedJet"), subConstituent.pt()); } } - std::vector jetProtons; - std::vector jetAntiprotons; - std::vector jetDeuterons; - std::vector jetAntideuterons; + if (!hardestJet.has_constituents()) + return; + constituents = hardestJet.constituents(); + + // QA for comparison with nuclei_in_jets + const auto& leadingTrack = tracks.iteratorAt(leadingID); + TVector3 pLeading(leadingTrack.px(), leadingTrack.py(), leadingTrack.pz()); + TVector3 pJet(hardestJet.px(), hardestJet.py(), hardestJet.pz()); + TVector3 UEAxis1(0.0, 0.0, 0.0); + TVector3 UEAxis2(0.0, 0.0, 0.0); + getPerpendicularAxis(pJet, UEAxis1, +1.0); + getPerpendicularAxis(pJet, UEAxis2, -1.0); - for (int i = 0; i < constituents.size(); i++) { - fastjet::PseudoJet pseudoParticle = constituents[i]; + doCorrelations(particlesForCF, fBufferFull, fTempBufferFull, -1, pJet); + setTrackBuffer(fTempBufferFull, fBufferFull); + + if (UEAxis1.Mag() == 0 || UEAxis2.Mag() == 0) + return; + double deltaEta = pLeading.Eta() - pJet.Eta(); + double deltaPhi = getDeltaPhi(pLeading.Phi(), pJet.Phi()); + registryQA.fill(HIST("hPtLeading"), leadingTrack.pt()); + registryQA.fill(HIST("hPhiLeading"), leadingTrack.phi()); + registryQA.fill(HIST("hEtaLeading"), leadingTrack.eta()); + registryQA.fill(HIST("hAngleJetLeadingTrack"), (180.0 / TMath::Pi()) * pLeading.Angle(pJet)); + if (deltaPhi != -999) + registryQA.fill(HIST("hDeltaEtadeltaPhiLeadingJet"), deltaEta, deltaPhi); + + double NchJetPlusUE(0); + double NchJet(0); + double NchUE(0); + double ptJetPlusUE(0); + double ptJet(0); + double ptUE(0); + + for (const auto& [index, track] : particles) { + TVector3 particleDir(track.px(), track.py(), track.pz()); + double deltaEtaJet = particleDir.Eta() - pJet.Eta(); + double deltaPhiJet = getDeltaPhi(particleDir.Phi(), pJet.Phi()); + double deltaRJet = sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + double deltaEtaUE1 = particleDir.Eta() - UEAxis1.Eta(); + double deltaPhiUE1 = getDeltaPhi(particleDir.Phi(), UEAxis1.Phi()); + double deltaRUE1 = sqrt(deltaEtaUE1 * deltaEtaUE1 + deltaPhiUE1 * deltaPhiUE1); + double deltaEtaUE2 = particleDir.Eta() - UEAxis2.Eta(); + double deltaPhiUE2 = getDeltaPhi(particleDir.Phi(), UEAxis2.Phi()); + double deltaRUE2 = sqrt(deltaEtaUE2 * deltaEtaUE2 + deltaPhiUE2 * deltaPhiUE2); + + if (deltaRJet < fRmax) { + if (deltaPhiJet != -999) + registryQA.fill(HIST("hDeltaEtadeltaPhiJet"), deltaEtaJet, deltaPhiJet); + registryQA.fill(HIST("hRJet"), deltaRJet); + NchJetPlusUE++; + ptJetPlusUE = ptJetPlusUE + track.pt(); + } + if (deltaRUE1 < fRmax) { + if (deltaPhiUE1 != -999) + registryQA.fill(HIST("hDeltaEtadeltaPhiUE"), deltaEtaUE1, deltaPhiUE1); + registryQA.fill(HIST("hRUE"), deltaRUE1); + NchUE++; + ptUE = ptUE + track.pt(); + } + if (deltaRUE2 < fRmax) { + if (deltaPhiUE2 != -999) + registryQA.fill(HIST("hDeltaEtadeltaPhiUE"), deltaEtaUE2, deltaPhiUE2); + registryQA.fill(HIST("hRUE"), deltaRUE2); + NchUE++; + ptUE = ptUE + track.pt(); + } + } // for (const auto& [index, track] : particles) + + NchJet = NchJetPlusUE - 0.5 * NchUE; + ptJet = ptJetPlusUE - 0.5 * ptUE; + registryQA.fill(HIST("hMultiplicityJetPlusUE"), NchJetPlusUE); + registryQA.fill(HIST("hMultiplicityJet"), NchJet); + registryQA.fill(HIST("hMultiplicityUE"), 0.5 * NchUE); + registryQA.fill(HIST("hPtJetPlusUE"), ptJetPlusUE); + registryQA.fill(HIST("hPtJet"), ptJet); + registryQA.fill(HIST("hPtUE"), 0.5 * ptUE); + registryQA.fill(HIST("hDeltaJetPt"), hardestJet.pt() - ptJetPlusUE); + + int nPartClusteredJet = static_cast(constituents.size()); + + // Fill QA Histograms + if (ptJetPlusUE < fMinJetPt) { + + registryQA.fill(HIST("hNParticlesClusteredInJet"), nPartClusteredJet); + double dEta = pLeading.Eta() - pJet.Eta(); + double dPhi = getDeltaPhi(pLeading.Phi(), pJet.Phi()); + if (dPhi != -999) + registryQA.fill(HIST("hDeltaEtaDeltaPhiJetAxisLeading"), dEta, dPhi); + + for (const auto& track : constituents) { + TVector3 particleDir(track.px(), track.py(), track.pz()); + double dEta = particleDir.Eta() - pJet.Eta(); + double dPhi = getDeltaPhi(particleDir.Phi(), pJet.Phi()); + registryQA.fill(HIST("hPtParticlesClusteredInJet"), track.pt()); + if (dPhi != -999) + registryQA.fill(HIST("hDeltaEtaDeltaPhiJetAxis"), dEta, dPhi); + } + } + + std::vector jetProtons; + std::vector jetAntiprotons; + std::vector jetDeuterons; + std::vector jetAntideuterons; + std::vector jetHelium; + std::vector jetAntihelium; + std::vector jetAll; + + for (int i = 0; i < static_cast(constituents.size()); i++) { + registryData.fill(HIST("hTrackProtocol"), 3); + fastjet::PseudoJet pseudoParticle = constituents.at(i); int id = pseudoParticle.user_index(); - typename TracksType::iterator jetParticle = tracks.iteratorAt(id); + const auto& jetParticle = particles[id]; + jetAll.emplace_back(jetParticle); + registryData.fill(HIST("hDCAxyFullJet"), jetParticle.pt() * jetParticle.sign(), jetParticle.dcaXY()); registryData.fill(HIST("hDCAzFullJet"), jetParticle.pt() * jetParticle.sign(), jetParticle.dcaZ()); - registryData.fill(HIST("hTPCnsigma"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcNSigmaPr()); - registryData.fill(HIST("hTOFnsigma"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaPr()); + registryData.fill(HIST("hTPCsignal"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcSignal()); + if (jetParticle.hasTOF()) + registryData.fill(HIST("hTOFsignal"), jetParticle.pt() * jetParticle.sign(), jetParticle.beta()); double ptDiff = pseudoParticle.pt() - jetParticle.pt(); registryData.fill(HIST("hPtDiff"), ptDiff); - int particleType = 0; if (jetParticle.pt() < fMinJetParticlePt) continue; - if (IsProton(jetParticle) || IsAntiproton(jetParticle)) { // collect (anti)protons in jet + if (isProton(jetParticle, false)) { // collect protons in jet + registryData.fill(HIST("hPtJetProton"), jetParticle.pt()); registryData.fill(HIST("hTPCnsigmaProton"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcNSigmaPr()); - registryData.fill(HIST("hTOFnsigmaProton"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaPr()); - if (IsProton(jetParticle)) { - particleType = 1; - registryData.fill(HIST("hTrackProtocol"), 6); // # protons + if (jetParticle.hasTOF()) + registryData.fill(HIST("hTOFnsigmaProton"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaPr()); + registryData.fill(HIST("hTrackProtocol"), 4); // # protons + if (isProton(jetParticle, true)) { + registryData.fill(HIST("hTrackProtocol"), 5); // # high purity protons jetProtons.emplace_back(jetParticle); - } else { - particleType = 2; - registryData.fill(HIST("hTrackProtocol"), 7); // # antiprotons + registryData.fill(HIST("hDCAzJetProton"), jetParticle.pt(), jetParticle.dcaZ()); + } + } else if (isAntiproton(jetParticle, false)) { // collect antiprotons in jet + registryData.fill(HIST("hPtJetAntiproton"), jetParticle.pt()); + registryData.fill(HIST("hTPCnsigmaProton"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcNSigmaPr()); + if (jetParticle.hasTOF()) + registryData.fill(HIST("hTOFnsigmaProton"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaPr()); + registryData.fill(HIST("hTrackProtocol"), 6); // # antiprotons + if (isAntiproton(jetParticle, true)) { + registryData.fill(HIST("hTrackProtocol"), 7); // # high purity antiprotons jetAntiprotons.emplace_back(jetParticle); + registryData.fill(HIST("hDCAzJetAntiproton"), jetParticle.pt(), jetParticle.dcaZ()); } - } else if (IsDeuteron(jetParticle) || IsAntideuteron(jetParticle)) { // collect (anti)deuterons in jet + } else if (isDeuteron(jetParticle, false)) { // collect deuterons in jet + registryData.fill(HIST("hPtJetDeuteron"), jetParticle.pt()); registryData.fill(HIST("hTPCnsigmaDeuteron"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcNSigmaDe()); - registryData.fill(HIST("hTOFnsigmaDeuteron"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaDe()); - if (IsDeuteron(jetParticle)) { - particleType = 3; - registryData.fill(HIST("hTrackProtocol"), 8); // # deuterons + if (jetParticle.hasTOF()) + registryData.fill(HIST("hTOFnsigmaDeuteron"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaDe()); + registryData.fill(HIST("hTrackProtocol"), 8); // # deuterons + if (isDeuteron(jetParticle, true)) { + registryData.fill(HIST("hTrackProtocol"), 9); // # high purity deuterons jetDeuterons.emplace_back(jetParticle); + registryData.fill(HIST("hDCAzJetDeuteron"), jetParticle.pt(), jetParticle.dcaZ()); + } + } else if (isAntideuteron(jetParticle, false)) { + registryData.fill(HIST("hPtJetAntideuteron"), jetParticle.pt()); + registryData.fill(HIST("hTPCnsigmaDeuteron"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcNSigmaDe()); + if (jetParticle.hasTOF()) + registryData.fill(HIST("hTOFnsigmaDeuteron"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaDe()); + registryData.fill(HIST("hTrackProtocol"), 10); // # antideuterons + if (isAntideuteron(jetParticle, true)) { + registryData.fill(HIST("hTrackProtocol"), 11); // # high purity antideuterons + jetAntideuterons.emplace_back(jetParticle); + registryData.fill(HIST("hDCAzJetAntideuteron"), jetParticle.pt(), jetParticle.dcaZ()); + } + } else if (isHelium(jetParticle) || isAntihelium(jetParticle)) { // collect (anti)helium in jet + registryData.fill(HIST("hPtJetHelium"), jetParticle.pt()); + registryData.fill(HIST("hTPCnsigmaHelium"), jetParticle.pt() * jetParticle.sign(), jetParticle.tpcNSigmaHe()); + if (jetParticle.hasTOF()) + registryData.fill(HIST("hTOFnsigmaHelium"), jetParticle.pt() * jetParticle.sign(), jetParticle.tofNSigmaHe()); + if (isHelium(jetParticle)) { + registryData.fill(HIST("hTrackProtocol"), 12); // # helium + jetDeuterons.emplace_back(jetParticle); + registryData.fill(HIST("hDCAzJetHelium"), jetParticle.pt(), jetParticle.dcaZ()); } else { - particleType = 4; - registryData.fill(HIST("hTrackProtocol"), 9); // # antideuterons + registryData.fill(HIST("hTrackProtocol"), 13); // # antihelium jetAntideuterons.emplace_back(jetParticle); + registryData.fill(HIST("hDCAzJetAntihelium"), jetParticle.pt(), jetParticle.dcaZ()); } } - registryData.fill(HIST("hPtJetProtonDeuteron"), particleType, jetParticle.pt()); - } // for (int i=0; i<(int)constituents.size(); i++) + } // for (int i=0; i(constituents.size()); i++) + + if (jetAll.size() > 1) { // general correlation function + doCorrelations(jetAll, fBufferJet, fTempBufferJet, 0, pJet); + setTrackBuffer(fTempBufferJet, fBufferJet); + } if ((jetProtons.size() < 2) && (jetAntiprotons.size() < 2) && (jetDeuterons.size() < 2) && (jetAntideuterons.size() < 2)) return; - registryData.fill(HIST("hEventProtocol"), 5); + registryData.fill(HIST("hEventProtocol"), 6); if (jetProtons.size() > 1) { - for (int i = 0; i < jetProtons.size(); i++) { - for (int j = i + 1; j < jetProtons.size(); j++) { - double DeltaPhi = TVector2::Phi_0_2pi(jetProtons[i].phi() - jetProtons[j].phi()); - double DeltaEta = TMath::Abs(jetProtons[i].eta() - jetProtons[j].eta()); - if (DeltaPhi > (1.5 * TMath::Pi())) { - DeltaPhi = DeltaPhi - 2 * TMath::Pi(); - } - registryData.fill(HIST("hDeltaPhiSE"), 1, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaSE"), 1, DeltaPhi, DeltaEta); - } - FillMixedEventDeltas(jetProtons[i], 1); - SetTrackBuffer(jetProtons[i], 1); - } + doCorrelations(jetProtons, fBufferProton, fTempBufferProton, 1, pJet); + setTrackBuffer(fTempBufferProton, fBufferProton); } if (jetAntiprotons.size() > 1) { - for (int i = 0; i < jetAntiprotons.size(); i++) { - for (int j = i + 1; j < jetAntiprotons.size(); j++) { - double DeltaPhi = TVector2::Phi_0_2pi(jetAntiprotons[i].phi() - jetAntiprotons[j].phi()); - double DeltaEta = TMath::Abs(jetAntiprotons[i].eta() - jetAntiprotons[j].eta()); - if (DeltaPhi > (1.5 * TMath::Pi())) { - DeltaPhi = DeltaPhi - 2 * TMath::Pi(); - } - registryData.fill(HIST("hDeltaPhiSE"), 2, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaSE"), 2, DeltaPhi, DeltaEta); - } - FillMixedEventDeltas(jetAntiprotons[i], 2); - SetTrackBuffer(jetAntiprotons[i], 2); - } + doCorrelations(jetAntiprotons, fBufferAntiproton, fTempBufferAntiproton, 2, pJet); + setTrackBuffer(fTempBufferAntiproton, fBufferAntiproton); } if (jetDeuterons.size() > 1) { - for (int i = 0; i < jetDeuterons.size(); i++) { - for (int j = i + 1; j < jetDeuterons.size(); j++) { - double DeltaPhi = TVector2::Phi_0_2pi(jetDeuterons[i].phi() - jetDeuterons[j].phi()); - double DeltaEta = TMath::Abs(jetDeuterons[i].eta() - jetDeuterons[j].eta()); - if (DeltaPhi > (1.5 * TMath::Pi())) { - DeltaPhi = DeltaPhi - 2 * TMath::Pi(); - } - registryData.fill(HIST("hDeltaPhiSE"), 3, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaSE"), 3, DeltaPhi, DeltaEta); - } - FillMixedEventDeltas(jetDeuterons[i], 3); - SetTrackBuffer(jetDeuterons[i], 3); - } + doCorrelations(jetDeuterons, fBufferDeuteron, fTempBufferDeuteron, 3, pJet); + setTrackBuffer(fTempBufferDeuteron, fBufferDeuteron); } if (jetAntideuterons.size() > 1) { - for (int i = 0; i < jetAntideuterons.size(); i++) { - for (int j = i + 1; j < jetAntideuterons.size(); j++) { - double DeltaPhi = TVector2::Phi_0_2pi(jetAntideuterons[i].phi() - jetAntideuterons[j].phi()); - double DeltaEta = TMath::Abs(jetAntideuterons[i].eta() - jetAntideuterons[j].eta()); - if (DeltaPhi > (1.5 * TMath::Pi())) { - DeltaPhi = DeltaPhi - 2 * TMath::Pi(); - } - registryData.fill(HIST("hDeltaPhiSE"), 4, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaSE"), 4, DeltaPhi, DeltaEta); - } - FillMixedEventDeltas(jetAntideuterons[i], 4); - SetTrackBuffer(jetAntideuterons[i], 4); - } + doCorrelations(jetAntideuterons, fBufferAntideuteron, fTempBufferAntideuteron, 4, pJet); + setTrackBuffer(fTempBufferAntideuteron, fBufferAntideuteron); } } - template - bool IsProton(const T1& track) - { - bool isProton = false; - if (track.sign() < 0) - return isProton; - - if (track.pt() < fProtonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) < fProtonTPCnsigLow) - isProton = true; - if (track.pt() > fProtonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) < fProtonTPCnsigHigh) - isProton = true; - - registryData.fill(HIST("hDCAzJetProton"), track.pt() * track.sign(), track.dcaZ()); - - if (TMath::Abs(track.dcaXY()) > fProtonDCAxy) - return false; - if (TMath::Abs(track.dcaZ()) > fProtonDCAz) - return false; - - if (track.pt() < fProtonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) < fProtonTOFnsigLow) - isProton = true; - if (track.pt() > fProtonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) < fProtonTOFnsigHigh) - isProton = true; - - return isProton; - } - - template - bool IsAntiproton(const T2& track) - { - bool isAntiproton = false; - if (track.sign() < 0) - return isAntiproton; - - if (track.pt() < fAntiprotonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) < fAntiprotonTPCnsigLow) - isAntiproton = true; - if (track.pt() > fAntiprotonTPCTOFpT && TMath::Abs(track.tpcNSigmaPr()) < fAntiprotonTPCnsigHigh) - isAntiproton = true; - - registryData.fill(HIST("hDCAzJetAntiproton"), track.pt() * track.sign(), track.dcaZ()); - - if (TMath::Abs(track.dcaXY()) > fAntiprotonDCAxy) - return false; - if (TMath::Abs(track.dcaZ()) > fAntiprotonDCAz) - return false; - - if (track.pt() < fAntiprotonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) < fAntiprotonTOFnsigLow) - isAntiproton = true; - if (track.pt() > fAntiprotonTPCTOFpT && TMath::Abs(track.tofNSigmaPr()) < fAntiprotonTOFnsigHigh) - isAntiproton = true; - - return isAntiproton; - } - - template - bool IsDeuteron(const T3& track) - { - bool isDeuteron = false; - if (track.sign() < 0) - return isDeuteron; - - if (track.pt() < fDeuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) < fDeuteronTPCnsigLow) - isDeuteron = true; - if (track.pt() > fDeuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) < fDeuteronTPCnsigHigh) - isDeuteron = true; - - registryData.fill(HIST("hDCAzJetDeuteron"), track.pt() * track.sign(), track.dcaZ()); - - if (TMath::Abs(track.dcaXY()) > fDeuteronDCAxy) - return false; - if (TMath::Abs(track.dcaZ()) > fDeuteronDCAz) - return false; - - if (track.pt() < fDeuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) < fDeuteronTOFnsigLow) - isDeuteron = true; - if (track.pt() > fDeuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) < fDeuteronTOFnsigHigh) - isDeuteron = true; - - return isDeuteron; - } - - template - bool IsAntideuteron(const T4& track) + void processRun2(soa::Join const& collisions, + soa::Filtered const& tracks, + BCsWithRun2Info const&) { - bool isAntideuteron = false; - if (track.sign() < 0) - return isAntideuteron; + for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); - if (track.pt() < fAntideuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) < fAntideuteronTPCnsigLow) - isAntideuteron = true; - if (track.pt() > fAntideuteronTPCTOFpT && TMath::Abs(track.tpcNSigmaDe()) < fAntideuteronTPCnsigHigh) - isAntideuteron = true; - - registryData.fill(HIST("hDCAzJetAntideuteron"), track.pt() * track.sign(), track.dcaZ()); - - if (TMath::Abs(track.dcaXY()) > fAntideuteronDCAxy) - return false; - if (TMath::Abs(track.dcaZ()) > fAntideuteronDCAz) - return false; - - if (track.pt() < fAntideuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) < fAntideuteronTOFnsigLow) - isAntideuteron = true; - if (track.pt() > fAntideuteronTPCTOFpT && TMath::Abs(track.tofNSigmaDe()) < fAntideuteronTOFnsigHigh) - isAntideuteron = true; + registryData.fill(HIST("hEventProtocol"), 0); + registryData.fill(HIST("hNumberOfEvents"), 0); + if (!collision.alias_bit(kINT7)) + continue; + registryData.fill(HIST("hEventProtocol"), 1); - return isAntideuteron; - } + auto slicedTracks = tracks.sliceBy(perCollisionFullTracksRun2, collision.globalIndex()); - template - void SetTrackBuffer(const T5& track, int particleType) - { - switch (particleType) { - case 1: - if (fTrackBufferProton.size() == fTrackBufferSize) { - fTrackBufferProton.insert(fTrackBufferProton.begin(), track); - fTrackBufferProton.resize(fTrackBufferSize); - } else if (fTrackBufferProton.size() < fTrackBufferSize) { - fTrackBufferProton.emplace_back(track); - } - break; - case 2: - if (fTrackBufferAntiproton.size() == fTrackBufferSize) { - fTrackBufferAntiproton.insert(fTrackBufferAntiproton.begin(), track); - fTrackBufferAntiproton.resize(fTrackBufferSize); - } else if (fTrackBufferAntiproton.size() < fTrackBufferSize) { - fTrackBufferAntiproton.emplace_back(track); - } - break; - case 3: - if (fTrackBufferDeuteron.size() == fTrackBufferSize) { - fTrackBufferDeuteron.insert(fTrackBufferDeuteron.begin(), track); - fTrackBufferDeuteron.resize(fTrackBufferSize); - } else if (fTrackBufferDeuteron.size() < fTrackBufferSize) { - fTrackBufferDeuteron.emplace_back(track); - } - break; - case 4: - if (fTrackBufferAntideuteron.size() == fTrackBufferSize) { - fTrackBufferAntideuteron.insert(fTrackBufferAntideuteron.begin(), track); - fTrackBufferAntideuteron.resize(fTrackBufferSize); - } else if (fTrackBufferAntideuteron.size() < fTrackBufferSize) { - fTrackBufferAntideuteron.emplace_back(track); - } - break; - default: - LOG(warn) << "SetTrackBuffer: invalid particle ID!"; + fillHistograms(slicedTracks); } } + PROCESS_SWITCH(AngularCorrelationsInJets, processRun2, "process Run 2 data", true); - template - void FillMixedEventDeltas(const T6& track, int particleType) + void processRun3(soa::Join const& collisions, + soa::Filtered const& tracks) { - switch (particleType) { - case 1: - if (fTrackBufferProton.size() == 0) - return; - for (int i = 0; i < fTrackBufferProton.size(); i++) { // can I do this even if the track buffer isn't even full yet? - double DeltaPhi = TVector2::Phi_0_2pi(track.phi() - fTrackBufferProton[i].phi()); - double DeltaEta = TMath::Abs(track.eta() - fTrackBufferProton[i].eta()); - registryData.fill(HIST("hDeltaPhiME"), particleType, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaME"), particleType, DeltaPhi, DeltaEta); - } - break; - case 2: - if (fTrackBufferAntiproton.size() == 0) - return; - for (int i = 0; i < fTrackBufferAntiproton.size(); i++) { - double DeltaPhi = TVector2::Phi_0_2pi(track.phi() - fTrackBufferAntiproton[i].phi()); - double DeltaEta = TMath::Abs(track.eta() - fTrackBufferAntiproton[i].eta()); - registryData.fill(HIST("hDeltaPhiME"), particleType, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaME"), particleType, DeltaPhi, DeltaEta); - } - break; - case 3: - if (fTrackBufferDeuteron.size() == 0) - return; - for (int i = 0; i < fTrackBufferDeuteron.size(); i++) { - double DeltaPhi = TVector2::Phi_0_2pi(track.phi() - fTrackBufferDeuteron[i].phi()); - double DeltaEta = TMath::Abs(track.eta() - fTrackBufferDeuteron[i].eta()); - registryData.fill(HIST("hDeltaPhiME"), particleType, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaME"), particleType, DeltaPhi, DeltaEta); - } - break; - case 4: - if (fTrackBufferAntideuteron.size() == 0) - return; - for (int i = 0; i < fTrackBufferAntideuteron.size(); i++) { - double DeltaPhi = TVector2::Phi_0_2pi(track.phi() - fTrackBufferAntideuteron[i].phi()); - double DeltaEta = TMath::Abs(track.eta() - fTrackBufferAntideuteron[i].eta()); - registryData.fill(HIST("hDeltaPhiME"), particleType, DeltaPhi); - registryData.fill(HIST("hDeltaPhiEtaME"), particleType, DeltaPhi, DeltaEta); - } - break; - default: - LOG(warn) << "FillMixedEventDeltas: invalid particle ID!"; - } - } - - //**************************************************************************************************** + for (const auto& collision : collisions) { + registryData.fill(HIST("hEventProtocol"), 0); + registryData.fill(HIST("hNumberOfEvents"), 0); + if (!collision.sel8()) + continue; + registryData.fill(HIST("hEventProtocol"), 1); + if (TMath::Abs(collision.posZ()) > fZVtx) + continue; - Filter prelimTrackCuts = (/* aod::track::TPCrefit == fTPCRefit && */ aod::track::itsChi2NCl < fMaxChi2ITS && aod::track::tpcChi2NCl < fMaxChi2TPC && nabs(aod::track::dcaXY) < fMaxDCAxy && nabs(aod::track::dcaZ) < fMaxDCAz && nabs(aod::track::eta) < fMaxEta); + auto slicedTracks = tracks.sliceBy(perCollisionFullTracksRun3, collision.globalIndex()); - void process_ang_corr_data(aod::Collision const& collision, soa::Filtered const& tracks) - { - angCorrData(collision, tracks); + fillHistograms(slicedTracks); + } } - PROCESS_SWITCH(AngularCorrelationsInJets, process_ang_corr_data, "ang correlations in reco'ed jets", true); + PROCESS_SWITCH(AngularCorrelationsInJets, processRun3, "process Run 3 data", false); }; -//**************************************************************************************************** - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"angular-correlations-in-jets"})}; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/Nuspex/AntimatterAbsorptionHMPID.cxx b/PWGLF/Tasks/Nuspex/AntimatterAbsorptionHMPID.cxx index 09382abe08a..b5a5a2c3ee4 100644 --- a/PWGLF/Tasks/Nuspex/AntimatterAbsorptionHMPID.cxx +++ b/PWGLF/Tasks/Nuspex/AntimatterAbsorptionHMPID.cxx @@ -26,18 +26,19 @@ #include "Framework/RunningWorkflowInfo.h" #include "Framework/DataTypes.h" #include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/PID/PIDTOF.h" #include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/TrackParametrization.h" #include "ReconstructionDataFormats/DCA.h" #include "DetectorsBase/Propagator.h" #include "Common/Core/trackUtilities.h" #include "ReconstructionDataFormats/PID.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "DataFormatsParameters/GRPMagField.h" using namespace o2; using namespace o2::framework; @@ -78,9 +79,23 @@ struct AntimatterAbsorptionHMPID { Configurable maxDCAxy{"maxDCAxy", 0.5f, "maxDCAxy"}; Configurable maxDCAz{"maxDCAz", 0.5f, "maxDCAz"}; Configurable use_hmpid_mom{"use_hmpid_mom", true, "use hmpid momentum"}; + // CCDB configurable + + Service ccdb; + struct : ConfigurableGroup { + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + } ccdbConfig; void init(o2::framework::InitContext&) { + // Configure CCDB + ccdb->setURL(ccdbConfig.ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Event Counter registryQC.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "counter"}}); @@ -304,6 +319,19 @@ struct AntimatterAbsorptionHMPID { return true; } + int mCCDBRunNumber = 0; + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mCCDBRunNumber == bc.runNumber()) { + return; + } + o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(ccdbConfig.grpmagPath, bc.timestamp()); + o2::base::MatLayerCylSet* lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbConfig.lutPath)); + o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); + mCCDBRunNumber = bc.runNumber(); + } + o2::track::TrackParametrizationWithError mPropagatedTrack; template bool propagateToRadius(const trackType& track, const float radius, const o2::track::PID::ID pidForTracking) @@ -322,16 +350,18 @@ struct AntimatterAbsorptionHMPID { } // Full Tracks - using TracksCandidates = soa::Join; + using CollisionCandidates = o2::soa::Join; + using TrackCandidates = soa::Join; // Process Data - void processData(o2::soa::Join::iterator const& event, + void processData(CollisionCandidates::iterator const& event, o2::aod::HMPIDs const& hmpids, - TracksCandidates const&) + TrackCandidates const&, + aod::BCsWithTimestamps const&) { + initCCDB(event.bc_as()); // Event Selection registryQC.fill(HIST("number_of_events_data"), 0.5); @@ -353,7 +383,7 @@ struct AntimatterAbsorptionHMPID { for (const auto& hmpid : hmpids) { // Get Track - const auto& track = hmpid.track_as(); + const auto& track = hmpid.track_as(); // Track Momentum float momentum = track.p(); diff --git a/PWGLF/Tasks/Nuspex/CMakeLists.txt b/PWGLF/Tasks/Nuspex/CMakeLists.txt index a69ac7d6743..8507049a6ad 100644 --- a/PWGLF/Tasks/Nuspex/CMakeLists.txt +++ b/PWGLF/Tasks/Nuspex/CMakeLists.txt @@ -31,7 +31,7 @@ o2physics_add_dpl_workflow(hypertriton3bodyanalysis o2physics_add_dpl_workflow(hypertriton3bodymcqa SOURCES hypertriton3bodyMCQA.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2::TOFBase COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(nuclei-in-jets @@ -134,6 +134,11 @@ o2physics_add_dpl_workflow(nuclei-ebye PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(nuclei-toward-transv + SOURCES nuclei_in_toward_transv_regions.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + if(FastJet_FOUND) o2physics_add_dpl_workflow(angular-correlations-in-jets SOURCES AngularCorrelationsInJets.cxx diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx index fef2e6e54a4..d1f0f3f3977 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx @@ -101,11 +101,11 @@ struct LFNucleiBATask { // Set the axis used in this task ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Centrality FT0M"}; - ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.5, 7.0, 7.5, 8.0}, ""}; + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.425, 0.45, 0.475, 0.5, 0.5125, 0.525, 0.5375, 0.55, 0.5625, 0.575, 0.5875, 0.6, 0.6125, 0.625, 0.6375, 0.65, 0.6625, 0.675, 0.6875, 0.7, 0.7125, 0.725, 0.7375, 0.75, 0.7625, 0.775, 0.7875, 0.8, 0.8125, 0.825, 0.8375, 0.85, 0.8625, 0.875, 0.8875, 0.9, 0.9125, 0.925, 0.9375, 0.95, 0.9625, 0.975, 0.9875, 1.0, 1.0125, 1.025, 1.0375, 1.05, 1.0625, 1.075, 1.0875, 1.1, 1.1125, 1.125, 1.1375, 1.15, 1.1625, 1.175, 1.1875, 1.2, 1.2125, 1.225, 1.2375, 1.25, 1.2625, 1.275, 1.2875, 1.3, 1.3125, 1.325, 1.3375, 1.35, 1.3625, 1.375, 1.3875, 1.4, 1.4125, 1.425, 1.4375, 1.45, 1.4625, 1.475, 1.4875, 1.5, 1.5125, 1.525, 1.5375, 1.55, 1.5625, 1.575, 1.5875, 1.6, 1.6125, 1.625, 1.6375, 1.65, 1.6625, 1.675, 1.6875, 1.7, 1.7125, 1.725, 1.7375, 1.75, 1.7625, 1.775, 1.7875, 1.8, 1.8125, 1.825, 1.8375, 1.85, 1.8625, 1.875, 1.8875, 1.9, 1.9125, 1.925, 1.9375, 1.95, 1.9625, 1.975, 1.9875, 2.0, 2.0625, 2.125, 2.1875, 2.25, 2.3125, 2.375, 2.4375, 2.5, 2.625, 2.75, 2.875, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, ""}; ConfigurableAxis binsPtHe{"binsPtHe", {VARIABLE_WIDTH, 1.0, 1.25, 1.50, 1.75, 2.0, 2.25, 2.50, 2.75, 3.0, 3.25, 3.50, 3.75, 4.0, 4.50, 5.0, 6.0, 7.0, 8.0}, ""}; ConfigurableAxis binsPtZHe{"binsPtZHe", {VARIABLE_WIDTH, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.375, 1.5, 1.625, 1.75, 1.875, 2.0, 2.25, 2.5, 3.0, 3.5, 4.0}, ""}; - ConfigurableAxis binsdEdx{"binsdEdx", {1000, 0.f, 1000.f}, ""}; + ConfigurableAxis binsdEdx{"binsdEdx", {600, 0.f, 3000.f}, ""}; ConfigurableAxis binsBeta{"binsBeta", {120, 0.0, 1.2}, ""}; ConfigurableAxis binsDCA{"binsDCA", {400, -1.f, 1.f}, ""}; ConfigurableAxis binsSigmaTPC{"binsSigmaTPC", {1000, -100, 100}, ""}; @@ -126,19 +126,20 @@ struct LFNucleiBATask { Configurable DCAzCustomCut{"DCAzCustomCut", 0.5f, "Value of the DCAz selection for spectra (default 0.5 cm)"}; } dcaConfOptions; - Configurable> parDCAxycuts{"parDCAxycuts", {0.004, 0.013, 1, 1}, "Parameters for Pt dependent DCAxy cut (if enabled): |DCAxy| < [3] * ([O] + [1]/Pt^[2])."}; - Configurable> parDCAzcuts{"parDCAzcuts", {0.004, 0.013, 1, 1}, "Parameters for Pt dependent DCAz cut (if enabled): |DCAz| < [3] * ([O] + [1]/Pt^[2])."}; + Configurable> parDCAxycuts{"parDCAxycuts", {0.004f, 0.013f, 1, 1}, "Parameters for Pt dependent DCAxy cut (if enabled): |DCAxy| < [3] * ([O] + [1]/Pt^[2])."}; + Configurable> parDCAzcuts{"parDCAzcuts", {0.004f, 0.013f, 1, 1}, "Parameters for Pt dependent DCAz cut (if enabled): |DCAz| < [3] * ([O] + [1]/Pt^[2])."}; // Enable output histograms - Configurable makeDCABeforeCutPlots{"makeDCABeforeCutPlots", false, "Flag to enable plots of DCA before cuts"}; - Configurable makeDCAAfterCutPlots{"makeDCAAfterCutPlots", false, "Flag to enable plots of DCA after cuts"}; - Configurable doTOFplots{"doTOFplots", true, "Flag to export plots of tracks with 1 hit on TOF."}; - Configurable enableExpSignalTPC{"enableExpSignalTPC", true, "Flag to export dEdX - dEdX(exp) plots."}; - Configurable enableExpSignalTOF{"enableExpSignalTOF", false, "Flag to export T - T(exp) plots."}; + struct : ConfigurableGroup { + Configurable makeDCABeforeCutPlots{"makeDCABeforeCutPlots", false, "Flag to enable plots of DCA before cuts"}; + Configurable makeDCAAfterCutPlots{"makeDCAAfterCutPlots", false, "Flag to enable plots of DCA after cuts"}; + Configurable doTOFplots{"doTOFplots", true, "Flag to export plots of tracks with 1 hit on TOF."}; + Configurable enableExpSignalTPC{"enableExpSignalTPC", true, "Flag to export dEdX - dEdX(exp) plots."}; + Configurable enableExpSignalTOF{"enableExpSignalTOF", false, "Flag to export T - T(exp) plots."}; + Configurable enableBetaCut{"enableBetaCut", false, "Flag to enable TOF histograms with beta cut for debug"}; + } outFlagOptions; Configurable enablePIDplot{"enablePIDplot", false, "Flag to enable PID histograms for debug"}; - Configurable enableBetaCut{"enableBetaCut", false, "Flag to enable TOF histograms with beta cut for debug"}; - Configurable enableDebug{"enableDebug", false, "Flag to enable histograms for debug"}; Configurable enablePtSpectra{"enablePtSpectra", false, "Flag to enable histograms for efficiency debug."}; @@ -260,13 +261,13 @@ struct LFNucleiBATask { if (enablePtSpectra) { histos.add("tracks/eff/h2pVsTPCmomentum", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); - if (doTOFplots) + if (outFlagOptions.doTOFplots) histos.add("tracks/eff/h2TPCmomentumVsTOFExpMomentum", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); if (enablePr) { histos.add("tracks/eff/proton/h2pVsTPCmomentumPr", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/proton/h2pVsTPCmomentumantiPr", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/eff/proton/h2pVsTOFExpMomentumPr", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/proton/h2pVsTOFExpMomentumantiPr", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumPr", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); @@ -276,7 +277,7 @@ struct LFNucleiBATask { if (enableDe) { histos.add("tracks/eff/deuteron/h2pVsTPCmomentumDe", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/deuteron/h2pVsTPCmomentumantiDe", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/eff/deuteron/h2pVsTOFExpMomentumDe", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/deuteron/h2pVsTOFExpMomentumantiDe", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumDe", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); @@ -286,7 +287,7 @@ struct LFNucleiBATask { if (enableTr) { histos.add("tracks/eff/triton/h2pVsTPCmomentumTr", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/triton/h2pVsTPCmomentumantiTr", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/eff/triton/h2pVsTOFExpMomentumTr", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/triton/h2pVsTOFExpMomentumantiTr", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumTr", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); @@ -296,7 +297,7 @@ struct LFNucleiBATask { if (enableHe) { histos.add("tracks/eff/helium/h2pVsTPCmomentumHe", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/helium/h2pVsTPCmomentumantiHe", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/eff/helium/h2pVsTOFExpMomentumHe", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/helium/h2pVsTOFExpMomentumantiHe", "#it{p}_{TOF} vs #it{p}; #it{p}_{TOF}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); histos.add("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumHe", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); @@ -320,7 +321,7 @@ struct LFNucleiBATask { debugHistos.add("tracks/eff/hPtPrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); debugHistos.add("tracks/eff/hPtantiPrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { debugHistos.add("tracks/eff/hPtPTOF", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); debugHistos.add("tracks/eff/hPtantiPTOF", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); debugHistos.add("tracks/eff/hPtPTOFrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); @@ -359,25 +360,25 @@ struct LFNucleiBATask { } // tracks // DCAxy,z - if (makeDCABeforeCutPlots) { - histos.add("tracks/dca/before/hDCAxyVsDCAzVsPt", "DCAxy vs DCAz vs Pt/z; DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); - histos.add("tracks/dca/before/hDCAxyVsDCAz", "DCAxy vs DCAz (before cuts)", HistType::kTH2F, {{1100, -1.1, 1.1}, {1100, -1.1, 1.1}}); + if (outFlagOptions.makeDCABeforeCutPlots) { + histos.add("tracks/dca/before/hDCAxyVsDCAzVsPt", "DCAxy vs DCAz vs Pt/z; DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); + histos.add("tracks/dca/before/hDCAxyVsDCAz", "DCAxy vs DCAz (before cuts)", HistType::kTH2F, {{550, -1.1, 1.1}, {550, -1.1, 1.1}}); histos.add("tracks/dca/before/hDCAxy", "DCAxy", HistType::kTH1F, {dcaxyAxis}); histos.add("tracks/dca/before/hDCAz", "DCAz", HistType::kTH1F, {dcazAxis}); - histos.add("tracks/dca/before/hDCAxyVsPt", "DCAxy vs Pt", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/dca/before/hDCAzVsPt", "DCAz vs Pt", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/dca/before/hDCAxyVsPt", "DCAxy vs Pt", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/dca/before/hDCAzVsPt", "DCAz vs Pt", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); if (enablePr) { - // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtProton", "DCAxy vs DCAz vs Pt/z (p)", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtantiProton", "DCAxy vs DCAz vs Pt/z (#bar{p})", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); + // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtProton", "DCAxy vs DCAz vs Pt/z (p)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); + // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtantiProton", "DCAxy vs DCAz vs Pt/z (#bar{p})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableDe) { - // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtDeuteron", "DCAxy vs DCAz vs Pt/z (d)", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtantiDeuteron", "DCAxy vs DCAz vs Pt/z (#bar{d})", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); + // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtDeuteron", "DCAxy vs DCAz vs Pt/z (d)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); + // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtantiDeuteron", "DCAxy vs DCAz vs Pt/z (#bar{d})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); if (enableCentrality) { histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult", "DCAxy vs Pt (d)", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult", "DCAxy vs Pt (#bar{d})", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); @@ -388,44 +389,44 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF", "DCAxy vs Pt (d)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF", "DCAz vs Pt (d)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableTr) { - // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtTriton", "DCAxy vs DCAz vs Pt/z (t)", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtantiTriton", "DCAxy vs DCAz vs Pt/z (#bar{t})", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtHe}}); + // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtTriton", "DCAxy vs DCAz vs Pt/z (t)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); + // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtantiTriton", "DCAxy vs DCAz vs Pt/z (#bar{t})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtTriton", "DCAxy vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTriton", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAzVsPtTriton", "DCAz vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/triton/dca/before/hDCAzVsPtantiTriton", "DCAz vs Pt (#bar{t})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableHe) { - histos.add("tracks/helium/dca/before/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/before/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF", "DCAxy vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF", "DCAz vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - - if (doTOFplots) { - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He) (w/TOF); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}) (w/TOF); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/before/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + + if (outFlagOptions.doTOFplots) { + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He) (w/TOF); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}) (w/TOF); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); } } if (enableAl) { - // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtAlpha", "DCAxy vs DCAz vs Pt/z (#alpha)", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtantiAlpha", "DCAxy vs DCAz vs Pt/z (#bar{#alpha})", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); + // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtAlpha", "DCAxy vs DCAz vs Pt/z (#alpha)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtantiAlpha", "DCAxy vs DCAz vs Pt/z (#bar{#alpha})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlpha", "DCAxy vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlpha", "DCAxy vs Pt (#bar{#alpha})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAzVsPtAlpha", "DCAz vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -433,48 +434,48 @@ struct LFNucleiBATask { } } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/dca/after/hDCAxy", "DCAxy; DCAxy; counts", HistType::kTH1F, {{dcaxyAxis}}); histos.add("tracks/dca/after/hDCAz", "DCAz; DCAz; counts", HistType::kTH1F, {{dcazAxis}}); - histos.add("tracks/dca/after/hDCAxyVsPt", "DCAxy vs Pt", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/dca/after/hDCAzVsPt", "DCAz vs Pt", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/dca/after/hDCAxyVsPt", "DCAxy vs Pt", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/dca/after/hDCAzVsPt", "DCAz vs Pt", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (enablePr && makeDCAAfterCutPlots) { + if (enablePr && outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/proton/dca/after/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/after/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/after/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/after/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (enableDe && makeDCAAfterCutPlots) { + if (enableDe && outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteron", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (enableTr && makeDCAAfterCutPlots) { + if (enableTr && outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/triton/dca/after/hDCAxyVsPtTriton", "DCAxy vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTriton", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/after/hDCAzVsPtTriton", "DCAz vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/triton/dca/after/hDCAzVsPtantiTriton", "DCAz vs Pt (#bar{t})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (enableHe && makeDCAAfterCutPlots) { - histos.add("tracks/helium/dca/after/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/after/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - - if (doTOFplots) { - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}); DCAxy; DCAz", HistType::kTH3F, {{240, -0.6f, 0.6f}, {320, -0.8f, 0.8f}, {binsPtZHe}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + if (enableHe && outFlagOptions.makeDCAAfterCutPlots) { + histos.add("tracks/helium/dca/after/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/after/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + + if (outFlagOptions.doTOFplots) { + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsDCAzVsPtantiHelium", "DCAxy vs DCAz vs Pt/z (#bar{He}); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHelium", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHelium", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); } } - if (enableAl && makeDCAAfterCutPlots) { + if (enableAl && outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlpha", "DCAxy vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/after/hDCAxyVsPtantiAlpha", "DCAxy vs Pt (#bar{#alpha})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/after/hDCAzVsPtAlpha", "DCAz vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -742,14 +743,14 @@ struct LFNucleiBATask { histos.add("tracks/helium/h1antiHeliumSpectraTrueSec_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1antiHeliumSpectraTrueTransport_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/helium/TOF/h1HeliumSpectraTruePrim_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/TOF/h1antiHeliumSpectraTruePrim_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); } if (enablePtSpectra) { histos.add("tracks/eff/helium/hPtHeTrue", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); histos.add("tracks/eff/helium/hPtantiHeTrue", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/eff/helium/hPtHeTOFTrue", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); histos.add("tracks/eff/helium/hPtantiHeTOFTrue", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); } @@ -768,7 +769,7 @@ struct LFNucleiBATask { } // 2D-DCAxy if (enablePr) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -781,34 +782,34 @@ struct LFNucleiBATask { histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueSec", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueTransport", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - if (doTOFplots) { - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + if (outFlagOptions.doTOFplots) { + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrueSec", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrueTransport", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrueSec", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrueTransport", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrue", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrue", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTruePrim", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrueSec", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrueTransport", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTruePrim", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrueSec", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrueTransport", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrueSec", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrueTransport", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrueSec", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrueTransport", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrue", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrue", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTruePrim", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrueSec", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrueTransport", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTruePrim", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrueSec", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrueTransport", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/proton/dca/after/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/after/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -823,7 +824,7 @@ struct LFNucleiBATask { } } if (enableDe) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -849,94 +850,94 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - if (doTOFplots) { - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + if (outFlagOptions.doTOFplots) { + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/TOF/wrong/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/TOF/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -953,7 +954,7 @@ struct LFNucleiBATask { } } if (enableTr) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/triton/dca/before/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -966,7 +967,7 @@ struct LFNucleiBATask { histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueSec", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueTransport", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/triton/dca/before/TOF/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/TOF/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -993,7 +994,7 @@ struct LFNucleiBATask { } } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/triton/dca/after/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/after/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -1006,7 +1007,7 @@ struct LFNucleiBATask { histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueSec", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueTransport", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/triton/dca/after/TOF/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/after/TOF/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -1035,210 +1036,210 @@ struct LFNucleiBATask { } if (enableHe) { // all tracks - if (makeDCABeforeCutPlots) { - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + if (outFlagOptions.makeDCABeforeCutPlots) { + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - if (doTOFplots) { - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + if (outFlagOptions.doTOFplots) { + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); } // Fake & wrong histos - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - if (doTOFplots) { - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + if (outFlagOptions.doTOFplots) { + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); } } - if (makeDCAAfterCutPlots) { - histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + if (outFlagOptions.makeDCAAfterCutPlots) { + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - if (doTOFplots) { - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + if (outFlagOptions.doTOFplots) { + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); - histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{900, 0.5f, 5.f}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); } } } if (enableAl) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrue", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlphaTruePrim", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -1252,7 +1253,7 @@ struct LFNucleiBATask { histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrueTransport", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrue", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlphaTruePrim", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); @@ -1268,7 +1269,7 @@ struct LFNucleiBATask { } // 2D-DCAz if (enablePr) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/proton/dca/before/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1281,7 +1282,7 @@ struct LFNucleiBATask { histos.add("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueSec", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueTransport", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/proton/dca/after/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/after/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1296,7 +1297,7 @@ struct LFNucleiBATask { } } if (enableDe) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1321,20 +1322,20 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/fake/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + // histos.add("tracks/deuteron/dca/before/wrong/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1351,7 +1352,7 @@ struct LFNucleiBATask { } } if (enableTr) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/triton/dca/before/hDCAzVsPtTritonTrue", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/triton/dca/before/hDCAzVsPtTritonTruePrim", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1365,7 +1366,7 @@ struct LFNucleiBATask { histos.add("tracks/triton/dca/before/hDCAzVsPtantiTritonTrueTransport", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/triton/dca/after/hDCAzVsPtTritonTrue", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/triton/dca/after/hDCAzVsPtTritonTruePrim", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1381,7 +1382,7 @@ struct LFNucleiBATask { } if (enableAl) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.add("tracks/alpha/dca/before/hDCAzVsPtAlphaTrue", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/alpha/dca/before/hDCAzVsPtAlphaTruePrim", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1395,7 +1396,7 @@ struct LFNucleiBATask { histos.add("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrueTransport", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.add("tracks/alpha/dca/after/hDCAzVsPtAlphaTrue", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/alpha/dca/after/hDCAzVsPtAlphaTruePrim", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1412,42 +1413,42 @@ struct LFNucleiBATask { } // Bethe-Bloch TPC distribution and Beta vs pT TOF distribution - histos.add("tracks/h2TPCsignVsTPCmomentum", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, -5.f, 5.f}, {dedxAxis}}); + histos.add("tracks/h2TPCsignVsTPCmomentum", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); if (enableDebug) { - debugHistos.add("debug/h2TPCsignVsTPCmomentum_AllTracks", "TPC <-dE/dX> vs #it{p}/Z (w/o rejection); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, -5.f, 5.f}, {dedxAxis}}); - debugHistos.add("debug/h2TPCsignVsTPCmomentum_FakeHits", "TPC <-dE/dX> vs #it{p}/Z (Fake hits); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, -5.f, 5.f}, {dedxAxis}}); + debugHistos.add("debug/h2TPCsignVsTPCmomentum_AllTracks", "TPC <-dE/dX> vs #it{p}/Z (w/o rejection); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); + debugHistos.add("debug/h2TPCsignVsTPCmomentum_FakeHits", "TPC <-dE/dX> vs #it{p}/Z (Fake hits); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); } if (enablePIDplot) { if (enablePr) { - histos.add("tracks/proton/h2TPCsignVsTPCmomentumProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); - histos.add("tracks/proton/h2TPCsignVsTPCmomentumantiProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); + histos.add("tracks/proton/h2TPCsignVsTPCmomentumProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/proton/h2TPCsignVsTPCmomentumantiProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); - histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); + histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); } if (enableTr) { - histos.add("tracks/triton/h2TPCsignVsTPCmomentumTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); - histos.add("tracks/triton/h2TPCsignVsTPCmomentumantiTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); + histos.add("tracks/triton/h2TPCsignVsTPCmomentumTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/triton/h2TPCsignVsTPCmomentumantiTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); } if (enableHe) { - histos.add("tracks/helium/h2TPCsignVsTPCmomentumHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); - histos.add("tracks/helium/h2TPCsignVsTPCmomentumantiHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); + histos.add("tracks/helium/h2TPCsignVsTPCmomentumHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/helium/h2TPCsignVsTPCmomentumantiHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); } if (enableAl) { - histos.add("tracks/alpha/h2TPCsignVsTPCmomentumAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); - histos.add("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{500, 0.f, 5.f}, {dedxAxis}}); + histos.add("tracks/alpha/h2TPCsignVsTPCmomentumAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); } } - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { histos.add("tracks/h2TPCsignVsBetaGamma", "TPC <-dE/dX> vs #beta#gamma/Z; Signed #beta#gamma; TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, -5.f, 5.f}, {dedxAxis}}); histos.add("tracks/h2TOFbetaVsP", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); - if (enableBetaCut) + if (outFlagOptions.enableBetaCut) histos.add("tracks/h2TOFbetaVsP_BetaCut", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); } - if (enableExpSignalTPC) { + if (outFlagOptions.enableExpSignalTPC) { // TPCExpSignal histograms if (enablePr) { histos.add("tracks/proton/h2ProtonTPCExpSignalDiffVsPt", "TPC <-dE/dX> - Exp <-dE/dX> (p) vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (p)", HistType::kTH2F, {{ptAxis}, {16000, -800, 800.}}); @@ -1498,7 +1499,7 @@ struct LFNucleiBATask { } // TOF plots - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { // TOF beta histograms if (enablePr) { histos.add("tracks/proton/h2ProtonTOFbetaVsP", "TOF #beta (p) vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta (p)", HistType::kTH2F, {{250, 0.f, 5.f}, {betaAxis}}); @@ -1516,7 +1517,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2HeliumTOFbetaVsP", "TOF #beta (He) vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta (He)", HistType::kTH2F, {{250, 0.f, 5.f}, {betaAxis}}); histos.add("tracks/helium/h2antiHeliumTOFbetaVsP", "TOF #beta (#bar{He}) vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta (#bar{He})", HistType::kTH2F, {{250, 0.f, 5.f}, {betaAxis}}); } - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { // TOFExpSignal histograms if (enablePr) { histos.add("tracks/proton/h2ProtonTOFExpSignalDiffVsPt", "TOF t - t_{exp}(p) vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TOF t - t_{exp} (p)", HistType::kTH2F, {{ptAxis}, {2000, -25000, 25000}}); @@ -1560,7 +1561,7 @@ struct LFNucleiBATask { if (enablePr) { histos.add("tracks/proton/h2TOFmassProtonVsPt", "h2TOFmassProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/proton/h2TOFmassantiProtonVsPt", "h2TOFmassantiProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/proton/h2TOFmassProtonVsPt_BetaCut", "h2TOFmassProtonVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/proton/h2TOFmassantiProtonVsPt_BetaCut", "h2TOFmassantiProtonVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); } @@ -1568,7 +1569,7 @@ struct LFNucleiBATask { if (enableDe) { histos.add("tracks/deuteron/h2TOFmassDeuteronVsPt", "h2TOFmassDeuteronVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/deuteron/h2TOFmassantiDeuteronVsPt", "h2TOFmassantiDeuteronVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/deuteron/h2TOFmassDeuteronVsPt_BetaCut", "h2TOFmassDeuteronVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/deuteron/h2TOFmassantiDeuteronVsPt_BetaCut", "h2TOFmassantiDeuteronVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); } @@ -1576,7 +1577,7 @@ struct LFNucleiBATask { if (enableTr) { histos.add("tracks/triton/h2TOFmassTritonVsPt", "h2TOFmassTritonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/triton/h2TOFmassantiTritonVsPt", "h2TOFmassantiTritonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/triton/h2TOFmassTritonVsPt_BetaCut", "h2TOFmassTritonVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/triton/h2TOFmassantiTritonVsPt_BetaCut", "h2TOFmassantiTritonVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); } @@ -1584,7 +1585,7 @@ struct LFNucleiBATask { if (enableHe) { histos.add("tracks/helium/h2TOFmassHeliumVsPt", "h2TOFmassHeliumVsPt; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); histos.add("tracks/helium/h2TOFmassantiHeliumVsPt", "h2TOFmassantiHeliumVsPt; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/helium/h2TOFmassHeliumVsPt_BetaCut", "h2TOFmassHeliumVsPt_BetaCut; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); histos.add("tracks/helium/h2TOFmassantiHeliumVsPt_BetaCut", "h2TOFmassantiHeliumVsPt_BetaCut; TOFmass; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {ptZHeAxis}}); } @@ -1593,7 +1594,7 @@ struct LFNucleiBATask { if (enablePr) { histos.add("tracks/proton/h2TOFmass2ProtonVsPt", "#Delta M^{2} (p) vs #it{p}_{T}; #Delta M^{2} (p); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); histos.add("tracks/proton/h2TOFmass2antiProtonVsPt", "#Delta M^{2} (#bar{p}) vs #it{p}_{T}; #Delta M^{2} (#bar{p}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/proton/h2TOFmass2ProtonVsPt_BetaCut", "#Delta M^{2} (p) vs #it{p}_{T}; #Delta M^{2} (p); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); histos.add("tracks/proton/h2TOFmass2antiProtonVsPt_BetaCut", "#Delta M^{2} (#bar{p}) vs #it{p}_{T}; #Delta M^{2} (#bar{p}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massPrAxis}, {250, 0., 5.}}); } @@ -1606,7 +1607,7 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/h2TOFmass2DeuteronVsPt", "#Delta M^{2} (d) vs #it{p}_{T}; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); histos.add("tracks/deuteron/h2TOFmass2antiDeuteronVsPt", "#Delta M^{2} (#bar{d}) vs #it{p}_{T}; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); } - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/deuteron/h2TOFmass2DeuteronVsPt_BetaCut", "#Delta M^{2} (d) vs #it{p}_{T}; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); histos.add("tracks/deuteron/h2TOFmass2antiDeuteronVsPt_BetaCut", "#Delta M^{2} (#bar{d}) vs #it{p}_{T}; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); } @@ -1614,7 +1615,7 @@ struct LFNucleiBATask { if (enableTr) { histos.add("tracks/triton/h2TOFmass2TritonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; #Delta M^{2} (t); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); histos.add("tracks/triton/h2TOFmass2antiTritonVsPt", "#Delta M^{2} (#bar{t}) vs #it{p}_{T}; #Delta M^{2} (#bar{t}; #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/triton/h2TOFmass2TritonVsPt_BetaCut", "#Delta M^{2} (t) vs #it{p}_{T}; #Delta M^{2} (t); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); histos.add("tracks/triton/h2TOFmass2antiTritonVsPt_BetaCut", "#Delta M^{2} (#bar{t}) vs #it{p}_{T}; #Delta M^{2} (#bar{t}; #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massTrAxis}, {250, 0., 5.}}); } @@ -1624,7 +1625,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2TOFmass2HeliumVsPt", "#Delta M^{2} (He) vs #it{p}_{T}/z; #Delta M^{2} (He); #it{p}_{T}/z (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); histos.add("tracks/helium/h2TOFmassDeltaHeliumVsPt", "#Delta M (He) vs #it{p}_{T}/z; #Delta M (He); #it{p}_{T}/z (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); histos.add("tracks/helium/h2TOFmassDeltaantiHeliumVsPt", "#Delta M (#bar{He}) vs #it{p}_{T}/z; #Delta M (#bar{He}); #it{p}_{T}/z (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); - if (enableBetaCut) { + if (outFlagOptions.enableBetaCut) { histos.add("tracks/helium/h2TOFmass2antiHeliumVsPt_BetaCut", "#Delta M^{2} (#bar{He}) vs #it{p}_{T}/z; #Delta M^{2} (#bar{He}); #it{p}_{T}/z (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); histos.add("tracks/helium/h2TOFmass2HeliumVsPt_BetaCut", "#Delta M^{2} (He) vs #it{p}_{T}/z; #Delta M^{2} (He); #it{p}_{T}/z (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); } @@ -1643,7 +1644,7 @@ struct LFNucleiBATask { evtimeHistos.add("tracks/evtime/ft0/h2TOFbetaVsP", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{500, -5.f, 5.f}, {betaAxis}}); evtimeHistos.add("tracks/evtime/ft0tof/h2TOFbetaVsP", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{500, -5.f, 5.f}, {betaAxis}}); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { // TOFExpSignal histograms - TOF EvTime Splitted if (enablePr) { evtimeHistos.add("tracks/evtime/fill/proton/h2ProtonTOFExpSignalDiffVsPt", "TOF t - t_{exp}(p) vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TOF t - t_{exp} (p)", HistType::kTH2F, {{ptAxis}, {2000, -25000, 25000}}); @@ -1802,7 +1803,7 @@ struct LFNucleiBATask { debugHistos.add("debug/evtime/ft0tof/deuteron/h2antiDeuteronVspTNSigmaTOF_BetaCut", "NSigmaTOF(#bar{d}) vs pT (#beta < 0.5); #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {SigmaTOFAxis}}); } - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { // TOFExpSignal histograms - TOF EvTime Splitted if (enablePr) { debugHistos.add("debug/evtime/fill/proton/h2ProtonTOFExpSignalDiffVsPt_BetaCut", "TOF t - t_{exp}(p) vs #it{p}_{T} (#beta < 0.5); #it{p}_{T} (GeV/#it{c}); TOF t - t_{exp} (p)", HistType::kTH2F, {{ptAxis}, {2000, -25000, 25000}}); @@ -2321,19 +2322,19 @@ struct LFNucleiBATask { passDCAxyzCut = passDCAxyCut && passDCAzCut; // DCAxy vs DCAz plots BEFORE cut - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/dca/before/hDCAxyVsDCAzVsPt"), track.dcaXY(), track.dcaZ(), track.pt()); histos.fill(HIST("tracks/dca/before/hDCAxyVsDCAz"), track.dcaZ(), track.dcaXY()); if (isHe && std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsDCAzVsPtHelium"), track.dcaXY(), track.dcaZ(), hePt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtHelium"), track.dcaXY(), track.dcaZ(), hePt); } } if (isAntiHe && std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsDCAzVsPtantiHelium"), track.dcaXY(), track.dcaZ(), antihePt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtantiHelium"), track.dcaXY(), track.dcaZ(), antihePt); } } @@ -2387,7 +2388,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHelium"), hePt, track.dcaZ()); if (!track.hasTOF()) histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHelium"), hePt, track.dcaZ()); } } @@ -2396,7 +2397,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); if (!track.hasTOF()) histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); } } @@ -2424,17 +2425,17 @@ struct LFNucleiBATask { pdgCode = track.mcParticle().pdgCode(); } - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { switch (pdgCode) { case PDGProton: if (enablePr && prRapCut && passDCAxyCut) { histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTrue"), track.pt(), track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrue"), track.pt(), track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTruePrim"), track.pt(), track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTruePrim"), track.pt(), track.dcaZ()); } } @@ -2443,7 +2444,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTrueSec"), track.pt(), track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrueTransport"), track.pt(), track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtProtonTrueSec"), track.pt(), track.dcaZ()); @@ -2455,12 +2456,12 @@ struct LFNucleiBATask { case -PDGProton: if (enablePr && prRapCut && passDCAxyCut) { histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTrue"), track.pt(), track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrue"), track.pt(), track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTruePrim"), track.pt(), track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTruePrim"), track.pt(), track.dcaZ()); } } @@ -2469,7 +2470,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueSec"), track.pt(), track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrueTransport"), hePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAzVsPtantiProtonTrueSec"), hePt, track.dcaZ()); @@ -2481,12 +2482,12 @@ struct LFNucleiBATask { case PDGDeuteron: if (isDeWoDCAz) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrue"), DPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrue"), DPt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTruePrim"), DPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTruePrim"), DPt, track.dcaZ()); } } @@ -2495,7 +2496,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrueSec"), DPt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrueTransport"), DPt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtDeuteronTrueSec"), DPt, track.dcaZ()); @@ -2507,12 +2508,12 @@ struct LFNucleiBATask { case -PDGDeuteron: if (isAntiDeWoDCAz) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrue"), antiDPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrue"), antiDPt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTruePrim"), antiDPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTruePrim"), antiDPt, track.dcaZ()); } } @@ -2521,7 +2522,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrueSec"), antiDPt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAzVsPtantiDeuteronTrueSec"), antiDPt, track.dcaZ()); @@ -2561,12 +2562,12 @@ struct LFNucleiBATask { case PDGHelium: if (isHeWoDCAz) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); } } @@ -2575,7 +2576,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); @@ -2587,12 +2588,12 @@ struct LFNucleiBATask { if ((event.has_mcCollision() && (track.mcParticle().mcCollisionId() != event.mcCollisionId())) || !event.has_mcCollision()) { if (isHeWoDCAz) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); } } @@ -2601,7 +2602,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); @@ -2615,12 +2616,12 @@ struct LFNucleiBATask { case -PDGHelium: if (isAntiHeWoDCAz) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); } } @@ -2629,7 +2630,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrueTransport"), antihePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); @@ -2641,12 +2642,12 @@ struct LFNucleiBATask { if ((event.has_mcCollision() && (track.mcParticle().mcCollisionId() != event.mcCollisionId())) || !event.has_mcCollision()) { if (isAntiHeWoDCAz) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); } } @@ -2655,7 +2656,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrueTransport"), antihePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); @@ -2705,12 +2706,12 @@ struct LFNucleiBATask { default: if (isDeWoDCAzWTPCpid) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAzVsPtDeuteronTrue"), DPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrue"), DPt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAzVsPtDeuteronTruePrim"), DPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTruePrim"), DPt, track.dcaZ()); } } @@ -2719,7 +2720,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAzVsPtDeuteronTrueSec"), DPt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrueTransport"), DPt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrueSec"), DPt, track.dcaZ()); @@ -2728,12 +2729,12 @@ struct LFNucleiBATask { } } else if (isAntiDeWoDCAzWTPCpid) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAzVsPtantiDeuteronTrue"), antiDPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrue"), antiDPt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAzVsPtantiDeuteronTruePrim"), antiDPt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTruePrim"), antiDPt, track.dcaZ()); } } @@ -2742,7 +2743,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAzVsPtantiDeuteronTrueSec"), antiDPt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtantiDeuteronTrueSec"), antiDPt, track.dcaZ()); @@ -2760,12 +2761,12 @@ struct LFNucleiBATask { default: if (isHeWoDCAzWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); } } @@ -2774,7 +2775,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); @@ -2784,12 +2785,12 @@ struct LFNucleiBATask { } if (isAntiHeWoDCAzWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); } } @@ -2798,7 +2799,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrueTransport"), antihePt, track.dcaZ()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); @@ -2811,7 +2812,7 @@ struct LFNucleiBATask { } } // Tracks DCA histos fill - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { if (passDCAzCut) { histos.fill(HIST("tracks/dca/before/hDCAxy"), track.dcaXY()); histos.fill(HIST("tracks/dca/before/hDCAxyVsPt"), track.pt(), track.dcaXY()); @@ -2871,7 +2872,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHelium"), hePt, track.dcaXY()); if (!track.hasTOF()) histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHelium"), hePt, track.dcaXY()); } } @@ -2879,7 +2880,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); if (!track.hasTOF()) histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); } } @@ -2924,14 +2925,14 @@ struct LFNucleiBATask { } switch (pdgCode) { case PDGProton: - if (enablePr && prRapCut && makeDCABeforeCutPlots && passDCAzCut) { + if (enablePr && prRapCut && outFlagOptions.makeDCABeforeCutPlots && passDCAzCut) { histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTrue"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrue"), track.pt(), track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTruePrim"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTruePrim"), track.pt(), track.dcaXY()); } } @@ -2940,7 +2941,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTrueSec"), track.pt(), track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrueTransport"), track.pt(), track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtProtonTrueSec"), track.pt(), track.dcaXY()); @@ -2950,14 +2951,14 @@ struct LFNucleiBATask { } break; case -PDGProton: - if (enablePr && prRapCut && makeDCABeforeCutPlots && passDCAzCut) { + if (enablePr && prRapCut && outFlagOptions.makeDCABeforeCutPlots && passDCAzCut) { histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrue"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrue"), track.pt(), track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTruePrim"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTruePrim"), track.pt(), track.dcaXY()); } } @@ -2966,7 +2967,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueSec"), track.pt(), track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrueTransport"), track.pt(), track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/proton/dca/before/TOF/hDCAxyVsPtantiProtonTrueSec"), track.pt(), track.dcaXY()); @@ -2977,16 +2978,16 @@ struct LFNucleiBATask { break; case PDGDeuteron: if (isDeWoDCAxy) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrue"), DPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrue"), DPt, track.dcaXY()); } } if (isPhysPrim) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTruePrim"), DPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTruePrim"), DPt, track.dcaXY()); } } @@ -3007,14 +3008,14 @@ struct LFNucleiBATask { } } if (!isPhysPrim && !isProdByGen) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueTransport"), DPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueSec"), DPt, track.dcaXY()); } else { // LOG(info) << " PID: "<< pdgCode << " Prod. by Gen: "<< isProdByGen << " Process: " << track.mcParticle().getProcess() << " HasMothers: " << track.mcParticle().has_mothers() << " and MomIs: "<< mother.pdgCode(); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrueTransport"), DPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtDeuteronTrueSec"), DPt, track.dcaXY()); @@ -3026,16 +3027,16 @@ struct LFNucleiBATask { break; case -PDGDeuteron: if (isAntiDeWoDCAxy) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrue"), antiDPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrue"), antiDPt, track.dcaXY()); } } if (isPhysPrim) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTruePrim"), antiDPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTruePrim"), antiDPt, track.dcaXY()); } } @@ -3056,12 +3057,12 @@ struct LFNucleiBATask { } } if (!isPhysPrim && !isProdByGen) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrueSec"), antiDPt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/TOF/hDCAxyVsPtantiDeuteronTrueSec"), antiDPt, track.dcaXY()); @@ -3072,25 +3073,25 @@ struct LFNucleiBATask { } break; case PDGTriton: - if (enableTr && trRapCut && makeDCABeforeCutPlots && passDCAzCut) { + if (enableTr && trRapCut && outFlagOptions.makeDCABeforeCutPlots && passDCAzCut) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTrue"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtTritonTrue"), track.pt(), track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTruePrim"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtTritonTruePrim"), track.pt(), track.dcaXY()); } } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTrueTransport"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtTritonTrueTransport"), track.pt(), track.dcaXY()); } if (isWeakDecay) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTrueSec"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtTritonTrueSec"), track.pt(), track.dcaXY()); } } @@ -3098,15 +3099,15 @@ struct LFNucleiBATask { } break; case -PDGTriton: - if (enableTr && trRapCut && makeDCABeforeCutPlots && passDCAzCut) { + if (enableTr && trRapCut && outFlagOptions.makeDCABeforeCutPlots && passDCAzCut) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrue"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtantiTritonTrue"), track.pt(), track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTruePrim"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtantiTritonTruePrim"), track.pt(), track.dcaXY()); } } @@ -3115,12 +3116,12 @@ struct LFNucleiBATask { } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueTransport"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtantiTritonTrueTransport"), track.pt(), track.dcaXY()); } if (isWeakDecay) { histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueSec"), track.pt(), track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/triton/dca/before/TOF/hDCAxyVsPtantiTritonTrueSec"), track.pt(), track.dcaXY()); } } @@ -3129,9 +3130,9 @@ struct LFNucleiBATask { break; case PDGHelium: if (isHeWoDCAxy) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); } } @@ -3147,19 +3148,19 @@ struct LFNucleiBATask { spectraGen.fill(HIST("helium/histPShiftHe"), 2.f * heP, 2.f * heP - track.mcParticle().p()); spectraGen.fill(HIST("helium/histPShiftVsEtaHe"), track.eta(), 2.f * heP - track.mcParticle().p()); } - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); } } } - if (!isPhysPrim && !isProdByGen && makeDCABeforeCutPlots) { + if (!isPhysPrim && !isProdByGen && outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); @@ -3169,14 +3170,14 @@ struct LFNucleiBATask { } if constexpr (!IsFilteredData) { if ((event.has_mcCollision() && (track.mcParticle().mcCollisionId() != event.mcCollisionId())) || !event.has_mcCollision()) { - if (isHeWoDCAxy && makeDCABeforeCutPlots) { + if (isHeWoDCAxy && outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); } } @@ -3185,7 +3186,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); @@ -3198,9 +3199,9 @@ struct LFNucleiBATask { break; case -PDGHelium: if (isAntiHeWoDCAxy) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); } } @@ -3216,20 +3217,20 @@ struct LFNucleiBATask { spectraGen.fill(HIST("helium/histPShiftantiHe"), 2.f * antiheP, 2.f * antiheP - track.mcParticle().p()); spectraGen.fill(HIST("helium/histPShiftVsEtaantiHe"), track.eta(), 2.f * antiheP - track.mcParticle().p()); } - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); } } } - if (!isPhysPrim && !isProdByGen && makeDCABeforeCutPlots) { + if (!isPhysPrim && !isProdByGen && outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueTransport"), antihePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrueTransport"), antihePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); @@ -3239,14 +3240,14 @@ struct LFNucleiBATask { } if constexpr (!IsFilteredData) { if ((event.has_mcCollision() && (track.mcParticle().mcCollisionId() != event.mcCollisionId())) || !event.has_mcCollision()) { - if (isHeWoDCAxy && makeDCABeforeCutPlots) { + if (isAntiHeWoDCAxy && outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); } } @@ -3255,7 +3256,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrueTransport"), antihePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/wrong/TOF/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); @@ -3267,7 +3268,7 @@ struct LFNucleiBATask { } break; case PDGAlpha: - if (enableAl && alRapCut && makeDCABeforeCutPlots && passDCAzCut) { + if (enableAl && alRapCut && outFlagOptions.makeDCABeforeCutPlots && passDCAzCut) { histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrue"), track.pt(), track.dcaXY()); if (isPhysPrim) { histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtAlphaTruePrim"), track.pt(), track.dcaXY()); @@ -3281,7 +3282,7 @@ struct LFNucleiBATask { } break; case -PDGAlpha: - if (enableAl && alRapCut && makeDCABeforeCutPlots && passDCAzCut) { + if (enableAl && alRapCut && outFlagOptions.makeDCABeforeCutPlots && passDCAzCut) { histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrue"), track.pt(), track.dcaXY()); if (isPhysPrim) { histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTruePrim"), track.pt(), track.dcaXY()); @@ -3303,26 +3304,26 @@ struct LFNucleiBATask { break; default: if (isDeWoDCAxyWTPCpid) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTrue"), DPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrue"), DPt, track.dcaXY()); } } if (isPhysPrim) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTruePrim"), DPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTruePrim"), DPt, track.dcaXY()); } } } if (!isPhysPrim && !isProdByGen) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTrueTransport"), DPt, track.dcaXY()); if (isWeakDecay) histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTrueSec"), DPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueTransport"), DPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueSec"), DPt, track.dcaXY()); @@ -3332,27 +3333,27 @@ struct LFNucleiBATask { } } if (isAntiDeWoDCAxyWTPCpid) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrue"), antiDPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrue"), antiDPt, track.dcaXY()); } } if (isPhysPrim) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTruePrim"), antiDPt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTruePrim"), antiDPt, track.dcaXY()); } } } if (!isPhysPrim && !isProdByGen) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueSec"), antiDPt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueSec"), antiDPt, track.dcaXY()); @@ -3370,14 +3371,14 @@ struct LFNucleiBATask { break; default: if (isHeWoDCAxyWTPCpid) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); } } @@ -3386,7 +3387,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); @@ -3396,14 +3397,14 @@ struct LFNucleiBATask { } } if (isAntiHeWoDCAxyWTPCpid) { - if (makeDCABeforeCutPlots) { + if (outFlagOptions.makeDCABeforeCutPlots) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); } } @@ -3412,7 +3413,7 @@ struct LFNucleiBATask { if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrueTransport"), antihePt, track.dcaXY()); if (isWeakDecay) { histos.fill(HIST("tracks/helium/dca/before/fake/TOF/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); @@ -3440,17 +3441,17 @@ struct LFNucleiBATask { continue; } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { if (isHeWTPCpid) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsDCAzVsPtHelium"), track.dcaXY(), track.dcaZ(), hePt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsDCAzVsPtHelium"), track.dcaXY(), track.dcaZ(), hePt); } } if (isAntiHeWTPCpid) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsDCAzVsPtantiHelium"), track.dcaXY(), track.dcaZ(), antihePt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsDCAzVsPtantiHelium"), track.dcaXY(), track.dcaZ(), antihePt); } } @@ -3510,7 +3511,7 @@ struct LFNucleiBATask { if (isHeWTPCpid) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHelium"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHelium"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtHelium"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtHelium"), hePt, track.dcaZ()); } @@ -3518,7 +3519,7 @@ struct LFNucleiBATask { if (isAntiHeWTPCpid) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); } @@ -3589,7 +3590,7 @@ struct LFNucleiBATask { if (track.sign() > 0) { if (enablePr && prRapCut) { - if (enableExpSignalTPC) + if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/proton/h2ProtonTPCExpSignalDiffVsPt"), track.pt(), track.tpcExpSignalDiffPr()); switch (useHasTRDConfig) { @@ -3616,7 +3617,7 @@ struct LFNucleiBATask { } } else { if (enablePr && prRapCut) { - if (enableExpSignalTPC) + if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/proton/h2antiProtonTPCExpSignalDiffVsPt"), track.pt(), track.tpcExpSignalDiffPr()); switch (useHasTRDConfig) { case 0: @@ -3643,7 +3644,7 @@ struct LFNucleiBATask { } // TOF - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { if (enableDebug) { histos.fill(HIST("tracks/pion/h2PionVspTNSigmaTOF"), track.pt(), track.tofNSigmaPi()); histos.fill(HIST("tracks/kaon/h2KaonVspTNSigmaTOF"), track.pt(), track.tofNSigmaKa()); @@ -3666,7 +3667,7 @@ struct LFNucleiBATask { } break; } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/proton/h2ProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); } @@ -3676,7 +3677,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h2ProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/deuteron/h2DeuteronVspTNSigmaTOF"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h2ProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3696,7 +3697,7 @@ struct LFNucleiBATask { debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2ProtonVspTNSigmaTOF_BetaCut"), track.pt(), track.tofNSigmaPr()); if (enableDe) debugHistos.fill(HIST("debug/evtime/ft0tof/deuteron/h2DeuteronVspTNSigmaTOF_BetaCut"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2ProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) debugHistos.fill(HIST("debug/evtime/ft0tof/deuteron/h2DeuteronTOFExpSignalDiffVsPt_BetaCut"), DPt, track.tofExpSignalDiffDe()); @@ -3708,7 +3709,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0/proton/h2ProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0/deuteron/h2DeuteronVspTNSigmaTOF"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/ft0/proton/h2ProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3727,7 +3728,7 @@ struct LFNucleiBATask { debugHistos.fill(HIST("debug/evtime/ft0/proton/h2ProtonVspTNSigmaTOF_BetaCut"), track.pt(), track.tofNSigmaPr()); if (enableDe) debugHistos.fill(HIST("debug/evtime/ft0/deuteron/h2DeuteronVspTNSigmaTOF_BetaCut"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0/proton/h2ProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3740,7 +3741,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/tof/proton/h2ProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/tof/deuteron/h2DeuteronVspTNSigmaTOF"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/tof/proton/h2ProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3761,7 +3762,7 @@ struct LFNucleiBATask { if (enableDe) debugHistos.fill(HIST("debug/evtime/tof/deuteron/h2DeuteronVspTNSigmaTOF_BetaCut"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/tof/proton/h2ProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3774,7 +3775,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/fill/proton/h2ProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/fill/deuteron/h2DeuteronVspTNSigmaTOF"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/fill/proton/h2ProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3795,7 +3796,7 @@ struct LFNucleiBATask { if (enableDe) debugHistos.fill(HIST("debug/evtime/fill/deuteron/h2DeuteronVspTNSigmaTOF_BetaCut"), DPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/fill/proton/h2ProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3821,7 +3822,7 @@ struct LFNucleiBATask { } break; } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/proton/h2antiProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); } if (enableEvTimeSplitting && track.hasTOF()) { @@ -3830,7 +3831,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h2antiProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/deuteron/h2antiDeuteronVspTNSigmaTOF"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h2antiProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3850,7 +3851,7 @@ struct LFNucleiBATask { if (enableDe) debugHistos.fill(HIST("debug/evtime/ft0tof/deuteron/h2antiDeuteronVspTNSigmaTOF_BetaCut"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2antiProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3863,7 +3864,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0/proton/h2antiProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0/deuteron/h2antiDeuteronVspTNSigmaTOF"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/ft0/proton/h2antiProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3879,7 +3880,7 @@ struct LFNucleiBATask { if (enableDe) debugHistos.fill(HIST("debug/evtime/ft0/deuteron/h2antiDeuteronVspTNSigmaTOF_BetaCut"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0/proton/h2antiProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3892,7 +3893,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/tof/proton/h2antiProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/tof/deuteron/h2antiDeuteronVspTNSigmaTOF"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/tof/proton/h2antiProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3909,7 +3910,7 @@ struct LFNucleiBATask { if (enableDe) debugHistos.fill(HIST("debug/evtime/tof/deuteron/h2antiDeuteronVspTNSigmaTOF_BetaCut"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/tof/proton/h2antiProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3922,7 +3923,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/fill/proton/h2antiProtonVspTNSigmaTOF"), track.pt(), track.tofNSigmaPr()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/fill/deuteron/h2antiDeuteronVspTNSigmaTOF"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) evtimeHistos.fill(HIST("tracks/evtime/fill/proton/h2antiProtonTOFExpSignalDiffVsPt"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3939,7 +3940,7 @@ struct LFNucleiBATask { if (enableDe) debugHistos.fill(HIST("debug/evtime/fill/deuteron/h2antiDeuteronVspTNSigmaTOF_BetaCut"), antiDPt, track.tofNSigmaDe()); - if (enableExpSignalTOF) { + if (outFlagOptions.enableExpSignalTOF) { if (enablePr) debugHistos.fill(HIST("debug/evtime/fill/proton/h2antiProtonTOFExpSignalDiffVsPt_BetaCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableDe) @@ -3953,7 +3954,7 @@ struct LFNucleiBATask { } if (isDeWoTPCpid) { - if (enableExpSignalTPC) + if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/deuteron/h2DeuteronTPCExpSignalDiffVsPt"), DPt, track.tpcExpSignalDiffDe()); switch (useHasTRDConfig) { @@ -3976,7 +3977,7 @@ struct LFNucleiBATask { } } if (isAntiDeWoTPCpid) { - if (enableExpSignalTPC) + if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/deuteron/h2antiDeuteronTPCExpSignalDiffVsPt"), antiDPt, track.tpcExpSignalDiffDe()); switch (useHasTRDConfig) { @@ -4000,18 +4001,18 @@ struct LFNucleiBATask { } if (isHeWoTPCpid) { - if (enableExpSignalTPC) + if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/helium/h2HeliumTPCExpSignalDiffVsPt"), hePt, track.tpcExpSignalDiffHe()); histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTPC"), hePt, track.tpcNSigmaHe()); } if (isAntiHeWoTPCpid) { - if (enableExpSignalTPC) + if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/helium/h2antiHeliumTPCExpSignalDiffVsPt"), antihePt, track.tpcExpSignalDiffHe()); histos.fill(HIST("tracks/helium/h2antiHeliumVspTNSigmaTPC"), antihePt, track.tpcNSigmaHe()); } // TOF - if (doTOFplots) { + if (outFlagOptions.doTOFplots) { if (isDeWoTPCpid) { switch (useHasTRDConfig) { @@ -4029,7 +4030,7 @@ struct LFNucleiBATask { } break; } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/deuteron/h2DeuteronTOFExpSignalDiffVsPt"), DPt, track.tofExpSignalDiffDe()); } @@ -4049,19 +4050,19 @@ struct LFNucleiBATask { } break; } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/deuteron/h2antiDeuteronTOFExpSignalDiffVsPt"), antiDPt, track.tofExpSignalDiffDe()); } if (isHeWoTPCpid) { histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTOF"), hePt, track.tofNSigmaHe()); - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/helium/h2HeliumTOFExpSignalDiffVsPt"), hePt, track.tofExpSignalDiffHe()); } if (isAntiHeWoTPCpid) { histos.fill(HIST("tracks/helium/h2antiHeliumVspTNSigmaTOF"), antihePt, track.tofNSigmaHe()); - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/helium/h2antiHeliumTOFExpSignalDiffVsPt"), antihePt, track.tofExpSignalDiffHe()); } } @@ -4142,7 +4143,7 @@ struct LFNucleiBATask { } } - if (doTOFplots && track.hasTOF()) { + if (outFlagOptions.doTOFplots && track.hasTOF()) { if (enablePtSpectra && enableDebug) { if (track.sign() > 0) { debugHistos.fill(HIST("tracks/eff/hPtPTOF"), track.pt()); @@ -4153,7 +4154,7 @@ struct LFNucleiBATask { } } - if (enableBetaCut && (track.beta() > betaCut)) + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) histos.fill(HIST("tracks/h2TOFbetaVsP_BetaCut"), track.p() / (1.f * track.sign()), track.beta()); switch (useHasTRDConfig) { case 0: @@ -4273,7 +4274,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumantiHelium"), antiheTPCmomentum, track.tpcSignal()); } - if (doTOFplots && track.hasTOF()) { + if (outFlagOptions.doTOFplots && track.hasTOF()) { if (isDeWTPCpid) { histos.fill(HIST("tracks/deuteron/h2DeuteronTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { @@ -4354,11 +4355,11 @@ struct LFNucleiBATask { } histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_BetaCut"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/proton/h2ProtonTOFExpSignalDiffVsPtCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableEvTimeSplitting) { if (track.isEvTimeTOF() && track.isEvTimeT0AC()) { @@ -4378,11 +4379,11 @@ struct LFNucleiBATask { } histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt_BetaCut"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/proton/h2antiProtonTOFExpSignalDiffVsPtCut"), track.pt(), track.tofExpSignalDiffPr()); if (enableEvTimeSplitting) { if (track.isEvTimeTOF() && track.isEvTimeT0AC()) { @@ -4406,7 +4407,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/eff/triton/hPtTrTOF"), track.pt()); histos.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - fMassTriton * fMassTriton, track.pt()); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_BetaCut"), massTOF * massTOF - fMassTriton * fMassTriton, track.pt()); } @@ -4415,7 +4416,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/eff/triton/hPtantiTrTOF"), track.pt()); histos.fill(HIST("tracks/triton/h2TOFmassantiTritonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - fMassTriton * fMassTriton, track.pt()); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/triton/h2TOFmassantiTritonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2antiTritonVsPt_BetaCut"), massTOF * massTOF - fMassTriton * fMassTriton, track.pt()); } @@ -4432,11 +4433,11 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/h3TOFmass2DeuteronVsPtVsMult"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, DPt, event.centFT0M()); else histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, DPt); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_BetaCut"), massTOF, DPt); histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_BetaCut"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, DPt); } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/deuteron/h2DeuteronTOFExpSignalDiffVsPtCut"), DPt, track.tofExpSignalDiffDe()); if (enableEvTimeSplitting) { if (track.isEvTimeTOF() && track.isEvTimeT0AC()) { @@ -4458,11 +4459,11 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/h3TOFmass2antiDeuteronVsPtVsMult"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt, event.centFT0M()); else histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt_BetaCut"), massTOF, antiDPt); histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt_BetaCut"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt); } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/deuteron/h2antiDeuteronTOFExpSignalDiffVsPtCut"), antiDPt, track.tofExpSignalDiffDe()); if (enableEvTimeSplitting) { if (track.isEvTimeTOF() && track.isEvTimeT0AC()) { @@ -4483,11 +4484,11 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), 2.f * massTOFhe, hePt); histos.fill(HIST("tracks/helium/h2TOFmassDeltaHeliumVsPt"), 2.f * massTOFhe - fMassHelium, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), 2.f * massTOFhe * 2.f * massTOFhe - fMassHelium * fMassHelium, hePt); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_BetaCut"), 2.f * massTOFhe, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_BetaCut"), 2.f * massTOFhe * 2.f * massTOFhe - fMassHelium * fMassHelium, hePt); } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/helium/h2HeliumTOFExpSignalDiffVsPtCut"), hePt, track.tofExpSignalDiffHe()); } if (isAntiHeWTPCpid) { @@ -4496,11 +4497,11 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt"), 2.f * massTOFantihe, antihePt); histos.fill(HIST("tracks/helium/h2TOFmassDeltaantiHeliumVsPt"), 2.f * massTOFantihe - fMassHelium, antihePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt"), 2.f * massTOFantihe * 2.f * massTOFantihe - fMassHelium * fMassHelium, antihePt); - if (enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt_BetaCut"), 2.f * massTOFantihe, antihePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt_BetaCut"), 2.f * massTOFantihe * 2.f * massTOFantihe - fMassHelium * fMassHelium, antihePt); } - if (enableExpSignalTOF) + if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/helium/h2antiHeliumTOFExpSignalDiffVsPtCut"), antihePt, track.tofExpSignalDiffHe()); } } @@ -4645,7 +4646,7 @@ struct LFNucleiBATask { case PDGProton: if (enablePr && prRapCut && passDCAxyzCut) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrue"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTrue"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTrue"), track.pt(), track.dcaZ()); } @@ -4654,7 +4655,7 @@ struct LFNucleiBATask { } if (isPhysPrim) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTruePrim"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTruePrim"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTruePrim"), track.pt(), track.dcaZ()); } @@ -4751,13 +4752,13 @@ struct LFNucleiBATask { } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrueTransport"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTrueTransport"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTrueTransport"), track.pt(), track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrueSec"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTrueSec"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTrueSec"), track.pt(), track.dcaZ()); } @@ -4768,7 +4769,7 @@ struct LFNucleiBATask { case -PDGProton: if (enablePr && prRapCut && passDCAxyzCut) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrue"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrue"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTrue"), track.pt(), track.dcaZ()); } @@ -4777,7 +4778,7 @@ struct LFNucleiBATask { } if (isPhysPrim) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTruePrim"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTruePrim"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTruePrim"), track.pt(), track.dcaZ()); } @@ -4875,13 +4876,13 @@ struct LFNucleiBATask { if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrueTransport"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrueTransport"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTrueTransport"), track.pt(), track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrueSec"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrueSec"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTrueSec"), track.pt(), track.dcaZ()); } @@ -4892,20 +4893,20 @@ struct LFNucleiBATask { case PDGDeuteron: if (isDeuteron && passDCAzCutDe && passDCAxyCutDe) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrue"), DPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrue"), DPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrue"), DPt, track.dcaZ()); } if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCvar.nsigmaTPCDe) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueWPID"), DPt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/hPtDeuteronTOFTrue"), DPt); } } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTPCTruePrim"), DPt, track.tpcNSigmaDe()); histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTruePrim"), DPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTruePrim"), DPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTruePrim"), DPt, track.dcaZ()); } @@ -4956,11 +4957,11 @@ struct LFNucleiBATask { if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCvar.nsigmaTPCDe) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueWPIDPrim"), DPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueWPIDPrim"), DPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueWPIDPrim"), DPt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/hPtDeuteronTOFTrueWPIDPrim"), DPt); } @@ -5011,13 +5012,13 @@ struct LFNucleiBATask { } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueTransport"), DPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueTransport"), DPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueTransport"), DPt, track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueSec"), DPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueSec"), DPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueSec"), DPt, track.dcaZ()); } @@ -5028,20 +5029,20 @@ struct LFNucleiBATask { case -PDGDeuteron: if (isDeuteron && passDCAzCutAntiDe && passDCAxyCutAntiDe) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrue"), antiDPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrue"), antiDPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrue"), antiDPt, track.dcaZ()); } if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCvar.nsigmaTPCDe) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueWPID"), antiDPt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/hPtantiDeuteronTOFTrue"), antiDPt); } } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspTNSigmaTPCTruePrim"), antiDPt, track.tpcNSigmaDe()); histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTruePrim"), antiDPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTruePrim"), antiDPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTruePrim"), antiDPt, track.dcaZ()); } @@ -5092,11 +5093,11 @@ struct LFNucleiBATask { if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCvar.nsigmaTPCDe) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueWPIDPrim"), antiDPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueWPIDPrim"), antiDPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueWPIDPrim"), antiDPt, track.dcaZ()); } - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/deuteron/hPtantiDeuteronTOFTrueWPIDPrim"), antiDPt); } @@ -5147,13 +5148,13 @@ struct LFNucleiBATask { } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueTransport"), antiDPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueTransport"), antiDPt, track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueSec"), antiDPt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueSec"), antiDPt, track.dcaXY()); histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueSec"), antiDPt, track.dcaZ()); } @@ -5164,26 +5165,26 @@ struct LFNucleiBATask { case PDGTriton: if (enableTr && trRapCut && passDCAxyzCut) { histos.fill(HIST("tracks/triton/h1TritonSpectraTrue"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTrue"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTrue"), track.pt(), track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/triton/h1TritonSpectraTruePrim"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTruePrim"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTruePrim"), track.pt(), track.dcaZ()); } } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/triton/h1TritonSpectraTrueTransport"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTrueTransport"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTrueTransport"), track.pt(), track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/triton/h1TritonSpectraTrueSec"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTrueSec"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTrueSec"), track.pt(), track.dcaZ()); } @@ -5194,26 +5195,26 @@ struct LFNucleiBATask { case -PDGTriton: if (enableTr && trRapCut && passDCAxyzCut) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTrue"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrue"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTrue"), track.pt(), track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTruePrim"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTruePrim"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTruePrim"), track.pt(), track.dcaZ()); } } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTrueTransport"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueTransport"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTrueTransport"), track.pt(), track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTrueSec"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueSec"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTrueSec"), track.pt(), track.dcaZ()); } @@ -5226,11 +5227,11 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue_Z2"), 2 * hePt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); } @@ -5240,7 +5241,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID_Z2"), 2 * hePt); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/helium/hPtHeTrue"), 2 * hePt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/eff/helium/hPtHeTOFTrue"), 2 * hePt); } } @@ -5250,15 +5251,15 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim_Z2"), 2 * hePt); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/TOF/h1HeliumSpectraTruePrim_Z2"), 2 * hePt); } } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); } @@ -5269,10 +5270,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport_Z2"), 2 * hePt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); } @@ -5281,10 +5282,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec_Z2"), 2 * hePt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); } @@ -5298,10 +5299,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue_Z2"), 2 * antihePt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrue"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrue"), antihePt, track.dcaZ()); } @@ -5311,7 +5312,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID_Z2"), 2 * antihePt); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/helium/hPtantiHeTrue"), 2 * antihePt); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/eff/helium/hPtantiHeTOFTrue"), 2 * antihePt); } } @@ -5321,15 +5322,15 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim_Z2"), 2 * antihePt); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/TOF/h1antiHeliumSpectraTruePrim_Z2"), 2 * antihePt); } } - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTruePrim"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTruePrim"), antihePt, track.dcaZ()); } @@ -5339,10 +5340,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport_Z2"), 2 * antihePt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueTransport"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueTransport"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrueTransport"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrueTransport"), antihePt, track.dcaZ()); } @@ -5352,10 +5353,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec_Z2"), 2 * antihePt); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); - if (track.hasTOF() && doTOFplots) { + if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAxyVsPtantiHeliumTrueSec"), antihePt, track.dcaXY()); histos.fill(HIST("tracks/helium/dca/after/TOF/hDCAzVsPtantiHeliumTrueSec"), antihePt, track.dcaZ()); } @@ -5367,27 +5368,27 @@ struct LFNucleiBATask { case PDGAlpha: if (enableAl && alRapCut && passDCAxyzCut) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTrue"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrue"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTrue"), track.pt(), track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTruePrim"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTruePrim"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTruePrim"), track.pt(), track.dcaZ()); } } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTrueTransport"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrueTransport"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTrueTransport"), track.pt(), track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTrueSec"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrueSec"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTrueSec"), track.pt(), track.dcaZ()); } @@ -5398,26 +5399,26 @@ struct LFNucleiBATask { case -PDGAlpha: if (enableAl && alRapCut && passDCAxyzCut) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTrue"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrue"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrue"), track.pt(), track.dcaZ()); } if (isPhysPrim) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTruePrim"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTruePrim"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTruePrim"), track.pt(), track.dcaZ()); } } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTrueTransport"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrueTransport"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrueTransport"), track.pt(), track.dcaZ()); } if (isWeakDecay) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTrueSec"), track.pt()); - if (makeDCAAfterCutPlots) { + if (outFlagOptions.makeDCAAfterCutPlots) { histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrueSec"), track.pt(), track.dcaXY()); histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrueSec"), track.pt(), track.dcaZ()); } diff --git a/PWGLF/Tasks/Nuspex/NucleiHistTask.cxx b/PWGLF/Tasks/Nuspex/NucleiHistTask.cxx index a9ec41750dc..8d55234b567 100644 --- a/PWGLF/Tasks/Nuspex/NucleiHistTask.cxx +++ b/PWGLF/Tasks/Nuspex/NucleiHistTask.cxx @@ -442,55 +442,55 @@ struct NucleiHistTask { MC_recon_reg.add("histChi2TPC", "chi^2 TPC vs Pt", HistType::kTH3F, {ptAxis, {100, 0.0, 5.0, "chi^2"}, PDGBINNING}); MC_recon_reg.add("histChi2ITS", "chi^2 ITS vs Pt", HistType::kTH3F, {ptAxis, {500, 0.0, 50.0, "chi^2"}, PDGBINNING}); MC_recon_reg.add("histChi2TOF", "chi^2 TOF vs Pt", HistType::kTH3F, {ptAxis, {75, 0.0, 15.0, "chi^2"}, PDGBINNING}); - MC_recon_reg.add("histTpcNsigmaDataPi", "TPC nSigma (#pi^{+})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTpcNsigmaDataaPi", "TPC nSigma (#pi^{-})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTpcNsigmaDataPr", "TPC nSigma (p)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTpcNsigmaDataaPr", "TPC nSigma (#bar{p})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTpcNsigmaDataDe", "TPC nSigma (d)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTpcNsigmaDataaDe", "TPC nSigma (#bar{d})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTpcNsigmaDataTr", "TPC nSigma (t)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTpcNsigmaDataaTr", "TPC nSigma (#bar{t})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTpcNsigmaDataHe", "TPC nSigma (^{3}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}}); - MC_recon_reg.add("histTpcNsigmaDataaHe", "TPC nSigma (^{3}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}}); - MC_recon_reg.add("histTpcNsigmaDataAl", "TPC nSigma (^{4}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}}); - MC_recon_reg.add("histTpcNsigmaDataaAl", "TPC nSigma (^{4}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}}); - MC_recon_reg.add("histTofNsigmaDataPi", "TOF nSigma (#pi^{+})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTofNsigmaDataaPi", "TOF nSigma (#pi^{-})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTofNsigmaDataPr", "TOF nSigma (p)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTofNsigmaDataaPr", "TOF nSigma (#bar{p})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTofNsigmaDataDe", "TOF nSigma (d)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTofNsigmaDataaDe", "TOF nSigma (#bar{d})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTofNsigmaDataTr", "TOF nSigma (t)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTofNsigmaDataaTr", "TOF nSigma (#bar{t})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTofNsigmaDataHe", "TOF nSigma (^{3}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); - MC_recon_reg.add("histTofNsigmaDataaHe", "TOF nSigma (^{3}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); - MC_recon_reg.add("histTofNsigmaDataAl", "TOF nSigma (^{4}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); - MC_recon_reg.add("histTofNsigmaDataaAl", "TOF nSigma (^{4}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); - - MC_recon_reg.add("histTpcNsigmaDataPi_pT", "TPC nSigma (#pi^{+})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTpcNsigmaDataaPi_pT", "TPC nSigma (#pi^{-})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTpcNsigmaDataPr_pT", "TPC nSigma (p)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTpcNsigmaDataaPr_pT", "TPC nSigma (#bar{p})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTpcNsigmaDataDe_pT", "TPC nSigma (d)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTpcNsigmaDataaDe_pT", "TPC nSigma (#bar{d})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTpcNsigmaDataTr_pT", "TPC nSigma (t)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTpcNsigmaDataaTr_pT", "TPC nSigma (#bar{t})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTpcNsigmaDataHe_pT", "TPC nSigma (^{3}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-3}"}}); - MC_recon_reg.add("histTpcNsigmaDataaHe_pT", "TPC nSigma (^{3}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-3}"}}); - MC_recon_reg.add("histTpcNsigmaDataAl_pT", "TPC nSigma (^{4}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-4}"}}); - MC_recon_reg.add("histTpcNsigmaDataaAl_pT", "TPC nSigma (^{4}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-4}"}}); - MC_recon_reg.add("histTofNsigmaDataPi_pT", "TOF nSigma (#pi^{+})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTofNsigmaDataaPi_pT", "TOF nSigma (#pi^{-})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); - MC_recon_reg.add("histTofNsigmaDataPr_pT", "TOF nSigma (p)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTofNsigmaDataaPr_pT", "TOF nSigma (#bar{p})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); - MC_recon_reg.add("histTofNsigmaDataDe_pT", "TOF nSigma (d)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTofNsigmaDataaDe_pT", "TOF nSigma (#bar{d})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); - MC_recon_reg.add("histTofNsigmaDataTr_pT", "TOF nSigma (t)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTofNsigmaDataaTr_pT", "TOF nSigma (#bar{t})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); - MC_recon_reg.add("histTofNsigmaDataHe_pT", "TOF nSigma (^{3}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); - MC_recon_reg.add("histTofNsigmaDataaHe_pT", "TOF nSigma (^{3}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); - MC_recon_reg.add("histTofNsigmaDataAl_pT", "TOF nSigma (^{4}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); - MC_recon_reg.add("histTofNsigmaDataaAl_pT", "TOF nSigma (^{4}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); + MC_recon_reg.add("histTpcNsigmaDataPi", "TPC nSigma (#pi^{+})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTpcNsigmaDataaPi", "TPC nSigma (#pi^{-})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTpcNsigmaDataPr", "TPC nSigma (p)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTpcNsigmaDataaPr", "TPC nSigma (#bar{p})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTpcNsigmaDataDe", "TPC nSigma (d)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTpcNsigmaDataaDe", "TPC nSigma (#bar{d})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTpcNsigmaDataTr", "TPC nSigma (t)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTpcNsigmaDataaTr", "TPC nSigma (#bar{t})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTpcNsigmaDataHe", "TPC nSigma (^{3}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-3}"}}); + MC_recon_reg.add("histTpcNsigmaDataaHe", "TPC nSigma (^{3}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-3}"}}); + MC_recon_reg.add("histTpcNsigmaDataAl", "TPC nSigma (^{4}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-4}"}}); + MC_recon_reg.add("histTpcNsigmaDataaAl", "TPC nSigma (^{4}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{He-4}"}}); + MC_recon_reg.add("histTofNsigmaDataPi", "TOF nSigma (#pi^{+})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTofNsigmaDataaPi", "TOF nSigma (#pi^{-})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTofNsigmaDataPr", "TOF nSigma (p)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTofNsigmaDataaPr", "TOF nSigma (#bar{p})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTofNsigmaDataDe", "TOF nSigma (d)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTofNsigmaDataaDe", "TOF nSigma (#bar{d})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTofNsigmaDataTr", "TOF nSigma (t)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTofNsigmaDataaTr", "TOF nSigma (#bar{t})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTofNsigmaDataHe", "TOF nSigma (^{3}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); + MC_recon_reg.add("histTofNsigmaDataaHe", "TOF nSigma (^{3}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); + MC_recon_reg.add("histTofNsigmaDataAl", "TOF nSigma (^{4}He)", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); + MC_recon_reg.add("histTofNsigmaDataaAl", "TOF nSigma (^{4}#bar{He})", HistType::kTH2F, {pAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); + + MC_recon_reg.add("histTpcNsigmaDataPi_pT", "TPC nSigma (#pi^{+})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTpcNsigmaDataaPi_pT", "TPC nSigma (#pi^{-})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTpcNsigmaDataPr_pT", "TPC nSigma (p)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTpcNsigmaDataaPr_pT", "TPC nSigma (#bar{p})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTpcNsigmaDataDe_pT", "TPC nSigma (d)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTpcNsigmaDataaDe_pT", "TPC nSigma (#bar{d})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTpcNsigmaDataTr_pT", "TPC nSigma (t)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTpcNsigmaDataaTr_pT", "TPC nSigma (#bar{t})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTpcNsigmaDataHe_pT", "TPC nSigma (^{3}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}}); + MC_recon_reg.add("histTpcNsigmaDataaHe_pT", "TPC nSigma (^{3}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}}); + MC_recon_reg.add("histTpcNsigmaDataAl_pT", "TPC nSigma (^{4}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}}); + MC_recon_reg.add("histTpcNsigmaDataaAl_pT", "TPC nSigma (^{4}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}}); + MC_recon_reg.add("histTofNsigmaDataPi_pT", "TOF nSigma (#pi^{+})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTofNsigmaDataaPi_pT", "TOF nSigma (#pi^{-})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{#pi^{+}}"}}); + MC_recon_reg.add("histTofNsigmaDataPr_pT", "TOF nSigma (p)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTofNsigmaDataaPr_pT", "TOF nSigma (#bar{p})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); + MC_recon_reg.add("histTofNsigmaDataDe_pT", "TOF nSigma (d)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTofNsigmaDataaDe_pT", "TOF nSigma (#bar{d})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); + MC_recon_reg.add("histTofNsigmaDataTr_pT", "TOF nSigma (t)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTofNsigmaDataaTr_pT", "TOF nSigma (#bar{t})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); + MC_recon_reg.add("histTofNsigmaDataHe_pT", "TOF nSigma (^{3}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); + MC_recon_reg.add("histTofNsigmaDataaHe_pT", "TOF nSigma (^{3}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{3}He}"}}); + MC_recon_reg.add("histTofNsigmaDataAl_pT", "TOF nSigma (^{4}He)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); + MC_recon_reg.add("histTofNsigmaDataaAl_pT", "TOF nSigma (^{4}#bar{He})", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{^{4}He}"}}); } // Configurables diff --git a/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx b/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx index 563fee5f604..f31fff08713 100644 --- a/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx +++ b/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx @@ -843,7 +843,7 @@ struct antidLambdaEbye { // reject events having multiple v0s from same tracks (TODO: also across collisions?) std::sort(trkId.begin(), trkId.end()); - if (std::adjacent_find(trkId.begin(), trkId.end()) != trkId.end()) { + if ((std::adjacent_find(trkId.begin(), trkId.end()) != trkId.end()) && config.fillOnlySignal) { candidateV0s.clear(); CandidateV0 candV0; diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index 64f02f95886..47b9a5eb886 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -181,7 +181,7 @@ struct hadronnucleicorrelation { AxisSpec etaBinnedAxis = {etaBins, "#eta"}; AxisSpec phiBinnedAxis = {phiBins, "#phi"}; AxisSpec etaAxis = {100, -1.5, 1.5, "#Delta#eta"}; - AxisSpec phiAxis = {100, -TMath::Pi() / 2, 1.5 * TMath::Pi(), "#Delta#phi"}; + AxisSpec phiAxis = {60, -TMath::Pi() / 2, 1.5 * TMath::Pi(), "#Delta#phi"}; AxisSpec pTAxis = {200, -10.f, 10.f, "p_{T} GeV/c"}; registry.add("hNEvents", "hNEvents", {HistType::kTH1I, {{3, 0.f, 3.f}}}); @@ -358,6 +358,9 @@ struct hadronnucleicorrelation { registry.add("hReco_EtaPhiPtMC_Proton", "Gen (anti)protons in reco collisions (MC info used)", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., 2 * TMath::Pi(), "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); registry.add("hReco_EtaPhiPtMC_Deuteron", "Gen (anti)deuteron in reco collisions (MC info used)", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., 2 * TMath::Pi(), "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); + registry.add("hSec_EtaPhiPt_Proton", "Secondary (anti)protons", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., 2 * TMath::Pi(), "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); + registry.add("hPrimSec_EtaPhiPt_Proton", "Primary + Secondary (anti)protons", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., 2 * TMath::Pi(), "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); + registry.add("hnSigmaTPCVsPt_Pr_MC", "n#sigma TPC vs p_{T} for p hypothesis true MC; p_{T} (GeV/c); n#sigma TPC", {HistType::kTH2F, {pTAxis, AxisNSigma}}); registry.add("hnSigmaTPCVsPt_De_MC", "n#sigma TPC vs p_{T} for d hypothesis true MC; p_{T} (GeV/c); n#sigma TPC", {HistType::kTH2F, {pTAxis, AxisNSigma}}); registry.add("hnSigmaTOFVsPt_Pr_MC", "n#sigma TOF vs p_{T} for p hypothesis true MC; p_{T} (GeV/c); n#sigma TOF", {HistType::kTH2F, {pTAxis, AxisNSigma}}); @@ -568,6 +571,9 @@ struct hadronnucleicorrelation { if (abs(track.dcaXY()) > max_dcaxy || abs(track.dcaZ()) > max_dcaz) { // For now no filtering on the DCAxy or DCAz (casting not supported) continue; } + if (track.tpcFractionSharedCls() > max_tpcSharedCls || track.itsNCls() < min_itsNCls) + continue; + if (doQA) { QA.fill(HIST("QA/hTPCnClusters"), track.tpcNClsFound()); QA.fill(HIST("QA/hTPCchi2"), track.tpcChi2NCl()); @@ -585,10 +591,6 @@ struct hadronnucleicorrelation { if (track.pt() > pTBins.value.at(nBinspT) || track.pt() < pTBins.value.at(0)) continue; - // Additional track cuts - if (track.tpcFractionSharedCls() > max_tpcSharedCls || track.itsNCls() < min_itsNCls) - continue; - bool isPr = false; bool isAntiPr = false; bool isDeTPCTOF = false; @@ -608,10 +610,13 @@ struct hadronnucleicorrelation { isAntiPr = true; } } - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && track.sign() > 0) - isDeTPCTOF = true; - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && track.sign() < 0) - isAntiDeTPCTOF = true; + if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && TMath::Abs(track.tofNSigmaPr()) >= nsigmaTOF) { + if (track.sign() > 0) { + isDeTPCTOF = true; + } else if (track.sign() < 0) { + isAntiDeTPCTOF = true; + } + } if (!isPr && !isAntiPr && !isDeTPCTOF && !isAntiDeTPCTOF) continue; @@ -832,6 +837,8 @@ struct hadronnucleicorrelation { if (abs(track.dcaXY()) > max_dcaxy || abs(track.dcaZ()) > max_dcaz) { // For now no filtering on the DCAxy or DCAz (casting not supported) continue; } + if (abs(track.pdgCode()) != pdgProton && abs(track.pdgCode()) != pdgDeuteron) + continue; if (doQA) { QA.fill(HIST("QA/hTPCnClusters"), track.tpcNClsFound()); @@ -847,10 +854,35 @@ struct hadronnucleicorrelation { QA.fill(HIST("QA/hnSigmaTOFVsPt_De"), track.pt() * track.sign(), track.tofNSigmaDe()); } - if (track.origin() != 0) - continue; + int s = +1; + if (track.pdgCode() == -pdgProton) { + s = -1; + } - if (abs(track.pdgCode()) != pdgProton && abs(track.pdgCode()) != pdgDeuteron) + if (track.origin() == 1) { // secondaries + if (TMath::Abs(track.pdgCode()) == pdgProton) { + if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC) { + if (track.pt() < pTthrpr_TOF) { + registry.fill(HIST("hSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); + } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { + registry.fill(HIST("hSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); + } + } + } + } + if (track.origin() == 1 || track.origin() == 0) { // primaries and secondaries + if (TMath::Abs(track.pdgCode()) == pdgProton) { + if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC) { + if (track.pt() < pTthrpr_TOF) { + registry.fill(HIST("hPrimSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); + } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { + registry.fill(HIST("hPrimSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); + } + } + } + } + + if (track.origin() != 0) continue; bool isPr = false; @@ -902,7 +934,7 @@ struct hadronnucleicorrelation { registry.fill(HIST("hResEta_Deuteron"), track.eta_MC(), track.eta() - track.eta_MC()); registry.fill(HIST("hResPhi_Deuteron"), track.phi_MC(), track.phi() - track.phi_MC()); - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF) { + if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && TMath::Abs(track.tofNSigmaPr()) >= nsigmaTOF) { registry.fill(HIST("hReco_PID_EtaPhiPt_Deuteron"), track.eta(), track.phi(), track.pt()); } registry.fill(HIST("hnSigmaTPCVsPt_De_MC"), track.pt(), track.tpcNSigmaDe()); @@ -915,7 +947,7 @@ struct hadronnucleicorrelation { registry.fill(HIST("hResEta_AntiDeuteron"), track.eta_MC(), track.eta() - track.eta_MC()); registry.fill(HIST("hResPhi_AntiDeuteron"), track.phi_MC(), track.phi() - track.phi_MC()); - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF) { + if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && TMath::Abs(track.tofNSigmaPr()) >= nsigmaTOF) { isAntiDeTPCTOF = true; registry.fill(HIST("hReco_PID_EtaPhiPt_Deuteron"), track.eta(), track.phi(), track.pt() * -1); } diff --git a/PWGLF/Tasks/Nuspex/hypertriton3bodyMCQA.cxx b/PWGLF/Tasks/Nuspex/hypertriton3bodyMCQA.cxx index a01b19ba2be..0b25ef70d33 100644 --- a/PWGLF/Tasks/Nuspex/hypertriton3bodyMCQA.cxx +++ b/PWGLF/Tasks/Nuspex/hypertriton3bodyMCQA.cxx @@ -21,6 +21,8 @@ #include #include +#include "CommonDataFormat/InteractionRecord.h" +#include "CommonDataFormat/IRFrame.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -29,19 +31,22 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/pidTOFGeneric.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" #include "CommonConstants/PhysicsConstants.h" +#include "CCDB/BasicCCDBManager.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; - -using FullTracksExtIU = soa::Join; +using ColwithEvTimes = o2::soa::Join; +using FullTracksExtIU = soa::Join; using MCLabeledTracksIU = soa::Join; template @@ -101,6 +106,10 @@ bool isPairedH3LDaughters(TMCParticle const& mctrack0, TMCParticle const& mctrac // check the properties of daughters candidates and true daughters struct hypertriton3bodyTrackMcinfo { + + Service ccdb; + Preslice perCollisionTracks = aod::track::collisionId; + // Basic checks HistogramRegistry registry{ "registry", @@ -153,7 +162,7 @@ struct hypertriton3bodyTrackMcinfo { {"hDauPionNsigmaPion", "hDauPionNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, {"hDauPionTPCVsPt", "hDauPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronCount", "hDeuteronCount", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, + {"hDeuteronCount", "hDeuteronCount", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, {"hDeuteronPt", "hDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hDeuteronP", "hDeuteronP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hDeuteronMcPt", "hDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, @@ -169,7 +178,6 @@ struct hypertriton3bodyTrackMcinfo { {"hDauDeuteronTPCVsPt", "hDauDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, {"hDauDeuteronTOFNSigmaVsP", "hDauDeuteronTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, {"hDauDeuteronTOFNSigmaVsPHasTOF", "hDauDeuteronTOFNSigmaVsPHasTOF", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFMatchCounter", "hDeuteronTOFMatchCounter", {HistType::kTH1F, {{8, 0.0f, 8.0f}}}}, {"hDauDeuteronMatchCounter", "hDauDeuteronMatchCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, {"hTPCBB", "hTPCBB", {HistType::kTH2F, {{120, -8.0f, 8.0f, "p/z(GeV/c)"}, {100, 0.0f, 1000.0f, "TPCSignal"}}}}, @@ -177,7 +185,28 @@ struct hypertriton3bodyTrackMcinfo { {"hPairedH3LDaughers", "hPairedH3LDaughers", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, {"hPairedH3LDaughersInvMass", "hPairedH3LDaughersInvMass", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, {"hDuplicatedH3LDaughers", "hDuplicatedH3LDaughers", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hTestCounter", "hTestCounter", {HistType::kTH1F, {{22, 0.0f, 22.0f}}}}, + + // Diff checks always requir hasTOF + {"hDiffTrackTOFSignal", "hDiffTrackTOFSignal", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hDiffEvTimeForTrack", "hDiffEvTimeForTrack", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hDiffTrackTOFNSigmaDe", "hDiffTrackTOFNSigmaDe", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hDauDeuteronNewTOFNSigmaVsP", "hDauDeuteronNewTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hWrongDeuteronTOFNSigmaVsP", "hWrongDeuteronTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hWrongDeuteronNewTOFNSigmaVsP", "hWrongDeuteronNewTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDiffColTime", "hDiffColTime", {HistType::kTH1F, {{200, -100.0f, 100.0f}}}}, + {"hDauDeuteronDiffTOFNsigmaDeHasTOF", "hDauDeuteronDiffTOFNsigmaDeHasTOF", {HistType::kTH1F, {{200, -100.0f, 100.0f}}}}, + + // _v2 for using relinked collision + {"hDauDeuteronTOFNSigmaVsP_CorrectCol", "hDauDeuteronTOFNSigmaVsP_CorrectCol", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronNewTOFNSigmaVsP_CorrectCol", "hDauDeuteronNewTOFNSigmaVsP_CorrectCol", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronTOFNSigmaVsP_v2", "hDauDeuteronTOFNSigmaVsP_v2", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronNewTOFNSigmaVsP_v2_AO2D", "hDauDeuteronNewTOFNSigmaVsP_v2 AO2D", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronNewTOFNSigmaVsP_v2_EvSel", "hDauDeuteronNewTOFNSigmaVsP_v2 EvSel", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronTOFNSigmaVsColTimeRes_v2", "hDauDeuteronTOFNSigmaVsColTimeRes_v2", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronTOFNSigmaVsColTimeRes_v2_AO2D", "hDauDeuteronTOFNSigmaVsColTimeRes_v2 AO2D", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronTOFNSigmaVsColTimeRes_v2_EvSel", "hDauDeuteronTOFNSigmaVsColTimeRes_v2 EvSel", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, + {"hDauDeuteronTOFPIDCounter", "hDauDeuteronTOFPIDCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, + {"hDauDeuteronTOFPIDCounter_CloseBC", "hDauDeuteronTOFPIDCounter CloseBC", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, }, }; @@ -191,16 +220,6 @@ struct hypertriton3bodyTrackMcinfo { registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(6, "McisPion"); registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(7, "McisDeuteron"); - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(1, "All track"); - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(2, "hasMC"); - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(3, "hasMC&TPC&TOF"); - for (int i = 0; i < 16; i++) { - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(i + 4, Form("Bit %d", i)); - } - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(20, "hasMC&TPC&TOF&(!Bit15)"); - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(21, "hasMC&TPC&TOF&(!Bit11)"); - registry.get(HIST("hTestCounter"))->GetXaxis()->SetBinLabel(21, "hasMC&TPC&TOF&(!Bit13)&(Bit15)"); - TString TrackCounterbinLabel[6] = {"hasMom", "FromHypertriton", "TPCNcls", "Eta", "Pt", "TPCPID"}; for (int i{0}; i < 6; i++) { registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(i + 1, TrackCounterbinLabel[i]); @@ -208,7 +227,6 @@ struct hypertriton3bodyTrackMcinfo { registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(i + 1, TrackCounterbinLabel[i]); } registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(7, "DcatoPV"); - registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(7, "hasTOF"); registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(1, "proton"); registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(2, "pion"); registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(3, "deuteron"); @@ -217,6 +235,17 @@ struct hypertriton3bodyTrackMcinfo { registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(2, "correct collision"); registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(3, "hasTOF"); registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(4, "hasTOF & correct collsion"); + + registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(1, "Origin |n#sigma| >= 6"); + registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(2, "BothBC work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(3, "Only BCAO2D work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(4, "Only BCEvSel work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(5, "BothBC not work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(1, "Origin |n#sigma| < 6"); + registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(2, "BothBC work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(3, "Only BCAO2D work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(4, "Only BCEvSel work"); + registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(5, "BothBC not work"); } Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; @@ -226,8 +255,83 @@ struct hypertriton3bodyTrackMcinfo { Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; + Configurable event_sel8_selection{"event_sel8_selection", false, "event selection count post sel8 cut"}; + Configurable event_posZ_selection{"event_posZ_selection", false, "event selection count post poZ cut"}; + + // CCDB TOF PID paras + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; + Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; + Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; + Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; + Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; + Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; + + o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; + o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + // Initial TOF PID Paras, copied from PIDTOF.h + timestamp.value = bc.timestamp(); + ccdb->setTimestamp(timestamp.value); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + // TODO: implement the automatic pass name detection from metadata + if (passName.value == "") { + passName.value = "unanchored"; // temporary default + LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; + } + LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; + + const std::string fname = paramFileName.value; + if (!fname.empty()) { // Loading the parametrization from file + LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; + if (1) { + o2::tof::ParameterCollection paramCollection; + paramCollection.loadParamFromFile(fname, parametrizationPath.value); + LOG(info) << "+++ Loaded parameter collection from file +++"; + if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { + if (fatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } + } else { + mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); + mRespParamsV2.printShiftParameters(); + } + } else { + mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); + } + } else if (loadResponseFromCCDB) { // Loading it from CCDB + LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; + o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); + paramCollection->print(); + if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined + if (fatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + } + } else { // Pass is available, load non standard parameters + mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); + mRespParamsV2.printShiftParameters(); + } + } + mRespParamsV2.print(); + if (timeShiftCCDBPath.value != "") { + if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { + mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); + mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); + } else { + mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); + mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); + } + } + + bachelorTOFPID.SetParams(mRespParamsV2); + } struct Indexdaughters { // check duplicated paired daughters int64_t index0; @@ -239,292 +343,392 @@ struct hypertriton3bodyTrackMcinfo { } }; - void process(soa::Join::iterator const& collision, aod::McParticles const& /*particlesMC*/, MCLabeledTracksIU const& tracks, aod::McCollisions const& /*mcCollisions*/) + void process(ColwithEvTimes const& collisions, MCLabeledTracksIU const& tracks, aod::McParticles const& /*particlesMC*/, aod::McCollisions const& /*mcCollisions*/, aod::BCsWithTimestamps const&) { + for (auto collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - if (event_sel8_selection && !collision.sel8()) { - return; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && abs(collision.posZ()) > 10.f) { // 10cm - return; - } - registry.fill(HIST("hEventCounter"), 2.5); + registry.fill(HIST("hEventCounter"), 0.5); + if (event_sel8_selection && !collision.sel8()) { + return; + } + registry.fill(HIST("hEventCounter"), 1.5); + if (event_posZ_selection && abs(collision.posZ()) > 10.f) { // 10cm + return; + } + registry.fill(HIST("hEventCounter"), 2.5); - std::vector protons, pions, deuterons; // index for daughter tracks - std::unordered_set set_proton, set_pion, set_deuteron; // check duplicated daughters - int itrack = -1; + std::vector protons, pions, deuterons; // index for daughter tracks + std::unordered_set set_proton, set_pion, set_deuteron; // check duplicated daughters + int itrack = -1; - for (auto& track : tracks) { + auto coltracks = tracks.sliceBy(perCollisionTracks, collision.globalIndex()); - ++itrack; - registry.fill(HIST("hParticleCount"), 0.5); - registry.fill(HIST("hTrackITSNcls"), track.itsNCls()); - registry.fill(HIST("hTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); - registry.fill(HIST("hTrackNsigmaDeuteron"), track.tpcNSigmaDe()); - registry.fill(HIST("hTrackNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hTrackNsigmaPion"), track.tpcNSigmaPi()); - - registry.fill(HIST("hTestCounter"), 0.5); - for (int i = 0; i < 16; i++) { - if (track.mcMask() & 1 << i) { // Bit ON means mismatch - registry.fill(HIST("hTestCounter"), i + 3.5); - } - } + for (auto& track : coltracks) { - if (!track.has_mcParticle()) { - continue; - } - registry.fill(HIST("hTestCounter"), 1.5); - auto mcparticle = track.mcParticle_as(); - registry.fill(HIST("hTPCBB"), track.p() * track.sign(), track.tpcSignal()); + ++itrack; + registry.fill(HIST("hParticleCount"), 0.5); + registry.fill(HIST("hTrackITSNcls"), track.itsNCls()); + registry.fill(HIST("hTPCNCls"), track.tpcNClsFound()); + registry.fill(HIST("hTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("hTrackNsigmaDeuteron"), track.tpcNSigmaDe()); + registry.fill(HIST("hTrackNsigmaProton"), track.tpcNSigmaPr()); + registry.fill(HIST("hTrackNsigmaPion"), track.tpcNSigmaPi()); - if (track.hasTOF() && track.hasTPC()) { - registry.fill(HIST("hTestCounter"), 2.5); - if (!(track.mcMask() & 1 << 15)) { - registry.fill(HIST("hTestCounter"), 19.5); - } - if (!(track.mcMask() & 1 << 11)) { - registry.fill(HIST("hTestCounter"), 20.5); + if (!track.has_mcParticle()) { + continue; } - if (!(track.mcMask() & 1 << 13) && (track.mcMask() & 1 << 15)) { - registry.fill(HIST("hTestCounter"), 21.5); + auto mcparticle = track.mcParticle_as(); + registry.fill(HIST("hTPCBB"), track.p() * track.sign(), track.tpcSignal()); + + registry.fill(HIST("hParticleCount"), 1.5); + + // if (TMath::Abs(mcparticle.y()) > 0.9) {continue;} + registry.fill(HIST("hParticleCount"), 2.5); + registry.fill(HIST("hTrackEta"), track.eta()); + registry.fill(HIST("hTrackMcRapidity"), mcparticle.y()); + + // Hypertriton detected directly + if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { + registry.fill(HIST("hParticleCount"), 3.5); + registry.fill(HIST("hHypertritonMcPt"), mcparticle.pt()); + registry.fill(HIST("hHypertritonEta"), track.eta()); + registry.fill(HIST("hHypertritonMcRapidity"), mcparticle.y()); } - } - registry.fill(HIST("hParticleCount"), 1.5); - // if (TMath::Abs(mcparticle.y()) > 0.9) {continue;} - registry.fill(HIST("hParticleCount"), 2.5); - registry.fill(HIST("hTrackEta"), track.eta()); - registry.fill(HIST("hTrackMcRapidity"), mcparticle.y()); - - // Hypertriton detected directly - if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hParticleCount"), 3.5); - registry.fill(HIST("hHypertritonMcPt"), mcparticle.pt()); - registry.fill(HIST("hHypertritonEta"), track.eta()); - registry.fill(HIST("hHypertritonMcRapidity"), mcparticle.y()); - } - - // Proton - if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { - registry.fill(HIST("hParticleCount"), 4.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hProtonTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } + // Proton + if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { + registry.fill(HIST("hParticleCount"), 4.5); + if (track.tpcNClsFound() > 70) { + registry.fill(HIST("hProtonTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + } - if (mcparticle.has_mothers()) { - registry.fill(HIST("hProtonCount"), 0.5); - for (auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - protons.push_back(itrack); - auto p = set_proton.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 0); - registry.fill(HIST("hProtonCount"), 1.5); - registry.fill(HIST("hDauProtonPt"), track.pt()); - registry.fill(HIST("hDauProtonMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauProtonNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hDauProtonTPCVsPt"), track.pt(), track.tpcNSigmaPr()); - if (track.tpcNClsFound() < 70) { - continue; - } - registry.fill(HIST("hProtonCount"), 2.5); - if (TMath::Abs(track.eta()) > 0.9) { - continue; - } - registry.fill(HIST("hProtonCount"), 3.5); - if (track.pt() < minProtonPt || track.pt() > maxProtonPt) { - continue; - } - registry.fill(HIST("hProtonCount"), 4.5); - if (TMath::Abs(track.tpcNSigmaPr()) > 5) { - continue; + if (mcparticle.has_mothers()) { + registry.fill(HIST("hProtonCount"), 0.5); + for (auto& particleMother : mcparticle.mothers_as()) { + bool flag_H3L = is3bodyDecayedH3L(particleMother); + if (!flag_H3L) { + continue; + } + protons.push_back(itrack); + auto p = set_proton.insert(mcparticle.globalIndex()); + if (p.second == false) + registry.fill(HIST("hDuplicatedH3LDaughers"), 0); + registry.fill(HIST("hProtonCount"), 1.5); + registry.fill(HIST("hDauProtonPt"), track.pt()); + registry.fill(HIST("hDauProtonMcPt"), mcparticle.pt()); + registry.fill(HIST("hDauProtonNsigmaProton"), track.tpcNSigmaPr()); + registry.fill(HIST("hDauProtonTPCVsPt"), track.pt(), track.tpcNSigmaPr()); + if (track.tpcNClsFound() < 70) { + continue; + } + registry.fill(HIST("hProtonCount"), 2.5); + if (TMath::Abs(track.eta()) > 0.9) { + continue; + } + registry.fill(HIST("hProtonCount"), 3.5); + if (track.pt() < minProtonPt || track.pt() > maxProtonPt) { + continue; + } + registry.fill(HIST("hProtonCount"), 4.5); + if (TMath::Abs(track.tpcNSigmaPr()) > 5) { + continue; + } + registry.fill(HIST("hProtonCount"), 5.5); } - registry.fill(HIST("hProtonCount"), 5.5); } - } - registry.fill(HIST("hProtonMcPt"), mcparticle.pt()); - registry.fill(HIST("hProtonMcP"), mcparticle.p()); - registry.fill(HIST("hProtonPt"), track.pt()); - registry.fill(HIST("hProtonP"), track.p()); + registry.fill(HIST("hProtonMcPt"), mcparticle.pt()); + registry.fill(HIST("hProtonMcP"), mcparticle.p()); + registry.fill(HIST("hProtonPt"), track.pt()); + registry.fill(HIST("hProtonP"), track.p()); - registry.fill(HIST("hProtonNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hProtonTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hProtonEta"), track.eta()); - registry.fill(HIST("hProtonMcRapidity"), mcparticle.y()); - registry.fill(HIST("hProtonTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } - - // Pion - if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { - registry.fill(HIST("hParticleCount"), 5.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hPionTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + registry.fill(HIST("hProtonNsigmaProton"), track.tpcNSigmaPr()); + registry.fill(HIST("hProtonTPCNCls"), track.tpcNClsFound()); + registry.fill(HIST("hProtonEta"), track.eta()); + registry.fill(HIST("hProtonMcRapidity"), mcparticle.y()); + registry.fill(HIST("hProtonTPCBB"), track.p() * track.sign(), track.tpcSignal()); } - if (mcparticle.has_mothers()) { - registry.fill(HIST("hPionCount"), 0.5); - for (auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - pions.push_back(itrack); - auto p = set_pion.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 1); - registry.fill(HIST("hPionCount"), 1.5); - registry.fill(HIST("hDauPionPt"), track.pt()); - registry.fill(HIST("hDauPionMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauPionTPCVsPt"), track.pt(), track.tpcNSigmaPi()); - if (track.tpcNClsFound() < 70) { - continue; - } - registry.fill(HIST("hPionCount"), 2.5); - if (TMath::Abs(track.eta()) > 0.9) { - continue; - } - registry.fill(HIST("hPionCount"), 3.5); - if (track.pt() < minPionPt || track.pt() > maxPionPt) { - continue; - } - registry.fill(HIST("hPionCount"), 4.5); - if (TMath::Abs(track.tpcNSigmaPi()) > 5) { - continue; - } - registry.fill(HIST("hPionCount"), 5.5); - if (TMath::Abs(track.dcaXY()) < dcapiontopv) { - continue; + // Pion + if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { + registry.fill(HIST("hParticleCount"), 5.5); + if (track.tpcNClsFound() > 70) { + registry.fill(HIST("hPionTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + } + + if (mcparticle.has_mothers()) { + registry.fill(HIST("hPionCount"), 0.5); + for (auto& particleMother : mcparticle.mothers_as()) { + bool flag_H3L = is3bodyDecayedH3L(particleMother); + if (!flag_H3L) { + continue; + } + pions.push_back(itrack); + auto p = set_pion.insert(mcparticle.globalIndex()); + if (p.second == false) { + registry.fill(HIST("hDuplicatedH3LDaughers"), 1); + } + registry.fill(HIST("hPionCount"), 1.5); + registry.fill(HIST("hDauPionPt"), track.pt()); + registry.fill(HIST("hDauPionMcPt"), mcparticle.pt()); + registry.fill(HIST("hDauPionTPCVsPt"), track.pt(), track.tpcNSigmaPi()); + if (track.tpcNClsFound() < 70) { + continue; + } + registry.fill(HIST("hPionCount"), 2.5); + if (TMath::Abs(track.eta()) > 0.9) { + continue; + } + registry.fill(HIST("hPionCount"), 3.5); + if (track.pt() < minPionPt || track.pt() > maxPionPt) { + continue; + } + registry.fill(HIST("hPionCount"), 4.5); + if (TMath::Abs(track.tpcNSigmaPi()) > 5) { + continue; + } + registry.fill(HIST("hPionCount"), 5.5); + if (TMath::Abs(track.dcaXY()) < dcapiontopv) { + continue; + } + registry.fill(HIST("hPionCount"), 6.5); } - registry.fill(HIST("hPionCount"), 6.5); } + + registry.fill(HIST("hPionMcPt"), mcparticle.pt()); + registry.fill(HIST("hPionMcP"), mcparticle.p()); + registry.fill(HIST("hPionPt"), track.pt()); + registry.fill(HIST("hPionP"), track.p()); + + registry.fill(HIST("hPionNsigmaPion"), track.tpcNSigmaPi()); + registry.fill(HIST("hPionTPCNCls"), track.tpcNClsFound()); + registry.fill(HIST("hPionEta"), track.eta()); + registry.fill(HIST("hPionMcRapidity"), mcparticle.y()); + registry.fill(HIST("hPionTPCBB"), track.p() * track.sign(), track.tpcSignal()); } - registry.fill(HIST("hPionMcPt"), mcparticle.pt()); - registry.fill(HIST("hPionMcP"), mcparticle.p()); - registry.fill(HIST("hPionPt"), track.pt()); - registry.fill(HIST("hPionP"), track.p()); + float tofNsigmaDe = -999; + static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps - registry.fill(HIST("hPionNsigmaPion"), track.tpcNSigmaPi()); - registry.fill(HIST("hPionTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hPionEta"), track.eta()); - registry.fill(HIST("hPionMcRapidity"), mcparticle.y()); - registry.fill(HIST("hPionTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } + if (track.hasTOF() && track.has_collision()) { + auto responseDe = o2::pid::tof::ExpTimes(); + // float bachExpTime = track.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - // Deuteron - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - registry.fill(HIST("hParticleCount"), 6.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hDeuteronTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; + float bachExpTime = track.length() * sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v + float tofsignal = track.trackTime() * 1000 + bachExpTime; // in ps + + float expSigma = responseDe.GetExpectedSigma(mRespParamsV2, track, tofsignal, track.tofEvTimeErr()); + // tofNsigmaDe = (track.tofSignal() - track.tofEvTime() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + tofNsigmaDe = (tofsignal - track.tofEvTime() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + // tofNsigmaDe = (tofsignal - track.evTimeForTrack() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; + + if (collision.bcId() == collision.foundBCId()) { + registry.fill(HIST("hDiffColTime"), track.tofEvTime() - collision.collisionTime()); + } + + // Assume deuterons linked to the correct collision, result of new TOF PID should be same as the default one + registry.fill(HIST("hDiffTrackTOFSignal"), track.tofSignal() - tofsignal); + registry.fill(HIST("hDiffEvTimeForTrack"), track.tofEvTime() - track.evTimeForTrack()); + registry.fill(HIST("hDiffTrackTOFNSigmaDe"), track.tofNSigmaDe() - bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, collision, collision)); + // registry.fill(HIST("hDiffTrackTOFNSigmaDe"), track.tofExpSigmaDe() - bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, collision, collision)); } - if (mcparticle.has_mothers()) { - registry.fill(HIST("hDeuteronCount"), 0.5); - for (auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - deuterons.push_back(itrack); - auto p = set_deuteron.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 2); - registry.fill(HIST("hDeuteronCount"), 1.5); - registry.fill(HIST("hDauDeuteronPt"), track.pt()); - registry.fill(HIST("hDauDeuteronMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauDeuteronTPCVsPt"), track.pt(), track.tpcNSigmaDe()); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); - if (track.hasTOF()) { - registry.fill(HIST("hDauDeuteronTOFNSigmaVsPHasTOF"), track.sign() * track.p(), track.tofNSigmaDe()); - } - registry.fill(HIST("hDauDeuteronMatchCounter"), 0.5); - if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 1.5); - } - if (track.hasTOF()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 2.5); + // Deuteron + if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { + registry.fill(HIST("hParticleCount"), 6.5); + if (track.tpcNClsFound() > 70) { + registry.fill(HIST("hDeuteronTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + } + + if (mcparticle.has_mothers()) { + registry.fill(HIST("hDeuteronCount"), 0.5); + for (auto& particleMother : mcparticle.mothers_as()) { + bool flag_H3L = is3bodyDecayedH3L(particleMother); + if (!flag_H3L) { + continue; + } + deuterons.push_back(itrack); + auto p = set_deuteron.insert(mcparticle.globalIndex()); + if (p.second == false) + registry.fill(HIST("hDuplicatedH3LDaughers"), 2); + registry.fill(HIST("hDeuteronCount"), 1.5); + registry.fill(HIST("hDauDeuteronPt"), track.pt()); + registry.fill(HIST("hDauDeuteronMcPt"), mcparticle.pt()); + registry.fill(HIST("hDauDeuteronTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + registry.fill(HIST("hDauDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); + + registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP"), track.sign() * track.p(), tofNsigmaDe); + if (track.hasTOF()) { + registry.fill(HIST("hDauDeuteronTOFNSigmaVsPHasTOF"), track.sign() * track.p(), track.tofNSigmaDe()); + registry.fill(HIST("hDauDeuteronDiffTOFNsigmaDeHasTOF"), track.tofNSigmaDe() - tofNsigmaDe); + } + registry.fill(HIST("hDauDeuteronMatchCounter"), 0.5); if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 3.5); + registry.fill(HIST("hDauDeuteronMatchCounter"), 1.5); } + if (track.hasTOF()) { + registry.fill(HIST("hDauDeuteronMatchCounter"), 2.5); + if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { + registry.fill(HIST("hDauDeuteronMatchCounter"), 3.5); + } + } + if (track.tpcNClsFound() < 70) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 2.5); + if (TMath::Abs(track.eta()) > 0.9) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 3.5); + if (track.pt() < minDeuteronPt || track.pt() > maxDeuteronPt) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 4.5); + if (TMath::Abs(track.tpcNSigmaDe()) > 5) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 5.5); } - if (track.tpcNClsFound() < 70) { - continue; - } - registry.fill(HIST("hDeuteronCount"), 2.5); - if (TMath::Abs(track.eta()) > 0.9) { - continue; - } - registry.fill(HIST("hDeuteronCount"), 3.5); - if (track.pt() < minDeuteronPt || track.pt() > maxDeuteronPt) { - continue; - } - registry.fill(HIST("hDeuteronCount"), 4.5); - if (TMath::Abs(track.tpcNSigmaDe()) > 5) { - continue; - } - registry.fill(HIST("hDeuteronCount"), 5.5); - if (!track.hasTOF()) { - continue; - } - registry.fill(HIST("hDeuteronCount"), 6.5); + } + + registry.fill(HIST("hDeuteronMcPt"), mcparticle.pt()); + registry.fill(HIST("hDeuteronMcP"), mcparticle.p()); + registry.fill(HIST("hDeuteronPt"), track.pt()); + registry.fill(HIST("hDeuteronP"), track.p()); + + registry.fill(HIST("hDeuteronNsigmaDeuteron"), track.tpcNSigmaDe()); + registry.fill(HIST("hDeuteronTPCNCls"), track.tpcNClsFound()); + registry.fill(HIST("hDeuteronEta"), track.eta()); + registry.fill(HIST("hDeuteronMcRapidity"), mcparticle.y()); + registry.fill(HIST("hDeuteronTPCBB"), track.p() * track.sign(), track.tpcSignal()); + } else { + if (track.hasTOF()) { + registry.fill(HIST("hWrongDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); + registry.fill(HIST("hWrongDeuteronNewTOFNSigmaVsP"), track.sign() * track.p(), tofNsigmaDe); } } + } - registry.fill(HIST("hDeuteronMcPt"), mcparticle.pt()); - registry.fill(HIST("hDeuteronMcP"), mcparticle.p()); - registry.fill(HIST("hDeuteronPt"), track.pt()); - registry.fill(HIST("hDeuteronP"), track.p()); - - registry.fill(HIST("hDeuteronNsigmaDeuteron"), track.tpcNSigmaDe()); - registry.fill(HIST("hDeuteronTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hDeuteronEta"), track.eta()); - registry.fill(HIST("hDeuteronMcRapidity"), mcparticle.y()); - registry.fill(HIST("hDeuteronTPCBB"), track.p() * track.sign(), track.tpcSignal()); - registry.fill(HIST("hDeuteronTOFMatchCounter"), 0.5); - if (!(track.mcMask() & 1 << 15)) { - registry.fill(HIST("hDeuteronTOFMatchCounter"), 1.5); - if (track.hasTPC() && track.hasTOF()) { - registry.fill(HIST("hDeuteronTOFMatchCounter"), 2.5); - if (!(track.mcMask() & 1 << 11)) { // Bit ON means mismatch - registry.fill(HIST("hDeuteronTOFMatchCounter"), 3.5); + std::vector set_pair; + for (size_t iproton = 0; iproton < protons.size(); iproton++) { + auto track0 = tracks.iteratorAt(protons[iproton]); + auto mctrack0 = track0.mcParticle_as(); + for (size_t ipion = 0; ipion < pions.size(); ipion++) { + auto track1 = tracks.iteratorAt(pions[ipion]); + auto mctrack1 = track1.mcParticle_as(); + for (size_t ideuteron = 0; ideuteron < deuterons.size(); ideuteron++) { + auto track2 = tracks.iteratorAt(deuterons[ideuteron]); + auto mctrack2 = track2.mcParticle_as(); + if (isPairedH3LDaughters(mctrack0, mctrack1, mctrack2)) { + registry.fill(HIST("hPairedH3LDaughers"), 0); + // MC mass cut, to check if the daughters are from materials + double hypertritonMCMass = RecoDecay::m(array{array{mctrack0.px(), mctrack0.py(), mctrack0.pz()}, array{mctrack1.px(), mctrack1.py(), mctrack1.pz()}, array{mctrack2.px(), mctrack2.py(), mctrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); + registry.fill(HIST("hPairedH3LDaughersInvMass"), hypertritonMCMass); + if (hypertritonMCMass < 2.990 || hypertritonMCMass > 2.993) + continue; + registry.fill(HIST("hPairedH3LDaughers"), 1); + // duplicated daughters check + Indexdaughters temp = {mctrack0.globalIndex(), mctrack1.globalIndex(), mctrack2.globalIndex()}; + auto p = std::find(set_pair.begin(), set_pair.end(), temp); + if (p == set_pair.end()) { + set_pair.push_back(temp); + registry.fill(HIST("hPairedH3LDaughers"), 2); + } } } } } } - std::vector set_pair; - for (size_t iproton = 0; iproton < protons.size(); iproton++) { - auto track0 = tracks.iteratorAt(protons[iproton]); - auto mctrack0 = track0.mcParticle_as(); - for (size_t ipion = 0; ipion < pions.size(); ipion++) { - auto track1 = tracks.iteratorAt(pions[ipion]); - auto mctrack1 = track1.mcParticle_as(); - for (size_t ideuteron = 0; ideuteron < deuterons.size(); ideuteron++) { - auto track2 = tracks.iteratorAt(deuterons[ideuteron]); - auto mctrack2 = track2.mcParticle_as(); - if (isPairedH3LDaughters(mctrack0, mctrack1, mctrack2)) { - registry.fill(HIST("hPairedH3LDaughers"), 0); - // MC mass cut, to check if the daughters are from materials - double hypertritonMCMass = RecoDecay::m(array{array{mctrack0.px(), mctrack0.py(), mctrack0.pz()}, array{mctrack1.px(), mctrack1.py(), mctrack1.pz()}, array{mctrack2.px(), mctrack2.py(), mctrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hPairedH3LDaughersInvMass"), hypertritonMCMass); - if (hypertritonMCMass < 2.990 || hypertritonMCMass > 2.993) + // Check for recalculated TOF PID for secondary deuterons + + std::vector SelectedEvents(collisions.size()); + int nevts = 0; + for (const auto& collision : collisions) { + SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + } + + for (auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + auto mcparticle = track.mcParticle_as(); + if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { + if (!mcparticle.has_mothers()) { + continue; + } + const auto evtReconstructed = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcparticle.mcCollision_as().globalIndex()); + if (evtReconstructed == SelectedEvents.end() || !track.has_collision()) { + continue; + } + if (!track.has_collision()) { + continue; + } + auto collision = collisions.iteratorAt(evtReconstructed - SelectedEvents.begin()); + auto originalcollision = track.collision_as(); + + for (auto& particleMother : mcparticle.mothers_as()) { + bool flag_H3L = is3bodyDecayedH3L(particleMother); + if (!flag_H3L) { + continue; + } + + // auto bc = collision.bc_as(); + // initCCDB(bc); + float tofNsigmaDeAO2D = -999; + float tofNsigmaDeEvSel = -999; + + if (track.hasTOF()) { + /*auto responseDe = o2::pid::tof::ExpTimes(); + //float bachExpTime = track.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v + float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; + float bachExpTime = track.length() * sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v + */ + + tofNsigmaDeAO2D = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, originalcollision, collision); + tofNsigmaDeEvSel = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, originalcollision, collision, false); + + if (collision.globalIndex() == originalcollision.globalIndex()) { + registry.fill(HIST("hDauDeuteronTOFNSigmaVsP_CorrectCol"), track.sign() * track.p(), track.tofNSigmaDe()); + registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_CorrectCol"), track.sign() * track.p(), tofNsigmaDeAO2D); continue; - registry.fill(HIST("hPairedH3LDaughers"), 1); - // duplicated daughters check - Indexdaughters temp = {mctrack0.globalIndex(), mctrack1.globalIndex(), mctrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hPairedH3LDaughers"), 2); + } + + /*if (originalcollision.collisionTimeRes() > 40){ + continue; + }*/ + registry.fill(HIST("hDauDeuteronTOFNSigmaVsP_v2"), track.sign() * track.p(), track.tofNSigmaDe()); + registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_v2_AO2D"), track.sign() * track.p(), tofNsigmaDeAO2D); + registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_v2_EvSel"), track.sign() * track.p(), tofNsigmaDeEvSel); + registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2"), collision.collisionTimeRes(), track.tofNSigmaDe()); + registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2_AO2D"), originalcollision.collisionTimeRes(), tofNsigmaDeAO2D); + registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2_EvSel"), originalcollision.collisionTimeRes(), tofNsigmaDeEvSel); + + if (std::abs(track.tofNSigmaDe()) >= 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 0.5); + if (std::abs(tofNsigmaDeAO2D) < 6 && std::abs(tofNsigmaDeEvSel) < 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 1.5); + } else if (std::abs(tofNsigmaDeAO2D) < 6 && std::abs(tofNsigmaDeEvSel) >= 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 2.5); + } else if (std::abs(tofNsigmaDeAO2D) >= 6 && std::abs(tofNsigmaDeEvSel) < 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 3.5); + } else if (std::abs(tofNsigmaDeAO2D) >= 6 && std::abs(tofNsigmaDeEvSel) >= 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 4.5); + } + } else if (std::abs(track.tofNSigmaDe()) < 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 0.5); + if (std::abs(tofNsigmaDeAO2D) < 6 && std::abs(tofNsigmaDeEvSel) < 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 1.5); + } else if (std::abs(tofNsigmaDeAO2D) < 6 && std::abs(tofNsigmaDeEvSel) >= 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 2.5); + } else if (std::abs(tofNsigmaDeAO2D) >= 6 && std::abs(tofNsigmaDeEvSel) < 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 3.5); + } else if (std::abs(tofNsigmaDeAO2D) >= 6 && std::abs(tofNsigmaDeEvSel) >= 6) { + registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 4.5); + } } } } @@ -554,6 +758,8 @@ struct hypertriton3bodyMcParticleCount { }, }; + o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + void init(InitContext&) { registry.get(HIST("hTotalMcCollCounter"))->GetXaxis()->SetBinLabel(1, "Total Count"); @@ -579,8 +785,8 @@ struct hypertriton3bodyMcParticleCount { } Configurable rapidityMCcut{"rapidityMCcut", 1, "rapidity cut MC count"}; - Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; + Configurable event_sel8_selection{"event_sel8_selection", false, "event selection count post sel8 cut"}; + Configurable event_posZ_selection{"event_posZ_selection", false, "event selection count post poZ cut"}; void process(aod::McCollision const& mcCollision, aod::McParticles const& particlesMC, const soa::SmallGroups>& collisions) { diff --git a/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx b/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx index 4e0b781d897..ba415978df2 100644 --- a/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx +++ b/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx @@ -46,6 +46,7 @@ using namespace o2::framework::expressions; using std::array; using FullTracksExtIU = soa::Join; +// using FullTracksExtIU = soa::Join; // For TOF PID check using MCLabeledTracksIU = soa::Join; struct hypertriton3bodyQa { @@ -61,6 +62,9 @@ struct hypertriton3bodyQa { {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, @@ -102,6 +106,8 @@ struct hypertriton3bodyQa { registry.fill(HIST("hPtProton"), track0.pt()); registry.fill(HIST("hPtPionMinus"), track1.pt()); registry.fill(HIST("hPtDeuteron"), track2.pt()); + registry.fill(HIST("hDCAXYProtonToPV"), vtx.dcaXYtrack0topv()); + registry.fill(HIST("hDCAXYPionToPV"), vtx.dcaXYtrack1topv()); registry.fill(HIST("hDCAProtonToPV"), vtx.dcatrack0topv()); registry.fill(HIST("hDCAPionToPV"), vtx.dcatrack1topv()); registry.fill(HIST("hProtonTPCNcls"), track0.tpcNClsCrossedRows()); @@ -110,11 +116,14 @@ struct hypertriton3bodyQa { registry.fill(HIST("hPtPionPlus"), track0.pt()); registry.fill(HIST("hPtAntiProton"), track1.pt()); registry.fill(HIST("hPtAntiDeuteron"), track2.pt()); + registry.fill(HIST("hDCAXYProtonToPV"), vtx.dcaXYtrack1topv()); + registry.fill(HIST("hDCAXYPionToPV"), vtx.dcaXYtrack0topv()); registry.fill(HIST("hDCAProtonToPV"), vtx.dcatrack1topv()); registry.fill(HIST("hDCAPionToPV"), vtx.dcatrack0topv()); registry.fill(HIST("hProtonTPCNcls"), track1.tpcNClsCrossedRows()); registry.fill(HIST("hPionTPCNcls"), track0.tpcNClsCrossedRows()); } + registry.fill(HIST("hDCAXYDeuteronToPV"), vtx.dcaXYtrack2topv()); registry.fill(HIST("hDCADeuteronToPV"), vtx.dcatrack2topv()); registry.fill(HIST("hDeuteronTPCNcls"), track2.tpcNClsCrossedRows()); } @@ -164,6 +173,9 @@ struct hypertriton3bodyAnalysis { {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, + {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, @@ -183,7 +195,7 @@ struct hypertriton3bodyAnalysis { {"hPionTPCVsPt", "hPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, {"hDeuteronTPCVsPt", "hDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, {"hDeuteronTOFVsPBeforeTOFCut", "hDeuteronTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAtferTOFCut", "hDeuteronTOFVsPAtferTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, + {"hDeuteronTOFVsPAfterTOFCut", "hDeuteronTOFVsPAfterTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, {"hDalitz", "hDalitz", {HistType::kTH2F, {{120, 7.85, 8.45, "M^{2}(dp) (GeV^{2}/c^{4})"}, {60, 1.1, 1.4, "M^{2}(p#pi) (GeV^{2}/c^{4})"}}}}, {"h3dMassHypertriton", "h3dMassHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, @@ -192,8 +204,13 @@ struct hypertriton3bodyAnalysis { {"hTrueHypertritonCounter", "hTrueHypertritonCounter", {HistType::kTH1F, {{12, 0.0f, 12.0f}}}}, {"hDeuteronTOFVsPBeforeTOFCutSig", "hDeuteronTOFVsPBeforeTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAtferTOFCutSig", "hDeuteronTOFVsPAtferTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, + {"hDeuteronTOFVsPAfterTOFCutSig", "hDeuteronTOFVsPAfterTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, {"h3dTotalTrueHypertriton", "h3dTotalTrueHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, + // For TOF PID check + /*{"hDeuteronDefaultTOFVsPBeforeTOFCut", "hDeuteronDefaultTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, + {"hDeuteronDefaultTOFVsPAtferTOFCut", "hDeuteronDefaultTOFVsPAtferTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, + {"hDeuteronDefaultTOFVsPBeforeTOFCutSig", "hDeuteronDefaultTOFVsPBeforeTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, + {"hDeuteronDefaultTOFVsPAfterTOFCutSig", "hDeuteronDefaultTOFVsPAfterTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}},*/ // for mcparticles information {"hGeneratedHypertritonCounter", "hGeneratedHypertritonCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, @@ -315,17 +332,21 @@ struct hypertriton3bodyAnalysis { } FillCandCounter(kCandDcaDau, isTrueCand); + // registry.fill(HIST("hDeuteronDefaultTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); if (isTrueCand) { + // registry.fill(HIST("hDeuteronDefaultTOFVsPBeforeTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); } if ((candData.tofNSigmaBachDe() < TofPidNsigmaMin || candData.tofNSigmaBachDe() > TofPidNsigmaMax) && trackDeuteron.p() > minDeuteronPUseTOF) { return; } FillCandCounter(kCandTOFPID, isTrueCand); - registry.fill(HIST("hDeuteronTOFVsPAtferTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); + // registry.fill(HIST("hDeuteronDefaultTOFVsPAtferTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); + registry.fill(HIST("hDeuteronTOFVsPAfterTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); if (isTrueCand) { - registry.fill(HIST("hDeuteronTOFVsPAtferTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); + // registry.fill(HIST("hDeuteronDefaultTOFVsPAfterTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); + registry.fill(HIST("hDeuteronTOFVsPAfterTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); } if (TMath::Abs(trackProton.tpcNSigmaPr()) > TpcPidNsigmaCut || TMath::Abs(trackPion.tpcNSigmaPi()) > TpcPidNsigmaCut || TMath::Abs(trackDeuteron.tpcNSigmaDe()) > TpcPidNsigmaCut) { @@ -361,6 +382,8 @@ struct hypertriton3bodyAnalysis { registry.fill(HIST("hPtProton"), trackProton.pt()); registry.fill(HIST("hPtPionMinus"), trackPion.pt()); registry.fill(HIST("hPtDeuteron"), trackDeuteron.pt()); + registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack0topv()); + registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack1topv()); registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack0topv()); registry.fill(HIST("hDCAPionToPV"), candData.dcatrack1topv()); @@ -382,6 +405,8 @@ struct hypertriton3bodyAnalysis { registry.fill(HIST("hPtAntiProton"), trackProton.pt()); registry.fill(HIST("hPtPionPlus"), trackPion.pt()); registry.fill(HIST("hPtAntiDeuteron"), trackDeuteron.pt()); + registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack1topv()); + registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack0topv()); registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack1topv()); registry.fill(HIST("hDCAPionToPV"), candData.dcatrack0topv()); @@ -398,6 +423,7 @@ struct hypertriton3bodyAnalysis { } else { return; } + registry.fill(HIST("hDCAXYDeuteronToPV"), candData.dcaXYtrack2topv()); registry.fill(HIST("hDCADeuteronToPV"), candData.dcatrack2topv()); registry.fill(HIST("hVtxCosPA"), candData.vtxcosPA(dCollision.posX(), dCollision.posY(), dCollision.posZ())); registry.fill(HIST("hDCAVtxDau"), candData.dcaVtxdaughters()); diff --git a/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx b/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx index fe6056237c8..4dbc3f33b96 100644 --- a/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx +++ b/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx @@ -79,257 +79,188 @@ struct nuclei_in_jets { true}; // Global Parameters - Configurable min_pt_leading{"min_pt_leading", 5.0f, "minimum pt of leading particle"}; - Configurable Rparameter_jet{"Rparameter_jet", 0.3f, "jet resolution parameter R"}; - Configurable Rmax_jet_ue{"Rmax_jet_ue", 0.3f, "Maximum radius"}; - Configurable particle_of_interest{"particle_of_interest", 0, "0=antiproton, 1=antideuteron, 2=antihelium3"}; + Configurable min_jet_pt{"min_jet_pt", 10.0, "Minimum pt of the jet"}; + Configurable Rjet{"Rjet", 0.3, "Jet resolution parameter R"}; + Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; + Configurable min_nPartInJet{"min_nPartInJet", 2, "Minimum number of particles inside jet"}; + Configurable n_jets_per_event_max{"n_jets_per_event_max", 1000, "Maximum number of jets per event"}; + Configurable requireNoOverlap{"requireNoOverlap", false, "require no overlap between jets and UE cones"}; // Track Parameters - Configurable min_ITS_nClusters{"min_ITS_nClusters", 4, "minimum number of found ITS clusters"}; - Configurable min_TPC_nClusters{"min_TPC_nClusters", 80, "minimum number of found TPC clusters"}; + Configurable min_ITS_nClusters{"min_ITS_nClusters", 5, "minimum number of ITS clusters"}; + Configurable min_TPC_nClusters{"min_TPC_nClusters", 80, "minimum number of TPC clusters"}; Configurable min_TPC_nCrossedRows{"min_TPC_nCrossedRows", 80, "minimum number of TPC crossed pad rows"}; - Configurable max_chi2_TPC{"max_chi2_TPC", 4.0f, "maximum TPC chi^2/Ncls"}; - Configurable max_chi2_ITS{"max_chi2_ITS", 36.0f, "maximum ITS chi^2/Ncls"}; - Configurable min_pt{"min_pt", 0.2f, "minimum pt of the tracks"}; - Configurable min_eta{"min_eta", -0.8f, "minimum eta"}; - Configurable max_eta{"max_eta", +0.8f, "maximum eta"}; - Configurable min_y{"min_y", -0.5f, "minimum y"}; - Configurable max_y{"max_y", +0.5f, "maximum y"}; - Configurable max_dcaxy{"max_dcaxy", 0.1f, "Maximum DCAxy"}; - Configurable max_dcaz{"max_dcaz", 0.1f, "Maximum DCAz"}; - Configurable min_nsigmaTPC{"min_nsigmaTPC", -3.0f, "Minimum nsigma TPC"}; - Configurable max_nsigmaTPC{"max_nsigmaTPC", +3.0f, "Maximum nsigma TPC"}; - Configurable min_nsigmaTOF{"min_nsigmaTOF", -3.0f, "Minimum nsigma TOF"}; - Configurable max_nsigmaTOF{"max_nsigmaTOF", +3.5f, "Maximum nsigma TOF"}; - Configurable coalMom{"coalMom", +0.3f, "Coalescence Momentum"}; - Configurable require_primVtx_contributor{"require_primVtx_contributor", true, "require that the track is a PV contributor"}; - Configurable applyReweighting{"applyReweighting", true, "apply Reweighting"}; - Configurable> param_proton_ref{"param_proton_ref", {0.000000000151, 984.796940000000, 0.458560000000, 0.000360000000}, "Parameters of Levi-Tsallis fit of Protons from pythia"}; - Configurable> param_proton_jet{"param_proton_jet", {0.025285984480, 4.271090000000, 0.511730000000, 2.261760000000}, "Parameters for reweighting protons in jets"}; - Configurable> param_deuteron_jet{"param_deuteron_jet", {20.121453090900, 2.096620000000, 1.000000000000, 1.875610000000}, "Parameters for reweighting deuterons in jets"}; - Configurable> param_helium3_jet{"param_helium3_jet", {0.00026, 2.09662, 1.00000, 1.87561}, "Parameters for reweighting helium3 in jets"}; - Configurable> param_proton_ue{"param_proton_ue", {0.000000977546, 88.480170000000, 0.539520000000, 0.062120000000}, "Parameters for reweighting protons in ue"}; - Configurable> param_deuteron_ue{"param_deuteron_ue", {0.000294563800, 25.000000000000, 0.514970000000, 1.000000000000}, "Parameters for reweighting deuterons in ue"}; - Configurable> param_helium3_ue{"param_helium3_ue", {0.00000, 25.00000, 0.51497, 1.00000}, "Parameters for reweighting helium3 in ue"}; - - // List of Particles - enum nucleus { proton, - deuteron, - helium }; - - enum region { jet, - underlying_event }; + Configurable max_chi2_TPC{"max_chi2_TPC", 4.0, "maximum TPC chi^2/Ncls"}; + Configurable max_chi2_ITS{"max_chi2_ITS", 36.0, "maximum ITS chi^2/Ncls"}; + Configurable min_pt{"min_pt", 0.3, "minimum pt of the tracks"}; + Configurable min_eta{"min_eta", -0.8, "minimum eta"}; + Configurable max_eta{"max_eta", +0.8, "maximum eta"}; + Configurable max_dcaxy{"max_dcaxy", 0.05, "Maximum DCAxy"}; + Configurable max_dcaz{"max_dcaz", 0.05, "Maximum DCAz"}; + Configurable min_nsigmaTPC{"min_nsigmaTPC", -3.0, "Minimum nsigma TPC"}; + Configurable max_nsigmaTPC{"max_nsigmaTPC", +3.0, "Maximum nsigma TPC"}; + Configurable min_nsigmaTOF{"min_nsigmaTOF", -3.0, "Minimum nsigma TOF"}; + Configurable max_nsigmaTOF{"max_nsigmaTOF", +3.5, "Maximum nsigma TOF"}; + Configurable require_PV_contributor{"require_PV_contributor", true, "require that the track is a PV contributor"}; + Configurable setDCAselectionPtDep{"setDCAselectionPtDep", true, "require pt dependent selection"}; void init(InitContext const&) { - // Global Properties and QC - registryQC.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{15, 0, 15, "counter"}}); - registryQC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); - registryQC.add("event_counter_mc", "event_counter_mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); - registryQC.add("jet_plus_ue_multiplicity", "jet + underlying-event multiplicity", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); - registryQC.add("jet_multiplicity", "jet multiplicity", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); - registryQC.add("ue_multiplicity", "underlying-event multiplicity", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); - registryQC.add("pt_leading", "pt leading", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); - registryQC.add("eta_phi_jet", "DeltaEta DeltaPhi jet", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); - registryQC.add("eta_phi_ue", "DeltaEta DeltaPhi UE", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); - registryQC.add("r_max_jet", "R Max jet", HistType::kTH1F, {{200, 0.0, 6.0, "#it{R}_{max}"}}); - registryQC.add("r_jet", "R jet", HistType::kTH1F, {{200, 0.0, 1.0, "#it{R}"}}); - registryQC.add("r_ue", "R ue", HistType::kTH1F, {{200, 0.0, 1.0, "#it{R}"}}); - registryQC.add("eta_leading", "eta_leading", HistType::kTH1F, {{100, -1, 1, "#eta"}}); - registryQC.add("phi_leading", "phi_leading", HistType::kTH1F, {{100, -TMath::Pi(), TMath::Pi(), "#phi"}}); - registryQC.add("angle_jet_leading_track", "angle_jet_leading_track", HistType::kTH1F, {{200, 0.0, TMath::Pi() / 4.0, "#theta"}}); - registryQC.add("deltaPt", "deltaPt", HistType::kTH1F, {{200, -2, 2, "#Delta p_{T}"}}); + // QC Histograms + registryQC.add("deltaEtadeltaPhi_jet", "deltaEtadeltaPhi_jet", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); + registryQC.add("deltaEtadeltaPhi_ue", "deltaEtadeltaPhi_ue", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, 0.5 * TMath::Pi(), "#Delta#phi"}}); + registryQC.add("NchJetPlusUE", "NchJetPlusUE", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); + registryQC.add("NchJet", "NchJet", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); + registryQC.add("NchUE", "NchUE", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); + registryQC.add("sumPtJetPlusUE", "sumPtJetPlusUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQC.add("sumPtJet", "sumPtJet", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQC.add("sumPtUE", "sumPtUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); + registryQC.add("nJets_found", "nJets_found", HistType::kTH1F, {{10, 0, 10, "#it{n}_{Jet}"}}); + registryQC.add("nJets_selected", "nJets_selected", HistType::kTH1F, {{10, 0, 10, "#it{n}_{Jet}"}}); + registryQC.add("dcaxy_vs_pt", "dcaxy_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + registryQC.add("dcaz_vs_pt", "dcaz_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); + registryQC.add("jet_ue_overlaps", "jet_ue_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); + + // Event Counters + registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "counter"}}); + registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); + + // Binning + double min = 0.0; + double max = 6.0; + int nbins = 120; // Antiprotons - registryData.add("antiproton_jet_tpc", "antiproton_jet_tpc", HistType::kTH3F, {{20, 0.0, 1.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antiproton_jet_tof", "antiproton_jet_tof", HistType::kTH3F, {{90, 0.5, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antiproton_ue_tpc", "antiproton_ue_tpc", HistType::kTH3F, {{20, 0.0, 1.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antiproton_ue_tof", "antiproton_ue_tof", HistType::kTH3F, {{90, 0.5, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}, {2, 0, 100, "#it{N}_{ch}"}}); - - // Eta - pt Maps Antiprotons - registryData.add("antip_tpc_jet_eta_pt", "antip_tpc_jet_eta_pt", HistType::kTH2F, {{60, 0.0, 3.0, "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("antip_tpc_ue_eta_pt", "antip_tpc_ue_eta_pt", HistType::kTH2F, {{60, 0.0, 3.0, "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("antip_tof_jet_eta_pt", "antip_tof_jet_eta_pt", HistType::kTH2F, {{60, 0.0, 3.0, "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("antip_tof_ue_eta_pt", "antip_tof_ue_eta_pt", HistType::kTH2F, {{60, 0.0, 3.0, "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - - // DCA Distributions - registryData.add("antiproton_dca_jet", "antiproton_dca_jet", HistType::kTH3F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH3F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}, {2, 0, 100, "#it{N}_{ch}"}}); + registryData.add("antiproton_jet_tpc", "antiproton_jet_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antiproton_jet_tof", "antiproton_jet_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antiproton_ue_tpc", "antiproton_ue_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antiproton_ue_tof", "antiproton_ue_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antiproton_dca_jet", "antiproton_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); // Antideuterons - registryData.add("antideuteron_jet_tpc", "antideuteron_jet_tpc", HistType::kTH3F, {{10, 0.0, 1.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antideuteron_jet_tof", "antideuteron_jet_tof", HistType::kTH3F, {{45, 0.5, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antideuteron_ue_tpc", "antideuteron_ue_tpc", HistType::kTH3F, {{10, 0.0, 1.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antideuteron_ue_tof", "antideuteron_ue_tof", HistType::kTH3F, {{45, 0.5, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}, {2, 0, 100, "#it{N}_{ch}"}}); + registryData.add("antideuteron_jet_tpc", "antideuteron_jet_tpc", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antideuteron_jet_tof", "antideuteron_jet_tof", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antideuteron_ue_tpc", "antideuteron_ue_tpc", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antideuteron_ue_tof", "antideuteron_ue_tof", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); // Antihelium-3 - registryData.add("antihelium3_jet_tpc", "antihelium3_jet_tpc", HistType::kTH3F, {{40, 1.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}, {200, -10.0, 10.0, "n#sigma_{TPC}"}, {2, 0, 100, "#it{N}_{ch}"}}); - registryData.add("antihelium3_ue_tpc", "antihelium3_ue_tpc", HistType::kTH3F, {{40, 1.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}, {200, -10.0, 10.0, "n#sigma_{TPC}"}, {2, 0, 100, "#it{N}_{ch}"}}); - - // Input Antiproton Distribution - registryMC.add("antiproton_input", "antiproton_input", HistType::kTH1F, {{1000, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_weighted_jet", "antiproton_weighted_jet", HistType::kTH1F, {{1000, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_weighted_ue", "antiproton_weighted_ue", HistType::kTH1F, {{1000, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryData.add("antihelium3_jet_tpc", "antihelium3_jet_tpc", HistType::kTH2F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antihelium3_ue_tpc", "antihelium3_ue_tpc", HistType::kTH2F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); // Generated - registryMC.add("antiproton_jet_gen", "antiproton_jet_gen", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_jet_gen", "antideuteron_jet_gen", HistType::kTH1F, {{50, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antihelium3_jet_gen", "antihelium3_jet_gen", HistType::kTH1F, {{40, 1.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_gen", "antiproton_ue_gen", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_ue_gen", "antideuteron_ue_gen", HistType::kTH1F, {{50, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antihelium3_ue_gen", "antihelium3_ue_gen", HistType::kTH1F, {{40, 1.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_jet_gen", "antiproton_jet_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_jet_gen", "antideuteron_jet_gen", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_jet_gen", "antihelium3_jet_gen", HistType::kTH1F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_ue_gen", "antiproton_ue_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_ue_gen", "antideuteron_ue_gen", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_ue_gen", "antihelium3_ue_gen", HistType::kTH1F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}}); // Reconstructed TPC - registryMC.add("antiproton_jet_rec_tpc", "antiproton_jet_rec_tpc", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_jet_rec_tpc", "antideuteron_jet_rec_tpc", HistType::kTH1F, {{50, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antihelium3_jet_rec_tpc", "antihelium3_jet_rec_tpc", HistType::kTH1F, {{40, 1.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_rec_tpc", "antiproton_ue_rec_tpc", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_ue_rec_tpc", "antideuteron_ue_rec_tpc", HistType::kTH1F, {{50, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antihelium3_ue_rec_tpc", "antihelium3_ue_rec_tpc", HistType::kTH1F, {{40, 1.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_jet_rec_tpc", "antiproton_jet_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_jet_rec_tpc", "antideuteron_jet_rec_tpc", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_jet_rec_tpc", "antihelium3_jet_rec_tpc", HistType::kTH1F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_ue_rec_tpc", "antiproton_ue_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_ue_rec_tpc", "antideuteron_ue_rec_tpc", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_ue_rec_tpc", "antihelium3_ue_rec_tpc", HistType::kTH1F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}}); // Reconstructed TOF - registryMC.add("antiproton_jet_rec_tof", "antiproton_jet_rec_tof", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_jet_rec_tof", "antideuteron_jet_rec_tof", HistType::kTH1F, {{50, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_rec_tof", "antiproton_ue_rec_tof", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_ue_rec_tof", "antideuteron_ue_rec_tof", HistType::kTH1F, {{50, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_jet_rec_tof", "antiproton_jet_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_jet_rec_tof", "antideuteron_jet_rec_tof", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_ue_rec_tof", "antiproton_ue_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_ue_rec_tof", "antideuteron_ue_rec_tof", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); // DCA Templates - registryMC.add("antiproton_dca_prim", "antiproton_dca_prim", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); - registryMC.add("antiproton_dca_sec", "antiproton_dca_sec", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_dca_prim", "antiproton_dca_prim", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_dca_sec", "antiproton_dca_sec", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); // Fraction of Primary Antiprotons from MC - registryMC.add("antiproton_prim", "antiproton_prim", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_all", "antiproton_all", HistType::kTH1F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); - - // Histograms for reweighting - registryMC.add("antiproton_eta_pt_pythia", "antiproton_eta_pt_pythia", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {80, -0.8, 0.8, "#eta"}}); - registryMC.add("antiproton_eta_pt_jet", "antiproton_eta_pt_jet", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {80, -0.8, 0.8, "#eta"}}); - registryMC.add("antiproton_eta_pt_ue", "antiproton_eta_pt_ue", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {80, -0.8, 0.8, "#eta"}}); - registryMC.add("antideuteron_eta_pt_injected", "antideuteron_eta_pt_injected", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {80, -0.8, 0.8, "#eta"}}); - registryMC.add("antideuteron_eta_pt_jet", "antideuteron_eta_pt_jet", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {80, -0.8, 0.8, "#eta"}}); - registryMC.add("antideuteron_eta_pt_ue", "antideuteron_eta_pt_ue", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {80, -0.8, 0.8, "#eta"}}); + registryMC.add("antiproton_prim", "antiproton_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_all", "antiproton_all", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_prim_jet", "antiproton_prim_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_all_jet", "antiproton_all_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_prim_ue", "antiproton_prim_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_all_ue", "antiproton_all_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Antiproton Reweighting + registryMC.add("antiproton_eta_pt_pythia", "antiproton_eta_pt_pythia", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); + registryMC.add("antiproton_eta_pt_jet", "antiproton_eta_pt_jet", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); + registryMC.add("antiproton_eta_pt_ue", "antiproton_eta_pt_ue", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); } - // Single-Track Selection for the Particle of Interest + // Single-Track Selection for Particles inside Jets template - bool passedTrackSelection(const T1& track) + bool passedTrackSelectionForJetReconstruction(const T1& track) { if (!track.hasITS()) return false; - if (track.itsNCls() < min_ITS_nClusters) + if (track.itsNCls() < 3) return false; if (!track.hasTPC()) return false; - if (track.tpcNClsFound() < min_TPC_nClusters) - return false; - if (track.tpcNClsCrossedRows() < min_TPC_nCrossedRows) + if (track.tpcNClsCrossedRows() < 70) return false; - if (track.tpcChi2NCl() > max_chi2_TPC) + if (track.tpcChi2NCl() > 4) return false; - if (track.itsChi2NCl() > max_chi2_ITS) + if (track.itsChi2NCl() > 36) return false; - if (track.eta() < min_eta || track.eta() > max_eta) + if (track.eta() < -0.8 || track.eta() > 0.8) return false; - if (track.pt() < min_pt) + if (track.pt() < 0.15) return false; - // Rapidity Cut - double mass(0); - if (particle_of_interest == nucleus::proton) - mass = 0.93827208816; // Proton - if (particle_of_interest == nucleus::deuteron) - mass = 1.87561294257; // Deuteron - if (particle_of_interest == nucleus::helium) - mass = 2.80839160743; // Helium-3 - - TLorentzVector lorentzVect; - lorentzVect.SetXYZM(track.px(), track.py(), track.pz(), mass); - if (lorentzVect.Rapidity() < min_y || lorentzVect.Rapidity() > max_y) - return false; + // pt-dependent selection + if (setDCAselectionPtDep) { + if (TMath::Abs(track.dcaXY()) > (0.004f + 0.013f / track.pt())) + return false; + if (TMath::Abs(track.dcaZ()) > (0.004f + 0.013f / track.pt())) + return false; + } + + // standard selection + if (!setDCAselectionPtDep) { + if (TMath::Abs(track.dcaXY()) > 0.1) + return false; + if (TMath::Abs(track.dcaZ()) > 0.1) + return false; + } return true; } - // Single-Track Selection for Particles inside Jets + // Single-Track Selection template - bool passedMinimalTrackSelection(const T2& track) + bool passedTrackSelection(const T2& track) { if (!track.hasITS()) return false; - if (track.itsNCls() < 2) + if (track.itsNCls() < min_ITS_nClusters) return false; if (!track.hasTPC()) return false; - if (track.tpcNClsFound() < 70) - return false; - if (track.tpcNClsCrossedRows() < 70) - return false; - if (track.tpcChi2NCl() > 4) + if (track.tpcNClsFound() < min_TPC_nClusters) return false; - if (track.itsChi2NCl() > 36) + if (track.tpcNClsCrossedRows() < min_TPC_nCrossedRows) return false; - if (track.eta() < -0.8 || track.eta() > 0.8) + if (track.tpcChi2NCl() > max_chi2_TPC) return false; - if (track.pt() < 0.15) + if (track.itsChi2NCl() > max_chi2_ITS) return false; - if (TMath::Abs(track.dcaXY()) > 0.5) + if (track.eta() < min_eta || track.eta() > max_eta) return false; - if (TMath::Abs(track.dcaZ()) > 0.5) + if (track.pt() < min_pt) return false; return true; } template - bool isParticleOfInterest(const T3& track) + bool isHighPurityAntiproton(const T3& track) { // Variables - float nsigmaTPCPr = track.tpcNSigmaPr(); - float nsigmaTOFPr = track.tofNSigmaPr(); - float nsigmaTPCDe = track.tpcNSigmaDe(); - float nsigmaTOFDe = track.tofNSigmaDe(); - float nsigmaTPCHe = track.tpcNSigmaHe(); - float pt = track.pt(); - - // Antimatter Only - if (track.sign() > 0) - return false; - - // Proton ID - if (particle_of_interest == nucleus::proton) { - if (pt < 1.0 && TMath::Abs(nsigmaTPCPr) < 8.0) - return true; - if (pt >= 1.0 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && track.hasTOF() && TMath::Abs(nsigmaTOFPr) < 10.0) - return true; - return false; - } - - // Deuteron ID - if (particle_of_interest == nucleus::deuteron) { - if (pt < 1.0 && TMath::Abs(nsigmaTPCDe) < 8.0) - return true; - if (pt >= 1.0 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC && track.hasTOF() && TMath::Abs(nsigmaTOFDe) < 10.0) - return true; - return false; - } - - // Helium-3 ID - if (particle_of_interest == nucleus::helium) { - if ((0.5 * pt) >= 1.0 && TMath::Abs(nsigmaTPCHe) < 8.0) - return true; - return false; - } - - return false; - } - - template - bool isHighPurityAntiproton(const T4& track) - { - // Variables - float nsigmaTPCPr = track.tpcNSigmaPr(); - float nsigmaTOFPr = track.tofNSigmaPr(); - float pt = track.pt(); + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double pt = track.pt(); if (pt < 0.5 && TMath::Abs(nsigmaTPCPr) < 2.0) return true; @@ -339,9 +270,9 @@ struct nuclei_in_jets { } // Minimum - float Minimum(float x1, float x2) + double Minimum(double x1, double x2) { - float x_min(x1); + double x_min(x1); if (x1 < x2) x_min = x1; if (x1 >= x2) @@ -353,9 +284,7 @@ struct nuclei_in_jets { // Deltaphi double GetDeltaPhi(double a1, double a2) { - double delta_phi(0); - double phi1 = TVector2::Phi_0_2pi(a1); double phi2 = TVector2::Phi_0_2pi(a2); double diff = TMath::Abs(phi1 - phi2); @@ -368,59 +297,8 @@ struct nuclei_in_jets { return delta_phi; } - float Weight(float pt, int event_region, int nucleus_of_interest) - { - - if (!applyReweighting) - return 1; - - auto par_proton_ref = static_cast>(param_proton_ref); - auto par_proton_jet = static_cast>(param_proton_jet); - auto par_deuteron_jet = static_cast>(param_deuteron_jet); - auto par_helium3_jet = static_cast>(param_helium3_jet); - auto par_proton_ue = static_cast>(param_proton_ue); - auto par_deuteron_ue = static_cast>(param_deuteron_ue); - auto par_helium3_ue = static_cast>(param_helium3_ue); - - float dNdpt_proton_ref = GetTsallis(par_proton_ref[0], par_proton_ref[1], par_proton_ref[2], par_proton_ref[3], pt); - float dNdpt_proton_jet = GetTsallis(par_proton_jet[0], par_proton_jet[1], par_proton_jet[2], par_proton_jet[3], pt); - float dNdpt_proton_ue = GetTsallis(par_proton_ue[0], par_proton_ue[1], par_proton_ue[2], par_proton_ue[3], pt); - float dNdpt_deuteron_jet = GetTsallis(par_deuteron_jet[0], par_deuteron_jet[1], par_deuteron_jet[2], par_deuteron_jet[3], pt); - float dNdpt_deuteron_ue = GetTsallis(par_deuteron_ue[0], par_deuteron_ue[1], par_deuteron_ue[2], par_deuteron_ue[3], pt); - float dNdpt_helium3_jet = GetTsallis(par_helium3_jet[0], par_helium3_jet[1], par_helium3_jet[2], par_helium3_jet[3], pt); - float dNdpt_helium3_ue = GetTsallis(par_helium3_ue[0], par_helium3_ue[1], par_helium3_ue[2], par_helium3_ue[3], pt); - - if (nucleus_of_interest == nucleus::proton && event_region == region::jet) - return dNdpt_proton_jet / dNdpt_proton_ref; - if (nucleus_of_interest == nucleus::proton && event_region == region::underlying_event) - return dNdpt_proton_ue / dNdpt_proton_ref; - if (nucleus_of_interest == nucleus::deuteron && event_region == region::jet) - return dNdpt_deuteron_jet; - if (nucleus_of_interest == nucleus::deuteron && event_region == region::underlying_event) - return dNdpt_deuteron_ue; - if (nucleus_of_interest == nucleus::helium && event_region == region::jet) - return dNdpt_helium3_jet; - if (nucleus_of_interest == nucleus::helium && event_region == region::underlying_event) - return dNdpt_helium3_ue; - - return 1; - } - - float GetTsallis(float p0, float p1, float p2, float p3, float pt) - { - - float dNdpt(1); - float part1 = p0 * pt * (p1 - 1.0) * (p1 - 2.0); - float part2 = part1 * TMath::Power(1.0 + (TMath::Sqrt(p3 * p3 + pt * pt) - p3) / (p1 * p2), -p1); - float part3 = part2 / TMath::TwoPi() * (p1 * p2 * (p1 * p2 + p3 * (p1 - 2.0))); - dNdpt = part3; - - return dNdpt; - } - void get_perpendicular_axis(TVector3 p, TVector3& u, double sign) { - // Initialization double ux(0), uy(0), uz(0); @@ -468,478 +346,343 @@ struct nuclei_in_jets { return; } - // Lorentz Transformation - TLorentzVector LorentzTransform(TLorentzVector R, TVector3 beta_vect) + double calculate_dij(TVector3 t1, TVector3 t2, double R) { + double distance_jet(0); + double x1 = 1.0 / (t1.Pt() * t1.Pt()); + double x2 = 1.0 / (t2.Pt() * t2.Pt()); + double deltaEta = t1.Eta() - t2.Eta(); + double deltaPhi = GetDeltaPhi(t1.Phi(), t2.Phi()); + double min = Minimum(x1, x2); + double Delta2 = deltaEta * deltaEta + deltaPhi * deltaPhi; + distance_jet = min * Delta2 / (R * R); + return distance_jet; + } - // Inizialization - TLorentzVector R_prime(0.0, 0.0, 0.0, 0.0); - - // Beta Components - Double_t Bx = beta_vect.X(); - Double_t By = beta_vect.Y(); - Double_t Bz = beta_vect.Z(); - - // Beta & Gamma - Double_t beta = TMath::Sqrt(Bx * Bx + By * By + Bz * Bz); - if (beta >= 1.0) { - return R_prime; - } - Double_t gamma = 1.0 / TMath::Sqrt(1.0 - (beta * beta)); - - // Coordinates in the Lab System - Double_t t = R.T(); - Double_t x = R.X(); - Double_t y = R.Y(); - Double_t z = R.Z(); - - // Coordinates in the Deuteron Frame - Double_t t_prime = gamma * t - gamma * Bx * x - gamma * By * y - gamma * Bz * z; - Double_t x_prime = -gamma * Bx * t + (1.0 + (gamma - 1.0) * Bx * Bx / (beta * beta)) * x + (gamma - 1.0) * (Bx * By / (beta * beta)) * y + (gamma - 1.0) * (Bx * Bz / (beta * beta)) * z; - Double_t y_prime = -gamma * By * t + (gamma - 1.0) * (Bx * By / (beta * beta)) * x + (1.0 + (gamma - 1.0) * By * By / (beta * beta)) * y + (gamma - 1.0) * (By * Bz / (beta * beta)) * z; - Double_t z_prime = -gamma * Bz * t + (gamma - 1.0) * (Bx * Bz / (beta * beta)) * x + (gamma - 1.0) * (By * Bz / (beta * beta)) * y + (1.0 + (gamma - 1.0) * Bz * Bz / (beta * beta)) * z; - - // Set Coordinates - R_prime.SetXYZT(x_prime, y_prime, z_prime, t_prime); - - return R_prime; + bool overlap(TVector3 v1, TVector3 v2, double R) + { + double dx = v1.Eta() - v2.Eta(); + double dy = GetDeltaPhi(v1.Phi(), v2.Phi()); + double d = sqrt(dx * dx + dy * dy); + if (d < 2.0 * R) + return true; + return false; } // Process Data void processData(SelectedCollisions::iterator const& collision, FullTracks const& tracks) { - // Event Counter: before event selection - registryQC.fill(HIST("number_of_events_data"), 0.5); + registryData.fill(HIST("number_of_events_data"), 0.5); // Event Selection if (!collision.sel8()) return; // Event Counter: after event selection sel8 - registryQC.fill(HIST("number_of_events_data"), 1.5); + registryData.fill(HIST("number_of_events_data"), 1.5); - // Cut on Zvertex - if (abs(collision.posZ()) > 10.0) + // Cut on z-vertex + if (abs(collision.posZ()) > zVtx) return; - // Event Counter: after |z|<10 cm cut - registryQC.fill(HIST("number_of_events_data"), 2.5); + // Event Counter: after z-vertex cut + registryData.fill(HIST("number_of_events_data"), 2.5); - // Reduced Event - std::vector particle_ID; - int leading_ID = 0; - bool containsParticleOfInterest(false); - float pt_max(0); - int i = -1; + // List of Tracks + std::vector trk; - // Loop over Reconstructed Tracks for (auto track : tracks) { - // Global Track - i++; - - // Track Selection for Jet - if (!passedMinimalTrackSelection(track)) + if (!passedTrackSelectionForJetReconstruction(track)) continue; + registryQC.fill(HIST("dcaxy_vs_pt"), track.pt(), track.dcaXY()); + registryQC.fill(HIST("dcaz_vs_pt"), track.pt(), track.dcaZ()); - // Trigger: Particle of Interest - if (isParticleOfInterest(track)) - containsParticleOfInterest = true; - - // Find pt Leading - if (track.pt() > pt_max) { - leading_ID = i; - pt_max = track.pt(); - } - - // Store Array Element - particle_ID.push_back(i); + TVector3 momentum(track.px(), track.py(), track.pz()); + trk.push_back(momentum); } - // Event Counter: Skip Events with no trigger Particle (pmax=0) - if (pt_max == 0) - return; - registryQC.fill(HIST("number_of_events_data"), 3.5); - - // Histogram with pt_leading - registryQC.fill(HIST("pt_leading"), pt_max); - - // Event Counter: Skip Events with pt(particle_ID.size()); + // Anti-kt Jet Finder + int n_particles_removed(0); + std::vector jet; + std::vector ue1; + std::vector ue2; - // Event Counter: Skip Events with 0 Particles - if (nParticles < 1) - return; - registryQC.fill(HIST("number_of_events_data"), 5.5); - - // Momentum of the Leading Particle - auto const& leading_track = tracks.iteratorAt(leading_ID); - TVector3 p_leading(leading_track.px(), leading_track.py(), leading_track.pz()); - TVector3 p_highest_pt_track(leading_track.px(), leading_track.py(), leading_track.pz()); - - // Event Counter: Skip Events with no Particle of Interest - if (!containsParticleOfInterest) - return; - registryQC.fill(HIST("number_of_events_data"), 6.5); - - // Array of Particles inside Jet - std::vector jet_particle_ID; - jet_particle_ID.push_back(leading_ID); - - // Labels - Int_t exit(0); - Int_t nPartAssociated(0); - - // Jet Finder do { - // Initialization - float distance_jet_min(1e+08); - float distance_bkg_min(1e+08); - int label_jet_particle(0); - int i_jet_particle(0); - - for (int i = 0; i < nParticles; i++) { - - // Skip Leading Particle & Elements already associated to the Jet - if (particle_ID[i] == leading_ID || particle_ID[i] == -1) + double dij_min(1e+06), diB_min(1e+06); + int i_min(0), j_min(0), iB_min(0); + for (int i = 0; i < static_cast(trk.size()); i++) { + if (trk[i].Mag() == 0) continue; - - // Get Particle Momentum - auto stored_track = tracks.iteratorAt(particle_ID[i]); - TVector3 p_particle(stored_track.px(), stored_track.py(), stored_track.pz()); - - // Variables - float one_over_pt2_part = 1.0 / (p_particle.Pt() * p_particle.Pt()); - float one_over_pt2_lead = 1.0 / (p_leading.Pt() * p_leading.Pt()); - float deltaEta = p_particle.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_particle.Phi(), p_leading.Phi()); - float min = Minimum(one_over_pt2_part, one_over_pt2_lead); - float Delta2 = deltaEta * deltaEta + deltaPhi * deltaPhi; - - // Distances - float distance_jet = min * Delta2 / (Rparameter_jet * Rparameter_jet); - float distance_bkg = one_over_pt2_part; - - // Find Minimum Distance Jet - if (distance_jet < distance_jet_min) { - distance_jet_min = distance_jet; - label_jet_particle = particle_ID[i]; - i_jet_particle = i; + double diB = 1.0 / (trk[i].Pt() * trk[i].Pt()); + if (diB < diB_min) { + diB_min = diB; + iB_min = i; } - - // Find Minimum Distance Bkg - if (distance_bkg < distance_bkg_min) { - distance_bkg_min = distance_bkg; + for (int j = (i + 1); j < static_cast(trk.size()); j++) { + if (trk[j].Mag() == 0) + continue; + double dij = calculate_dij(trk[i], trk[j], Rjet); + if (dij < dij_min) { + dij_min = dij; + i_min = i; + j_min = j; + } } } - - if (distance_jet_min <= distance_bkg_min) { - - // Add Particle to Jet - jet_particle_ID.push_back(label_jet_particle); - - // Update Momentum of Leading Particle - auto jet_track = tracks.iteratorAt(label_jet_particle); - TVector3 p_i(jet_track.px(), jet_track.py(), jet_track.pz()); - p_leading = p_leading + p_i; - - // Remove Element - particle_ID[i_jet_particle] = -1; - nPartAssociated++; + if (dij_min < diB_min) { + trk[i_min] = trk[i_min] + trk[j_min]; + trk[j_min].SetXYZ(0, 0, 0); + n_particles_removed++; } + if (dij_min > diB_min) { + jet.push_back(trk[iB_min]); + trk[iB_min].SetXYZ(0, 0, 0); + n_particles_removed++; + } + } while (n_particles_removed < static_cast(trk.size())); - if (nPartAssociated >= (nParticles - 1)) - exit = 1; - if (distance_jet_min > distance_bkg_min) - exit = 2; - - } while (exit == 0); - - // Multiplicity inside Jet + UE - int nParticlesJetUE = static_cast(jet_particle_ID.size()); - - // QA Plots - registryQC.fill(HIST("eta_leading"), p_leading.Eta()); - registryQC.fill(HIST("phi_leading"), TVector2::Phi_0_2pi(p_leading.Phi())); - registryQC.fill(HIST("angle_jet_leading_track"), p_leading.Angle(p_highest_pt_track)); - - // Rmax and Area Cut - float Rmax(0); - int nParticlesJetAndUE(0); - for (int i = 0; i < nParticlesJetUE; i++) { - - const auto& jet_track = tracks.iteratorAt(jet_particle_ID[i]); - TVector3 p_i(jet_track.px(), jet_track.py(), jet_track.pz()); + registryQC.fill(HIST("nJets_found"), static_cast(jet.size())); - float deltaEta = p_i.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_i.Phi(), p_leading.Phi()); - float R = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); - if (R < Rmax_jet_ue) - nParticlesJetAndUE++; - if (R > Rmax) - Rmax = R; + // Jet Selection + std::vector isSelected; + for (int i = 0; i < static_cast(jet.size()); i++) { + isSelected.push_back(0); } - // Rmax Distribution - registryQC.fill(HIST("r_max_jet"), Rmax); + int n_jets_selected(0); + for (int i = 0; i < static_cast(jet.size()); i++) { - // Event Counter: Skip Events with jet not fully inside acceptance - float eta_jet_axis = p_leading.Eta(); - if ((TMath::Abs(eta_jet_axis) + Rmax_jet_ue) > max_eta) - return; - registryQC.fill(HIST("number_of_events_data"), 7.5); + if ((abs(jet[i].Eta()) + Rjet) > max_eta) + continue; - // Fill Jet Multiplicity - registryQC.fill(HIST("jet_plus_ue_multiplicity"), nParticlesJetAndUE); + // Perpendicular cones + TVector3 ue_axis1(0, 0, 0); + TVector3 ue_axis2(0, 0, 0); + get_perpendicular_axis(jet[i], ue_axis1, +1); + get_perpendicular_axis(jet[i], ue_axis2, -1); + ue1.push_back(ue_axis1); + ue2.push_back(ue_axis2); - // Perpendicular Cones for UE Estimate - TVector3 ue_axis1(0.0, 0.0, 0.0); - TVector3 ue_axis2(0.0, 0.0, 0.0); - get_perpendicular_axis(p_leading, ue_axis1, +1.0); - get_perpendicular_axis(p_leading, ue_axis2, -1.0); + double nPartJetPlusUE(0); + double nPartJet(0); + double nPartUE(0); + double ptJetPlusUE(0); + double ptJet(0); + double ptUE(0); - // Protection against delta<0 - if (ue_axis1.X() == 0 && ue_axis1.Y() == 0 && ue_axis1.Z() == 0) - return; - if (ue_axis2.X() == 0 && ue_axis2.Y() == 0 && ue_axis2.Z() == 0) - return; - - registryQC.fill(HIST("number_of_events_data"), 8.5); + for (auto track : tracks) { - // Store UE - std::vector ue_particle_ID; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + TVector3 sel_track(track.px(), track.py(), track.pz()); + + double deltaEta_jet = sel_track.Eta() - jet[i].Eta(); + double deltaPhi_jet = GetDeltaPhi(sel_track.Phi(), jet[i].Phi()); + double deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + double deltaEta_ue1 = sel_track.Eta() - ue_axis1.Eta(); + double deltaPhi_ue1 = GetDeltaPhi(sel_track.Phi(), ue_axis1.Phi()); + double deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + double deltaEta_ue2 = sel_track.Eta() - ue_axis2.Eta(); + double deltaPhi_ue2 = GetDeltaPhi(sel_track.Phi(), ue_axis2.Phi()); + double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + if (deltaR_jet < Rjet) { + registryQC.fill(HIST("deltaEtadeltaPhi_jet"), deltaEta_jet, deltaPhi_jet); + nPartJetPlusUE++; + ptJetPlusUE = ptJetPlusUE + sel_track.Pt(); + } + if (deltaR_ue1 < Rjet) { + registryQC.fill(HIST("deltaEtadeltaPhi_ue"), deltaEta_ue1, deltaPhi_ue1); + nPartUE++; + ptUE = ptUE + sel_track.Pt(); + } + if (deltaR_ue2 < Rjet) { + registryQC.fill(HIST("deltaEtadeltaPhi_ue"), deltaEta_ue2, deltaPhi_ue2); + nPartUE++; + ptUE = ptUE + sel_track.Pt(); + } + } + nPartJet = nPartJetPlusUE - 0.5 * nPartUE; + ptJet = ptJetPlusUE - 0.5 * ptUE; + registryQC.fill(HIST("NchJetPlusUE"), nPartJetPlusUE); + registryQC.fill(HIST("NchJet"), nPartJet); + registryQC.fill(HIST("NchUE"), nPartUE); + registryQC.fill(HIST("sumPtJetPlusUE"), ptJetPlusUE); + registryQC.fill(HIST("sumPtJet"), ptJet); + registryQC.fill(HIST("sumPtUE"), ptUE); + + if (ptJet < min_jet_pt) + continue; + if (nPartJetPlusUE < min_nPartInJet) + continue; + n_jets_selected++; + isSelected[i] = 1; + } + registryQC.fill(HIST("nJets_selected"), n_jets_selected); - for (int i = 0; i < nParticles; i++) { + if (n_jets_selected == 0) + return; + registryData.fill(HIST("number_of_events_data"), 3.5); + //************************************************************************************************************************************ - // Skip Leading Particle & Elements already associated to the Jet - if (particle_ID[i] == leading_ID || particle_ID[i] == -1) + // Overlaps + int nOverlaps(0); + for (int i = 0; i < static_cast(jet.size()); i++) { + if (isSelected[i] == 0) continue; - // Get UE Track - const auto& ue_track = tracks.iteratorAt(particle_ID[i]); - - // Variables - float deltaEta1 = ue_track.eta() - ue_axis1.Eta(); - float deltaPhi1 = GetDeltaPhi(ue_track.phi(), ue_axis1.Phi()); - float dr1 = TMath::Sqrt(deltaEta1 * deltaEta1 + deltaPhi1 * deltaPhi1); - float deltaEta2 = ue_track.eta() - ue_axis2.Eta(); - float deltaPhi2 = GetDeltaPhi(ue_track.phi(), ue_axis2.Phi()); - float dr2 = TMath::Sqrt(deltaEta2 * deltaEta2 + deltaPhi2 * deltaPhi2); - - // Store Particles in the UE - if (dr1 < Rmax_jet_ue) { - registryQC.fill(HIST("eta_phi_ue"), deltaEta1, deltaPhi1); - registryQC.fill(HIST("r_ue"), dr1); - ue_particle_ID.push_back(particle_ID[i]); - } - - if (dr2 < Rmax_jet_ue) { - registryQC.fill(HIST("eta_phi_ue"), deltaEta2, deltaPhi2); - registryQC.fill(HIST("r_ue"), dr2); - ue_particle_ID.push_back(particle_ID[i]); + for (int j = 0; j < static_cast(jet.size()); j++) { + if (isSelected[j] == 0 || i == j) + continue; + if (overlap(jet[i], ue1[j], Rjet) || overlap(jet[i], ue2[j], Rjet)) + nOverlaps++; } } + registryQC.fill(HIST("jet_ue_overlaps"), n_jets_selected, nOverlaps); - // UE Multiplicity - int nParticlesUE = static_cast(ue_particle_ID.size()); - registryQC.fill(HIST("ue_multiplicity"), static_cast(nParticlesUE) / 2.0); - - // Jet Multiplicity - float jet_Nch = static_cast(nParticlesJetAndUE) - static_cast(nParticlesUE) / 2.0; - registryQC.fill(HIST("jet_multiplicity"), jet_Nch); - - // Loop over particles inside Jet - for (int i = 0; i < nParticlesJetUE; i++) { - - const auto& jet_track = tracks.iteratorAt(jet_particle_ID[i]); - TVector3 p_i(jet_track.px(), jet_track.py(), jet_track.pz()); - - float deltaEta = p_i.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_i.Phi(), p_leading.Phi()); - float R = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); - if (R > Rmax_jet_ue) - continue; + if (n_jets_selected > n_jets_per_event_max) + return; + registryData.fill(HIST("number_of_events_data"), 4.5); - if (deltaEta != 0 && deltaPhi != 0) { - registryQC.fill(HIST("eta_phi_jet"), deltaEta, deltaPhi); - registryQC.fill(HIST("r_jet"), TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi)); - } + if (requireNoOverlap && nOverlaps > 0) + return; + registryData.fill(HIST("number_of_events_data"), 5.5); - // Track Selection - if (!passedTrackSelection(jet_track)) - continue; - if (require_primVtx_contributor && !(jet_track.isPVContributor())) - continue; + //************************************************************************************************************************************ - // Variables - float nsigmaTPCPr = jet_track.tpcNSigmaPr(); - float nsigmaTOFPr = jet_track.tofNSigmaPr(); - float nsigmaTPCDe = jet_track.tpcNSigmaDe(); - float nsigmaTOFDe = jet_track.tofNSigmaDe(); - float nsigmaTPCHe = jet_track.tpcNSigmaHe(); - float pt = jet_track.pt(); - float eta = jet_track.eta(); - - // DCA - if (isHighPurityAntiproton(jet_track) && TMath::Abs(jet_track.dcaZ()) < max_dcaz) { - registryData.fill(HIST("antiproton_dca_jet"), pt, jet_track.dcaXY(), jet_Nch); - } + for (int i = 0; i < static_cast(jet.size()); i++) { - // DCA Cuts - if (TMath::Abs(jet_track.dcaXY()) > max_dcaxy) - continue; - if (TMath::Abs(jet_track.dcaZ()) > max_dcaz) + if (isSelected[i] == 0) continue; - // Antiproton - if (particle_of_interest == nucleus::proton) { - if (pt < 1.0) - registryData.fill(HIST("antiproton_jet_tpc"), pt, nsigmaTPCPr, jet_Nch); - if (pt >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && jet_track.hasTOF()) - registryData.fill(HIST("antiproton_jet_tof"), pt, nsigmaTOFPr, jet_Nch); - if (pt < 1.0 && TMath::Abs(nsigmaTPCPr) < 2.0) - registryData.fill(HIST("antip_tpc_jet_eta_pt"), pt, eta); - if (pt >= 0.5 && TMath::Abs(nsigmaTPCPr) < 2.0 && jet_track.hasTOF() && TMath::Abs(nsigmaTOFPr) < 2.0) - registryData.fill(HIST("antip_tof_jet_eta_pt"), pt, eta); - } + for (auto track : tracks) { + if (!passedTrackSelection(track)) + continue; + if (require_PV_contributor && !(track.isPVContributor())) + continue; + if (track.sign() > 0) + continue; - // Antideuteron - if (particle_of_interest == nucleus::deuteron) { - if (pt < 1.0) - registryData.fill(HIST("antideuteron_jet_tpc"), pt, nsigmaTPCDe, jet_Nch); - if (pt >= 0.5 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC && jet_track.hasTOF()) - registryData.fill(HIST("antideuteron_jet_tof"), pt, nsigmaTOFDe, jet_Nch); - } + // Variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double nsigmaTPCDe = track.tpcNSigmaDe(); + double nsigmaTOFDe = track.tofNSigmaDe(); + double nsigmaTPCHe = track.tpcNSigmaHe(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); + + TVector3 particle_dir(track.px(), track.py(), track.pz()); + double deltaEta_jet = particle_dir.Eta() - jet[i].Eta(); + double deltaPhi_jet = GetDeltaPhi(particle_dir.Phi(), jet[i].Phi()); + double deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + double deltaEta_ue1 = particle_dir.Eta() - ue1[i].Eta(); + double deltaPhi_ue1 = GetDeltaPhi(particle_dir.Phi(), ue1[i].Phi()); + double deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + double deltaEta_ue2 = particle_dir.Eta() - ue2[i].Eta(); + double deltaPhi_ue2 = GetDeltaPhi(particle_dir.Phi(), ue2[i].Phi()); + double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + // DCAxy Distributions of Antiprotons + if (isHighPurityAntiproton(track) && TMath::Abs(dcaz) < max_dcaz) { + if (deltaR_jet < Rjet) { + registryData.fill(HIST("antiproton_dca_jet"), pt, dcaxy); + } + if (deltaR_ue1 < Rjet || deltaR_ue2 < Rjet) { + registryData.fill(HIST("antiproton_dca_ue"), pt, dcaxy); + } + } - // Antihelium3 - if (particle_of_interest == nucleus::helium) { - registryData.fill(HIST("antihelium3_jet_tpc"), 2.0 * pt, nsigmaTPCHe, jet_Nch); - } - } + // DCA Cuts + if (TMath::Abs(dcaxy) > max_dcaxy) + continue; + if (TMath::Abs(dcaz) > max_dcaz) + continue; - // Loop over particles inside UE - for (int i = 0; i < nParticlesUE; i++) { + // Jet + if (deltaR_jet < Rjet) { - const auto& ue_track = tracks.iteratorAt(ue_particle_ID[i]); + // Antiproton + if (pt < 1.0) + registryData.fill(HIST("antiproton_jet_tpc"), pt, nsigmaTPCPr); + if (pt >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && track.hasTOF()) + registryData.fill(HIST("antiproton_jet_tof"), pt, nsigmaTOFPr); - // Track Selection - if (!passedTrackSelection(ue_track)) - continue; - if (require_primVtx_contributor && !(ue_track.isPVContributor())) - continue; + // Antideuteron + if (pt < 1.0) + registryData.fill(HIST("antideuteron_jet_tpc"), pt, nsigmaTPCDe); + if (pt >= 0.5 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC && track.hasTOF()) + registryData.fill(HIST("antideuteron_jet_tof"), pt, nsigmaTOFDe); - // Variables - float nsigmaTPCPr = ue_track.tpcNSigmaPr(); - float nsigmaTOFPr = ue_track.tofNSigmaPr(); - float nsigmaTPCDe = ue_track.tpcNSigmaDe(); - float nsigmaTOFDe = ue_track.tofNSigmaDe(); - float nsigmaTPCHe = ue_track.tpcNSigmaHe(); - float pt = ue_track.pt(); - float eta = ue_track.eta(); - - // DCA - if (isHighPurityAntiproton(ue_track) && TMath::Abs(ue_track.dcaZ()) < max_dcaz) { - registryData.fill(HIST("antiproton_dca_ue"), pt, ue_track.dcaXY(), jet_Nch); - } + // Antihelium3 + registryData.fill(HIST("antihelium3_jet_tpc"), 2.0 * pt, nsigmaTPCHe); + } - // DCA Cuts - if (TMath::Abs(ue_track.dcaXY()) > max_dcaxy) - continue; - if (TMath::Abs(ue_track.dcaZ()) > max_dcaz) - continue; + // UE + if (deltaR_ue1 < Rjet || deltaR_ue2 < Rjet) { - // Antiproton - if (particle_of_interest == nucleus::proton) { - if (pt < 1.0) - registryData.fill(HIST("antiproton_ue_tpc"), pt, nsigmaTPCPr, jet_Nch); - if (pt >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && ue_track.hasTOF()) - registryData.fill(HIST("antiproton_ue_tof"), pt, nsigmaTOFPr, jet_Nch); - if (pt < 1.0 && TMath::Abs(nsigmaTPCPr) < 2.0) - registryData.fill(HIST("antip_tpc_ue_eta_pt"), pt, eta); - if (pt >= 0.5 && TMath::Abs(nsigmaTPCPr) < 2.0 && ue_track.hasTOF() && TMath::Abs(nsigmaTOFPr) < 2.0) - registryData.fill(HIST("antip_tof_ue_eta_pt"), pt, eta); - } + // Antiproton + if (pt < 1.0) + registryData.fill(HIST("antiproton_ue_tpc"), pt, nsigmaTPCPr); + if (pt >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && track.hasTOF()) + registryData.fill(HIST("antiproton_ue_tof"), pt, nsigmaTOFPr); - // Antideuteron - if (particle_of_interest == nucleus::deuteron) { - if (pt < 1.0) - registryData.fill(HIST("antideuteron_ue_tpc"), pt, nsigmaTPCDe, jet_Nch); - if (pt >= 0.5 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC && ue_track.hasTOF()) - registryData.fill(HIST("antideuteron_ue_tof"), pt, nsigmaTOFDe, jet_Nch); - } + // Antideuteron + if (pt < 1.0) + registryData.fill(HIST("antideuteron_ue_tpc"), pt, nsigmaTPCDe); + if (pt >= 0.5 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC && track.hasTOF()) + registryData.fill(HIST("antideuteron_ue_tof"), pt, nsigmaTOFDe); - // Antihelium3 - if (particle_of_interest == nucleus::helium) { - registryData.fill(HIST("antihelium3_ue_tpc"), 2.0 * pt, nsigmaTPCHe, jet_Nch); + // Antihelium3 + registryData.fill(HIST("antihelium3_ue_tpc"), 2.0 * pt, nsigmaTPCHe); + } } } } + PROCESS_SWITCH(nuclei_in_jets, processData, "Process Data", true); Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; Preslice perCollision = o2::aod::track::collisionId; - void processGen(o2::aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + void processEfficiency(o2::aod::McCollisions const& mcCollisions, SimCollisions const& collisions, MCTracks const& mcTracks, aod::McParticles const& mcParticles) { + // Generated Events for (const auto& mccollision : mcCollisions) { - // Event Counter (before event sel) - registryQC.fill(HIST("number_of_events_mc"), 0.5); - + registryMC.fill(HIST("number_of_events_mc"), 0.5); auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); - // Generated Particles for (auto& particle : mcParticles_per_coll) { if (!particle.isPhysicalPrimary()) continue; if ((particle.pdgCode() != -2212) && (particle.pdgCode() != -1000010020) && (particle.pdgCode() != -1000020030)) continue; - if (particle.y() < min_y || particle.y() > max_y) + if (particle.eta() < min_eta || particle.eta() > max_eta) continue; - // Reweighting - float wpr_jet = Weight(particle.pt(), region::jet, nucleus::proton); - float wpr_ue = Weight(particle.pt(), region::underlying_event, nucleus::proton); - float wde_jet = Weight(particle.pt(), region::jet, nucleus::deuteron); - float wde_ue = Weight(particle.pt(), region::underlying_event, nucleus::deuteron); - float whe_jet = Weight(particle.pt(), region::jet, nucleus::helium); - float whe_ue = Weight(particle.pt(), region::underlying_event, nucleus::helium); - - // Fill Histograms if (particle.pdgCode() == -2212) { - registryMC.fill(HIST("antiproton_input"), particle.pt()); - registryMC.fill(HIST("antiproton_weighted_jet"), particle.pt(), wpr_jet); - registryMC.fill(HIST("antiproton_weighted_ue"), particle.pt(), wpr_ue); - registryMC.fill(HIST("antiproton_jet_gen"), particle.pt(), wpr_jet); - registryMC.fill(HIST("antiproton_ue_gen"), particle.pt(), wpr_ue); - registryMC.fill(HIST("antiproton_eta_pt_pythia"), particle.pt(), particle.eta()); + registryMC.fill(HIST("antiproton_jet_gen"), particle.pt()); + registryMC.fill(HIST("antiproton_ue_gen"), particle.pt()); } if (particle.pdgCode() == -1000010020) { - registryMC.fill(HIST("antideuteron_jet_gen"), particle.pt(), wde_jet); - registryMC.fill(HIST("antideuteron_ue_gen"), particle.pt(), wde_ue); - registryMC.fill(HIST("antideuteron_eta_pt_injected"), particle.pt(), particle.eta()); + registryMC.fill(HIST("antideuteron_jet_gen"), particle.pt()); + registryMC.fill(HIST("antideuteron_ue_gen"), particle.pt()); } if (particle.pdgCode() == -1000020030) { - registryMC.fill(HIST("antihelium3_jet_gen"), particle.pt(), whe_jet); - registryMC.fill(HIST("antihelium3_ue_gen"), particle.pt(), whe_ue); + registryMC.fill(HIST("antihelium3_jet_gen"), particle.pt()); + registryMC.fill(HIST("antihelium3_ue_gen"), particle.pt()); } } } - } - - void processRec(SimCollisions const& collisions, MCTracks const& mcTracks, aod::McCollisions const&, const aod::McParticles&) - { + // Reconstructed Events for (const auto& collision : collisions) { - // Event Counter (before event sel) - registryQC.fill(HIST("number_of_events_mc"), 1.5); + registryMC.fill(HIST("number_of_events_mc"), 1.5); // Event Selection if (!collision.sel8()) @@ -949,7 +692,7 @@ struct nuclei_in_jets { continue; // Event Counter (after event sel) - registryQC.fill(HIST("number_of_events_mc"), 2.5); + registryMC.fill(HIST("number_of_events_mc"), 2.5); auto tracks_per_coll = mcTracks.sliceBy(perCollision, collision.globalIndex()); @@ -967,17 +710,9 @@ struct nuclei_in_jets { // Track Selection if (!passedTrackSelection(track)) continue; - if (require_primVtx_contributor && !(track.isPVContributor())) + if (require_PV_contributor && !(track.isPVContributor())) continue; - // Reweighting - float wpr_jet = Weight(particle.pt(), region::jet, nucleus::proton); - float wpr_ue = Weight(particle.pt(), region::underlying_event, nucleus::proton); - float wde_jet = Weight(particle.pt(), region::jet, nucleus::deuteron); - float wde_ue = Weight(particle.pt(), region::underlying_event, nucleus::deuteron); - float whe_jet = Weight(particle.pt(), region::jet, nucleus::helium); - float whe_ue = Weight(particle.pt(), region::underlying_event, nucleus::helium); - // Variables float nsigmaTPCPr = track.tpcNSigmaPr(); float nsigmaTOFPr = track.tofNSigmaPr(); @@ -1013,637 +748,447 @@ struct nuclei_in_jets { // Antiproton if (particle.pdgCode() == -2212) { if (pt < 1.0 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC) { - registryMC.fill(HIST("antiproton_jet_rec_tpc"), pt, wpr_jet); - registryMC.fill(HIST("antiproton_ue_rec_tpc"), pt, wpr_ue); + registryMC.fill(HIST("antiproton_jet_rec_tpc"), pt); + registryMC.fill(HIST("antiproton_ue_rec_tpc"), pt); } if (pt >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && track.hasTOF() && nsigmaTOFPr > min_nsigmaTOF && nsigmaTOFPr < max_nsigmaTOF) { - registryMC.fill(HIST("antiproton_jet_rec_tof"), pt, wpr_jet); - registryMC.fill(HIST("antiproton_ue_rec_tof"), pt, wpr_ue); + registryMC.fill(HIST("antiproton_jet_rec_tof"), pt); + registryMC.fill(HIST("antiproton_ue_rec_tof"), pt); } } // Antideuteron if (particle.pdgCode() == -1000010020) { if (pt < 1.0 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC) { - registryMC.fill(HIST("antideuteron_jet_rec_tpc"), pt, wde_jet); - registryMC.fill(HIST("antideuteron_ue_rec_tpc"), pt, wde_ue); + registryMC.fill(HIST("antideuteron_jet_rec_tpc"), pt); + registryMC.fill(HIST("antideuteron_ue_rec_tpc"), pt); } if (pt >= 0.5 && nsigmaTPCDe > min_nsigmaTPC && nsigmaTPCDe < max_nsigmaTPC && track.hasTOF() && nsigmaTOFDe > min_nsigmaTOF && nsigmaTOFDe < max_nsigmaTOF) { - registryMC.fill(HIST("antideuteron_jet_rec_tof"), pt, wde_jet); - registryMC.fill(HIST("antideuteron_ue_rec_tof"), pt, wde_ue); + registryMC.fill(HIST("antideuteron_jet_rec_tof"), pt); + registryMC.fill(HIST("antideuteron_ue_rec_tof"), pt); } } // Antihelium-3 if (particle.pdgCode() == -1000020030) { if (nsigmaTPCHe > min_nsigmaTPC && nsigmaTPCHe < max_nsigmaTPC) { - registryMC.fill(HIST("antihelium3_jet_rec_tpc"), 2.0 * pt, whe_jet); - registryMC.fill(HIST("antihelium3_ue_rec_tpc"), 2.0 * pt, whe_ue); + registryMC.fill(HIST("antihelium3_jet_rec_tpc"), 2.0 * pt); + registryMC.fill(HIST("antihelium3_ue_rec_tpc"), 2.0 * pt); } } } } } + PROCESS_SWITCH(nuclei_in_jets, processEfficiency, "process efficiency", false); - void processAntiNucleiJet(o2::aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + void processSecondaryAntiprotons(SimCollisions const& collisions, MCTracks const& mcTracks, aod::McCollisions const&, const aod::McParticles&) { + for (const auto& collision : collisions) { - // Loop over MC Collisions - for (const auto& mccollision : mcCollisions) { - - registryQC.fill(HIST("event_counter_mc"), 0.5); + registryMC.fill(HIST("number_of_events_mc"), 3.5); - // Selection on z_{vertex} - if (abs(mccollision.posZ()) > 10) + // Event Selection + if (!collision.sel8()) continue; - registryQC.fill(HIST("event_counter_mc"), 1.5); - - // MC Particles per Collision - auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); - - // Reduced Event - std::vector particle_ID; - int leading_ID = 0; - float pt_max(0); + registryMC.fill(HIST("number_of_events_mc"), 4.5); - // Generated Particles - for (auto& particle : mcParticles_per_coll) { + if (abs(collision.posZ()) > zVtx) + continue; + registryMC.fill(HIST("number_of_events_mc"), 5.5); - // Global Index - int i = particle.globalIndex(); + auto tracks_per_coll = mcTracks.sliceBy(perCollision, collision.globalIndex()); - // Select Primary Particles - float deltaX = particle.vx() - mccollision.posX(); - float deltaY = particle.vy() - mccollision.posY(); - float deltaZ = particle.vz() - mccollision.posZ(); - float deltaR = sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); - if (deltaR > 0.1) - continue; + // List of Tracks + std::vector trk; - // Pseudorapidity Selection - if (abs(particle.eta()) > 0.8) - continue; + for (auto track : tracks_per_coll) { - // PDG Selection - int pdg = abs(particle.pdgCode()); - if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212) && (pdg != 1000010020)) + if (!passedTrackSelectionForJetReconstruction(track)) continue; - // Find pt Leading - if (particle.pt() > pt_max) { - leading_ID = i; - pt_max = particle.pt(); - } - - // Store Array Element - particle_ID.push_back(i); + TVector3 momentum(track.px(), track.py(), track.pz()); + trk.push_back(momentum); } - // Skip Events with pt(particle_ID.size()); - - // Momentum of the Leading Particle - auto const& leading_track = mcParticles_per_coll.iteratorAt(leading_ID); - TVector3 p_leading(leading_track.px(), leading_track.py(), leading_track.pz()); - registryQC.fill(HIST("deltaPt"), leading_track.pt() - pt_max); - - // Array of Particles inside Jet - std::vector jet_particle_ID; - jet_particle_ID.push_back(leading_ID); - - // Labels - Int_t exit(0); - Int_t nPartAssociated(0); + // Anti-kt Jet Finder + int n_particles_removed(0); + std::vector jet; + std::vector ue1; + std::vector ue2; - // Jet Finder do { - // Initialization - float distance_jet_min(1e+08); - float distance_bkg_min(1e+08); - int label_jet_particle(0); - int i_jet_particle(0); - - for (int i = 0; i < nParticles; i++) { - - // Skip Leading Particle & Elements already associated to the Jet - if (particle_ID[i] == leading_ID || particle_ID[i] == -1) + double dij_min(1e+06), diB_min(1e+06); + int i_min(0), j_min(0), iB_min(0); + for (int i = 0; i < static_cast(trk.size()); i++) { + if (trk[i].Mag() == 0) continue; - - // Get Particle Momentum - auto stored_track = mcParticles_per_coll.iteratorAt(particle_ID[i]); - TVector3 p_particle(stored_track.px(), stored_track.py(), stored_track.pz()); - - // Variables - float one_over_pt2_part = 1.0 / (p_particle.Pt() * p_particle.Pt()); - float one_over_pt2_lead = 1.0 / (p_leading.Pt() * p_leading.Pt()); - float deltaEta = p_particle.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_particle.Phi(), p_leading.Phi()); - float min = Minimum(one_over_pt2_part, one_over_pt2_lead); - float Delta2 = deltaEta * deltaEta + deltaPhi * deltaPhi; - - // Distances - float distance_jet = min * Delta2 / (Rparameter_jet * Rparameter_jet); - float distance_bkg = one_over_pt2_part; - - // Find Minimum Distance Jet - if (distance_jet < distance_jet_min) { - distance_jet_min = distance_jet; - label_jet_particle = particle_ID[i]; - i_jet_particle = i; + double diB = 1.0 / (trk[i].Pt() * trk[i].Pt()); + if (diB < diB_min) { + diB_min = diB; + iB_min = i; } - - // Find Minimum Distance Bkg - if (distance_bkg < distance_bkg_min) { - distance_bkg_min = distance_bkg; + for (int j = (i + 1); j < static_cast(trk.size()); j++) { + if (trk[j].Mag() == 0) + continue; + double dij = calculate_dij(trk[i], trk[j], Rjet); + if (dij < dij_min) { + dij_min = dij; + i_min = i; + j_min = j; + } } } - - if (distance_jet_min <= distance_bkg_min) { - - // Add Particle to Jet - jet_particle_ID.push_back(label_jet_particle); - - // Update Momentum of Leading Particle - auto jet_track = mcParticles_per_coll.iteratorAt(label_jet_particle); - TVector3 p_i(jet_track.px(), jet_track.py(), jet_track.pz()); - p_leading = p_leading + p_i; - - // Remove Element - particle_ID[i_jet_particle] = -1; - nPartAssociated++; + if (dij_min < diB_min) { + trk[i_min] = trk[i_min] + trk[j_min]; + trk[j_min].SetXYZ(0, 0, 0); + n_particles_removed++; } - - if (nPartAssociated >= (nParticles - 1)) - exit = 1; - if (distance_jet_min > distance_bkg_min) - exit = 2; - - } while (exit == 0); - - // Multiplicity inside Jet + UE - int nParticlesJetUE = static_cast(jet_particle_ID.size()); - - // Event Counter: Skip Events with jet not fully inside acceptance - float eta_jet_axis = p_leading.Eta(); - if ((TMath::Abs(eta_jet_axis) + Rmax_jet_ue) > max_eta) - continue; - registryQC.fill(HIST("event_counter_mc"), 3.5); - - // Perpendicular Cones for UE Estimate - TVector3 ue_axis1(0.0, 0.0, 0.0); - TVector3 ue_axis2(0.0, 0.0, 0.0); - get_perpendicular_axis(p_leading, ue_axis1, +1.0); - get_perpendicular_axis(p_leading, ue_axis2, -1.0); - - // Protection against delta<0 - if (ue_axis1.X() == 0 && ue_axis1.Y() == 0 && ue_axis1.Z() == 0) - continue; - if (ue_axis2.X() == 0 && ue_axis2.Y() == 0 && ue_axis2.Z() == 0) - continue; - registryQC.fill(HIST("event_counter_mc"), 4.5); - - // Store UE - std::vector ue_particle_ID; - - for (int i = 0; i < nParticles; i++) { - - // Skip Leading Particle & Elements already associated to the Jet - if (particle_ID[i] == leading_ID || particle_ID[i] == -1) - continue; - - // Get UE Track - const auto& ue_track = mcParticles_per_coll.iteratorAt(particle_ID[i]); - - // Variables - float deltaEta1 = ue_track.eta() - ue_axis1.Eta(); - float deltaPhi1 = GetDeltaPhi(ue_track.phi(), ue_axis1.Phi()); - float dr1 = TMath::Sqrt(deltaEta1 * deltaEta1 + deltaPhi1 * deltaPhi1); - float deltaEta2 = ue_track.eta() - ue_axis2.Eta(); - float deltaPhi2 = GetDeltaPhi(ue_track.phi(), ue_axis2.Phi()); - float dr2 = TMath::Sqrt(deltaEta2 * deltaEta2 + deltaPhi2 * deltaPhi2); - - // Store Particles in the UE 1 - if (dr1 < Rmax_jet_ue) { - ue_particle_ID.push_back(particle_ID[i]); + if (dij_min > diB_min) { + jet.push_back(trk[iB_min]); + trk[iB_min].SetXYZ(0, 0, 0); + n_particles_removed++; } + } while (n_particles_removed < static_cast(trk.size())); - // Store Particles in the UE 2 - if (dr2 < Rmax_jet_ue) { - ue_particle_ID.push_back(particle_ID[i]); - } + // Jet Selection + std::vector isSelected; + for (int i = 0; i < static_cast(jet.size()); i++) { + isSelected.push_back(0); } - // UE Multiplicity - int nParticlesUE = static_cast(ue_particle_ID.size()); + int n_jets_selected(0); + for (int i = 0; i < static_cast(jet.size()); i++) { - // Loop over particles inside Jet - for (int i = 0; i < nParticlesJetUE; i++) { + if ((abs(jet[i].Eta()) + Rjet) > max_eta) + continue; - const auto& jet_track = mcParticles_per_coll.iteratorAt(jet_particle_ID[i]); + // Perpendicular cones + TVector3 ue_axis1(0, 0, 0); + TVector3 ue_axis2(0, 0, 0); + get_perpendicular_axis(jet[i], ue_axis1, +1); + get_perpendicular_axis(jet[i], ue_axis2, -1); + ue1.push_back(ue_axis1); + ue2.push_back(ue_axis2); - float deltaEta = jet_track.eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(jet_track.phi(), p_leading.Phi()); - float R = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); - if (R > Rmax_jet_ue) - continue; + double nPartJetPlusUE(0); + double ptJetPlusUE(0); + double ptJet(0); + double ptUE(0); - // Rapidity Cut - if (jet_track.y() < min_y || jet_track.y() > max_y) - continue; + for (auto track : tracks_per_coll) { - if (jet_track.pdgCode() == -2212) { - registryMC.fill(HIST("antiproton_eta_pt_jet"), jet_track.pt(), - jet_track.eta()); + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + TVector3 sel_track(track.px(), track.py(), track.pz()); + + double deltaEta_jet = sel_track.Eta() - jet[i].Eta(); + double deltaPhi_jet = GetDeltaPhi(sel_track.Phi(), jet[i].Phi()); + double deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + double deltaEta_ue1 = sel_track.Eta() - ue_axis1.Eta(); + double deltaPhi_ue1 = GetDeltaPhi(sel_track.Phi(), ue_axis1.Phi()); + double deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + double deltaEta_ue2 = sel_track.Eta() - ue_axis2.Eta(); + double deltaPhi_ue2 = GetDeltaPhi(sel_track.Phi(), ue_axis2.Phi()); + double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + if (deltaR_jet < Rjet) { + nPartJetPlusUE++; + ptJetPlusUE = ptJetPlusUE + sel_track.Pt(); + } + if (deltaR_ue1 < Rjet) { + ptUE = ptUE + sel_track.Pt(); + } + if (deltaR_ue2 < Rjet) { + ptUE = ptUE + sel_track.Pt(); + } } + ptJet = ptJetPlusUE - 0.5 * ptUE; - if (jet_track.pdgCode() == -1000010020) { - registryMC.fill(HIST("antideuteron_eta_pt_jet"), jet_track.pt(), - jet_track.eta()); - } + if (ptJet < min_jet_pt) + continue; + if (nPartJetPlusUE < min_nPartInJet) + continue; + n_jets_selected++; + isSelected[i] = 1; } + if (n_jets_selected == 0) + continue; + registryMC.fill(HIST("number_of_events_mc"), 6.5); - // Loop over particles inside UE - for (int i = 0; i < nParticlesUE; i++) { - - const auto& ue_track = mcParticles_per_coll.iteratorAt(ue_particle_ID[i]); + for (int i = 0; i < static_cast(jet.size()); i++) { - // Rapidity Cut - if (ue_track.y() < min_y || ue_track.y() > max_y) + if (isSelected[i] == 0) continue; - if (ue_track.pdgCode() != -2212) { - registryMC.fill(HIST("antiproton_eta_pt_ue"), ue_track.pt(), - ue_track.eta()); - } + for (auto track : tracks_per_coll) { + if (!passedTrackSelection(track)) + continue; + if (require_PV_contributor && !(track.isPVContributor())) + continue; + if (track.sign() > 0) + continue; + if (TMath::Abs(track.dcaXY()) > max_dcaxy) + continue; + if (TMath::Abs(track.dcaZ()) > max_dcaz) + continue; + if (!track.has_mcParticle()) + continue; + const auto particle = track.mcParticle(); + if (particle.pdgCode() != -2212) + continue; - if (ue_track.pdgCode() != -1000010020) { - registryMC.fill(HIST("antideuteron_eta_pt_ue"), ue_track.pt(), - ue_track.eta()); + TVector3 particle_dir(track.px(), track.py(), track.pz()); + float deltaEta_jet = particle_dir.Eta() - jet[i].Eta(); + float deltaPhi_jet = GetDeltaPhi(particle_dir.Phi(), jet[i].Phi()); + float deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + float deltaEta_ue1 = particle_dir.Eta() - ue1[i].Eta(); + float deltaPhi_ue1 = GetDeltaPhi(particle_dir.Phi(), ue1[i].Phi()); + float deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + float deltaEta_ue2 = particle_dir.Eta() - ue2[i].Eta(); + float deltaPhi_ue2 = GetDeltaPhi(particle_dir.Phi(), ue2[i].Phi()); + float deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + if (deltaR_jet < Rjet) { + registryMC.fill(HIST("antiproton_all_jet"), track.pt()); + if (particle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_jet"), track.pt()); + } + } + if (deltaR_ue1 < Rjet || deltaR_ue2 < Rjet) { + registryMC.fill(HIST("antiproton_all_ue"), track.pt()); + if (particle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_ue"), track.pt()); + } + } } } } } + PROCESS_SWITCH(nuclei_in_jets, processSecondaryAntiprotons, "process secondary antiprotons", false); - /* - void processAntidJet(o2::aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + void processAntiprotonReweighting(o2::aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { - - // Particle Masses [GeV/c^2] - Double_t mp = 0.93827208816; - Double_t mn = 0.93956542052; - Double_t md = 1.87561294257; - for (const auto& mccollision : mcCollisions) { + registryMC.fill(HIST("number_of_events_mc"), 7.5); + // Selection on z_{vertex} if (abs(mccollision.posZ()) > 10) continue; + registryMC.fill(HIST("number_of_events_mc"), 8.5); // MC Particles per Collision - auto mcParticles_per_coll = - mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); - - // Reduced Event - std::vector particle_ID; - int leading_ID = 0; - float pt_max(0); + auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); - // Specific Flags - bool containsProton(false); - bool containsNeutron(false); + // List of Tracks + std::vector trk; - // Generated Particles for (auto& particle : mcParticles_per_coll) { - - // Global Index - int i = particle.globalIndex(); + if (particle.isPhysicalPrimary() && particle.pdgCode() == -2212) { + registryMC.fill(HIST("antiproton_eta_pt_pythia"), particle.pt(), particle.eta()); + } // Select Primary Particles - float deltaX = particle.vx() - mccollision.posX(); - float deltaY = particle.vy() - mccollision.posY(); - float deltaZ = particle.vz() - mccollision.posZ(); - float deltaR = sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); - if (deltaR > 0.1) - continue; + double dx = particle.vx() - mccollision.posX(); + double dy = particle.vy() - mccollision.posY(); + double dz = particle.vz() - mccollision.posZ(); + double dcaxy = sqrt(dx * dx + dy * dy); + double dcaz = abs(dz); + + if (setDCAselectionPtDep) { + if (dcaxy > (0.004f + 0.013f / particle.pt())) + continue; + if (dcaz > (0.004f + 0.013f / particle.pt())) + continue; + } + if (!setDCAselectionPtDep) { + if (dcaxy > 0.1) + continue; + if (dcaz > 0.1) + continue; + } - // Pseudorapidity Selection if (abs(particle.eta()) > 0.8) continue; + if (particle.pt() < 0.15) + continue; // PDG Selection int pdg = abs(particle.pdgCode()); - if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212) && (pdg != 2112)) + if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212)) continue; - // Nucleon Selection - if (particle.pdgCode() == -2212) - containsProton = true; - if (particle.pdgCode() == -2112) - containsNeutron = true; - - // Find pt Leading - if (particle.pt() > pt_max && (pdg != 2112)) { - leading_ID = i; - pt_max = particle.pt(); - } - - // Store Array Element - particle_ID.push_back(i); + TVector3 momentum(particle.px(), particle.py(), particle.pz()); + trk.push_back(momentum); } - // Skip Events with pt(particle_ID.size()); - - if (nParticles < 2) - continue; - if (!containsProton) - continue; - if (!containsNeutron) - continue; - - // Momentum of the Leading Particle - auto const& leading_track = mcParticles_per_coll.iteratorAt(leading_ID); - TVector3 p_leading(leading_track.px(), leading_track.py(), - leading_track.pz()); - - // Array of Particles inside Jet - std::vector jet_particle_ID; - jet_particle_ID.push_back(leading_ID); - - // Labels - Int_t exit(0); - Int_t nPartAssociated(0); + // Anti-kt Jet Finder + int n_particles_removed(0); + std::vector jet; + std::vector ue1; + std::vector ue2; - // Jet Finder do { - // Initialization - float distance_jet_min(1e+08); - float distance_bkg_min(1e+08); - int label_jet_particle(0); - int i_jet_particle(0); - - for (int i = 0; i < nParticles; i++) { - - // Skip Leading Particle & Elements already associated to the Jet - if (particle_ID[i] == leading_ID || particle_ID[i] == -1) + double dij_min(1e+06), diB_min(1e+06); + int i_min(0), j_min(0), iB_min(0); + for (int i = 0; i < static_cast(trk.size()); i++) { + if (trk[i].Mag() == 0) continue; - - // Get Particle Momentum - auto stored_track = mcParticles_per_coll.iteratorAt(particle_ID[i]); - TVector3 p_particle(stored_track.px(), stored_track.py(), - stored_track.pz()); - - // Variables - float one_over_pt2_part = 1.0 / (p_particle.Pt() * p_particle.Pt()); - float one_over_pt2_lead = 1.0 / (p_leading.Pt() * p_leading.Pt()); - float deltaEta = p_particle.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_particle.Phi(), p_leading.Phi()); - float min = Minimum(one_over_pt2_part, one_over_pt2_lead); - float Delta2 = deltaEta * deltaEta + deltaPhi * deltaPhi; - - // Distances - float distance_jet = min * Delta2 / (Rparameter_jet * Rparameter_jet); - float distance_bkg = one_over_pt2_part; - - // Find Minimum Distance Jet - if (distance_jet < distance_jet_min) { - distance_jet_min = distance_jet; - label_jet_particle = particle_ID[i]; - i_jet_particle = i; + double diB = 1.0 / (trk[i].Pt() * trk[i].Pt()); + if (diB < diB_min) { + diB_min = diB; + iB_min = i; } - - // Find Minimum Distance Bkg - if (distance_bkg < distance_bkg_min) { - distance_bkg_min = distance_bkg; + for (int j = (i + 1); j < static_cast(trk.size()); j++) { + if (trk[j].Mag() == 0) + continue; + double dij = calculate_dij(trk[i], trk[j], Rjet); + if (dij < dij_min) { + dij_min = dij; + i_min = i; + j_min = j; + } } } - - if (distance_jet_min <= distance_bkg_min) { - - // Add Particle to Jet - jet_particle_ID.push_back(label_jet_particle); - - // Update Momentum of Leading Particle - auto jet_track = mcParticles_per_coll.iteratorAt(label_jet_particle); - TVector3 p_i(jet_track.px(), jet_track.py(), jet_track.pz()); - p_leading = p_leading + p_i; - - // Remove Element - particle_ID[i_jet_particle] = -1; - nPartAssociated++; - } - - if (nPartAssociated >= (nParticles - 1)) - exit = 1; - if (distance_jet_min > distance_bkg_min) - exit = 2; - - } while (exit == 0); - - // Multiplicity inside Jet + UE - int nParticlesJetUE = static_cast(jet_particle_ID.size()); - - // Event Counter: Skip Events with jet not fully inside acceptance - float eta_jet_axis = p_leading.Eta(); - if ((TMath::Abs(eta_jet_axis) + Rmax_jet_ue) > max_eta) - continue; - - // Perpendicular Cones for UE Estimate - TVector3 ue_axis1(0.0, 0.0, 0.0); - TVector3 ue_axis2(0.0, 0.0, 0.0); - get_perpendicular_axis(p_leading, ue_axis1, +1.0); - get_perpendicular_axis(p_leading, ue_axis2, -1.0); - - // Protection against delta<0 - if (ue_axis1.X() == 0 && ue_axis1.Y() == 0 && ue_axis1.Z() == 0) - continue; - if (ue_axis2.X() == 0 && ue_axis2.Y() == 0 && ue_axis2.Z() == 0) - continue; - - // Store UE - std::vector ue_particle_ID; - - for (int i = 0; i < nParticles; i++) { - - // Skip Leading Particle & Elements already associated to the Jet - if (particle_ID[i] == leading_ID || particle_ID[i] == -1) - continue; - - // Get UE Track - const auto& ue_track = mcParticles_per_coll.iteratorAt(particle_ID[i]); - - // Variables - float deltaEta1 = ue_track.eta() - ue_axis1.Eta(); - float deltaPhi1 = GetDeltaPhi(ue_track.phi(), ue_axis1.Phi()); - float dr1 = TMath::Sqrt(deltaEta1 * deltaEta1 + deltaPhi1 * deltaPhi1); - float deltaEta2 = ue_track.eta() - ue_axis2.Eta(); - float deltaPhi2 = GetDeltaPhi(ue_track.phi(), ue_axis2.Phi()); - float dr2 = TMath::Sqrt(deltaEta2 * deltaEta2 + deltaPhi2 * deltaPhi2); - - // Store Particles in the UE - if (dr1 < Rmax_jet_ue) { - ue_particle_ID.push_back(particle_ID[i]); + if (dij_min < diB_min) { + trk[i_min] = trk[i_min] + trk[j_min]; + trk[j_min].SetXYZ(0, 0, 0); + n_particles_removed++; } - - if (dr2 < Rmax_jet_ue) { - ue_particle_ID.push_back(particle_ID[i]); + if (dij_min > diB_min) { + jet.push_back(trk[iB_min]); + trk[iB_min].SetXYZ(0, 0, 0); + n_particles_removed++; } - } - - // UE Multiplicity - int nParticlesUE = static_cast(ue_particle_ID.size()); - - vector neutron_status_jet; - for (int i = 0; i < nParticlesJetUE; i++) { + } while (n_particles_removed < static_cast(trk.size())); - neutron_status_jet.push_back(0); + // Jet Selection + std::vector isSelected; + for (int i = 0; i < static_cast(jet.size()); i++) { + isSelected.push_back(0); } - // Loop over particles inside Jet - for (int i = 0; i < nParticlesJetUE; i++) { + int n_jets_selected(0); + for (int i = 0; i < static_cast(jet.size()); i++) { - // Proton Selection - const auto& proton_jet = mcParticles_per_coll.iteratorAt(jet_particle_ID[i]); - if (proton_jet.pdgCode() != -2212) + if ((abs(jet[i].Eta()) + Rjet) > max_eta) continue; - // Proton 4-Momentum - TLorentzVector p_proton; - p_proton.SetXYZM(proton_jet.px(), proton_jet.py(), proton_jet.pz(), mp); - - for (int j = 0; j < nParticlesJetUE; j++) { + // Perpendicular cones + TVector3 ue_axis1(0, 0, 0); + TVector3 ue_axis2(0, 0, 0); + get_perpendicular_axis(jet[i], ue_axis1, +1); + get_perpendicular_axis(jet[i], ue_axis2, -1); + ue1.push_back(ue_axis1); + ue2.push_back(ue_axis2); + + double nPartJetPlusUE(0); + double ptJetPlusUE(0); + double ptJet(0); + double ptUE(0); + + for (auto& particle : mcParticles_per_coll) { + + // Select Primary Particles + double dx = particle.vx() - mccollision.posX(); + double dy = particle.vy() - mccollision.posY(); + double dz = particle.vz() - mccollision.posZ(); + double dcaxy = sqrt(dx * dx + dy * dy); + double dcaz = abs(dz); + + if (setDCAselectionPtDep) { + if (dcaxy > (0.004f + 0.013f / particle.pt())) + continue; + if (dcaz > (0.004f + 0.013f / particle.pt())) + continue; + } + if (!setDCAselectionPtDep) { + if (dcaxy > 0.1) + continue; + if (dcaz > 0.1) + continue; + } - // Neutron Selection - const auto& neutron_jet = mcParticles_per_coll.iteratorAt(jet_particle_ID[j]); - if (neutron_jet.pdgCode() != -2112) + if (abs(particle.eta()) > 0.8) continue; - - // Neutron 4-Momentum - TLorentzVector p_neutron; - p_neutron.SetXYZM(neutron_jet.px(), neutron_jet.py(), neutron_jet.pz(), mn); - - // Deuteron 4-Momentum - TLorentzVector p_deuteron; - p_deuteron.SetXYZM(p_proton.X() + p_neutron.X(), p_proton.Y() + p_neutron.Y(), p_proton.Z() + p_neutron.Z(), md); - Double_t beta_x = p_deuteron.Px() / p_deuteron.E(); - Double_t beta_y = p_deuteron.Py() / p_deuteron.E(); - Double_t beta_z = p_deuteron.Pz() / p_deuteron.E(); - TVector3 beta(beta_x, beta_y, beta_z); - - // Lorentz Transformation - TLorentzVector p_proton_prime = LorentzTransform(p_proton, beta); - TLorentzVector p_neutron_prime = LorentzTransform(p_neutron, beta); - - // Variables - Double_t deltaP = (p_proton_prime - p_neutron_prime).P(); - - // Skip already used Neutrons - if (neutron_status_jet[j] == 1) + if (particle.pt() < 0.15) continue; - // Coalescence Condition - if (deltaP < coalMom) { - - neutron_status_jet[j] = 1; - Double_t y = p_deuteron.Rapidity(); - - float deltaEta = p_deuteron.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_deuteron.Phi(), p_leading.Phi()); - float R = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); - - if (R < Rmax_jet_ue && TMath::Abs(y) < 0.5) { + // PDG Selection + int pdg = abs(particle.pdgCode()); + if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212)) + continue; - registryMC.fill(HIST("antideuteron_eta_pt_jet"), p_deuteron.Pt(), p_deuteron.Eta()); - } - break; + TVector3 sel_track(particle.px(), particle.py(), particle.pz()); + + double deltaEta_jet = sel_track.Eta() - jet[i].Eta(); + double deltaPhi_jet = GetDeltaPhi(sel_track.Phi(), jet[i].Phi()); + double deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + double deltaEta_ue1 = sel_track.Eta() - ue_axis1.Eta(); + double deltaPhi_ue1 = GetDeltaPhi(sel_track.Phi(), ue_axis1.Phi()); + double deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + double deltaEta_ue2 = sel_track.Eta() - ue_axis2.Eta(); + double deltaPhi_ue2 = GetDeltaPhi(sel_track.Phi(), ue_axis2.Phi()); + double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + if (deltaR_jet < Rjet) { + nPartJetPlusUE++; + ptJetPlusUE = ptJetPlusUE + sel_track.Pt(); + } + if (deltaR_ue1 < Rjet) { + ptUE = ptUE + sel_track.Pt(); + } + if (deltaR_ue2 < Rjet) { + ptUE = ptUE + sel_track.Pt(); } } - } - - vector neutron_status_ue; - for (int i = 0; i < nParticlesUE; i++) { + ptJet = ptJetPlusUE - 0.5 * ptUE; - neutron_status_ue.push_back(0); + if (ptJet < min_jet_pt) + continue; + if (nPartJetPlusUE < min_nPartInJet) + continue; + n_jets_selected++; + isSelected[i] = 1; } + if (n_jets_selected == 0) + continue; - // Loop over particles inside UE - for (int i = 0; i < nParticlesUE; i++) { + for (int i = 0; i < static_cast(jet.size()); i++) { - // Proton Selection - const auto& proton_ue = mcParticles_per_coll.iteratorAt(ue_particle_ID[i]); - if (proton_ue.pdgCode() != -2212) + if (isSelected[i] == 0) continue; - // Proton 4-Momentum - TLorentzVector p_proton; - p_proton.SetXYZM(proton_ue.px(), proton_ue.py(), proton_ue.pz(), mp); - - for (int j = 0; j < nParticlesUE; j++) { + // Generated Particles + for (auto& particle : mcParticles_per_coll) { - // Neutron Selection - const auto& neutron_ue = mcParticles_per_coll.iteratorAt(ue_particle_ID[j]); - if (neutron_ue.pdgCode() != -2112) + if (!particle.isPhysicalPrimary()) continue; - - // Neutron 4-Momentum - TLorentzVector p_neutron; - p_neutron.SetXYZM(neutron_ue.px(), neutron_ue.py(), neutron_ue.pz(), mn); - - // Deuteron 4-Momentum - TLorentzVector p_deuteron; - p_deuteron.SetXYZM(p_proton.X() + p_neutron.X(), p_proton.Y() + p_neutron.Y(), p_proton.Z() + p_neutron.Z(), md); - Double_t beta_x = p_deuteron.Px() / p_deuteron.E(); - Double_t beta_y = p_deuteron.Py() / p_deuteron.E(); - Double_t beta_z = p_deuteron.Pz() / p_deuteron.E(); - TVector3 beta(beta_x, beta_y, beta_z); - - // Lorentz Transformation - TLorentzVector p_proton_prime = LorentzTransform(p_proton, beta); - TLorentzVector p_neutron_prime = LorentzTransform(p_neutron, beta); - - // Variables - Double_t deltaP = (p_proton_prime - p_neutron_prime).P(); - - // Skip already used Neutrons - if (neutron_status_ue[j] == 1) + if (particle.pdgCode() != -2212) continue; - // Coalescence Condition - if (deltaP < coalMom) { - - neutron_status_ue[j] = 1; - Double_t y = p_deuteron.Rapidity(); - - float deltaEta = p_deuteron.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_deuteron.Phi(), p_leading.Phi()); - float R = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); - - if (R < Rmax_jet_ue && TMath::Abs(y) < 0.5) { - - registryMC.fill(HIST("antideuteron_eta_pt_ue"), p_deuteron.Pt(), p_deuteron.Eta()); - } - break; + TVector3 particle_dir(particle.px(), particle.py(), particle.pz()); + double deltaEta_jet = particle_dir.Eta() - jet[i].Eta(); + double deltaPhi_jet = GetDeltaPhi(particle_dir.Phi(), jet[i].Phi()); + double deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + double deltaEta_ue1 = particle_dir.Eta() - ue1[i].Eta(); + double deltaPhi_ue1 = GetDeltaPhi(particle_dir.Phi(), ue1[i].Phi()); + double deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + double deltaEta_ue2 = particle_dir.Eta() - ue2[i].Eta(); + double deltaPhi_ue2 = GetDeltaPhi(particle_dir.Phi(), ue2[i].Phi()); + double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + if (deltaR_jet < Rjet) { + registryMC.fill(HIST("antiproton_eta_pt_jet"), particle.pt(), particle.eta()); + } + if (deltaR_ue1 < Rjet || deltaR_ue2 < Rjet) { + registryMC.fill(HIST("antiproton_eta_pt_ue"), particle.pt(), particle.eta()); } } } } } - */ - - PROCESS_SWITCH(nuclei_in_jets, processData, "Process data", true); - PROCESS_SWITCH(nuclei_in_jets, processGen, "process Gen MC", false); - PROCESS_SWITCH(nuclei_in_jets, processRec, "process Rec MC", false); - PROCESS_SWITCH(nuclei_in_jets, processAntiNucleiJet, "process antinuclei in jet and UE (MC)", false); - // PROCESS_SWITCH(nuclei_in_jets, processAntidJet, "process antideuterons in jet and UE (MC)", false); + PROCESS_SWITCH(nuclei_in_jets, processAntiprotonReweighting, "Process antiproton reweighting", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Nuspex/nuclei_in_toward_transv_regions.cxx b/PWGLF/Tasks/Nuspex/nuclei_in_toward_transv_regions.cxx new file mode 100644 index 00000000000..a64ba6dc09c --- /dev/null +++ b/PWGLF/Tasks/Nuspex/nuclei_in_toward_transv_regions.cxx @@ -0,0 +1,392 @@ +// Copyright 2019-2020 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. +/// +/// \author Alberto Caliva (alberto.caliva@cern.ch) +/// \since August 22, 2024 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/DataTypes.h" +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/DCA.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" + +using namespace std; +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using std::array; + +using SelectedCollisions = soa::Join; +using SimCollisions = soa::Join; + +using FullTracks = soa::Join; + +using MCTracks = soa::Join; + +struct nuclei_in_toward_transv_regions { + + // Analysis Histograms: Data + HistogramRegistry registryData{ + "registryData", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // Analysis Histograms: MC + HistogramRegistry registryMC{ + "registryMC", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // Global Parameters + Configurable min_pt_leading{"min_pt_leading", 5.0, "Minimum pt of leading particle"}; + Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; + + // Track Parameters + Configurable min_ITS_nClusters{"min_ITS_nClusters", 5, "minimum number of ITS clusters"}; + Configurable min_TPC_nClusters{"min_TPC_nClusters", 80, "minimum number of TPC clusters"}; + Configurable min_TPC_nCrossedRows{"min_TPC_nCrossedRows", 80, "minimum number of TPC crossed pad rows"}; + Configurable max_chi2_TPC{"max_chi2_TPC", 4.0, "maximum TPC chi^2/Ncls"}; + Configurable max_chi2_ITS{"max_chi2_ITS", 36.0, "maximum ITS chi^2/Ncls"}; + Configurable min_pt{"min_pt", 0.3, "minimum pt of the tracks"}; + Configurable min_eta{"min_eta", -0.8, "minimum eta"}; + Configurable max_eta{"max_eta", +0.8, "maximum eta"}; + Configurable min_y{"min_y", -0.5, "minimum y"}; + Configurable max_y{"max_y", +0.5, "maximum y"}; + Configurable max_dcaxy{"max_dcaxy", 0.1, "Maximum DCAxy"}; + Configurable max_dcaz{"max_dcaz", 0.1, "Maximum DCAz"}; + Configurable min_nsigmaTPC{"min_nsigmaTPC", -3.0, "Minimum nsigma TPC"}; + Configurable max_nsigmaTPC{"max_nsigmaTPC", +3.0, "Maximum nsigma TPC"}; + Configurable min_nsigmaTOF{"min_nsigmaTOF", -3.0, "Minimum nsigma TOF"}; + Configurable max_nsigmaTOF{"max_nsigmaTOF", +3.5, "Maximum nsigma TOF"}; + Configurable require_PV_contributor{"require_PV_contributor", true, "require that the track is a PV contributor"}; + + void init(InitContext const&) + { + // Event Counters + registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "counter"}}); + registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); + + // Data + registryData.add("antiproton_jet_tpc", "antiproton_jet_tpc", HistType::kTH2F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antiproton_jet_tof", "antiproton_jet_tof", HistType::kTH2F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antiproton_ue_tpc", "antiproton_ue_tpc", HistType::kTH2F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antiproton_ue_tof", "antiproton_ue_tof", HistType::kTH2F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + + // MC + registryMC.add("antiproton_prim_jet", "antiproton_prim_jet", HistType::kTH1F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_all_jet", "antiproton_all_jet", HistType::kTH1F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_prim_ue", "antiproton_prim_ue", HistType::kTH1F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_all_ue", "antiproton_all_ue", HistType::kTH1F, {{120, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}}); + } + + // Single-Track Selection for Particles inside Jets + template + bool passedTrackSelectionForJetReconstruction(const JetTrackType& track) + { + if (!track.hasITS()) + return false; + if (track.itsNCls() < 3) + return false; + if (!track.hasTPC()) + return false; + if (track.tpcNClsCrossedRows() < 70) + return false; + if (track.tpcChi2NCl() > 4) + return false; + if (track.itsChi2NCl() > 36) + return false; + if (track.eta() < -0.8 || track.eta() > 0.8) + return false; + if (track.pt() < 0.1) + return false; + if (TMath::Abs(track.dcaXY()) > (0.004f + 0.013f / track.pt())) + return false; + if (TMath::Abs(track.dcaZ()) > 2.0) + return false; + + return true; + } + + // Single-Track Selection + template + bool passedTrackSelection(const TrackType& track) + { + if (!track.hasITS()) + return false; + if (track.itsNCls() < min_ITS_nClusters) + return false; + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < min_TPC_nClusters) + return false; + if (track.tpcNClsCrossedRows() < min_TPC_nCrossedRows) + return false; + if (track.tpcChi2NCl() > max_chi2_TPC) + return false; + if (track.itsChi2NCl() > max_chi2_ITS) + return false; + if (track.eta() < min_eta || track.eta() > max_eta) + return false; + if (track.pt() < min_pt) + return false; + + return true; + } + + // Rapidity + double get_rapidity(double px, double py, double pz, double mass) + { + double rap(0); + TLorentzVector lorentzVect; + lorentzVect.SetXYZM(px, py, pz, mass); + rap = lorentzVect.Rapidity(); + return rap; + } + + template + bool isTrackInTowardRegion(const T1& track, const T2& leading_track) + { + // Initialization + bool isInTowardRegion = false; + + // DeltaPhi + double phi_ref = TVector2::Phi_0_2pi(leading_track.phi()); + double phi_trk = TVector2::Phi_0_2pi(track.phi()); + double delta_phi = (180.0 / TMath::Pi()) * TVector2::Phi_0_2pi(phi_trk - phi_ref); + if (delta_phi >= 0.0 && delta_phi < 60.0) + isInTowardRegion = true; + if (delta_phi >= 300.0 && delta_phi <= 360.0) + isInTowardRegion = true; + + return isInTowardRegion; + } + + template + bool isTrackInTransverseRegion(const T3& track, const T4& leading_track) + { + // Initialization + bool isInTransverseRegion = false; + + // DeltaPhi + double phi_ref = TVector2::Phi_0_2pi(leading_track.phi()); + double phi_trk = TVector2::Phi_0_2pi(track.phi()); + double delta_phi = (180.0 / TMath::Pi()) * TVector2::Phi_0_2pi(phi_trk - phi_ref); + if (delta_phi >= 60.0 && delta_phi < 120.0) + isInTransverseRegion = true; + if (delta_phi >= 240.0 && delta_phi < 300.0) + isInTransverseRegion = true; + + return isInTransverseRegion; + } + + // Process Data + void processData(SelectedCollisions::iterator const& collision, FullTracks const& tracks) + { + // Event Counter: before event selection + registryData.fill(HIST("number_of_events_data"), 0.5); + + // Event Selection + if (!collision.sel8()) + return; + + // Event Counter: after event selection sel8 + registryData.fill(HIST("number_of_events_data"), 1.5); + + // Cut on z-vertex + if (abs(collision.posZ()) > zVtx) + return; + + // Event Counter: after z-vertex cut + registryData.fill(HIST("number_of_events_data"), 2.5); + + // Leading Track + int leading_ID(0); + double pt_max(0); + + // Track Index + int i = -1; + + // Loop over Reconstructed Tracks + for (auto track : tracks) { + + i++; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + if (track.pt() > pt_max) { + leading_ID = i; + pt_max = track.pt(); + } + } + // Event Counter: Skip Events with pt 0) + continue; + if (TMath::Abs(track.dcaXY()) > max_dcaxy) + continue; + if (TMath::Abs(track.dcaZ()) > max_dcaz) + continue; + + // Variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double y_proton = get_rapidity(track.px(), track.py(), track.pz(), 0.93827208816); + if (y_proton < min_y || y_proton > max_y) + continue; + + // Jet + if (isTrackInTowardRegion(track, leading_track)) { + if (track.pt() < 1.0) + registryData.fill(HIST("antiproton_jet_tpc"), track.pt(), nsigmaTPCPr); + if (track.pt() >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && track.hasTOF()) + registryData.fill(HIST("antiproton_jet_tof"), track.pt(), nsigmaTOFPr); + } + + // UE + if (isTrackInTransverseRegion(track, leading_track)) { + if (track.pt() < 1.0) + registryData.fill(HIST("antiproton_ue_tpc"), track.pt(), nsigmaTPCPr); + if (track.pt() >= 0.5 && nsigmaTPCPr > min_nsigmaTPC && nsigmaTPCPr < max_nsigmaTPC && track.hasTOF()) + registryData.fill(HIST("antiproton_ue_tof"), track.pt(), nsigmaTOFPr); + } + } + } + + Preslice perCollision = o2::aod::track::collisionId; + + void processSecAntiprotons(SimCollisions const& collisions, MCTracks const& mcTracks, aod::McCollisions const&, const aod::McParticles&) + { + for (const auto& collision : collisions) { + + registryMC.fill(HIST("number_of_events_mc"), 0.5); + + // Event Selection + if (!collision.sel8()) + continue; + registryMC.fill(HIST("number_of_events_mc"), 1.5); + + if (abs(collision.posZ()) > zVtx) + continue; + registryMC.fill(HIST("number_of_events_mc"), 2.5); + + auto tracks_per_coll = mcTracks.sliceBy(perCollision, collision.globalIndex()); + + int leading_ID(0); + double pt_max(0); + int i = -1; + + // Loop over Reconstructed Tracks + for (auto track : tracks_per_coll) { + + i++; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + if (track.pt() > pt_max) { + leading_ID = i; + pt_max = track.pt(); + } + } + if (pt_max < min_pt_leading) + continue; + registryMC.fill(HIST("number_of_events_mc"), 3.5); + + // Momentum of the Leading Particle + auto const& leading_track = tracks_per_coll.iteratorAt(leading_ID); + + // Loop over Reconstructed Tracks + for (auto track : tracks_per_coll) { + + if (!passedTrackSelection(track)) + continue; + if (require_PV_contributor && !(track.isPVContributor())) + continue; + if (track.sign() > 0) + continue; + if (TMath::Abs(track.dcaXY()) > max_dcaxy) + continue; + if (TMath::Abs(track.dcaZ()) > max_dcaz) + continue; + double y_proton = get_rapidity(track.px(), track.py(), track.pz(), 0.93827208816); + if (y_proton < min_y || y_proton > max_y) + continue; + + // Get MC Particle + if (!track.has_mcParticle()) + continue; + const auto particle = track.mcParticle(); + if (particle.pdgCode() != -2212) + continue; + + // Jet + if (isTrackInTowardRegion(track, leading_track)) { + registryMC.fill(HIST("antiproton_all_jet"), track.pt()); + if (particle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_jet"), track.pt()); + } + } + // UE + if (isTrackInTransverseRegion(track, leading_track)) { + registryMC.fill(HIST("antiproton_all_ue"), track.pt()); + if (particle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_ue"), track.pt()); + } + } + } + } + } + PROCESS_SWITCH(nuclei_in_toward_transv_regions, processData, "Process Data", true); + PROCESS_SWITCH(nuclei_in_toward_transv_regions, processSecAntiprotons, "Process sec antip", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index a127f5efc46..e30d511ee88 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -64,6 +64,7 @@ struct tofSpectra { Configurable requireIsGoodZvtxFT0vsPV{"requireIsGoodZvtxFT0vsPV", false, "Remove TF border"}; Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "Remove TF border"}; Configurable removeNoTimeFrameBorder{"removeNoTimeFrameBorder", false, "Remove TF border"}; + Configurable requirekIsVertexTOFmatched{"requirekIsVertexTOFmatched", false, "Require requirekIsVertexTOFmatched"}; } evselOptions; struct : ConfigurableGroup { @@ -92,6 +93,7 @@ struct tofSpectra { ConfigurableAxis binsdeltaTOF{"binsdeltaTOF", {500, -1000, 1000}, "Binning of the nsigmaTOF axis"}; ConfigurableAxis binsDca{"binsDca", {VARIABLE_WIDTH, -3.0, -2.95, -2.9, -2.85, -2.8, -2.75, -2.7, -2.65, -2.6, -2.55, -2.5, -2.45, -2.4, -2.35, -2.3, -2.25, -2.2, -2.15, -2.1, -2.05, -2.0, -1.975, -1.95, -1.925, -1.9, -1.875, -1.85, -1.825, -1.8, -1.775, -1.75, -1.725, -1.7, -1.675, -1.65, -1.625, -1.6, -1.575, -1.55, -1.525, -1.5, -1.475, -1.45, -1.425, -1.4, -1.375, -1.35, -1.325, -1.3, -1.275, -1.25, -1.225, -1.2, -1.175, -1.15, -1.125, -1.1, -1.075, -1.05, -1.025, -1.0, -0.99, -0.98, -0.97, -0.96, -0.95, -0.94, -0.93, -0.92, -0.91, -0.9, -0.89, -0.88, -0.87, -0.86, -0.85, -0.84, -0.83, -0.82, -0.81, -0.8, -0.79, -0.78, -0.77, -0.76, -0.75, -0.74, -0.73, -0.72, -0.71, -0.7, -0.69, -0.68, -0.67, -0.66, -0.65, -0.64, -0.63, -0.62, -0.61, -0.6, -0.59, -0.58, -0.57, -0.56, -0.55, -0.54, -0.53, -0.52, -0.51, -0.5, -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, -0.42, -0.41, -0.4, -0.396, -0.392, -0.388, -0.384, -0.38, -0.376, -0.372, -0.368, -0.364, -0.36, -0.356, -0.352, -0.348, -0.344, -0.34, -0.336, -0.332, -0.328, -0.324, -0.32, -0.316, -0.312, -0.308, -0.304, -0.3, -0.296, -0.292, -0.288, -0.284, -0.28, -0.276, -0.272, -0.268, -0.264, -0.26, -0.256, -0.252, -0.248, -0.244, -0.24, -0.236, -0.232, -0.228, -0.224, -0.22, -0.216, -0.212, -0.208, -0.204, -0.2, -0.198, -0.196, -0.194, -0.192, -0.19, -0.188, -0.186, -0.184, -0.182, -0.18, -0.178, -0.176, -0.174, -0.172, -0.17, -0.168, -0.166, -0.164, -0.162, -0.16, -0.158, -0.156, -0.154, -0.152, -0.15, -0.148, -0.146, -0.144, -0.142, -0.14, -0.138, -0.136, -0.134, -0.132, -0.13, -0.128, -0.126, -0.124, -0.122, -0.12, -0.118, -0.116, -0.114, -0.112, -0.11, -0.108, -0.106, -0.104, -0.102, -0.1, -0.099, -0.098, -0.097, -0.096, -0.095, -0.094, -0.093, -0.092, -0.091, -0.09, -0.089, -0.088, -0.087, -0.086, -0.085, -0.084, -0.083, -0.082, -0.081, -0.08, -0.079, -0.078, -0.077, -0.076, -0.075, -0.074, -0.073, -0.072, -0.071, -0.07, -0.069, -0.068, -0.067, -0.066, -0.065, -0.064, -0.063, -0.062, -0.061, -0.06, -0.059, -0.058, -0.057, -0.056, -0.055, -0.054, -0.053, -0.052, -0.051, -0.05, -0.049, -0.048, -0.047, -0.046, -0.045, -0.044, -0.043, -0.042, -0.041, -0.04, -0.039, -0.038, -0.037, -0.036, -0.035, -0.034, -0.033, -0.032, -0.031, -0.03, -0.029, -0.028, -0.027, -0.026, -0.025, -0.024, -0.023, -0.022, -0.021, -0.02, -0.019, -0.018, -0.017, -0.016, -0.015, -0.014, -0.013, -0.012, -0.011, -0.01, -0.009, -0.008, -0.007, -0.006, -0.005, -0.004, -0.003, -0.002, -0.001, -0.0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.011, 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018, 0.019, 0.02, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.029, 0.03, 0.031, 0.032, 0.033, 0.034, 0.035, 0.036, 0.037, 0.038, 0.039, 0.04, 0.041, 0.042, 0.043, 0.044, 0.045, 0.046, 0.047, 0.048, 0.049, 0.05, 0.051, 0.052, 0.053, 0.054, 0.055, 0.056, 0.057, 0.058, 0.059, 0.06, 0.061, 0.062, 0.063, 0.064, 0.065, 0.066, 0.067, 0.068, 0.069, 0.07, 0.071, 0.072, 0.073, 0.074, 0.075, 0.076, 0.077, 0.078, 0.079, 0.08, 0.081, 0.082, 0.083, 0.084, 0.085, 0.086, 0.087, 0.088, 0.089, 0.09, 0.091, 0.092, 0.093, 0.094, 0.095, 0.096, 0.097, 0.098, 0.099, 0.1, 0.102, 0.104, 0.106, 0.108, 0.11, 0.112, 0.114, 0.116, 0.118, 0.12, 0.122, 0.124, 0.126, 0.128, 0.13, 0.132, 0.134, 0.136, 0.138, 0.14, 0.142, 0.144, 0.146, 0.148, 0.15, 0.152, 0.154, 0.156, 0.158, 0.16, 0.162, 0.164, 0.166, 0.168, 0.17, 0.172, 0.174, 0.176, 0.178, 0.18, 0.182, 0.184, 0.186, 0.188, 0.19, 0.192, 0.194, 0.196, 0.198, 0.2, 0.204, 0.208, 0.212, 0.216, 0.22, 0.224, 0.228, 0.232, 0.236, 0.24, 0.244, 0.248, 0.252, 0.256, 0.26, 0.264, 0.268, 0.272, 0.276, 0.28, 0.284, 0.288, 0.292, 0.296, 0.3, 0.304, 0.308, 0.312, 0.316, 0.32, 0.324, 0.328, 0.332, 0.336, 0.34, 0.344, 0.348, 0.352, 0.356, 0.36, 0.364, 0.368, 0.372, 0.376, 0.38, 0.384, 0.388, 0.392, 0.396, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0, 1.025, 1.05, 1.075, 1.1, 1.125, 1.15, 1.175, 1.2, 1.225, 1.25, 1.275, 1.3, 1.325, 1.35, 1.375, 1.4, 1.425, 1.45, 1.475, 1.5, 1.525, 1.55, 1.575, 1.6, 1.625, 1.65, 1.675, 1.7, 1.725, 1.75, 1.775, 1.8, 1.825, 1.85, 1.875, 1.9, 1.925, 1.95, 1.975, 2.0, 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85, 2.9, 2.95, 3.0}, "Binning of DCA xy and z axis"}; ConfigurableAxis binsMultiplicity{"binsMultiplicity", {100, 0, 100}, "Binning for multiplicity"}; + ConfigurableAxis binsOccupancy{"binsOccupancy", {3000, 0, 15000}, "Binning for occupancy"}; ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Binning for percentiles"}; ConfigurableAxis binsImpactParam{"binsImpactParam", {2500, 0, 25}, "Binning for impact parameter"}; } binsOptions; @@ -216,7 +218,7 @@ struct tofSpectra { const AxisSpec ptAxis{binsOptions.binsPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec etaAxis{binsOptions.binsEta, "#eta"}; const AxisSpec impParamAxis{binsOptions.binsImpactParam, "Impact parameter"}; - + const AxisSpec occupancyAxis{binsOptions.binsOccupancy, "Occupancy Axis"}; AxisSpec multAxis{binsOptions.binsMultiplicity, "Undefined multiplicity estimator"}; switch (multiplicityEstimator) { case MultCodes::kNoMultiplicity: // No multiplicity @@ -262,15 +264,16 @@ struct tofSpectra { h->GetXaxis()->SetBinLabel(3, "INEL>1 (fraction)"); h->GetXaxis()->SetBinLabel(4, "Ev. sel. passed"); h->GetXaxis()->SetBinLabel(5, "NoITSROFrameBorder"); - h->GetXaxis()->SetBinLabel(6, "NoSameBunchPileup"); - h->GetXaxis()->SetBinLabel(7, "IsGoodZvtxFT0vsPV"); - h->GetXaxis()->SetBinLabel(8, "IsVertexITSTPC"); - h->GetXaxis()->SetBinLabel(9, "NoTimeFrameBorder"); - h->GetXaxis()->SetBinLabel(10, "INEL>0 (fraction)"); - h->GetXaxis()->SetBinLabel(11, "INEL>1 (fraction)"); - h->GetXaxis()->SetBinLabel(12, "posZ passed"); - h->GetXaxis()->SetBinLabel(13, evselOptions.cfgINELCut.value == 1 ? "INEL>0" : "INEL>0 (fraction)"); - h->GetXaxis()->SetBinLabel(14, evselOptions.cfgINELCut.value == 2 ? "INEL>1" : "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(6, "NoITSROFrameBorder"); + h->GetXaxis()->SetBinLabel(7, "NoSameBunchPileup"); + h->GetXaxis()->SetBinLabel(8, "IsGoodZvtxFT0vsPV"); + h->GetXaxis()->SetBinLabel(9, "IsVertexITSTPC"); + h->GetXaxis()->SetBinLabel(10, "NoTimeFrameBorder"); + h->GetXaxis()->SetBinLabel(11, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(12, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(13, "posZ passed"); + h->GetXaxis()->SetBinLabel(14, evselOptions.cfgINELCut.value == 1 ? "INEL>0" : "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(15, evselOptions.cfgINELCut.value == 2 ? "INEL>1" : "INEL>1 (fraction)"); h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); h->GetXaxis()->SetBinLabel(1, "Tracks read"); @@ -307,6 +310,7 @@ struct tofSpectra { histos.add("Mult/PerBC/sel8/FT0M", "FT0M", HistType::kTH1D, {{binsOptions.binsMultiplicity, "Multiplicity FT0M"}}); histos.add("Mult/PerBC/sel8/FT0A", "FT0A", HistType::kTH1D, {{binsOptions.binsMultiplicity, "Multiplicity FT0A"}}); histos.add("Mult/PerBC/sel8/FT0C", "FT0C", HistType::kTH1D, {{binsOptions.binsMultiplicity, "Multiplicity FT0C"}}); + histos.add("Mult/PerBC/sel8/FT0AvsFT0C", "FT0C", HistType::kTH2D, {{binsOptions.binsMultiplicity, "Multiplicity FT0A"}, {binsOptions.binsMultiplicity, "Multiplicity FT0C"}}); } // histos.add("Mult/Tracklets", "MultTracklets", HistType::kTH1D, {{binsOptions.binsMultiplicity, "MultTracklets"}}); histos.add("Mult/TPC", "MultTPC", HistType::kTH1D, {{binsOptions.binsMultiplicity, "MultTPC"}}); @@ -335,7 +339,9 @@ struct tofSpectra { histos.add("track/TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH2D, {{60, 0.7, 1.3}, chargeAxis}); histos.add("track/TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH2D, {{100, 0, 10}, chargeAxis}); histos.add("Vertex/histGenVtxMC", "MC generated vertex z position", HistType::kTH1F, {{400, -40., +40., "z position (cm)"}}); + histos.add("Vertex/RecoEvs/histGenVtxMC", "MC generated vertex z position", HistType::kTH1F, {{400, -40., +40., "z position (cm)"}}); histos.add("Centrality/ImpParm", "Centrality", HistType::kTH1F, {impParamAxis}); + histos.add("Centrality/RecoEvs/ImpParm", "Centrality", HistType::kTH1F, {impParamAxis}); histos.addClone("track/ITS/itsNCls", "track/selected/ITS/itsNCls"); histos.addClone("track/ITS/itsChi2NCl", "track/selected/ITS/itsChi2NCl"); @@ -394,6 +400,23 @@ struct tofSpectra { histos.add("Data/neg/pt/its", "neg ITS", kTH1D, {ptAxis}); histos.add("Data/pos/pt/tpc", "pos TPC", kTH1D, {ptAxis}); histos.add("Data/neg/pt/tpc", "neg TPC", kTH1D, {ptAxis}); + if (doprocessOccupancy) { + const AxisSpec nsigmaTPCAxisOccupancy{binsOptions.binsnsigmaTPC, "nsigmaTPC"}; + histos.add("nsigmatpc/test_occupancy/Mult_vs_Occupancy", "occuppancy vs Multiplicity", kTHnSparseD, {multAxis, occupancyAxis}); + histos.add("nsigmatpc/test_occupancy/pos/pi", "occuppancy dependent pion", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatpc/test_occupancy/neg/pi", "occuppancy dependent pion", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatpc/test_occupancy/pos/ka", "occuppancy dependent kaon", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatpc/test_occupancy/neg/ka", "occuppancy dependent kaon", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatpc/test_occupancy/pos/pr", "occuppancy dependent proton", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatpc/test_occupancy/neg/pr", "occuppancy dependent proton", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + + histos.add("nsigmatof/test_occupancy/pos/pi", "occuppancy dependent pion", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatof/test_occupancy/neg/pi", "occuppancy dependent pion", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatof/test_occupancy/pos/ka", "occuppancy dependent kaon", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatof/test_occupancy/neg/ka", "occuppancy dependent kaon", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatof/test_occupancy/pos/pr", "occuppancy dependent proton", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + histos.add("nsigmatof/test_occupancy/neg/pr", "occuppancy dependent proton", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis, occupancyAxis}); + } if (doprocessMC) { histos.add("MC/fake/pos", "Fake positive tracks", kTH1D, {ptAxis}); @@ -407,6 +430,14 @@ struct tofSpectra { histos.add("MC/test/ka/neg/prm/pt/den", "generated MC K^{-}", kTHnSparseD, {ptAxis, impParamAxis}); histos.add("MC/test/pr/pos/prm/pt/den", "generated MC p", kTHnSparseD, {ptAxis, impParamAxis}); histos.add("MC/test/pr/neg/prm/pt/den", "generated MC #bar{p}", kTHnSparseD, {ptAxis, impParamAxis}); + if (doprocessMCgen_RecoEvs) { + histos.add("MC/test/RecoEvs/pi/pos/prm/pt/den", "generated MC #pi^{+} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); + histos.add("MC/test/RecoEvs/pi/neg/prm/pt/den", "generated MC #pi^{-} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); + histos.add("MC/test/RecoEvs/ka/pos/prm/pt/den", "generated MC K^{+} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); + histos.add("MC/test/RecoEvs/ka/neg/prm/pt/den", "generated MC K^{-} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); + histos.add("MC/test/RecoEvs/pr/pos/prm/pt/den", "generated MC p from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); + histos.add("MC/test/RecoEvs/pr/neg/prm/pt/den", "generated MC #bar{p} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); + } } auto hh = histos.add("MC/GenRecoCollisions", "Generated and Reconstructed MC Collisions", kTH1D, {{10, 0.5, 10.5}}); hh->GetXaxis()->SetBinLabel(1, "Collisions generated"); @@ -636,6 +667,8 @@ struct tofSpectra { histos.fill(HIST("Mult/PerBC/sel8/FT0A"), ft0.sumAmpA()); histos.fill(HIST("Mult/PerBC/sel8/FT0C"), ft0.sumAmpC()); + histos.fill(HIST("Mult/PerBC/sel8/FT0AvsFT0C"), ft0.sumAmpA(), ft0.sumAmpC()); + } // end of the process function PROCESS_SWITCH(tofSpectra, processBC, "Processor of BCs for the FT0 calibration", true); @@ -922,57 +955,63 @@ struct tofSpectra { return false; } } - if (evselOptions.removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (evselOptions.requirekIsVertexTOFmatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { return false; } if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 4.f); } - if (evselOptions.removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (evselOptions.removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return false; } if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 5.f); } - if (evselOptions.requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (evselOptions.removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 6.f); } - if (evselOptions.requireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { + if (evselOptions.requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 7.f); } - if (evselOptions.removeNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + if (evselOptions.requireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { return false; } if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 8.f); } + if (evselOptions.removeNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 9.f); + } + if constexpr (fillHistograms) { + histos.fill(HIST("evsel"), 10.f); if (collision.isInelGt0()) { - histos.fill(HIST("evsel"), 10.f); + histos.fill(HIST("evsel"), 11.f); } if (collision.isInelGt1()) { - histos.fill(HIST("evsel"), 11.f); + histos.fill(HIST("evsel"), 12.f); } } if (abs(collision.posZ()) > evselOptions.cfgCutVertex) { return false; } if constexpr (fillHistograms) { - histos.fill(HIST("evsel"), 12.f); + histos.fill(HIST("evsel"), 13.f); if (collision.isInelGt0()) { - histos.fill(HIST("evsel"), 13.f); + histos.fill(HIST("evsel"), 14.f); } else if (evselOptions.cfgINELCut == 1) { return false; } if (collision.isInelGt1()) { - histos.fill(HIST("evsel"), 14.f); + histos.fill(HIST("evsel"), 15.f); } else if (evselOptions.cfgINELCut == 2) { return false; } @@ -1233,10 +1272,51 @@ struct tofSpectra { return false; } - using CollisionCandidates = soa::Join; + using CollisionCandidates = soa::Join; using TrackCandidates = soa::Join; + void processOccupancy(CollisionCandidates::iterator const& collision, + soa::Join const& tracks) + { + if (!isEventSelected(collision)) { + return; + } + int occupancy = collision.trackOccupancyInTimeRange(); + const float multiplicity = collision.centFT0C(); + histos.fill(HIST("nsigmatpc/test_occupancy/Mult_vs_Occupancy"), multiplicity, occupancy); + for (const auto& track : tracks) { + if (!isTrackSelected(track)) { + continue; + } + const auto& nsigmaTPCPi = o2::aod::pidutils::tpcNSigma<2>(track); + const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); + const auto& nsigmaTPCPr = o2::aod::pidutils::tpcNSigma<4>(track); + const auto& nsigmaTOFPi = o2::aod::pidutils::tofNSigma<2>(track); + const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); + const auto& nsigmaTOFPr = o2::aod::pidutils::tofNSigma<4>(track); + histos.fill(HIST("nsigmatpc/test_occupancy/pos/pi"), track.pt(), nsigmaTPCPi, multiplicity, occupancy); + histos.fill(HIST("nsigmatpc/test_occupancy/neg/pi"), track.pt(), nsigmaTPCPi, multiplicity, occupancy); + histos.fill(HIST("nsigmatpc/test_occupancy/pos/ka"), track.pt(), nsigmaTPCKa, multiplicity, occupancy); + histos.fill(HIST("nsigmatpc/test_occupancy/neg/ka"), track.pt(), nsigmaTPCKa, multiplicity, occupancy); + histos.fill(HIST("nsigmatpc/test_occupancy/pos/pr"), track.pt(), nsigmaTPCPr, multiplicity, occupancy); + histos.fill(HIST("nsigmatpc/test_occupancy/neg/pr"), track.pt(), nsigmaTPCPr, multiplicity, occupancy); + + histos.fill(HIST("nsigmatof/test_occupancy/pos/pi"), track.pt(), nsigmaTOFPi, multiplicity, occupancy); + histos.fill(HIST("nsigmatof/test_occupancy/neg/pi"), track.pt(), nsigmaTOFPi, multiplicity, occupancy); + histos.fill(HIST("nsigmatof/test_occupancy/pos/ka"), track.pt(), nsigmaTOFKa, multiplicity, occupancy); + histos.fill(HIST("nsigmatof/test_occupancy/neg/ka"), track.pt(), nsigmaTOFKa, multiplicity, occupancy); + histos.fill(HIST("nsigmatof/test_occupancy/pos/pr"), track.pt(), nsigmaTOFPr, multiplicity, occupancy); + histos.fill(HIST("nsigmatof/test_occupancy/neg/pr"), track.pt(), nsigmaTOFPr, multiplicity, occupancy); + + } // track + } // process function + PROCESS_SWITCH(tofSpectra, processOccupancy, "check for occupancy plots", false); + void processStandard(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) { @@ -1519,18 +1599,37 @@ struct tofSpectra { if (!mcParticle.isPhysicalPrimary()) { if (mcParticle.getProcess() == 4) { - histos.fill(HIST(hpt_num_str[i]), track.pt(), multiplicity, track.dcaXY()); + if (includeCentralityMC) { + histos.fill(HIST(hpt_num_str[i]), track.pt(), multiplicity, track.dcaXY()); + } else { + histos.fill(HIST(hpt_num_str[i]), track.pt(), multiplicity); + } if (track.hasTOF()) { - histos.fill(HIST(hpt_numtof_str[i]), track.pt(), multiplicity, track.dcaXY()); + if (includeCentralityMC) { + histos.fill(HIST(hpt_numtof_str[i]), track.pt(), multiplicity, track.dcaXY()); + } else { + histos.fill(HIST(hpt_numtof_str[i]), track.pt(), multiplicity); + } } } else { - histos.fill(HIST(hpt_num_mat[i]), track.pt(), multiplicity, track.dcaXY()); - if (track.hasTOF()) { - histos.fill(HIST(hpt_numtof_mat[i]), track.pt(), multiplicity, track.dcaXY()); + if (includeCentralityMC) { + histos.fill(HIST(hpt_num_mat[i]), track.pt(), multiplicity, track.dcaXY()); + if (track.hasTOF()) { + histos.fill(HIST(hpt_numtof_mat[i]), track.pt(), multiplicity, track.dcaXY()); + } + } else { + histos.fill(HIST(hpt_num_mat[i]), track.pt(), multiplicity); + if (track.hasTOF()) { + histos.fill(HIST(hpt_numtof_mat[i]), track.pt(), multiplicity); + } } } } else { - histos.fill(HIST(hpt_num_prm[i]), track.pt(), multiplicity, track.dcaXY()); + if (includeCentralityMC) { + histos.fill(HIST(hpt_num_prm[i]), track.pt(), multiplicity, track.dcaXY()); + } else { + histos.fill(HIST(hpt_num_prm[i]), track.pt(), multiplicity); + } if (track.hasTRD() && trkselOptions.lastRequiredTrdCluster > 0) { int lastLayer = 0; for (int l = 7; l >= 0; l--) { @@ -1544,7 +1643,11 @@ struct tofSpectra { } } if (track.hasTOF()) { - histos.fill(HIST(hpt_numtof_prm[i]), track.pt(), multiplicity, track.dcaXY()); + if (includeCentralityMC) { + histos.fill(HIST(hpt_numtof_prm[i]), track.pt(), multiplicity, track.dcaXY()); + } else { + histos.fill(HIST(hpt_numtof_prm[i]), track.pt(), multiplicity); + } if (!(track.mcMask() & (1 << 11))) { if (includeCentralityMC) { histos.fill(HIST(hpt_numtofgoodmatch_prm[i]), track.pt(), multiplicity, track.eta()); // RD @@ -1865,6 +1968,55 @@ struct tofSpectra { } } PROCESS_SWITCH(tofSpectra, processMCgen, "process generated MC", false); + void processMCgen_RecoEvs(GenMCCollisions const&, RecoMCCollisions const& collisions, aod::McParticles const& mcParticles) + { + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + const auto& mcCollision = collision.mcCollision_as(); + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + histos.fill(HIST("Vertex/RecoEvs/histGenVtxMC"), mcCollision.posZ()); + histos.fill(HIST("Centrality/RecoEvs/ImpParm"), mcCollision.impactParameter()); + const float multiplicity = mcCollision.impactParameter(); + for (const auto& mcParticleGen : particlesInCollision) { + if (!mcParticleGen.isPhysicalPrimary()) + continue; + int pdgCode = mcParticleGen.pdgCode(); + float pt = mcParticleGen.pt(); + float absY = std::abs(mcParticleGen.y()); + // Apply rapidity cut + if (absY > trkselOptions.cfgCutY) { + continue; + } + + // Fill histograms based on particle type + switch (pdgCode) { + case 2212: + histos.fill(HIST("MC/test/RecoEvs/pr/pos/prm/pt/den"), pt, multiplicity); + break; + case -2212: + histos.fill(HIST("MC/test/RecoEvs/pr/neg/prm/pt/den"), pt, multiplicity); + break; + case 211: + histos.fill(HIST("MC/test/RecoEvs/pi/pos/prm/pt/den"), pt, multiplicity); + break; + case -211: + histos.fill(HIST("MC/test/RecoEvs/pi/neg/prm/pt/den"), pt, multiplicity); + break; + case 321: + histos.fill(HIST("MC/test/RecoEvs/ka/pos/prm/pt/den"), pt, multiplicity); + break; + case -321: + histos.fill(HIST("MC/test/RecoEvs/ka/neg/prm/pt/den"), pt, multiplicity); + break; + default: + break; + } + } + } + } + PROCESS_SWITCH(tofSpectra, processMCgen_RecoEvs, "process generated MC (reconstructed events)", false); }; // end of spectra task diff --git a/PWGLF/Tasks/QC/lfITSTPCMatchingQA.cxx b/PWGLF/Tasks/QC/lfITSTPCMatchingQA.cxx index f3bd0adecb7..c31258d51ae 100644 --- a/PWGLF/Tasks/QC/lfITSTPCMatchingQA.cxx +++ b/PWGLF/Tasks/QC/lfITSTPCMatchingQA.cxx @@ -94,7 +94,7 @@ struct lfmatchingqa { float getITSClSize(T const& track) { float sum{0.f}; - for (int iL{0}; iL < 6; ++iL) { + for (int iL{0}; iL < 7; ++iL) { sum += (track.itsClusterSizes() >> (iL * 4)) & 0xf; } return sum / track.itsNCls(); diff --git a/PWGLF/Tasks/QC/mcParticlePrediction.cxx b/PWGLF/Tasks/QC/mcParticlePrediction.cxx index 9ecc451f58d..fcf08c1f823 100644 --- a/PWGLF/Tasks/QC/mcParticlePrediction.cxx +++ b/PWGLF/Tasks/QC/mcParticlePrediction.cxx @@ -26,6 +26,7 @@ #include "Common/DataModel/Multiplicity.h" #include "PWGLF/Utils/mcParticle.h" #include "PWGLF/Utils/inelGt.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "CommonConstants/LHCConstants.h" #include "TPDGCode.h" @@ -42,21 +43,24 @@ bool enabledParticlesArray[PIDExtended::NIDsTot]; // Estimators struct Estimators { - static const int FT0A = 0; - static const int FT0C = 1; - static const int FT0AC = 2; - static const int FV0A = 3; - static const int FDDA = 4; - static const int FDDC = 5; - static const int FDDAC = 6; - static const int ZNA = 7; - static const int ZNC = 8; - static const int ZEM1 = 9; - static const int ZEM2 = 10; - static const int ZPA = 11; - static const int ZPC = 12; - static const int ITS = 13; - static const int nEstimators = 14; + static constexpr int FT0A = 0; + static constexpr int FT0C = 1; + static constexpr int FT0AC = 2; + static constexpr int FV0A = 3; + static constexpr int FDDA = 4; + static constexpr int FDDC = 5; + static constexpr int FDDAC = 6; + static constexpr int ZNA = 7; + static constexpr int ZNC = 8; + static constexpr int ZEM1 = 9; + static constexpr int ZEM2 = 10; + static constexpr int ZPA = 11; + static constexpr int ZPC = 12; + static constexpr int ITS = 13; + static constexpr int V0A = 14; // (Run2) + static constexpr int V0C = 15; // (Run2) + static constexpr int V0AC = 16; // (Run2) + static constexpr int nEstimators = 17; static constexpr const char* estimatorNames[nEstimators] = {"FT0A", "FT0C", @@ -71,7 +75,10 @@ struct Estimators { "ZEM2", "ZPA", "ZPC", - "ITS"}; + "ITS", + "V0A", + "V0C", + "V0AC"}; static std::vector arrayNames() { std::vector names; @@ -82,10 +89,10 @@ struct Estimators { } }; bool enabledEstimatorsArray[Estimators::nEstimators]; -static const int defaultEstimators[Estimators::nEstimators][nParameters]{{1}, // FT0A - {1}, // FT0C +static const int defaultEstimators[Estimators::nEstimators][nParameters]{{0}, // FT0A + {0}, // FT0C {1}, // FT0AC - {1}, // FV0A + {0}, // FV0A {0}, // FDDA {0}, // FDDC {0}, // FDDAC @@ -95,15 +102,20 @@ static const int defaultEstimators[Estimators::nEstimators][nParameters]{{1}, / {0}, // ZEM2 {0}, // ZPA {0}, // ZPC - {1}}; // ITS + {0}, // ITS + {0}, // V0A (Run2) + {0}, // V0C (Run2) + {0}}; // V0AC (Run2) // Histograms std::array, Estimators::nEstimators> hestimators; std::array, Estimators::nEstimators> hestimatorsVsITS; std::array, Estimators::nEstimators> hestimatorsRecoEvGenVsReco; +std::array, Estimators::nEstimators> hestimatorsRecoEvGenVsReco_BCMC; std::array, Estimators::nEstimators> hestimatorsRecoEvGenVsRecoITS; std::array, Estimators::nEstimators> hestimatorsRecoEvRecoVsITS; std::array, Estimators::nEstimators> hestimatorsRecoEvRecoVsRecoITS; +std::array, Estimators::nEstimators> hestimatorsRecoEvRecoVsRecoITS_BCMC; std::array, Estimators::nEstimators> hestimatorsRecoEvRecoVsFT0A; std::array, Estimators::nEstimators> hestimatorsRecoEvRecoVsBCId; std::array, Estimators::nEstimators> hestimatorsRecoEvVsBCId; @@ -132,7 +144,17 @@ struct mcParticlePrediction { "Estimators enabled"}; Configurable selectInelGt0{"selectInelGt0", true, "Select only inelastic events"}; Configurable selectPrimaries{"selectPrimaries", true, "Select only primary particles"}; + + Configurable discardkIsGoodZvtxFT0vsPV{"discardkIsGoodZvtxFT0vsPV", false, "Select only collisions with matching BC and MC BC"}; Configurable discardMismatchedBCs{"discardMismatchedBCs", false, "Select only collisions with matching BC and MC BC"}; + Configurable discardMismatchedFoundBCs{"discardMismatchedFoundBCs", false, "Select only collisions with matching found BC and MC BC"}; + Configurable posZCut{"posZCut", 10.f, "Cut in the Z position of the primary vertex"}; + Configurable collisionTimeResCut{"collisionTimeResCut", -40.f, "Cut in the collisionTimeRes"}; + Configurable requirekIsGoodZvtxFT0vsPV{"requirekIsGoodZvtxFT0vsPV", false, "Require kIsGoodZvtxFT0vsPV: small difference between z-vertex from PV and from FT0"}; + Configurable requirekIsVertexITSTPC{"requirekIsVertexITSTPC", false, "Require kIsVertexITSTPC: at least one ITS-TPC track (reject vertices built from ITS-only tracks)"}; + Configurable requirekIsVertexTOFmatched{"requirekIsVertexTOFmatched", false, "Require kIsVertexTOFmatched: at least one of vertex contributors is matched to TOF"}; + Configurable requirekIsVertexTRDmatched{"requirekIsVertexTRDmatched", false, "Require kIsVertexTRDmatched: at least one of vertex contributors is matched to TRD"}; + Service pdgDB; o2::pwglf::ParticleCounter mCounter; @@ -148,6 +170,8 @@ struct mcParticlePrediction { const AxisSpec axisMultiplicity{binsMultiplicity, "Multiplicity (undefined)"}; const AxisSpec axisMultiplicityReco{binsMultiplicityReco, "Multiplicity Reco. (undefined)"}; const AxisSpec axisMultiplicityRecoITS{100, 0, 100, "Multiplicity Reco. ITS"}; + const AxisSpec axisMultiplicityGenV0s{100, 0, 100, "K0s gen"}; + const AxisSpec axisMultiplicityRecoV0s{20, 0, 20, "K0s reco"}; const AxisSpec axisBCID{o2::constants::lhc::LHCMaxBunches, -0.5, -0.5 + o2::constants::lhc::LHCMaxBunches, "BC ID in orbit"}; const AxisSpec axisBCIDMC{o2::constants::lhc::LHCMaxBunches, -0.5, -0.5 + o2::constants::lhc::LHCMaxBunches, "MC BC ID in orbit"}; const AxisSpec axisFT0{1000, -5, 5, "Coll time FT0 (ps)"}; @@ -156,18 +180,33 @@ struct mcParticlePrediction { h->GetXaxis()->SetBinLabel(1, "Read"); h->GetXaxis()->SetBinLabel(2, "INELgt0"); h->GetXaxis()->SetBinLabel(3, "|Z|<10"); - h = histos.add("collisions/reconstructed", "collisions", kTH1D, {{10, -0.5, 9.5}}); + h = histos.add("collisions/reconstructed", "collisions", kTH1D, {{20, -0.5, 19.5}}); h->GetXaxis()->SetBinLabel(1, "Read"); h->GetXaxis()->SetBinLabel(2, "has_mcCollision"); h->GetXaxis()->SetBinLabel(3, "sel8"); h->GetXaxis()->SetBinLabel(4, "kIsBBT0A"); h->GetXaxis()->SetBinLabel(5, "kIsBBT0C"); - h->GetXaxis()->SetBinLabel(6, "globalBC == MC globalBC"); - h->GetXaxis()->SetBinLabel(7, "isINELgt0mc"); - h->GetXaxis()->SetBinLabel(8, "VTXz"); + h->GetXaxis()->SetBinLabel(6, "collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))"); + h->GetXaxis()->SetBinLabel(7, "globalBC == MC globalBC"); + h->GetXaxis()->SetBinLabel(8, "found globalBC == MC globalBC"); + h->GetXaxis()->SetBinLabel(9, "isINELgt0mc"); + h->GetXaxis()->SetBinLabel(10, "VTXz"); + h->GetXaxis()->SetBinLabel(11, "collisionTimeRes"); + h->GetXaxis()->SetBinLabel(11, "collisionTimeRes"); + h->GetXaxis()->SetBinLabel(12, "kIsGoodZvtxFT0vsPV"); + h->GetXaxis()->SetBinLabel(13, "kIsVertexITSTPC"); + h->GetXaxis()->SetBinLabel(14, "kIsVertexTOFmatched"); + h->GetXaxis()->SetBinLabel(15, "kIsVertexTRDmatched"); + histos.add("collisions/Reco/BCvsMCBC", "BC vs MC BC", kTH2D, {axisBCID, axisBCIDMC}); + histos.add("collisions/Reco/FoundBCvsMCBC", "Found BC vs MC BC", kTH2D, {axisBCID, axisBCIDMC})->GetXaxis()->SetTitle("Found BC ID in orbit"); + histos.add("collisions/Reco/FoundBCvsBC", "Found BC vs MC BC", kTH2D, {axisBCID, axisBCID})->GetXaxis()->SetTitle("Found BC ID in orbit"); histos.add("collisions/Reco/collisionTime", "Collision Time", kTH1D, {{1000, -20, 20, "collisionTime"}}); - histos.add("collisions/Reco/collisionTimeRes", "Collision Time Res", kTH1D, {{1600, 0, 1600, "collisionTimeRes"}}); + histos.add("collisions/Reco/collisionTimeRes", "Collision Time Res", kTH1D, {{1600, 0, 1600, "collisionTimeRes (ns)"}}); + histos.add("collisions/Reco/bcMinusfoundBc", "bcMinusfoundBc", kTH1D, {{1600, -1000, 1000, "bc - foundBc (ns)"}}); + histos.add("collisions/Reco/bcMinusfoundBcRatio", "bcMinusfoundBcRatio", kTH1D, {{1600, -40, 40, "(bc - foundBc)/collisionTimeRes"}}); + histos.add("collisions/Reco/bcMinusMcBcRatio", "bcMinusMcBcRatio", kTH1D, {{1600, -40, 40, "(bc - mcBc)/collisionTimeRes"}}); + histos.add("collisions/Reco/foundbcMinusMcBcRatio", "foundbcMinusMcBcRatio", kTH1D, {{1600, -40, 40, "(foundBc-mcBc)/collisionTimeRes"}}); histos.add("collisions/Reco/FT0A", "FT0A", kTH1D, {axisFT0})->GetXaxis()->SetTitle("Coll time FT0A (ps)"); histos.add("collisions/Reco/FT0C", "FT0C", kTH1D, {axisFT0})->GetXaxis()->SetTitle("Coll time FT0C (ps)"); histos.add("collisions/Reco/FT0AC", "FT0AC", kTH1D, {axisFT0})->GetXaxis()->SetTitle("Coll time FT0AC (ps)"); @@ -176,6 +215,15 @@ struct mcParticlePrediction { histos.add("particles/vtx/x", "Vx", kTH1D, {axisVx}); histos.add("particles/vtx/y", "Vy", kTH1D, {axisVy}); histos.add("particles/vtx/z", "Vz", kTH1D, {axisVz}); + histos.add("particles/FromCollVsFromMCColl", "FromCollVsFromMCColl", kTH2D, {{binsMultiplicity, "PV contributor particles (good bc)"}, {binsMultiplicityReco, "Particles in MC collision"}}); + histos.add("particles/FromCollVsFromMCCollBad", "FromCollVsFromMCCollBad", kTH2D, {{binsMultiplicity, "PV contributor particles (bad bc)"}, {binsMultiplicityReco, "Particles in MC collision"}}); + histos.add("particles/FromCollVsFromCollBad", "FromCollVsFromCollBad", kTH2D, {{binsMultiplicity, "PV contributor particles (good bc)"}, {binsMultiplicity, "PV contributor particles (bad bc)"}}); + histos.add("particles/FromCollBadOverFromCollVsVsFromMCColl", "FromCollBadOverFromCollVsVsFromMCColl", kTH2D, {{100, 0, 2, "bad/good"}, {binsMultiplicityReco, "Particles in MC collision"}}); + histos.add("V0s/V0RecovsPV", "V0s Reco + Ass vs PV", kTH2D, {axisMultiplicityRecoITS, axisMultiplicityRecoV0s}); + histos.add("V0s/V0RecoAssvsPV", "V0s Reco + Ass vs PV", kTH2D, {axisMultiplicityRecoITS, axisMultiplicityRecoV0s}); + histos.add("V0s/V0AssvsPV", "V0s Ass vs PV", kTH2D, {axisMultiplicityRecoITS, axisMultiplicityGenV0s}); + histos.add("V0s/V0RecoAssvsPV_TOFOneLeg", "V0s Reco + Ass + TOF 1 Leg vs PV", kTH2D, {axisMultiplicityRecoITS, axisMultiplicityRecoV0s}); + histos.add("V0s/V0RecoAssvsPV_TOFTwoLegs", "V0s Reco + Ass + TOF 2 Legs vs PV", kTH2D, {axisMultiplicityRecoITS, axisMultiplicityRecoV0s}); for (int i = 0; i < Estimators::nEstimators; i++) { if (enabledEstimators->get(Estimators::estimatorNames[i], "Enable") != 1) { @@ -211,6 +259,10 @@ struct mcParticlePrediction { hestimatorsRecoEvGenVsReco[i]->GetXaxis()->SetTitle(Form("Multiplicity %s", name)); hestimatorsRecoEvGenVsReco[i]->GetYaxis()->SetTitle(Form("Multiplicity Reco. %s", name)); + hestimatorsRecoEvGenVsReco_BCMC[i] = histosRecoEvs.add(Form("multiplicity/Reco/GenVsReco_BCMC/%s", name), name, kTH2D, {axisMultiplicity, axisMultiplicityReco}); + hestimatorsRecoEvGenVsReco_BCMC[i]->GetXaxis()->SetTitle(Form("Multiplicity %s", name)); + hestimatorsRecoEvGenVsReco_BCMC[i]->GetYaxis()->SetTitle(Form("Multiplicity Reco. %s (BCMC)", name)); + hestimatorsRecoEvGenVsRecoITS[i] = histosRecoEvs.add(Form("multiplicity/Reco/GenVsRecoITS/%s", name), name, kTH2D, {axisMultiplicity, axisMultiplicityRecoITS}); hestimatorsRecoEvGenVsRecoITS[i]->GetXaxis()->SetTitle(Form("Multiplicity %s", name)); @@ -221,6 +273,9 @@ struct mcParticlePrediction { hestimatorsRecoEvRecoVsRecoITS[i] = histosRecoEvs.add(Form("multiplicity/Reco/RecoVsRecoITS/%s", name), name, kTH2D, {axisMultiplicityReco, axisMultiplicityRecoITS}); hestimatorsRecoEvRecoVsRecoITS[i]->GetXaxis()->SetTitle(Form("Multiplicity Reco. %s", name)); + hestimatorsRecoEvRecoVsRecoITS_BCMC[i] = histosRecoEvs.add(Form("multiplicity/Reco/RecoVsRecoITS_BCMC/%s", name), name, kTH2D, {axisMultiplicityReco, axisMultiplicityRecoITS}); + hestimatorsRecoEvRecoVsRecoITS_BCMC[i]->GetXaxis()->SetTitle(Form("Multiplicity Reco. %s (BCMC)", name)); + hestimatorsRecoEvRecoVsFT0A[i] = histosRecoEvs.add(Form("multiplicity/Reco/RecovsFT0A/%s", name), name, kTH2D, {axisMultiplicityReco, axisMultiplicity}); hestimatorsRecoEvRecoVsFT0A[i]->GetXaxis()->SetTitle(Form("Multiplicity Reco. %s", name)); hestimatorsRecoEvRecoVsFT0A[i]->GetYaxis()->SetTitle(Form("Multiplicity %s", Estimators::estimatorNames[Estimators::FT0A])); @@ -272,16 +327,45 @@ struct mcParticlePrediction { } histos.fill(HIST("collisions/generated"), 2); float nMult[Estimators::nEstimators]; - nMult[Estimators::FT0A] = mCounter.countFT0A(mcParticles); - nMult[Estimators::FT0C] = mCounter.countFT0C(mcParticles); - nMult[Estimators::FT0AC] = nMult[Estimators::FT0A] + nMult[Estimators::FT0C]; - nMult[Estimators::FV0A] = mCounter.countFV0A(mcParticles); - nMult[Estimators::FDDA] = mCounter.countFDDA(mcParticles); - nMult[Estimators::FDDC] = mCounter.countFDDC(mcParticles); - nMult[Estimators::FDDAC] = nMult[Estimators::FDDA] + nMult[Estimators::FDDC]; - nMult[Estimators::ZNA] = mCounter.countZNA(mcParticles); - nMult[Estimators::ZNC] = mCounter.countZNC(mcParticles); - nMult[Estimators::ITS] = mCounter.countITSIB(mcParticles); + if (enabledEstimatorsArray[Estimators::FT0A] || enabledEstimatorsArray[Estimators::FT0AC]) { + nMult[Estimators::FT0A] = mCounter.countFT0A(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FT0C] || enabledEstimatorsArray[Estimators::FT0AC]) { + nMult[Estimators::FT0C] = mCounter.countFT0C(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FT0AC]) { + nMult[Estimators::FT0AC] = nMult[Estimators::FT0A] + nMult[Estimators::FT0C]; + } + if (enabledEstimatorsArray[Estimators::FV0A]) { + nMult[Estimators::FV0A] = mCounter.countFV0A(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FDDA]) { + nMult[Estimators::FDDA] = mCounter.countFDDA(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FDDC]) { + nMult[Estimators::FDDC] = mCounter.countFDDC(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FDDAC]) { + nMult[Estimators::FDDAC] = nMult[Estimators::FDDA] + nMult[Estimators::FDDC]; + } + if (enabledEstimatorsArray[Estimators::ZNA]) { + nMult[Estimators::ZNA] = mCounter.countZNA(mcParticles); + } + if (enabledEstimatorsArray[Estimators::ZNC]) { + nMult[Estimators::ZNC] = mCounter.countZNC(mcParticles); + } + if (enabledEstimatorsArray[Estimators::ITS]) { + nMult[Estimators::ITS] = mCounter.countITSIB(mcParticles); + } + if (enabledEstimatorsArray[Estimators::V0A] || enabledEstimatorsArray[Estimators::V0AC]) { + nMult[Estimators::V0A] = mCounter.countV0A(mcParticles); + } + if (enabledEstimatorsArray[Estimators::V0C] || enabledEstimatorsArray[Estimators::V0AC]) { + nMult[Estimators::V0C] = mCounter.countV0C(mcParticles); + } + if (enabledEstimatorsArray[Estimators::V0AC]) { + nMult[Estimators::V0AC] = nMult[Estimators::V0A] + nMult[Estimators::V0C]; + } for (int i = 0; i < Estimators::nEstimators; i++) { if (!enabledEstimatorsArray[i]) { @@ -296,9 +380,9 @@ struct mcParticlePrediction { for (const auto& particle : mcParticles) { particle.pdgCode(); const auto id = PIDExtended::pdgToId(particle); - // if (id < 0) { // always false - // continue; - // } + if (id < 0) { + continue; + } if (!enabledParticlesArray[id]) { continue; } @@ -335,17 +419,22 @@ struct mcParticlePrediction { } } + using TracksMC = soa::Join; + Preslice perMCCol = aod::mcparticle::mcCollisionId; SliceCache cache; void processReco(soa::Join::iterator const& collision, + aod::McCollisions const& /*mcCollisions*/, + soa::Join const& /*bcs*/, aod::McParticles const& mcParticles, - aod::McCollisions const&, - aod::BCs const&) + TracksMC const& tracks, + aod::FT0s const&) { histos.fill(HIST("collisions/reconstructed"), 0); if (!collision.has_mcCollision()) { return; } + const auto& mcCollision = collision.mcCollision(); histos.fill(HIST("collisions/reconstructed"), 1); if (!collision.sel8()) { return; @@ -359,24 +448,60 @@ struct mcParticlePrediction { return; } histos.fill(HIST("collisions/reconstructed"), 4); - // Check that the BC in data and MC is the same - if (discardMismatchedBCs.value && collision.bc().globalBC() != collision.mcCollision().bc().globalBC()) { + if (discardkIsGoodZvtxFT0vsPV.value && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return; } histos.fill(HIST("collisions/reconstructed"), 5); - const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, collision.mcCollision().globalIndex(), cache); + const auto& recoBC = collision.bc_as>(); + const auto& foundBC = collision.foundBC_as>(); + const auto& mcBC = mcCollision.bc_as>(); - if (selectInelGt0.value && !o2::pwglf::isINELgt0mc(particlesInCollision, pdgDB)) { + // Check that the BC in data and MC is the same + if (discardMismatchedBCs.value && recoBC.globalBC() != mcBC.globalBC()) { return; } histos.fill(HIST("collisions/reconstructed"), 6); - - if (abs(collision.posZ()) > 10.f) { + if (discardMismatchedFoundBCs.value && foundBC.globalBC() != mcBC.globalBC()) { return; } histos.fill(HIST("collisions/reconstructed"), 7); + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + + if (selectInelGt0.value && !o2::pwglf::isINELgt0mc(particlesInCollision, pdgDB)) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 8); + + if (abs(collision.posZ()) > posZCut.value) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 9); + if (collisionTimeResCut.value > 0.f && collision.collisionTimeRes() > collisionTimeResCut.value) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 10); + if (requirekIsGoodZvtxFT0vsPV.value && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 11); + + if (requirekIsVertexITSTPC.value && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 12); + + if (requirekIsVertexTOFmatched.value && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 13); + + if (requirekIsVertexTRDmatched.value && !collision.selection_bit(aod::evsel::kIsVertexTRDmatched)) { + return; + } + histos.fill(HIST("collisions/reconstructed"), 14); + if (collision.t0ACorrectedValid()) { histos.fill(HIST("collisions/Reco/FT0A"), collision.t0ACorrected()); } @@ -386,23 +511,84 @@ struct mcParticlePrediction { if (collision.t0ACValid()) { histos.fill(HIST("collisions/Reco/FT0AC"), collision.t0AC()); } - histos.fill(HIST("collisions/Reco/BCvsMCBC"), collision.bc().globalBC() % o2::constants::lhc::LHCMaxBunches, - collision.mcCollision().bc().globalBC() % o2::constants::lhc::LHCMaxBunches); + const auto& recoBCid = recoBC.globalBC() % o2::constants::lhc::LHCMaxBunches; + const auto& mcBCid = mcBC.globalBC() % o2::constants::lhc::LHCMaxBunches; + const auto& foundBCid = foundBC.globalBC() % o2::constants::lhc::LHCMaxBunches; + const int diffRecoFoundBC = foundBC.globalBC() - recoBC.globalBC(); + const int diffRecoMCBC = recoBC.globalBC() - mcBC.globalBC(); + const int diffFoundMCBC = foundBC.globalBC() - mcBC.globalBC(); + histos.fill(HIST("collisions/Reco/BCvsMCBC"), recoBCid, mcBCid); + histos.fill(HIST("collisions/Reco/FoundBCvsMCBC"), foundBCid, mcBCid); + histos.fill(HIST("collisions/Reco/FoundBCvsBC"), foundBCid, recoBCid); + histos.fill(HIST("collisions/Reco/bcMinusfoundBc"), (diffRecoFoundBC)*o2::constants::lhc::LHCBunchSpacingNS); + histos.fill(HIST("collisions/Reco/bcMinusfoundBcRatio"), (diffRecoFoundBC)*o2::constants::lhc::LHCBunchSpacingNS / collision.collisionTimeRes()); + histos.fill(HIST("collisions/Reco/foundbcMinusMcBcRatio"), (diffFoundMCBC)*o2::constants::lhc::LHCBunchSpacingNS / collision.collisionTimeRes()); + histos.fill(HIST("collisions/Reco/bcMinusMcBcRatio"), (diffRecoMCBC)*o2::constants::lhc::LHCBunchSpacingNS / collision.collisionTimeRes()); + + int particlesFromColl = 0; + int particlesFromCollWrongBC = 0; + for (const auto& track : tracks) { + if (!track.isPVContributor()) { + continue; + } + if (!track.has_mcParticle()) { + continue; + } + const auto& mcParticle = track.mcParticle(); + if (mcParticle.mcCollision().bc_as>().globalBC() == mcBC.globalBC()) { + particlesFromColl++; + } else { + particlesFromCollWrongBC++; + } + } histos.fill(HIST("collisions/Reco/collisionTime"), collision.collisionTime()); histos.fill(HIST("collisions/Reco/collisionTimeRes"), collision.collisionTimeRes()); + histos.fill(HIST("particles/FromCollVsFromMCColl"), particlesFromColl, particlesInCollision.size()); + histos.fill(HIST("particles/FromCollVsFromMCCollBad"), particlesFromCollWrongBC, particlesInCollision.size()); + histos.fill(HIST("particles/FromCollVsFromCollBad"), particlesFromColl, particlesFromCollWrongBC); + histos.fill(HIST("particles/FromCollBadOverFromCollVsVsFromMCColl"), 1.f * particlesFromCollWrongBC / particlesFromColl, particlesInCollision.size()); float nMult[Estimators::nEstimators]; - nMult[Estimators::FT0A] = mCounter.countFT0A(particlesInCollision); - nMult[Estimators::FT0C] = mCounter.countFT0C(particlesInCollision); - nMult[Estimators::FT0AC] = nMult[Estimators::FT0A] + nMult[Estimators::FT0C]; - nMult[Estimators::FV0A] = mCounter.countFV0A(particlesInCollision); - nMult[Estimators::FDDA] = mCounter.countFDDA(particlesInCollision); - nMult[Estimators::FDDC] = mCounter.countFDDC(particlesInCollision); - nMult[Estimators::FDDAC] = nMult[Estimators::FDDA] + nMult[Estimators::FDDC]; - nMult[Estimators::ZNA] = mCounter.countZNA(particlesInCollision); - nMult[Estimators::ZNC] = mCounter.countZNC(particlesInCollision); - nMult[Estimators::ITS] = mCounter.countITSIB(particlesInCollision); + if (enabledEstimatorsArray[Estimators::FT0A] || enabledEstimatorsArray[Estimators::FT0AC]) { + nMult[Estimators::FT0A] = mCounter.countFT0A(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FT0C] || enabledEstimatorsArray[Estimators::FT0AC]) { + nMult[Estimators::FT0C] = mCounter.countFT0C(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FT0AC]) { + nMult[Estimators::FT0AC] = nMult[Estimators::FT0A] + nMult[Estimators::FT0C]; + } + if (enabledEstimatorsArray[Estimators::FV0A]) { + nMult[Estimators::FV0A] = mCounter.countFV0A(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FDDA]) { + nMult[Estimators::FDDA] = mCounter.countFDDA(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FDDC]) { + nMult[Estimators::FDDC] = mCounter.countFDDC(mcParticles); + } + if (enabledEstimatorsArray[Estimators::FDDAC]) { + nMult[Estimators::FDDAC] = nMult[Estimators::FDDA] + nMult[Estimators::FDDC]; + } + if (enabledEstimatorsArray[Estimators::ZNA]) { + nMult[Estimators::ZNA] = mCounter.countZNA(mcParticles); + } + if (enabledEstimatorsArray[Estimators::ZNC]) { + nMult[Estimators::ZNC] = mCounter.countZNC(mcParticles); + } + if (enabledEstimatorsArray[Estimators::ITS]) { + nMult[Estimators::ITS] = mCounter.countITSIB(mcParticles); + } + if (enabledEstimatorsArray[Estimators::V0A] || enabledEstimatorsArray[Estimators::V0AC]) { + nMult[Estimators::V0A] = mCounter.countV0A(mcParticles); + } + if (enabledEstimatorsArray[Estimators::V0C] || enabledEstimatorsArray[Estimators::V0AC]) { + nMult[Estimators::V0C] = mCounter.countV0C(mcParticles); + } + if (enabledEstimatorsArray[Estimators::V0AC]) { + nMult[Estimators::V0AC] = nMult[Estimators::V0A] + nMult[Estimators::V0C]; + } float nMultReco[Estimators::nEstimators]; nMultReco[Estimators::FT0A] = collision.multFT0A(); @@ -416,17 +602,34 @@ struct mcParticlePrediction { nMultReco[Estimators::ZNC] = collision.multZNC(); nMultReco[Estimators::ITS] = collision.multNTracksPV(); + float nMultRecoMCBC[Estimators::nEstimators] = {0}; + if (mcBC.has_ft0()) { + const auto& ft0 = mcBC.ft0(); + for (auto amplitude : ft0.amplitudeA()) { + nMultRecoMCBC[Estimators::FT0A] += amplitude; + } + for (auto amplitude : ft0.amplitudeC()) { + nMultRecoMCBC[Estimators::FT0C] += amplitude; + } + nMultRecoMCBC[Estimators::FT0AC] = nMultRecoMCBC[Estimators::FT0A] + nMultRecoMCBC[Estimators::FT0C]; + } else { + nMultRecoMCBC[Estimators::FT0A] = -999.f; + nMultRecoMCBC[Estimators::FT0C] = -999.f; + } + for (int i = 0; i < Estimators::nEstimators; i++) { if (!enabledEstimatorsArray[i]) { continue; } hestimatorsRecoEvGenVsReco[i]->Fill(nMult[i], nMultReco[i]); + hestimatorsRecoEvGenVsReco_BCMC[i]->Fill(nMult[i], nMultRecoMCBC[i]); hestimatorsRecoEvGenVsRecoITS[i]->Fill(nMult[i], nMultReco[Estimators::ITS]); hestimatorsRecoEvRecoVsITS[i]->Fill(nMultReco[i], nMult[Estimators::ITS]); hestimatorsRecoEvRecoVsRecoITS[i]->Fill(nMultReco[i], nMultReco[Estimators::ITS]); + hestimatorsRecoEvRecoVsRecoITS_BCMC[i]->Fill(nMultRecoMCBC[i], nMultReco[Estimators::ITS]); hestimatorsRecoEvRecoVsFT0A[i]->Fill(nMultReco[i], nMult[Estimators::FT0A]); - hestimatorsRecoEvRecoVsBCId[i]->Fill(collision.bc().globalBC() % o2::constants::lhc::LHCMaxBunches, nMult[i]); - hestimatorsRecoEvVsBCId[i]->Fill(collision.bc().globalBC() % o2::constants::lhc::LHCMaxBunches, nMultReco[i]); + hestimatorsRecoEvRecoVsBCId[i]->Fill(foundBCid, nMult[i]); + hestimatorsRecoEvVsBCId[i]->Fill(foundBCid, nMultReco[i]); } } PROCESS_SWITCH(mcParticlePrediction, processReco, "Process the reco info", true); diff --git a/PWGLF/Tasks/QC/tracked_cascade_properties.cxx b/PWGLF/Tasks/QC/tracked_cascade_properties.cxx index 623fe885759..e2f93dbe481 100644 --- a/PWGLF/Tasks/QC/tracked_cascade_properties.cxx +++ b/PWGLF/Tasks/QC/tracked_cascade_properties.cxx @@ -37,6 +37,8 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/DCA.h" +#define mXi 1.32171 +#define mOmega 1.67245 using namespace std; using namespace o2; @@ -75,38 +77,40 @@ struct tracked_cascade_properties { Configurable maximumCascRadius{"maximumCascRadius", 18.0f, "Maximum Cascade Radius"}; // Mass Cuts - Configurable mMin_xi{"mMin_xi", 1.31f, "mMin Xi"}; - Configurable mMax_xi{"mMax_xi", 1.33f, "mMax Xi"}; - Configurable mMin_omega{"mMin_omega", 1.66f, "mMin Omega"}; - Configurable mMax_omega{"mMax_omega", 1.68f, "mMax Omega"}; + Configurable mMin_xi{"mMin_xi", 1.315f, "mMin Xi"}; + Configurable mMax_xi{"mMax_xi", 1.328f, "mMax Xi"}; + Configurable mMin_omega{"mMin_omega", 1.665f, "mMin Omega"}; + Configurable mMax_omega{"mMax_omega", 1.680f, "mMax Omega"}; void init(InitContext const&) { - registryQC.add("matchingChi2", "matching Chi2", HistType::kTH1F, {{200, 0, 400, "#chi^{2}_{matching}"}}); - registryQC.add("topologyChi2", "topology Chi2", HistType::kTH1F, {{200, 0, 100, "#chi^{2}_{topology}"}}); - registryQC.add("nITS_Xi", "nITS Xi", HistType::kTH2F, {{100, 0, 10, "#it{p} (GeV/#it{c})"}, {8, 0, 8, "n_{ITS}^{cls}"}}); - registryQC.add("nITS_Omega", "nITS Omega", HistType::kTH2F, {{100, 0, 10, "#it{p} (GeV/#it{c})"}, {8, 0, 8, "n_{ITS}^{cls}"}}); + registryQC.add("matchingChi2", "matching Chi2", HistType::kTH1F, {{200, 0, 1000, "#chi^{2}_{matching}"}}); + registryQC.add("topologyChi2", "topology Chi2", HistType::kTH1F, {{500, 0, 0.5, "#chi^{2}_{topology}"}}); + registryQC.add("nITScls_vs_p_xi", "nITS Xi", HistType::kTH2F, {{100, 0, 10, "#it{p} (GeV/#it{c})"}, {8, 0, 8, "n_{ITS}^{cls}"}}); + registryQC.add("nITScls_vs_p_omega", "nITS Omega", HistType::kTH2F, {{100, 0, 10, "#it{p} (GeV/#it{c})"}, {8, 0, 8, "n_{ITS}^{cls}"}}); + registryQC.add("decayXY", "decayXY", HistType::kTH2F, {{500, -50, 50, "x"}, {500, -50, 50, "y"}}); + registryQC.add("deltaClsSize", "deltaClsSize", HistType::kTH1F, {{40, -20, 20, "#DeltaClsSize"}}); + registryQC.add("deltaP", "deltaP", HistType::kTH1F, {{1000, -1, 1, "#Deltap"}}); + registryQC.add("deltaEta", "deltaEta", HistType::kTH1F, {{200, -0.5, 0.5, "#Delta#eta"}}); + registryQC.add("deltaNclsITS", "deltaNclsITS", HistType::kTH1F, {{20, -10, 10, "#DeltaN"}}); + registryQC.add("deltaNclsITS_track", "deltaNclsITS_track", HistType::kTH1F, {{20, -10, 10, "#DeltaN"}}); + registryQC.add("deltaNclsITS_itstrack", "deltaNclsITS_itstrack", HistType::kTH1F, {{20, -10, 10, "#DeltaN"}}); registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{5, 0, 5, "Event Cuts"}}); - registryData.add("xi_pos_clustersize", "xi_pos_clustersize", HistType::kTH3F, {{100, 0.0, 100, "ITS cluster size"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("xi_neg_clustersize", "xi_neg_clustersize", HistType::kTH3F, {{100, 0.0, 100, "ITS cluster size"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("omega_pos_clustersize", "omega_pos_clustersize", HistType::kTH3F, {{100, 0.0, 100, "ITS cluster size"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("omega_neg_clustersize", "omega_neg_clustersize", HistType::kTH3F, {{100, 0.0, 100, "ITS cluster size"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - - registryData.add("xi_pos_avgclustersize", "xi_pos_avgclustersize", HistType::kTH3F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("xi_neg_avgclustersize", "xi_neg_avgclustersize", HistType::kTH3F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("omega_pos_avgclustersize", "omega_pos_avgclustersize", HistType::kTH3F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("omega_neg_avgclustersize", "omega_neg_avgclustersize", HistType::kTH3F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {16, -0.8, 0.8, "#eta"}}); - - registryData.add("xi_pos_avgclustersize_cosL", "xi_pos_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - registryData.add("xi_neg_avgclustersize_cosL", "xi_neg_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - registryData.add("omega_pos_avgclustersize_cosL", "omega_pos_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - registryData.add("omega_neg_avgclustersize_cosL", "omega_neg_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - - registryData.add("xi_pos_avgclustersize_sinL", "xi_pos_avgclustersize_sinL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT sin(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - registryData.add("xi_neg_avgclustersize_sinL", "xi_neg_avgclustersize_sinL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT sin(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - registryData.add("omega_pos_avgclustersize_sinL", "omega_pos_avgclustersize_sinL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT sin(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); - registryData.add("omega_neg_avgclustersize_sinL", "omega_neg_avgclustersize_sinL", HistType::kTH2F, {{100, 0.0, 20.0, "#LT ITS cluster size #GT sin(#lambda)"}, {100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}}); + registryData.add("xi_pos_avgclustersize", "xi_pos_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); + registryData.add("xi_neg_avgclustersize", "xi_neg_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); + registryData.add("omega_pos_avgclustersize", "omega_pos_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); + registryData.add("omega_neg_avgclustersize", "omega_neg_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); + + registryData.add("xi_pos_avgclustersize_cosL", "xi_pos_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("xi_neg_avgclustersize_cosL", "xi_neg_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_pos_avgclustersize_cosL", "omega_pos_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_neg_avgclustersize_cosL", "omega_neg_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + + registryData.add("xi_pos_avgclustersize_cosL_vs_betagamma", "xi_pos_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("xi_neg_avgclustersize_cosL_vs_betagamma", "xi_neg_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_pos_avgclustersize_cosL_vs_betagamma", "omega_pos_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_neg_avgclustersize_cosL_vs_betagamma", "omega_neg_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); registryData.add("xi_mass_pos", "xi_mass_pos", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}}); registryData.add("xi_mass_neg", "xi_mass_neg", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}}); @@ -114,15 +118,19 @@ struct tracked_cascade_properties { registryData.add("omega_mass_neg", "omega_mass_neg", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {200, 1.63, 1.71, "m_{p#piK} (GeV/#it{c}^{2})"}}); } - // Hits on ITS Layer - bool hasHitOnITSlayer(uint8_t itsClsmap, int layer) + double track_inclination(double eta) { - unsigned char test_bit = 1 << layer; - return (itsClsmap & test_bit); + double lambda(0); + double theta = 2.0 * atan(exp(-eta)); + if (theta <= TMath::Pi() / 2.0) + lambda = 0.5 * TMath::Pi() - theta; + if (theta > TMath::Pi() / 2.0) + lambda = theta - 0.5 * TMath::Pi(); + return lambda; } void processData(SelectedCollisions::iterator const& collision, aod::AssignedTrackedCascades const& trackedCascades, - aod::Cascades const&, FullTracks const& tracks) + aod::Cascades const&, FullTracks const&) { registryData.fill(HIST("number_of_events_data"), 0.5); if (!collision.sel8()) @@ -137,6 +145,16 @@ struct tracked_cascade_properties { for (const auto& trackedCascade : trackedCascades) { const auto track = trackedCascade.track_as(); + const auto trackITS = trackedCascade.itsTrack_as(); + + // Comparison between track and ITStrack + registryQC.fill(HIST("deltaP"), track.p() - trackITS.p()); + registryQC.fill(HIST("deltaEta"), track.eta() - trackITS.eta()); + registryQC.fill(HIST("deltaNclsITS"), track.itsNCls() - trackITS.itsNCls()); + for (int i = 0; i < 7; i++) { + registryQC.fill(HIST("deltaClsSize"), track.itsClsSizeInLayer(i) - trackITS.itsClsSizeInLayer(i)); + } + const auto& casc = trackedCascade.cascade(); const auto& btrack = casc.bachelor_as(); double dx = trackedCascade.decayX(); @@ -147,65 +165,69 @@ struct tracked_cascade_properties { registryQC.fill(HIST("matchingChi2"), trackedCascade.matchingChi2()); registryQC.fill(HIST("topologyChi2"), trackedCascade.topologyChi2()); + registryQC.fill(HIST("decayXY"), dx, dy); // Calculate (Average) Cluster Size - int clusterSize[7]; double averageClusterSize(0); + int nCls(0); for (int i = 0; i < 7; i++) { - clusterSize[i] = track.itsClsSizeInLayer(i); - // clusterSize[i] = (track.itsClusterSizes() >> (i * 4)) & 0xf; - averageClusterSize += static_cast(clusterSize[i]); + int clusterSize = trackITS.itsClsSizeInLayer(i); + averageClusterSize += static_cast(clusterSize); + if (clusterSize > 0) + nCls++; + } + averageClusterSize = averageClusterSize / static_cast(nCls); + + registryQC.fill(HIST("deltaNclsITS_track"), nCls - track.itsNCls()); + registryQC.fill(HIST("deltaNclsITS_itstrack"), nCls - trackITS.itsNCls()); + + // Xi Mass + if (btrack.sign() > 0) { + registryData.fill(HIST("xi_mass_pos"), track.p(), trackedCascade.xiMass()); + } + if (btrack.sign() < 0) { + registryData.fill(HIST("xi_mass_neg"), track.p(), trackedCascade.xiMass()); } - averageClusterSize = averageClusterSize / static_cast(track.itsNCls()); // Track Inclination - double lambda = atan(track.tgl()); - double cosL = cos(lambda); - double sinL = sin(lambda); + double lambda = track_inclination(track.eta()); // Xi if (trackedCascade.xiMass() > mMin_xi && trackedCascade.xiMass() < mMax_xi) { - registryQC.fill(HIST("nITS_Xi"), track.p(), track.itsNCls()); + registryQC.fill(HIST("nITScls_vs_p_xi"), track.p(), trackITS.itsNCls()); if (btrack.sign() > 0) { - for (int i = 0; i < 7; i++) { - registryData.fill(HIST("xi_pos_clustersize"), clusterSize[i], track.p(), track.eta()); - } - registryData.fill(HIST("xi_pos_avgclustersize"), averageClusterSize, track.p(), track.eta()); - registryData.fill(HIST("xi_pos_avgclustersize_cosL"), averageClusterSize * cosL, track.p()); - registryData.fill(HIST("xi_pos_avgclustersize_sinL"), averageClusterSize * sinL, track.p()); - registryData.fill(HIST("xi_mass_pos"), track.p(), trackedCascade.xiMass()); + registryData.fill(HIST("xi_pos_avgclustersize"), track.p(), averageClusterSize, track.eta()); + registryData.fill(HIST("xi_pos_avgclustersize_cosL"), track.p(), averageClusterSize * cos(lambda)); + registryData.fill(HIST("xi_pos_avgclustersize_cosL_vs_betagamma"), track.p() / mXi, averageClusterSize * cos(lambda)); } if (btrack.sign() < 0) { - for (int i = 0; i < 7; i++) { - registryData.fill(HIST("xi_neg_clustersize"), clusterSize[i], track.p(), track.eta()); - } - registryData.fill(HIST("xi_neg_avgclustersize"), averageClusterSize, track.p(), track.eta()); - registryData.fill(HIST("xi_neg_avgclustersize_cosL"), averageClusterSize * cosL, track.p()); - registryData.fill(HIST("xi_neg_avgclustersize_sinL"), averageClusterSize * sinL, track.p()); - registryData.fill(HIST("xi_mass_neg"), track.p(), trackedCascade.xiMass()); + registryData.fill(HIST("xi_neg_avgclustersize"), track.p(), averageClusterSize, track.eta()); + registryData.fill(HIST("xi_neg_avgclustersize_cosL"), track.p(), averageClusterSize * cos(lambda)); + registryData.fill(HIST("xi_neg_avgclustersize_cosL_vs_betagamma"), track.p() / mXi, averageClusterSize * cos(lambda)); } + continue; + } + + // Omega Mass + if (btrack.sign() > 0) { + registryData.fill(HIST("omega_mass_pos"), track.p(), trackedCascade.omegaMass()); + } + if (btrack.sign() < 0) { + registryData.fill(HIST("omega_mass_neg"), track.p(), trackedCascade.omegaMass()); } // Omega if (trackedCascade.omegaMass() > mMin_omega && trackedCascade.omegaMass() < mMax_omega) { - registryQC.fill(HIST("nITS_Omega"), track.p(), track.itsNCls()); + registryQC.fill(HIST("nITScls_vs_p_omega"), track.p(), trackITS.itsNCls()); if (btrack.sign() > 0) { - for (int i = 0; i < 7; i++) { - registryData.fill(HIST("omega_pos_clustersize"), clusterSize[i], track.p(), track.eta()); - } - registryData.fill(HIST("omega_pos_avgclustersize"), averageClusterSize, track.p(), track.eta()); - registryData.fill(HIST("omega_pos_avgclustersize_cosL"), averageClusterSize * cosL, track.p()); - registryData.fill(HIST("omega_pos_avgclustersize_sinL"), averageClusterSize * sinL, track.p()); - registryData.fill(HIST("omega_mass_pos"), track.p(), trackedCascade.omegaMass()); + registryData.fill(HIST("omega_pos_avgclustersize"), track.p(), averageClusterSize, track.eta()); + registryData.fill(HIST("omega_pos_avgclustersize_cosL"), track.p(), averageClusterSize * cos(lambda)); + registryData.fill(HIST("omega_pos_avgclustersize_cosL_vs_betagamma"), track.p() / mOmega, averageClusterSize * cos(lambda)); } if (btrack.sign() < 0) { - for (int i = 0; i < 7; i++) { - registryData.fill(HIST("omega_neg_clustersize"), clusterSize[i], track.p(), track.eta()); - } - registryData.fill(HIST("omega_neg_avgclustersize"), averageClusterSize, track.p(), track.eta()); - registryData.fill(HIST("omega_neg_avgclustersize_cosL"), averageClusterSize * cosL, track.p()); - registryData.fill(HIST("omega_neg_avgclustersize_sinL"), averageClusterSize * sinL, track.p()); - registryData.fill(HIST("omega_mass_neg"), track.p(), trackedCascade.omegaMass()); + registryData.fill(HIST("omega_neg_avgclustersize"), track.p(), averageClusterSize, track.eta()); + registryData.fill(HIST("omega_neg_avgclustersize_cosL"), track.p(), averageClusterSize * cos(lambda)); + registryData.fill(HIST("omega_neg_avgclustersize_cosL_vs_betagamma"), track.p() / mOmega, averageClusterSize * cos(lambda)); } } } diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index dbcbf6b1d37..5a30b91e5de 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -24,6 +24,11 @@ o2physics_add_dpl_workflow(k892analysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(kstar892analysis + SOURCES kstar892analysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(k892pmanalysis SOURCES k892pmanalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -138,3 +143,8 @@ o2physics_add_dpl_workflow(lambdav2 SOURCES lambdav2.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(highmasslambdasvx + SOURCES highmasslambdasvx.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Resonances/KshortKshort.cxx b/PWGLF/Tasks/Resonances/KshortKshort.cxx index 44ec7740f62..3fbe2da0bc7 100644 --- a/PWGLF/Tasks/Resonances/KshortKshort.cxx +++ b/PWGLF/Tasks/Resonances/KshortKshort.cxx @@ -21,17 +21,21 @@ #include #include #include -#include "TF1.h" - #include #include #include +#include "TF1.h" +#include "TRandom3.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Framework/AnalysisDataModel.h" #include "Framework/StepTHn.h" #include "ReconstructionDataFormats/Track.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" // @@ -42,9 +46,6 @@ #include "Framework/AnalysisTask.h" // #include "Framework/runDataProcessing.h" // #include "PWGLF/DataModel/LFStrangenessTables.h" // -#include "Framework/O2DatabasePDGPlugin.h" -// #include "CommonConstants/PhysicsConstants.h" -// #include "Framework/HistogramRegistry.h" using namespace o2; using namespace o2::framework; @@ -55,17 +56,20 @@ using std::array; struct strangeness_tutorial { SliceCache cache; - HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rKzeroShort{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry hglue{"hglueball", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Configurable QAv0{"QAv0", false, "QAv0"}; - Configurable QAPID{"QAPID", false, "QAPID"}; + Configurable QAPID{"QAPID", true, "QAPID"}; Configurable QAv0_daughters{"QAv0_daughters", false, "QA of v0 daughters"}; + Configurable QAevents{"QAevents", false, "QA of events"}; Configurable inv_mass1D{"inv_mass1D", false, "1D invariant mass histograms"}; + Configurable correlation2Dhist{"correlation2Dhist", true, "Lamda K0 mass correlation"}; Configurable DCAv0topv{"DCAv0topv", false, "DCA V0 to PV"}; Configurable armcut{"armcut", true, "arm cut"}; + Configurable globalTracks{"globalTracks", false, "Global tracks"}; + Configurable hasTPC{"hasTPC", false, "TPC"}; // Configurable for event selection Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; @@ -76,18 +80,14 @@ struct strangeness_tutorial { Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; - // Configurable parameters for V0 selection daughters + // Configurable parameters for V0 selection Configurable ConfV0DCADaughMax{"ConfV0DCADaughMax", 1.0f, "DCA b/w V0 daughters"}; Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.06, "DCA Pos To PV"}; Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.06, "DCA Neg To PV"}; - Configurable ConfDaughEta{"ConfDaughEta", 0.8f, "V0 Daugh sel: max eta"}; - Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 70.f, "V0 Daugh sel: Min. nCls TPC"}; - Configurable ConfTPCnsimacutpi{"ConfTPCnsimacutpi", 5, "PID selections for KS0 daughters"}; - Configurable ConfKsrapidity{"ConfKsrapidity", 0.5f, "Rapidity cut on K0s"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 1, "DCA V0 to PV"}; + // Configurable isStandarv0{"isStandarv0", false, "Standard V0"}; // Configurable ConfDaughDCAMin{"ConfDaughDCAMin", 0.06f, "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; // same as DCA pos to pv and neg to pv - // Configurable parameters for V0 selection - Configurable cMaxV0DCA{"cMaxV0DCA", 1, "DCA V0 to PV"}; Configurable ConfV0PtMin{"ConfV0PtMin", 0.f, "Minimum transverse momentum of V0"}; Configurable ConfV0CPAMin{"ConfV0CPAMin", 0.97f, "Minimum CPA of V0"}; Configurable ConfV0TranRadV0Min{"ConfV0TranRadV0Min", 0.5f, "Minimum transverse radius"}; @@ -95,10 +95,14 @@ struct strangeness_tutorial { Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 15, "Maximum V0 life time"}; Configurable cSigmaMassKs0{"cSigmaMassKs0", 4, "n Sigma cut on Ks0 mass (Mass (Ks) - cSigmaMassKs0*cWidthKs0)"}; Configurable cWidthKs0{"cWidthKs0", 0.005, "Width of KS0"}; + Configurable ConfDaughEta{"ConfDaughEta", 0.8f, "V0 Daugh sel: max eta"}; + Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 70.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 5, "PID selections for KS0 daughters"}; Configurable Confarmcut{"Confarmcut", 0.2f, "Armenteros cut"}; + Configurable ConfKsrapidity{"ConfKsrapidity", 0.5f, "Rapidity cut on K0s"}; + // Configurable lowmasscutks0{"lowmasscutks0", 0.497 - 4 * 0.005, "Low mass cut on K0s"}; // Configurable highmasscutks0{"highmasscutks0", 0.497 + 4 * 0.005, "High mass cut on K0s"}; - // Configurable isStandarv0{"isStandarv0", false, "Standard V0"}; // Configurable for track selection and multiplicity Configurable cfgPTcut{"cfgPTcut", 0.2f, "Track PT cut"}; @@ -106,24 +110,36 @@ struct strangeness_tutorial { Configurable cfgMultFOTM{"cfgMultFOTM", true, "Use FOTM multiplicity if pp else use 0 here for PbPb (FT0C)"}; ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 5., 10., 30., 50., 70., 100., 110., 150.}, "Binning of the centrality axis"}; + // output THnSparses + Configurable activateTHnSparseCosThStarHelicity{"activateTHnSparseCosThStarHelicity", false, "Activate the THnSparse with cosThStar w.r.t. helicity axis"}; + Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; + Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", true, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; + Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; + Configurable c_nof_rotations{"c_nof_rotations", 3, "Number of random rotations in the rotational background"}; + // Other cuts on Ks and glueball Configurable rapidityks{"rapidityks", true, "rapidity cut on K0s"}; - Configurable CompetingCascadeRejection{"CompetingCascadeRejection", false, "mass under lambda hypothesis"}; - Configurable LambdaRejectionCut{"LambdaRejectionCut", 4.3, "rejecting competing cascade lambda (MeV)"}; - Configurable AntiLambdaRejectionCut{"AntiLambdaRejectionCut", 4.3, "rejecting competing cascade anti-lambda (MeV)"}; + Configurable apply_competingcut{"apply_competingcut", false, "Competing cascade rejection cut"}; + Configurable competingcascrejlambda{"competingcascrejlambda", 0.005, "rejecting competing cascade lambda"}; + Configurable competingcascrejlambdaanti{"competingcascrejlambdaanti", 0.005, "rejecting competing cascade anti-lambda"}; // If one of the pions is misidentified as a proton, then instead of Ks we reconstruct lambda, therefore the competing cascade rejection cut is applied in which if the reconstrcted mass of a pion and proton (which we are assuming to be misidentified as proton) is close to lambda or anti-lambda, then the track is rejected. Configurable tpcCrossedrows{"tpcCrossedrows", 70, "TPC crossed rows"}; Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; // Mass and pT axis as configurables Configurable cPtMin{"cPtMin", 0.0f, "Minimum pT"}; - Configurable cPtMax{"cPtMax", 15.0f, "Maximum pT"}; - Configurable cPtBins{"cPtBins", 150, "Number of pT bins"}; + Configurable cPtMax{"cPtMax", 50.0f, "Maximum pT"}; + Configurable cPtBins{"cPtBins", 500, "Number of pT bins"}; Configurable cMassMin{"cMassMin", 0.9f, "Minimum mass of glueball"}; - Configurable cMassMax{"cMassMax", 2.4f, "Maximum mass of glueball"}; - Configurable cMassBins{"cMassBins", 150, "Number of mass bins for glueball"}; + Configurable cMassMax{"cMassMax", 3.0f, "Maximum mass of glueball"}; + Configurable cMassBins{"cMassBins", 210, "Number of mass bins for glueball"}; Configurable ksMassMin{"ksMassMin", 0.45f, "Minimum mass of K0s"}; Configurable ksMassMax{"ksMassMax", 0.55f, "Maximum mass of K0s"}; Configurable ksMassBins{"ksMassBins", 200, "Number of mass bins for K0s"}; + Configurable rotational_cut{"rotational_cut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; + ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; + ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; // Event selection cuts - Alex (Temporary, need to fix!) TF1* fMultPVCutLow = nullptr; @@ -131,39 +147,82 @@ struct strangeness_tutorial { TF1* fMultCutLow = nullptr; TF1* fMultCutHigh = nullptr; TF1* fMultMultPVCut = nullptr; - - // to get the particle masses - Service pdgDB; // pdg database + Service PDGdatabase; void init(InitContext const&) { // Axes AxisSpec K0ShortMassAxis = {ksMassBins, ksMassMin, ksMassMax, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec glueballMassAxis = {cMassBins, cMassMin, cMassMax, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - AxisSpec vertexZAxis = {100, -15.f, 15.f, "vrtx_{Z} [cm]"}; // for histogram + AxisSpec vertexZAxis = {60, -15.f, 15.f, "vrtx_{Z} [cm]"}; // for histogram AxisSpec ptAxis = {cPtBins, cPtMin, cPtMax, "#it{p}_{T} (GeV/#it{c})"}; // AxisSpec multiplicityAxis = {110, 0.0f, 150.0f, "Multiplicity Axis"}; AxisSpec multiplicityAxis = {binsCent, "Multiplicity Axis"}; + AxisSpec thnAxisPOL{configThnAxisPOL, "Configurabel theta axis"}; + + // THnSparses + std::array sparses = {activateTHnSparseCosThStarHelicity, activateTHnSparseCosThStarProduction, activateTHnSparseCosThStarBeam, activateTHnSparseCosThStarRandom}; + + // std::array sparses = {activateTHnSparseCosThStarHelicity}; + + if (std::accumulate(sparses.begin(), sparses.end(), 0) == 0) { + LOGP(fatal, "No output THnSparses enabled"); + } else { + if (activateTHnSparseCosThStarHelicity) { + LOGP(info, "THnSparse with cosThStar w.r.t. helicity axis active."); + } + if (activateTHnSparseCosThStarProduction) { + LOGP(info, "THnSparse with cosThStar w.r.t. production axis active."); + } + if (activateTHnSparseCosThStarBeam) { + LOGP(info, "THnSparse with cosThStar w.r.t. beam axis active. (Gottified jackson frame)"); + } + if (activateTHnSparseCosThStarRandom) { + LOGP(info, "THnSparse with cosThStar w.r.t. random axis active."); + } + } - // Histograms // Event selection - rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - rEventSelection.add("hmultiplicity", "hmultiplicity", {HistType::kTH1F, {{150, 0.0f, 150.0f}}}); + if (QAevents) { + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + rEventSelection.add("hmultiplicity", "multiplicity percentile distribution", {HistType::kTH1F, {{150, 0.0f, 150.0f}}}); + rEventSelection.add("multdist_FT0M", "FT0M Multiplicity distribution", kTH1F, {axisMultdist}); + rEventSelection.add("multdist_FT0A", "FT0A Multiplicity distribution", kTH1F, {axisMultdist}); + rEventSelection.add("multdist_FT0C", "FT0C Multiplicity distribution", kTH1F, {axisMultdist}); + rEventSelection.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); + } if (inv_mass1D) { hglue.add("h1glueInvMassDS", "h1glueInvMassDS", kTH1F, {glueballMassAxis}); hglue.add("h1glueInvMassME", "h1glueInvMassME", kTH1F, {glueballMassAxis}); + hglue.add("h1glueInvMassRot", "h1glueInvMassRot", kTH1F, {glueballMassAxis}); } - hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}, true); - hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}, true); - hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}, true); - hglue.add("heventscheck", "heventscheck", kTH1F, {{9, 0, 9}}); - hglue.add("hmasscorrelation", "hmasscorrelation", kTH2F, {K0ShortMassAxis, K0ShortMassAxis}); + + hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); + hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); + hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); + hglue.add("heventscheck", "heventscheck", kTH1I, {{10, 0, 10}}); + hglue.add("htrackscheck_v0", "htrackscheck_v0", kTH1I, {{15, 0, 15}}); + hglue.add("htrackscheck_v0_daughters", "htrackscheck_v0_daughters", kTH1I, {{15, 0, 15}}); // K0s topological/PID cuts + if (correlation2Dhist) { + rKzeroShort.add("mass_lambda_kshort_before", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after1", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after2", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after3", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after4", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after5", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after6", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after7", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after8", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after9", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + rKzeroShort.add("mass_lambda_kshort_after10", "mass under lambda hypotheses and Kshort mass", kTH2F, {{100, 0.2, 0.8}, {100, 0.9, 1.5}}); + } if (QAv0) { // Invariant Mass rKzeroShort.add("hMassK0Shortbefore", "hMassK0Shortbefore", kTHnSparseF, {K0ShortMassAxis, ptAxis}); + rKzeroShort.add("hMasscorrelationbefore", "hMasscorrelationbefore", kTH2F, {K0ShortMassAxis, K0ShortMassAxis}); rKzeroShort.add("hMassK0ShortSelected", "hMassK0ShortSelected", kTHnSparseF, {K0ShortMassAxis, ptAxis}); // Topological histograms (after the selection) rKzeroShort.add("hDCAV0Daughters", "DCA between v0 daughters", {HistType::kTH1F, {{60, -3.0f, 3.0f}}}); @@ -172,6 +231,7 @@ struct strangeness_tutorial { rKzeroShort.add("Mass_lambda", "Mass under lambda hypothesis", kTH1F, {glueballMassAxis}); rKzeroShort.add("mass_AntiLambda", "Mass under anti-lambda hypothesis", kTH1F, {glueballMassAxis}); rKzeroShort.add("mass_Gamma", "Mass under Gamma hypothesis", kTH1F, {glueballMassAxis}); + // rKzeroShort.add("mass_Hypertriton", "Mass under hypertriton hypothesis", kTH1F, {glueballMassAxis}); // rKzeroShort.add("mass_AnitHypertriton", "Mass under anti-hypertriton hypothesis", kTH1F, {glueballMassAxis}); rKzeroShort.add("rapidity", "Rapidity distribution", kTH1F, {{100, -1.0f, 1.0f}}); @@ -180,8 +240,9 @@ struct strangeness_tutorial { rKzeroShort.add("hDCAnegtopv", "DCA negative daughter to PV", kTH1F, {{1000, -10.0f, 10.0f}}); rKzeroShort.add("hDCAv0topv", "DCA V0 to PV", kTH1F, {{60, -3.0f, 3.0f}}); rKzeroShort.add("halpha", "Armenteros alpha", kTH1F, {{100, -5.0f, 5.0f}}); - rKzeroShort.add("hqtarm", "qtarm", kTH1F, {{100, 0.0f, 1.0f}}); + rKzeroShort.add("hqtarmbyalpha", "qtarm/alpha", kTH1F, {{100, 0.0f, 1.0f}}); rKzeroShort.add("hpsipair", "psi pair angle", kTH1F, {{100, -5.0f, 5.0f}}); + rKzeroShort.add("NksProduced", "Number of K0s produced", kTH1I, {{15, 0, 15}}); // // Topological histograms (before the selection) // rKzeroShort.add("hDCAV0Daughters_before", "DCA between v0 daughters before the selection", {HistType::kTH1F, {{60, -3.0f, 3.0f}}}); @@ -190,9 +251,10 @@ struct strangeness_tutorial { } if (QAPID) { rKzeroShort.add("hNSigmaPosPionK0s_before", "hNSigmaPosPionK0s_before", {HistType::kTH2F, {{ptAxis}, {100, -5.f, 5.f}}}); - rKzeroShort.add("hNSigmaPosPionK0s_after", "hNSigmaPosPionK0s_after", {HistType::kTH2F, {{ptAxis}, {100, -5.f, 5.f}}}); + // rKzeroShort.add("hNSigmaPosPionK0s_after", "hNSigmaPosPionK0s_after", {HistType::kTH2F, {{ptAxis}, {100, -5.f, 5.f}}}); rKzeroShort.add("hNSigmaNegPionK0s_before", "hNSigmaNegPionK0s_before", {HistType::kTH2F, {{ptAxis}, {100, -5.f, 5.f}}}); - rKzeroShort.add("hNSigmaNegPionK0s_after", "hNSigmaNegPionK0s_after", {HistType::kTH2F, {{ptAxis}, {100, -5.f, 5.f}}}); + // rKzeroShort.add("hNSigmaNegPionK0s_after", "hNSigmaNegPionK0s_after", {HistType::kTH2F, {{ptAxis}, {100, -5.f, 5.f}}}); + rKzeroShort.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {axisPtfordEbydx, axisdEdx}); } if (QAv0_daughters) { rKzeroShort.add("negative_pt", "Negative daughter pT", kTH1F, {ptAxis}); @@ -201,8 +263,6 @@ struct strangeness_tutorial { rKzeroShort.add("positive_eta", "Positive daughter eta", kTH1F, {{100, -1.0f, 1.0f}}); rKzeroShort.add("negative_phi", "Negative daughter phi", kTH1F, {{70, 0.0f, 7.0f}}); rKzeroShort.add("positive_phi", "Positive daughter phi", kTH1F, {{70, 0.0f, 7.0f}}); - rKzeroShort.add("negative_y", "Negative daughter y", kTH1F, {{100, -1.0f, 1.0f}}); - rKzeroShort.add("positive_y", "Positive daughter y", kTH1F, {{100, -1.0f, 1.0f}}); } if (additionalEvsel) { fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); @@ -221,96 +281,42 @@ struct strangeness_tutorial { template bool eventselection(Collision const& collision, const float& multiplicity) { - if (!collision.sel8()) { + hglue.fill(HIST("heventscheck"), 1.5); + + if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { return false; } - if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + hglue.fill(HIST("heventscheck"), 2.5); + + if (!collision.sel8()) { return false; } + hglue.fill(HIST("heventscheck"), 3.5); + if (piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } + hglue.fill(HIST("heventscheck"), 4.5); + if (goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } + hglue.fill(HIST("heventscheck"), 5.5); + if (itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { return false; } - // if (collision.alias_bit(kTVXinTRD)) { - // // TRD triggered - // // return 0; - // } + hglue.fill(HIST("heventscheck"), 6.5); + auto multNTracksPV = collision.multNTracksPV(); if (additionalEvsel && multNTracksPV < fMultPVCutLow->Eval(multiplicity)) { return false; } + hglue.fill(HIST("heventscheck"), 7.5); if (additionalEvsel && multNTracksPV > fMultPVCutHigh->Eval(multiplicity)) { return false; } - // if (multTrk < fMultCutLow->Eval(multiplicity)) - // return 0; - // if (multTrk > fMultCutHigh->Eval(multiplicity)) - // return 0; - // if (multTrk > fMultMultPVCut->Eval(multNTracksPV)) - // return 0; - return true; - } - - template - bool SelectionV0Daughter(T const& track, float charge, - double nsigmaV0Daughter, V0s const& /*candidate*/) - { - if (QAPID) { - // Filling the PID of the V0 daughters in the region of the K0 peak. - // tpcInnerParam is the momentum at the inner wall of TPC. So momentum of tpc vs nsigma of tpc is plotted. - // if (0.45 < candidate.mK0Short() && candidate.mK0Short() < 0.55) { - (charge == 1) ? rKzeroShort.fill(HIST("hNSigmaPosPionK0s_before"), track.tpcInnerParam(), track.tpcNSigmaPi()) : rKzeroShort.fill(HIST("hNSigmaNegPionK0s_before"), track.tpcInnerParam(), track.tpcNSigmaPi()); - // } - } - const auto eta = track.eta(); - const auto tpcNClsF = track.tpcNClsFound(); - // const auto dcaXY = track.dcaXY(); // for this we need TrackDCA table - const auto sign = track.sign(); - - if (!track.hasTPC()) - return false; - if (track.tpcNClsCrossedRows() < tpcCrossedrows) - return false; - if (track.tpcCrossedRowsOverFindableCls() < tpcCrossedrowsOverfcls) - return false; - - if (charge < 0 && sign > 0) { - return false; - } - if (charge > 0 && sign < 0) { - return false; - } - if (std::abs(eta) > ConfDaughEta) { - return false; - } - if (tpcNClsF < ConfDaughTPCnclsMin) { - return false; - } - // if (std::abs(dcaXY) < ConfDaughDCAMin) { - // return false; - // } - // v0 PID selection - if (std::abs(nsigmaV0Daughter) > ConfTPCnsimacutpi) { - return false; - } - - if (QAPID) { - // if (0.45 < candidate.mK0Short() && candidate.mK0Short() < 0.55) { - (charge == 1) ? rKzeroShort.fill(HIST("hNSigmaPosPionK0s_after"), track.tpcInnerParam(), track.tpcNSigmaPi()) : rKzeroShort.fill(HIST("hNSigmaNegPionK0s_after"), track.tpcInnerParam(), track.tpcNSigmaPi()); - // } - } - - if (QAv0_daughters) { - (charge == 1) ? rKzeroShort.fill(HIST("positive_pt"), track.pt()) : rKzeroShort.fill(HIST("negative_pt"), track.pt()); - (charge == 1) ? rKzeroShort.fill(HIST("positive_eta"), track.eta()) : rKzeroShort.fill(HIST("negative_eta"), track.eta()); - (charge == 1) ? rKzeroShort.fill(HIST("positive_phi"), track.phi()) : rKzeroShort.fill(HIST("negative_phi"), track.phi()); - (charge == 1) ? rKzeroShort.fill(HIST("positive_y"), track.y()) : rKzeroShort.fill(HIST("negative_y"), track.y()); - } + hglue.fill(HIST("heventscheck"), 8.5); return true; } @@ -326,14 +332,15 @@ struct strangeness_tutorial { const float tranRad = candidate.v0radius(); const float dcaDaughv0 = candidate.dcaV0daughters(); const float cpav0 = candidate.v0cosPA(); - auto pdgmasslambda = pdgDB->GetParticle(3122)->Mass(); - float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * pdgDB->GetParticle(310)->Mass(); + + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * PDGdatabase->Mass(310); float lowmasscutks0 = 0.497 - cWidthKs0 * cSigmaMassKs0; float highmasscutks0 = 0.497 + cWidthKs0 * cSigmaMassKs0; // float decayLength = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::sqrtSumOfSquares(candidate.px(), candidate.py(), candidate.pz()); if (QAv0) { rKzeroShort.fill(HIST("hMassK0Shortbefore"), candidate.mK0Short(), candidate.pt()); + rKzeroShort.fill(HIST("hMasscorrelationbefore"), candidate.mK0Short(), candidate.mK0Short()); rKzeroShort.fill(HIST("hLT"), CtauK0s); rKzeroShort.fill(HIST("hDCAV0Daughters"), candidate.dcaV0daughters()); rKzeroShort.fill(HIST("hV0CosPA"), candidate.v0cosPA()); @@ -348,53 +355,155 @@ struct strangeness_tutorial { rKzeroShort.fill(HIST("hDCAnegtopv"), candidate.dcanegtopv()); rKzeroShort.fill(HIST("hDCAv0topv"), candidate.dcav0topv()); rKzeroShort.fill(HIST("halpha"), candidate.alpha()); - rKzeroShort.fill(HIST("hqtarm"), candidate.qtarm()); + rKzeroShort.fill(HIST("hqtarmbyalpha"), arm); rKzeroShort.fill(HIST("hpsipair"), candidate.psipair()); } + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_before"), candidate.mK0Short(), candidate.mLambda()); + + hglue.fill(HIST("htrackscheck_v0"), 0.5); - if (!DCAv0topv && fabs(candidate.dcav0topv()) > cMaxV0DCA) { + if (DCAv0topv && fabs(candidate.dcav0topv()) > cMaxV0DCA) { return false; } + hglue.fill(HIST("htrackscheck_v0"), 1.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after1"), candidate.mK0Short(), candidate.mLambda()); if (rapidityks && TMath::Abs(candidate.yK0Short()) >= ConfKsrapidity) { return false; } - if (CompetingCascadeRejection && (TMath::Abs(candidate.mLambda() - pdgmasslambda) <= LambdaRejectionCut * 1e-3 || TMath::Abs(candidate.mAntiLambda() - pdgmasslambda) <= AntiLambdaRejectionCut * 1e-3)) { - return false; - } - // std::cout<<"candidate.mLambda() = "< ConfV0DCADaughMax) { return false; } + hglue.fill(HIST("htrackscheck_v0"), 4.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after4"), candidate.mK0Short(), candidate.mLambda()); + if (cpav0 < ConfV0CPAMin) { return false; } + hglue.fill(HIST("htrackscheck_v0"), 5.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after5"), candidate.mK0Short(), candidate.mLambda()); + if (tranRad < ConfV0TranRadV0Min) { return false; } + hglue.fill(HIST("htrackscheck_v0"), 6.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after6"), candidate.mK0Short(), candidate.mLambda()); + if (tranRad > ConfV0TranRadV0Max) { return false; } - if (fabs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + hglue.fill(HIST("htrackscheck_v0"), 7.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after7"), candidate.mK0Short(), candidate.mLambda()); + + if (fabs(CtauK0s) > cMaxV0LifeTime) { + return false; + } + hglue.fill(HIST("htrackscheck_v0"), 8.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after8"), candidate.mK0Short(), candidate.mLambda()); + + if (armcut && arm < Confarmcut) { return false; } - if (!armcut && arm < Confarmcut) { + hglue.fill(HIST("htrackscheck_v0"), 9.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after9"), candidate.mK0Short(), candidate.mLambda()); + + if (apply_competingcut && (TMath::Abs(candidate.mLambda() - PDGdatabase->Mass(3122)) <= competingcascrejlambda || TMath::Abs(candidate.mAntiLambda() - PDGdatabase->Mass(-3122)) <= competingcascrejlambdaanti)) { return false; } + hglue.fill(HIST("htrackscheck_v0"), 10.5); + if (correlation2Dhist) + rKzeroShort.fill(HIST("mass_lambda_kshort_after10"), candidate.mK0Short(), candidate.mLambda()); if (QAv0) { rKzeroShort.fill(HIST("hMassK0ShortSelected"), candidate.mK0Short(), candidate.pt()); + // rKzeroShort.fill(HIST("mass_lambda_kshort_after"), candidate.mK0Short(), candidate.mLambda()); + } + + if (candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + return false; } return true; } + template + bool isSelectedV0Daughter(T const& track, float charge, double nsigmaV0Daughter, V0s const& /*candidate*/) + { + if (QAPID) { + // Filling the PID of the V0 daughters in the region of the K0 peak. + (charge == 1) ? rKzeroShort.fill(HIST("hNSigmaPosPionK0s_before"), track.tpcInnerParam(), track.tpcNSigmaPi()) : rKzeroShort.fill(HIST("hNSigmaNegPionK0s_before"), track.tpcInnerParam(), track.tpcNSigmaPi()); + rKzeroShort.fill(HIST("dE_by_dx_TPC"), track.p(), track.tpcSignal()); + } + const auto eta = track.eta(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto sign = track.sign(); + + hglue.fill(HIST("htrackscheck_v0_daughters"), 0.5); + + if (hasTPC && !track.hasTPC()) + return false; + hglue.fill(HIST("htrackscheck_v0_daughters"), 1.5); + + if (!globalTracks) { + if (track.tpcNClsCrossedRows() < tpcCrossedrows) + return false; + hglue.fill(HIST("htrackscheck_v0_daughters"), 2.5); + + if (track.tpcCrossedRowsOverFindableCls() < tpcCrossedrowsOverfcls) + return false; + hglue.fill(HIST("htrackscheck_v0_daughters"), 3.5); + + if (tpcNClsF < ConfDaughTPCnclsMin) { + return false; + } + hglue.fill(HIST("htrackscheck_v0_daughters"), 4.5); + } else { + if (!track.isGlobalTrack()) + return false; + hglue.fill(HIST("htrackscheck_v0_daughters"), 4.5); + } + + if (charge < 0 && sign > 0) { + return false; + } + hglue.fill(HIST("htrackscheck_v0_daughters"), 5.5); + + if (charge > 0 && sign < 0) { + return false; + } + hglue.fill(HIST("htrackscheck_v0_daughters"), 6.5); + + if (std::abs(eta) > ConfDaughEta) { + return false; + } + hglue.fill(HIST("htrackscheck_v0_daughters"), 7.5); + + if (std::abs(nsigmaV0Daughter) > ConfDaughPIDCuts) { + return false; + } + hglue.fill(HIST("htrackscheck_v0_daughters"), 8.5); + + return true; + } + // Defining filters for events (event selection) // Filter eventFilter = (o2::aod::evsel::sel8 == true); Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); @@ -414,10 +523,12 @@ struct strangeness_tutorial { // soa::Filtered const& V0s, // DaughterTracks const&) + ROOT::Math::PxPyPzMVector daughter1, daughter2; + ROOT::Math::PxPyPzMVector lv3; void processSE(EventCandidates::iterator const& collision, TrackCandidates const& /*tracks*/, aod::V0Datas const& V0s) { hglue.fill(HIST("heventscheck"), 0.5); - const double massK0s = pdgDB->GetParticle(310)->Mass(); + const double massK0s = TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); float multiplicity = 0.0f; if (cfgMultFOTM) { multiplicity = collision.centFT0M(); @@ -428,14 +539,18 @@ struct strangeness_tutorial { return; } - hglue.fill(HIST("heventscheck"), 1.5); - - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - rEventSelection.fill(HIST("hmultiplicity"), multiplicity); + if (QAevents) { + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + rEventSelection.fill(HIST("hmultiplicity"), multiplicity); + rEventSelection.fill(HIST("multdist_FT0M"), collision.multFT0M()); + rEventSelection.fill(HIST("multdist_FT0A"), collision.multFT0A()); + rEventSelection.fill(HIST("multdist_FT0C"), collision.multFT0C()); + rEventSelection.fill(HIST("hNcontributor"), collision.numContrib()); + } - for (auto& [v1, v2] : combinations(CombinationsStrictlyUpperIndexPolicy(V0s, V0s))) { + std::vector v0indexes; - hglue.fill(HIST("heventscheck"), 2.5); + for (auto& [v1, v2] : combinations(CombinationsUpperIndexPolicy(V0s, V0s))) { if (v1.size() == 0 || v2.size() == 0) { continue; @@ -453,54 +568,131 @@ struct strangeness_tutorial { auto postrack2 = v2.template posTrack_as(); auto negtrack2 = v2.template negTrack_as(); - if (postrack1.globalIndex() == postrack2.globalIndex()) { - continue; - } - if (negtrack1.globalIndex() == negtrack2.globalIndex()) { - continue; - } double nTPCSigmaPos1{postrack1.tpcNSigmaPi()}; double nTPCSigmaNeg1{negtrack1.tpcNSigmaPi()}; double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; - if (!SelectionV0Daughter(postrack1, 1, nTPCSigmaPos1, v1)) { + if (!(isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, v1) && isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, v1))) { + continue; + } + if (!(isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, v2) && isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, v2))) { continue; } - if (!SelectionV0Daughter(postrack2, 1, nTPCSigmaPos2, v2)) { + + if (QAv0_daughters) { + rKzeroShort.fill(HIST("negative_pt"), negtrack1.pt()); + rKzeroShort.fill(HIST("positive_pt"), postrack1.pt()); + rKzeroShort.fill(HIST("negative_eta"), negtrack1.eta()); + rKzeroShort.fill(HIST("positive_eta"), postrack1.eta()); + rKzeroShort.fill(HIST("negative_phi"), negtrack1.phi()); + rKzeroShort.fill(HIST("positive_phi"), postrack1.phi()); + } + // if (!isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, v1)) { + // continue; + // } + // if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, v2)) { + // continue; + // } + + if (!(std::find(v0indexes.begin(), v0indexes.end(), v1.globalIndex()) != v0indexes.end())) { + v0indexes.push_back(v1.globalIndex()); + } + // std::cout << "global index of v1: " << v1.globalIndex() << " global index of v2: " << v2.globalIndex() << std::endl; + if (!(std::find(v0indexes.begin(), v0indexes.end(), v2.globalIndex()) != v0indexes.end())) { + v0indexes.push_back(v2.globalIndex()); + } + + if (v1.globalIndex() == v2.globalIndex()) { continue; } - if (!SelectionV0Daughter(negtrack1, -1, nTPCSigmaNeg1, v1)) { + + if (postrack1.globalIndex() == postrack2.globalIndex()) { continue; } - if (!SelectionV0Daughter(negtrack2, -1, nTPCSigmaNeg2, v2)) { + if (negtrack1.globalIndex() == negtrack2.globalIndex()) { continue; } - hglue.fill(HIST("heventscheck"), 3.5); + TLorentzVector lv1, lv2, lv3, lv4, lv5; - TLorentzVector lv1, lv2, lv3, lv4, lv5, lv6, lv7; lv1.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi(), massK0s); + lv2.SetPtEtaPhiM(v2.pt(), v2.eta(), v2.phi(), massK0s); + lv3 = lv1 + lv2; - lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + TMath::Pi(), massK0s); // for rotated background - lv5.SetPtEtaPhiM(v2.pt(), v2.eta(), v2.phi() + TMath::Pi(), massK0s); // for rotated background - lv6 = lv1 + lv5; // rotating one of the daughters - lv7 = lv2 + lv4; + + daughter1 = ROOT::Math::PxPyPzMVector(v1.px(), v1.py(), v1.pz(), massK0s); // Kplus + daughter2 = ROOT::Math::PxPyPzMVector(v2.px(), v2.py(), v2.pz(), massK0s); // Kminus + + // polarization calculations + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massK0s); // Kshort + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + + TRandom* rn = new TRandom(); if (TMath::Abs(lv3.Rapidity() < 0.5)) { + if (inv_mass1D) { - hglue.fill(HIST("h1glueInvMassDS"), lv3.M()); + hglue.fill(HIST("h1glueInvMassRot"), lv3.M()); } - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M()); - hglue.fill(HIST("hmasscorrelation"), v1.mK0Short(), v2.mK0Short()); - std::cout << "The value of mass of first daughter is: " << lv1.M() << std::endl; - std::cout << "The value of mass of second daughter is: " << lv2.M() << std::endl; - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv6.Pt(), lv6.M()); // rotating one of the daughters - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv7.Pt(), lv7.M()); // rotating one of the daughters + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + theta2, massK0s); // for rotated background + lv5 = lv2 + lv4; + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity); + } + + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + theta2, massK0s); // for rotated background + lv5 = lv2 + lv4; + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction); + } + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + theta2, massK0s); // for rotated background + lv5 = lv2 + lv4; + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam); + } + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + theta2, massK0s); // for rotated background + lv5 = lv2 + lv4; + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom); + } + } } } + if (QAv0) { + int sizeofv0indexes = v0indexes.size(); + rKzeroShort.fill(HIST("NksProduced"), sizeofv0indexes); + // std::cout << "Size of v0indexes: " << sizeofv0indexes << std::endl; + } } PROCESS_SWITCH(strangeness_tutorial, processSE, "same event process", true); @@ -514,9 +706,8 @@ struct strangeness_tutorial { void processME(EventCandidates const& collisions, TrackCandidates const& /*tracks*/, V0TrackCandidate const& v0s) { - hglue.fill(HIST("heventscheck"), 4.5); - const double massK0s = pdgDB->GetParticle(310)->Mass(); + const double massK0s = TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); auto tracksTuple = std::make_tuple(v0s); BinningTypeVertexContributor binningOnPositions1{{mevz, memult}, true}; BinningTypeCentralityM binningOnPositions2{{mevz, memult}, true}; @@ -527,18 +718,16 @@ struct strangeness_tutorial { if (cfgMultFOTM) { for (auto& [c1, tracks1, c2, tracks2] : pair2) // two different centrality c1 and c2 and tracks corresponding to them { - hglue.fill(HIST("heventscheck"), 5.5); float multiplicity = 0.0f; + multiplicity = c1.centFT0M(); if (!eventselection(c1, multiplicity) || !eventselection(c2, multiplicity)) { continue; } - hglue.fill(HIST("heventscheck"), 6.5); for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - hglue.fill(HIST("heventscheck"), 7.5); if (t1.size() == 0 || t2.size() == 0) { continue; @@ -564,31 +753,60 @@ struct strangeness_tutorial { double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; - if (!SelectionV0Daughter(postrack1, 1, nTPCSigmaPos1, t1)) { + if (!isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, t1)) { continue; } - if (!SelectionV0Daughter(postrack2, 1, nTPCSigmaPos2, t2)) { + if (!isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, t2)) { continue; } - if (!SelectionV0Daughter(negtrack1, -1, nTPCSigmaNeg1, t1)) { + if (!isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, t1)) { continue; } - if (!SelectionV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { + if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { continue; } - hglue.fill(HIST("heventscheck"), 8.5); - TLorentzVector lv1, lv2, lv3; lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massK0s); lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massK0s); lv3 = lv1 + lv2; + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massK0s); // Kshort + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + if (TMath::Abs(lv3.Rapidity() < 0.5)) { - if (inv_mass1D) { - hglue.fill(HIST("h1glueInvMassME"), lv3.M()); + + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); } - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M()); } + + // if (TMath::Abs(lv3.Rapidity() < 0.5)) { + // if (inv_mass1D) { + // hglue.fill(HIST("h1glueInvMassME"), lv3.M()); + // } + // hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M()); + // } } } } else { @@ -626,16 +844,16 @@ struct strangeness_tutorial { double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; - if (!SelectionV0Daughter(postrack1, 1, nTPCSigmaPos1, t1)) { + if (!isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, t1)) { continue; } - if (!SelectionV0Daughter(postrack2, 1, nTPCSigmaPos2, t2)) { + if (!isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, t2)) { continue; } - if (!SelectionV0Daughter(negtrack1, -1, nTPCSigmaNeg1, t1)) { + if (!isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, t1)) { continue; } - if (!SelectionV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { + if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { continue; } @@ -643,12 +861,47 @@ struct strangeness_tutorial { lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massK0s); lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massK0s); lv3 = lv1 + lv2; + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massK0s); // Kshort + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + if (TMath::Abs(lv3.Rapidity() < 0.5)) { - if (inv_mass1D) { - hglue.fill(HIST("h1glueInvMassME"), lv3.M()); + + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); } - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M()); } + + // TLorentzVector lv1, lv2, lv3; + // lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massK0s); + // lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massK0s); + // lv3 = lv1 + lv2; + // if (TMath::Abs(lv3.Rapidity() < 0.5)) { + // if (inv_mass1D) { + // hglue.fill(HIST("h1glueInvMassME"), lv3.M()); + // } + // hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M()); + // } } } } diff --git a/PWGLF/Tasks/Resonances/f0980analysis.cxx b/PWGLF/Tasks/Resonances/f0980analysis.cxx index 781fb837f1c..3353fbebbab 100644 --- a/PWGLF/Tasks/Resonances/f0980analysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980analysis.cxx @@ -11,6 +11,7 @@ /// \author Junlee Kim (jikim1290@gmail.com) +#include #include #include "TVector2.h" @@ -32,8 +33,6 @@ using namespace o2::constants::physics; struct f0980analysis { SliceCache cache; - Preslice perRCol = aod::resodaughter::resoCollisionId; - Preslice perCollision = aod::track::collisionId; HistogramRegistry histos{ "histos", {}, @@ -43,22 +42,17 @@ struct f0980analysis { "Minimum transverse momentum for charged track"}; Configurable cfgMaxEta{"cfgMaxEta", 0.8, "Maximum pseudorapidiy for charged track"}; - Configurable cfgMinDCArToPVcut{"cfgMinDCArToPVcut", -0.5, - "Minimum transverse DCA"}; Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.5, "Maximum transverse DCA"}; - Configurable cfgMinDCAzToPVcut{"cfgMinDCAzToPVcut", -2.0, - "Minimum longitudinal DCA"}; Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, "Maximum longitudinal DCA"}; - Configurable cfgMaxTPCStandalone{"cfgMaxTPCStandalone", 2.0, - "Maximum TPC PID as standalone"}; Configurable cfgMaxTPC{"cfgMaxTPC", 5.0, "Maximum TPC PID with TOF"}; Configurable cfgMaxTOF{"cfgMaxTOF", 3.0, "Maximum TOF PID with TPC"}; Configurable cfgMinRap{"cfgMinRap", -0.5, "Minimum rapidity for pair"}; Configurable cfgMaxRap{"cfgMaxRap", 0.5, "Maximum rapidity for pair"}; - Configurable cfgMinTPCncr{"cfgMinTPCncr", 70, "minimum TPC cluster"}; + Configurable cfgFindRT{"cfgFindRT", false, "boolean for RT analysis"}; + // Track selection Configurable cfgPrimaryTrack{ "cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz @@ -75,20 +69,36 @@ struct f0980analysis { Configurable cfgPVContributor{ "cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor - Configurable cfgUseTOF{ - "cfgUseTOF", false, - "Flag for the usage of TOF for PID"}; - + Configurable cfgGlobalTrack{ + "cfgGlobalTrack", false, + "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; + Configurable cfgRatioTPCRowsOverFindableCls{ + "cfgRatioTPCRowsOverFindableCls", 0.0f, + "TPC Crossed Rows to Findable Clusters"}; + Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 999.0, "ITS Chi2/NCl"}; + Configurable cfgTPCChi2NCl{"cfgTPCChi2NCl", 999.0, "TPC Chi2/NCl"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + Configurable cfgHasITS{"cfgHasITS", false, "Require ITS"}; + Configurable cfgHasTPC{"cfgHasTPC", false, "Require TPC"}; + Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + + // PID + Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC + Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; + Configurable SelectType{"SelectType", 0, "PID selection type"}; + + // Axis + ConfigurableAxis massAxis{"massAxis", {400, 0.2, 2.2}, "Invariant mass axis"}; + ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}, "Transverse momentum Binning"}; + ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 95.0, 100.0, 105.0, 110.0}, "Centrality Binning"}; void init(o2::framework::InitContext&) { - std::vector ptBinning = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, - 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, - 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}; std::vector lptBinning = {0, 5.0, 13.0, 20.0, 50.0, 1000.0}; - AxisSpec centAxis = {22, 0, 110}; - AxisSpec ptAxis = {ptBinning}; - AxisSpec massAxis = {400, 0.2, 2.2}; AxisSpec RTAxis = {3, 0, 3}; AxisSpec LptAxis = {lptBinning}; // Minimum leading hadron pT selection @@ -99,13 +109,14 @@ struct f0980analysis { AxisSpec EPqaAxis = {200, -constants::math::PI, constants::math::PI}; AxisSpec EPresAxis = {200, -2, 2}; - histos.add("hInvMass_f0980_US", "unlike invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); - histos.add("hInvMass_f0980_LSpp", "++ invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); - histos.add("hInvMass_f0980_LSmm", "-- invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); - + if (cfgFindRT) { + histos.add("hInvMass_f0980_US", "unlike invariant mass", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + histos.add("hInvMass_f0980_LSpp", "++ invariant mass", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + histos.add("hInvMass_f0980_LSmm", "-- invariant mass", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + } histos.add("hInvMass_f0980_US_EPA", "unlike invariant mass", {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, EPAxis}}); histos.add("hInvMass_f0980_LSpp_EPA", "++ invariant mass", @@ -152,19 +163,41 @@ struct f0980analysis { template bool SelTrack(const TrackType track) { - if (track.pt() < cfgMinPt) + if (std::abs(track.pt()) < cfgMinPt) return false; if (std::fabs(track.eta()) > cfgMaxEta) return false; - if (track.dcaXY() < cfgMinDCArToPVcut || track.dcaXY() > cfgMaxDCArToPVcut) + if (std::abs(track.dcaXY()) > cfgMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) + return false; + if (track.itsNCls() < cfgITScluster) + return false; + if (track.tpcNClsFound() < cfgTPCcluster) + return false; + if (track.tpcCrossedRowsOverFindableCls() < cfgRatioTPCRowsOverFindableCls) + return false; + if (track.itsChi2NCl() >= cfgITSChi2NCl) + return false; + if (track.tpcChi2NCl() >= cfgTPCChi2NCl) + return false; + if (cfgHasITS && !track.hasITS()) + return false; + if (cfgHasTPC && !track.hasTPC()) + return false; + if (cfgHasTOF && !track.hasTOF()) + return false; + if (cfgUseITSRefit && !track.passedITSRefit()) return false; - if (track.dcaZ() < cfgMinDCAzToPVcut || track.dcaZ() > cfgMaxDCAzToPVcut) + if (cfgUseTPCRefit && !track.passedTPCRefit()) + return false; + if (cfgPVContributor && !track.isPVContributor()) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cfgPVContributor && !track.isPVContributor()) + if (cfgGlobalTrack && !track.isGlobalTrack()) return false; return true; @@ -173,15 +206,17 @@ struct f0980analysis { template bool SelPion(const TrackType track) { - if (track.hasTOF() || !cfgUseTOF) { - if (std::fabs(track.tpcNSigmaPi()) > cfgMaxTPCStandalone) { + if (SelectType == 0) { + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) return false; - } - } else { - if (std::fabs(track.tpcNSigmaPi()) > cfgMaxTPC || - std::fabs(track.tofNSigmaPi()) > cfgMaxTOF) { + } + if (SelectType == 1) { + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion) + return false; + } + if (SelectType == 2) { + if (track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi() >= nsigmaCutCombinedPion * nsigmaCutCombinedPion) return false; - } } return true; } @@ -193,12 +228,15 @@ struct f0980analysis { double LHpt = 0.; double LHphi = 0.; double relPhi = 0.; - for (auto& trk : dTracks) { - if (trk.pt() > LHpt) { - LHpt = trk.pt(); - LHphi = trk.phi(); + if (cfgFindRT) { + for (auto& trk : dTracks) { + if (trk.pt() > LHpt) { + LHpt = trk.pt(); + LHphi = trk.phi(); + } } } + histos.fill(HIST("QA/EPhist"), collision.cent(), collision.evtPl()); histos.fill(HIST("QA/hEPResAB"), collision.cent(), collision.evtPlResAB()); histos.fill(HIST("QA/hEPResAC"), collision.cent(), collision.evtPlResBC()); @@ -207,7 +245,7 @@ struct f0980analysis { TLorentzVector Pion1, Pion2, Reco; for (auto& [trk1, trk2] : - combinations(CombinationsUpperIndexPolicy(dTracks, dTracks))) { + combinations(CombinationsStrictlyUpperIndexPolicy(dTracks, dTracks))) { if (trk1.index() == trk2.index()) { if (!SelTrack(trk1)) continue; @@ -235,8 +273,10 @@ struct f0980analysis { } if (trk1.sign() * trk2.sign() < 0) { - histos.fill(HIST("hInvMass_f0980_US"), Reco.M(), Reco.Pt(), - collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + if (cfgFindRT) { + histos.fill(HIST("hInvMass_f0980_US"), Reco.M(), Reco.Pt(), + collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + } histos.fill(HIST("hInvMass_f0980_US_EPA"), Reco.M(), Reco.Pt(), collision.cent(), relPhi); if constexpr (IsMC) { @@ -250,13 +290,17 @@ struct f0980analysis { collision.cent()); } } else if (trk1.sign() > 0 && trk2.sign() > 0) { - histos.fill(HIST("hInvMass_f0980_LSpp"), Reco.M(), Reco.Pt(), - collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + if (cfgFindRT) { + histos.fill(HIST("hInvMass_f0980_LSpp"), Reco.M(), Reco.Pt(), + collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + } histos.fill(HIST("hInvMass_f0980_LSpp_EPA"), Reco.M(), Reco.Pt(), collision.cent(), relPhi); } else if (trk1.sign() < 0 && trk2.sign() < 0) { - histos.fill(HIST("hInvMass_f0980_LSmm"), Reco.M(), Reco.Pt(), - collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + if (cfgFindRT) { + histos.fill(HIST("hInvMass_f0980_LSmm"), Reco.M(), Reco.Pt(), + collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + } histos.fill(HIST("hInvMass_f0980_LSmm_EPA"), Reco.M(), Reco.Pt(), collision.cent(), relPhi); } diff --git a/PWGLF/Tasks/Resonances/highmasslambda.cxx b/PWGLF/Tasks/Resonances/highmasslambda.cxx index 8b3a0bc6ade..c9b59e17180 100644 --- a/PWGLF/Tasks/Resonances/highmasslambda.cxx +++ b/PWGLF/Tasks/Resonances/highmasslambda.cxx @@ -79,7 +79,7 @@ struct highmasslambda { Configurable additionalEvSel{"additionalEvSel", true, "additionalEvSel"}; Configurable additionalEvSel2{"additionalEvSel2", false, "additionalEvSel2"}; Configurable fillDefault{"fillDefault", false, "fill Occupancy"}; - Configurable fillOccupancy{"fillOccupancy", true, "fill Occupancy"}; + Configurable cfgOccupancyCut{"cfgOccupancyCut", 2500, "Occupancy cut"}; Configurable fillDecayLength{"fillDecayLength", true, "fill decay length"}; Configurable fillPolarization{"fillPolarization", false, "fill polarization"}; Configurable fillRotation{"fillRotation", false, "fill rotation"}; @@ -90,7 +90,6 @@ struct highmasslambda { // proton track cut Configurable ispTdifferentialDCA{"ispTdifferentialDCA", true, "is pT differential DCA"}; Configurable isPVContributor{"isPVContributor", true, "is PV contributor"}; - Configurable rejectPID{"rejectPID", true, "Reject PID"}; Configurable confMinRot{"confMinRot", 5.0 * TMath::Pi() / 6.0, "Minimum of rotation"}; Configurable confMaxRot{"confMaxRot", 7.0 * TMath::Pi() / 6.0, "Maximum of rotation"}; Configurable confRapidity{"confRapidity", 0.8, "cut on Rapidity"}; @@ -108,10 +107,11 @@ struct highmasslambda { Configurable cfgCutDCAz{"cfgCutDCAz", 1.0f, "DCAz range for tracks"}; Configurable cfgITScluster{"cfgITScluster", 5, "Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; - Configurable ispTdepPID{"ispTdepPID", true, "pT dependent PID"}; + Configurable PIDstrategy{"PIDstrategy", 0, "0: TOF Veto, 1: TOF Veto opti, 2: TOF, 3: TOF loose 1, 4: TOF loose 2, 5: old pt dep"}; Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; - Configurable nsigmaCutTOF{"nsigmacutTOF", 3.0, "Value of the TOF Nsigma cut"}; - Configurable nsigmaCutTPCPre{"nsigmacutTPCPre", 5.0, "Value of the TPC Nsigma cut Pre filter"}; + Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "TPC TOF combined PID"}; + Configurable nsigmaCutTPCPre{"nsigmacutTPCPre", 3.0, "Value of the TPC Nsigma cut Pre filter"}; + Configurable kaonrejpar{"kaonrejpar", 1.0, "Kaon rej. par"}; // Configs for V0 Configurable ConfV0PtMin{"ConfV0PtMin", 0.f, "Minimum transverse momentum of V0"}; Configurable ConfV0DCADaughMax{"ConfV0DCADaughMax", 0.2f, "Maximum DCA between the V0 daughters"}; @@ -121,6 +121,8 @@ struct highmasslambda { Configurable cMaxV0DCA{"cMaxV0DCA", 0.2, "Maximum V0 DCA to PV"}; Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; Configurable cSigmaMassKs0{"cSigmaMassKs0", 0.006, "Sigma cut on KS0 mass"}; + Configurable cMinLambdaMass{"cMinLambdaMass", 2.18, "Minimum lambda mass"}; + Configurable cMaxLambdaMass{"cMaxLambdaMass", 2.42, "Maximum lambda mass"}; // config for V0 daughters Configurable ConfDaughEta{"ConfDaughEta", 0.8f, "V0 Daugh sel: max eta"}; Configurable ConfDaughPt{"ConfDaughPt", 0.1f, "V0 Daugh sel: min pt"}; @@ -154,7 +156,7 @@ struct highmasslambda { Filter pidFilter = nabs(aod::pidtpc::tpcNSigmaPr) < nsigmaCutTPCPre; using EventCandidates = soa::Filtered>; - using TrackCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; using AllTrackCandidates = soa::Join; using ResoV0s = aod::V0Datas; @@ -168,9 +170,9 @@ struct highmasslambda { { std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; // std::vector dcaBinning = {0.0, 0.0005, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.012, 0.014, 0.016, 0.02, 0.03, 0.05, 0.1, 0.5, 1.0}; - std::vector dcaBinning = {0.0, 0.0005, 0.001, 0.002, 0.003, 0.004, 0.006, 0.008, 0.01, 0.015, 0.02, 0.04, 0.08, 0.1, 0.3, 1.0}; - std::vector ptProtonBinning = {0.2, 0.3, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 100.0}; - std::vector ptLambdaBinning = {2.0, 3.0, 4.0, 5.0, 8.0, 16.0}; + std::vector dcaBinning = {0.0, 0.0005, 0.001, 0.0012, 0.0014, 0.0016, 0.002, 0.0025, 0.003, 0.004, 0.005, 0.006, 0.008, 0.01, 0.015, 0.02, 0.04, 0.05, 0.06, 0.08, 0.1, 0.3, 1.0}; + std::vector ptProtonBinning = {0.2, 0.3, 0.5, 0.6, 0.8, 1.2, 1.4, 1.6, 2.0, 3.0, 4.0, 6.0}; + std::vector ptLambdaBinning = {2.0, 3.0, 4.0, 5.0, 6.0}; const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; @@ -189,11 +191,10 @@ struct highmasslambda { AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; // AxisSpec ptProtonAxis = {16, 0.0, 8, "V0M (%)"}; AxisSpec dcaAxis = {dcaBinning, "DCAxy"}; - AxisSpec dcatoPVAxis = {50, 0.0, 0.4, "V0M (%)"}; + AxisSpec dcatoPVAxis = {50, 0.0, 0.5, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "occupancy"}; AxisSpec ptProtonAxis = {ptProtonBinning, "pT proton"}; - histos.add("hRejectPID", "hRejectPID", kTH1F, {{2, 0.0f, 2.0f}}); histos.add("hMomCorr", "hMomCorr", kTH3F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}, {8, 0.0f, 80.0f}}); histos.add("hInvMassKs0", "hInvMassKs0", kTH1F, {{200, 0.4f, 0.6f}}); histos.add("hV0Dca", "hV0Dca", kTH1F, {{2000, -1.0f, 1.0f}}); @@ -209,33 +210,42 @@ struct highmasslambda { histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{1000, -0.5f, 0.5f}}); histos.add("hDcaz", "Dcaz distribution", kTH1F, {{1000, -0.5f, 0.5f}}); histos.add("hNsigmaProtonTPCDiff", "Difference NsigmaProton NsigmaKaon TPC distribution", kTH3F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}, {80, 0.0f, 8.0f}}); - histos.add("hNsigmaProtonTPC", "NsigmaProton TPC distribution", kTH2F, {{100, -5.0f, 5.0f}, {80, 0.0f, 8.0f}}); - histos.add("hNsigmaProtonTOF", "NsigmaProton TOF distribution", kTH2F, {{100, -5.0f, 5.0f}, {80, 0.0f, 8.0f}}); + + histos.add("hNsigmaProtonElectronTPC", "NsigmaProton-Electron TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonPionTPC", "NsigmaProton-Pion TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonKaonTPC", "NsigmaProton-Kaon TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + + histos.add("hNsigmaProtonElectronTPC_afterPi", "NsigmaProton-Electron TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonPionTPC_afterPi", "NsigmaProton-Pion TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonKaonTPC_afterPi", "NsigmaProton-Kaon TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + + histos.add("hNsigmaProtonElectronTPC_afterEl", "NsigmaProton-Electron TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonPionTPC_afterEl", "NsigmaProton-Pion TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonKaonTPC_afterEl", "NsigmaProton-Kaon TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + + histos.add("hNsigmaProtonElectronTPC_afterKa", "NsigmaProton-Electron TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonPionTPC_afterKa", "NsigmaProton-Pion TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonKaonTPC_afterKa", "NsigmaProton-Kaon TPC distribution", kTH3F, {{60, -3.0f, 3.0f}, {200, -10.0f, 10.0f}, {60, 0.0f, 6.0f}}); + + histos.add("hNsigmaProtonTPC", "NsigmaProton TPC distribution", kTH2F, {{100, -5.0f, 5.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonTOF", "NsigmaProton TOF distribution", kTH2F, {{1000, -50.0f, 50.0f}, {60, 0.0f, 6.0f}}); + histos.add("hNsigmaProtonTOFPre", "NsigmaProton TOF distribution Pre sel", kTH2F, {{1000, -50.0f, 50.0f}, {60, 0.0f, 6.0f}}); histos.add("hMassvsDecaySum", "hMassvsDecaySum", kTH2F, {thnAxisInvMass, thnAxisDCASum}); histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, phiAxis, occupancyAxis}); histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, phiAxis, occupancyAxis}); histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, phiAxis, occupancyAxis}); histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, phiAxis, occupancyAxis}); histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, phiAxis, occupancyAxis}); + if (fillDefault) { - if (fillDecayLength) { - histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, thnAxisDCASum}); - histos.add("hSparseV2SAMixedEvent_V2", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, thnAxisDCASum}); - histos.add("hSparseV2SASameEventRotational_V2", "hSparseV2SASameEventRotational_V2", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, thnAxisDCASum}); - } - histos.add("hSparseV2SASameEvent_V2_new", "hSparseV2SASameEvent_V2_new", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis}); - histos.add("hSparseV2SAMixedEvent_V2_new", "hSparseV2SAMixedEvent_V2_new", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis}); - histos.add("hSparseV2SASameEventRotational_V2_new", "hSparseV2SASameEventRotational_V2_new", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis}); + histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis}); + histos.add("hSparseV2SASameEventRotational_V2", "hSparseV2SASameEventRotational", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis}); + histos.add("hSparseV2SAMixedEvent_V2", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis}); } - if (fillOccupancy) { - if (fillDecayLength) { - histos.add("hSparseV2SASameEvent_V2_occupancy", "hSparseV2SASameEvent_V2_occupancy", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, thnAxisDCASum, dcaAxis, occupancyAxis}); - histos.add("hSparseV2SASameEventRotational_V2_occupancy", "hSparseV2SASameEventRotational_V2_occupancy", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, thnAxisDCASum, dcaAxis, occupancyAxis}); - histos.add("hSparseV2SAMixedEvent_V2_occupancy", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, thnAxisDCASum, dcaAxis, occupancyAxis}); - } - histos.add("hSparseV2SASameEvent_V2_new_occupancy", "hSparseV2SASameEvent_V2_new_occupancy", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis, occupancyAxis}); - histos.add("hSparseV2SASameEventRotational_V2_new_occupancy", "hSparseV2SASameEventRotational_V2_new_occupancy", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis, occupancyAxis}); - histos.add("hSparseV2SAMixedEvent_V2_new_occupancy", "hSparseV2SAMixedEvent_V2_new", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcaAxis, ptProtonAxis, occupancyAxis}); + if (fillDecayLength) { + histos.add("hSparseV2SASameEvent_V2_dcatopv", "hSparseV2SASameEvent_V2_dcatopv", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcatoPVAxis, ptProtonAxis}); + histos.add("hSparseV2SASameEventRotational_V2_dcatopv", "hSparseV2SASameEventRotational_V2_dcatopv", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcatoPVAxis, ptProtonAxis}); + histos.add("hSparseV2SAMixedEvent_V2_dcatopv", "hSparseV2SAMixedEvent_V2_dcatopv", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSP, dcatoPVAxis, ptProtonAxis}); } if (fillPolarization) { histos.add("hSparseV2SASameEventplus_SA", "hSparseV2SASameEventplus_SA", HistType::kTHnSparseF, {thnAxisInvMass, ptLambdaBinning, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); @@ -264,10 +274,10 @@ struct highmasslambda { template bool selectionTrack(const T& candidate) { - if (isPVContributor && !(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster)) { + if (isPVContributor && !(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster && candidate.itsNClsInnerBarrel() >= 1)) { return false; } - if (!isPVContributor && !(candidate.isGlobalTrackWoDCA() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster)) { + if (!isPVContributor && !(candidate.isGlobalTrackWoDCA() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster && candidate.itsNClsInnerBarrel() >= 1)) { return false; } @@ -313,106 +323,172 @@ struct highmasslambda { } template - bool selectionPIDpTdependent(const T& candidate) + bool rejectPi(const T& candidate) { - if (candidate.p() <= 0.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 5.0) { - return true; + if (candidate.tpcInnerParam() > 0.9 && candidate.tpcInnerParam() < 1.0 && candidate.tpcNSigmaPi() < 6.0) { + return false; } - if (candidate.p() > 0.5 && candidate.p() <= 0.8 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { - return true; + if (candidate.tpcInnerParam() > 1.0 && candidate.tpcInnerParam() < 1.1 && candidate.tpcNSigmaPi() < 4.0) { + return false; } - if (candidate.p() > 0.8 && candidate.hasTOF() && TMath::Sqrt(candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < nsigmaCutTOF) { - return true; + if (candidate.tpcInnerParam() > 1.1 && candidate.tpcInnerParam() < 1.2 && candidate.tpcNSigmaPi() < 3.0) { + return false; } - return false; + if (candidate.tpcInnerParam() > 1.2 && candidate.tpcInnerParam() < 1.4 && candidate.tpcNSigmaPi() < 1.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.4 && candidate.tpcInnerParam() < 1.5 && candidate.tpcNSigmaPi() < 0.5) { + return false; + } + return true; } template - bool selectionPID(const T& candidate) + bool rejectEl(const T& candidate) { - if (candidate.hasTOF()) { - if (candidate.pt() < 0.8 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && TMath::Abs(candidate.tofNSigmaPr()) < 10.0) { - return true; - } - if (candidate.pt() >= 0.8 && candidate.pt() < 3.0 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && TMath::Abs(candidate.tofNSigmaPr()) < 3.0) { - return true; - } - if (candidate.pt() >= 3.0 && candidate.pt() < 4.0 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && candidate.tofNSigmaPr() > -2.0 && candidate.tofNSigmaPr() < 3.0) { - return true; - } - if (candidate.pt() >= 4.0 && candidate.pt() < 5.0 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && candidate.tofNSigmaPr() > -1.5 && candidate.tofNSigmaPr() < 3.0) { - return true; - } - if (candidate.pt() >= 5.0 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && candidate.tofNSigmaPr() > -1.5 && candidate.tofNSigmaPr() < 3.0) { - return true; - } + + if (candidate.tpcInnerParam() > 0.7 && candidate.tpcInnerParam() < 0.8 && candidate.tpcNSigmaEl() < 2.0) { + return false; } - if (!candidate.hasTOF()) { - if (candidate.pt() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { - return true; - } - if (candidate.pt() >= 0.7 && candidate.pt() < 0.8 && candidate.tpcNSigmaPr() > -2.0 && candidate.tpcNSigmaPr() < 3.0) { - return true; - } - if (candidate.pt() >= 0.8 && candidate.tpcNSigmaPr() > -1.5 && candidate.tpcNSigmaPr() < 3.0) { - return true; - } + if (candidate.tpcInnerParam() > 0.8 && candidate.tpcInnerParam() < 0.9 && candidate.tpcNSigmaEl() < 0.0) { + return false; } - return false; + if (candidate.tpcInnerParam() > 0.9 && candidate.tpcInnerParam() < 1.0 && candidate.tpcNSigmaEl() < -1.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.0 && candidate.tpcInnerParam() < 1.1 && candidate.tpcNSigmaEl() < -2.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.1 && candidate.tpcInnerParam() < 1.2 && candidate.tpcNSigmaEl() < -3.0) { + return false; + } + + return true; } template - bool selectionPIDNew(const T& candidate) + bool rejectKa(const T& candidate) { - if (candidate.pt() < 0.7 && !candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { - return true; + if (candidate.tpcInnerParam() > 0.7 && candidate.tpcInnerParam() < 0.8 && candidate.tpcNSigmaKa() < 7.5) { + return false; } - if (candidate.pt() >= 0.7 && !candidate.hasTOF() && candidate.pt() < 0.8 && candidate.tpcNSigmaPr() > -2.0 && candidate.tpcNSigmaPr() < 3.0) { - return true; + if (candidate.tpcInnerParam() > 0.8 && candidate.tpcInnerParam() < 0.9 && candidate.tpcNSigmaKa() < 6.0) { + return false; } - if (candidate.pt() < 0.8 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && TMath::Abs(candidate.tofNSigmaPr()) < 10.0) { - return true; + if (candidate.tpcInnerParam() > 0.9 && candidate.tpcInnerParam() < 1.1 && candidate.tpcNSigmaKa() < 5.0) { + return false; } - if (candidate.pt() >= 0.8 && candidate.pt() < 1.0 && !candidate.hasTOF() && candidate.tpcNSigmaPr() > -1.5 && candidate.tpcNSigmaPr() < 3.0) { - return true; + if (candidate.tpcInnerParam() > 1.1 && candidate.tpcInnerParam() < 1.2 && candidate.tpcNSigmaKa() < 3.5) { + return false; } - if (candidate.pt() >= 0.8 && candidate.pt() < 3.0 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && TMath::Abs(candidate.tofNSigmaPr()) < 3.0) { - return true; + if (candidate.tpcInnerParam() > 1.2 && candidate.tpcInnerParam() < 1.4 && candidate.tpcNSigmaKa() < 3.0) { + return false; } - if (candidate.pt() >= 3.0 && candidate.pt() < 4.0 && candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0 && candidate.tofNSigmaPr() > -2.0 && candidate.tofNSigmaPr() < 4.0) { - return true; + if (candidate.tpcInnerParam() > 1.4 && candidate.tpcInnerParam() < 1.5 && candidate.tpcNSigmaKa() < 2.5) { + return false; } - if (candidate.pt() >= 4.0 && candidate.pt() < 5.0 && candidate.hasTOF() && candidate.tofNSigmaPr() > -2.0) { + return true; + } + + // TPC TOF + template + bool selectionPID1(const T& candidate) + { + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { return true; } - if (candidate.pt() >= 5.0 && candidate.hasTOF() && candidate.tofNSigmaPr() > -1.5) { + if (candidate.tpcInnerParam() >= 0.7) { + // printf("I am here: %.3f\n", candidate.tpcInnerParam()); + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + // printf("combine PIDA: %.3f\n", combinedPID); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + if (!candidate.hasTOF()) { + if (candidate.tpcInnerParam() < 1.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 1.5 && candidate.tpcNSigmaPr() > -2.0 && candidate.tpcNSigmaPr() < 2.0) { + return true; + } + } + } + return false; + } + + // TOF Veto + template + bool selectionPID2(const T& candidate) + { + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { return true; } + if (candidate.tpcInnerParam() >= 0.7) { + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + } return false; } + // TOF veto loose template - bool RejectPion(const T& candidate) + bool selectionPID3(const T& candidate) { - if (candidate.p() > 1.0 && candidate.p() < 2.0 && !candidate.hasTOF() && candidate.tpcNSigmaPi() < 2) { - return false; + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; } - return true; + if (candidate.tpcInnerParam() >= 0.7) { + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + if (!candidate.hasTOF()) { + if (candidate.tpcInnerParam() < 1.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + } + } + return false; } + // TOF veto very loose template - bool RejectKaon(const T& candidate) + bool selectionPID4(const T& candidate) { - if (candidate.p() > 1.0 && candidate.p() < 2.0 && !candidate.hasTOF() && candidate.tpcNSigmaKa() < 2) { - return false; + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; } - return true; + if (candidate.tpcInnerParam() >= 0.7) { + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + if (!candidate.hasTOF()) { + if (candidate.tpcInnerParam() < 1.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 1.5 && candidate.tpcInnerParam() < 1.8 && candidate.tpcNSigmaPr() > -1.5 && candidate.tpcNSigmaPr() < 2.0) { + return true; + } + } + } + return false; } template bool SelectionV0(Collision const& collision, V0 const& candidate) { - if (fabs(candidate.dcav0topv()) > cMaxV0DCA) { + if (TMath::Abs(candidate.dcav0topv()) > cMaxV0DCA) { return false; } const float pT = candidate.pt(); @@ -440,7 +516,7 @@ struct highmasslambda { if (tranRad > ConfV0TranRadV0Max) { return false; } - if (fabs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + if (TMath::Abs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { return false; } return true; @@ -459,19 +535,19 @@ struct highmasslambda { if (charge > 0 && sign < 0) { return false; } - if (std::abs(eta) > ConfDaughEta) { + if (TMath::Abs(eta) > ConfDaughEta) { return false; } - if (std::abs(pt) < ConfDaughPt) { + if (TMath::Abs(pt) < ConfDaughPt) { return false; } if (tpcNClsF < ConfDaughTPCnclsMin) { return false; } - if (std::abs(dcaXY) < ConfDaughDCAMin) { + if (TMath::Abs(dcaXY) < ConfDaughDCAMin) { return false; } - if (std::abs(track.tpcNSigmaPi()) > ConfDaughPIDCuts) { + if (TMath::Abs(track.tpcNSigmaPi()) > ConfDaughPIDCuts) { return false; } return true; @@ -494,7 +570,7 @@ struct highmasslambda { ConfigurableAxis axisEPAngle{"axisEPAngle", {1, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; using BinningTypeVertexContributor = ColumnBinningPolicy; - ROOT::Math::PxPyPzMVector Lambdac, Proton, Kshort, LambdacRot, ProtonRot, fourVecDauCM; + ROOT::Math::PxPyPzMVector Lambdac, Proton, Kshort, LambdacRot, KshortRot, fourVecDauCM; ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY, eventplaneVec, eventplaneVecNorm, beamvector; double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); // FIXME: Get from the common header double massPr = TDatabasePDG::Instance()->GetParticle(kProton)->Mass(); // FIXME: Get from the common header @@ -551,28 +627,56 @@ struct highmasslambda { if (!selectionTrack(track1)) { continue; } + if (track1.hasTOF()) { + histos.fill(HIST("hNsigmaProtonTOFPre"), track1.tofNSigmaPr(), track1.pt()); + } + if (!track1.hasTOF()) { + histos.fill(HIST("hNsigmaProtonElectronTPC"), track1.tpcNSigmaPr(), track1.tpcNSigmaEl(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonPionTPC"), track1.tpcNSigmaPr(), track1.tpcNSigmaPi(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonKaonTPC"), track1.tpcNSigmaPr(), track1.tpcNSigmaKa(), track1.tpcInnerParam()); + if (!rejectPi(track1)) { + continue; + } + histos.fill(HIST("hNsigmaProtonElectronTPC_afterPi"), track1.tpcNSigmaPr(), track1.tpcNSigmaEl(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonPionTPC_afterPi"), track1.tpcNSigmaPr(), track1.tpcNSigmaPi(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonKaonTPC_afterPi"), track1.tpcNSigmaPr(), track1.tpcNSigmaKa(), track1.tpcInnerParam()); + if (!rejectEl(track1)) { + continue; + } + histos.fill(HIST("hNsigmaProtonElectronTPC_afterEl"), track1.tpcNSigmaPr(), track1.tpcNSigmaEl(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonPionTPC_afterEl"), track1.tpcNSigmaPr(), track1.tpcNSigmaPi(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonKaonTPC_afterEl"), track1.tpcNSigmaPr(), track1.tpcNSigmaKa(), track1.tpcInnerParam()); + if (!rejectKa(track1)) { + continue; + } + histos.fill(HIST("hNsigmaProtonElectronTPC_afterKa"), track1.tpcNSigmaPr(), track1.tpcNSigmaEl(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonPionTPC_afterKa"), track1.tpcNSigmaPr(), track1.tpcNSigmaPi(), track1.tpcInnerParam()); + histos.fill(HIST("hNsigmaProtonKaonTPC_afterKa"), track1.tpcNSigmaPr(), track1.tpcNSigmaKa(), track1.tpcInnerParam()); + } + // PID check - if (ispTdepPID && !selectionPIDNew(track1)) { + if (PIDstrategy == 0 && !selectionPID1(track1)) { continue; } - if (!ispTdepPID && !selectionPID(track1)) { + if (PIDstrategy == 1 && !selectionPID2(track1)) { continue; } - if (!ispTdepPID && rejectPID && !RejectPion(track1)) { - histos.fill(HIST("hRejectPID"), 0.5); + if (PIDstrategy == 2 && !selectionPID3(track1)) { continue; } - if (!ispTdepPID && rejectPID && !RejectKaon(track1)) { - histos.fill(HIST("hRejectPID"), 1.5); + if (PIDstrategy == 3 && !selectionPID4(track1)) { continue; } + histos.fill(HIST("hMomCorr"), track1.p() / track1.sign(), track1.p() - track1.tpcInnerParam(), centrality); histos.fill(HIST("hEta"), track1.eta()); histos.fill(HIST("hDcaxy"), track1.dcaXY()); histos.fill(HIST("hDcaz"), track1.dcaZ()); histos.fill(HIST("hNsigmaProtonTPCDiff"), track1.tpcNSigmaPr(), track1.tpcNSigmaKa(), track1.pt()); histos.fill(HIST("hNsigmaProtonTPC"), track1.tpcNSigmaPr(), track1.pt()); - histos.fill(HIST("hNsigmaProtonTOF"), track1.tofNSigmaPr(), track1.pt()); + if (track1.hasTOF()) { + histos.fill(HIST("hNsigmaProtonTOF"), track1.tofNSigmaPr(), track1.pt()); + } auto track1ID = track1.globalIndex(); for (auto v0 : V0s) { if (!SelectionV0(collision, v0)) { @@ -602,11 +706,8 @@ struct highmasslambda { } firstprimarytrack = firstprimarytrack + 1; Proton = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPr); - Kshort = ROOT::Math::PxPyPzMVector(v0.px(), v0.py(), v0.pz(), massK0s); + Kshort = ROOT::Math::PxPyPzMVector(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); Lambdac = Proton + Kshort; - if (TMath::Abs(Lambdac.Rapidity()) > confRapidity) { - continue; - } auto phiminuspsi = GetPhiInRange(Lambdac.Phi() - psiFT0C); if (useSP) { @@ -620,36 +721,29 @@ struct highmasslambda { dcasum = anglesign * (v0.dcav0topv()) - track1.dcaXY(); } if (!useSignDCAV0) { - dcasum = TMath::Sqrt((track1.dcaXY() + (v0.dcav0topv())) * (track1.dcaXY() + (v0.dcav0topv()))); + dcasum = v0.dcav0topv() - track1.dcaXY(); } - // auto diffangle = Proton.Phi() - Lambdac.Phi(); - // auto decaylength = std::abs((track1.dcaXY() / TMath::Sin(diffangle)) / (Lambdac.P() / 2.286)); - // auto dcasum = TMath::Sqrt(track1.dcaXY() * track1.dcaXY() + v0.dcav0topv() * v0.dcav0topv()); histos.fill(HIST("hMassvsDecaySum"), Lambdac.M(), dcasum); - if (fillDefault && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { - if (fillDecayLength) { - histos.fill(HIST("hSparseV2SASameEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, dcasum); + if (occupancy < cfgOccupancyCut && Lambdac.M() > cMinLambdaMass && Lambdac.M() <= cMaxLambdaMass && TMath::Abs(Lambdac.Rapidity()) < confRapidity && Lambdac.Pt() > 2.0 && Lambdac.Pt() <= 6.0) { + if (fillDefault) { + histos.fill(HIST("hSparseV2SASameEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, TMath::Abs(track1.dcaXY()), Proton.Pt()); } - histos.fill(HIST("hSparseV2SASameEvent_V2_new"), Lambdac.M(), Lambdac.Pt(), v2, std::abs(track1.dcaXY()), Proton.Pt()); - } - if (fillOccupancy && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { if (fillDecayLength) { - histos.fill(HIST("hSparseV2SASameEvent_V2_occupancy"), Lambdac.M(), Lambdac.Pt(), v2, dcasum, std::abs(track1.dcaXY()), occupancy); + histos.fill(HIST("hSparseV2SASameEvent_V2_dcatopv"), Lambdac.M(), Lambdac.Pt(), v2, v0.dcav0topv(), Proton.Pt()); } - histos.fill(HIST("hSparseV2SASameEvent_V2_new_occupancy"), Lambdac.M(), Lambdac.Pt(), v2, std::abs(track1.dcaXY()), Proton.Pt(), occupancy); } + if (fillRotation) { for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { auto anglestart = confMinRot; auto angleend = confMaxRot; - // auto anglestep = nrotbkg * (TMath::Pi() / nBkgRotations); auto anglestep = (angleend - anglestart) / (1.0 * (nBkgRotations - 1)); auto rotangle = anglestart + nrotbkg * anglestep; histos.fill(HIST("hRotation"), rotangle); - auto rotProtonPx = track1.px() * std::cos(rotangle) - track1.py() * std::sin(rotangle); - auto rotProtonPy = track1.px() * std::sin(rotangle) + track1.py() * std::cos(rotangle); - ProtonRot = ROOT::Math::PxPyPzMVector(rotProtonPx, rotProtonPy, track1.pz(), massPr); - LambdacRot = ProtonRot + Kshort; + auto rotKaonPx = Kshort.px() * std::cos(rotangle) - Kshort.py() * std::sin(rotangle); + auto rotKaonPy = Kshort.px() * std::sin(rotangle) + Kshort.py() * std::cos(rotangle); + KshortRot = ROOT::Math::PxPyPzMVector(rotKaonPx, rotKaonPy, Kshort.pz(), massK0s); + LambdacRot = Proton + KshortRot; auto phiminuspsiRot = GetPhiInRange(LambdacRot.Phi() - psiFT0C); if (useSP) { v2Rot = TMath::Cos(2.0 * phiminuspsiRot) * QFT0C; @@ -657,30 +751,26 @@ struct highmasslambda { if (!useSP) { v2Rot = TMath::Cos(2.0 * phiminuspsiRot); } - // auto diffangleRot = ProtonRot.Phi() - LambdacRot.Phi(); - // auto decaylengthRot = std::abs((track1.dcaXY() / TMath::Sin(diffangleRot)) / (Lambdac.P() / 2.286)); - if (fillDefault && LambdacRot.M() > 2.18 && LambdacRot.M() <= 2.42) { - if (fillDecayLength) { - histos.fill(HIST("hSparseV2SASameEventRotational_V2"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, dcasum); + + if (occupancy < cfgOccupancyCut && LambdacRot.M() > cMinLambdaMass && LambdacRot.M() <= cMaxLambdaMass && TMath::Abs(LambdacRot.Rapidity()) < confRapidity && LambdacRot.Pt() > 2.0 && LambdacRot.Pt() <= 6.0) { + if (fillDefault) { + histos.fill(HIST("hSparseV2SASameEventRotational_V2"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, TMath::Abs(track1.dcaXY()), Proton.Pt()); } - histos.fill(HIST("hSparseV2SASameEventRotational_V2_new"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, std::abs(track1.dcaXY()), Proton.Pt()); - } - if (fillOccupancy && LambdacRot.M() > 2.18 && LambdacRot.M() <= 2.42) { if (fillDecayLength) { - histos.fill(HIST("hSparseV2SASameEventRotational_V2_occupancy"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, dcasum, std::abs(track1.dcaXY()), occupancy); + histos.fill(HIST("hSparseV2SASameEventRotational_V2_dcatopv"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, v0.dcav0topv(), Proton.Pt()); } - histos.fill(HIST("hSparseV2SASameEventRotational_V2_new_occupancy"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, std::abs(track1.dcaXY()), Proton.Pt(), occupancy); } } } - ROOT::Math::Boost boost{Lambdac.BoostToCM()}; - fourVecDauCM = boost(Kshort); - threeVecDauCM = fourVecDauCM.Vect(); - threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); - beamvector = ROOT::Math::XYZVector(0, 0, 1); - auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); - auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); if (fillPolarization) { + ROOT::Math::Boost boost{Lambdac.BoostToCM()}; + fourVecDauCM = boost(Kshort); + threeVecDauCM = fourVecDauCM.Vect(); + threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); + beamvector = ROOT::Math::XYZVector(0, 0, 1); + auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); + auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + if (track1.sign() > 0) { histos.fill(HIST("hSparseV2SASameEventplus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); histos.fill(HIST("hSparseV2SASameEventplus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); @@ -723,18 +813,38 @@ struct highmasslambda { auto centrality = collision1.centFT0C(); auto psiFT0C = collision1.psiFT0C(); auto QFT0C = collision1.qFT0C(); - int occupancy = collision1.trackOccupancyInTimeRange(); + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision1.trackOccupancyInTimeRange(); for (auto& [track1, v0] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (!selectionTrack(track1)) { continue; } + if (!track1.hasTOF()) { + if (!rejectPi(track1)) { + continue; + } + if (!rejectEl(track1)) { + continue; + } + if (!rejectKa(track1)) { + continue; + } + } + // PID check - if (ispTdepPID && !selectionPIDNew(track1)) { + if (PIDstrategy == 0 && !selectionPID1(track1)) { + continue; + } + if (PIDstrategy == 1 && !selectionPID2(track1)) { + continue; + } + if (PIDstrategy == 2 && !selectionPID3(track1)) { continue; } - if (!ispTdepPID && !selectionPID(track1)) { + if (PIDstrategy == 3 && !selectionPID4(track1)) { continue; } + if (!SelectionV0(collision2, v0)) { continue; } @@ -746,10 +856,12 @@ struct highmasslambda { if (!isSelectedV0Daughter(negtrack, -1)) { continue; } - Proton = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPr); - Kshort = ROOT::Math::PxPyPzMVector(v0.px(), v0.py(), v0.pz(), massK0s); + Kshort = ROOT::Math::PxPyPzMVector(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); Lambdac = Proton + Kshort; + if (Lambdac.Pt() > 6.0 || Lambdac.Pt() < 2.0) { + continue; + } if (TMath::Abs(Lambdac.Rapidity()) > confRapidity) { continue; } @@ -767,31 +879,26 @@ struct highmasslambda { dcasum = anglesign * (v0.dcav0topv()) - track1.dcaXY(); } if (!useSignDCAV0) { - dcasum = TMath::Sqrt((track1.dcaXY() + (v0.dcav0topv())) * (track1.dcaXY() + (v0.dcav0topv()))); + dcasum = v0.dcav0topv() - track1.dcaXY(); } - // auto diffangle = Proton.Phi() - Lambdac.Phi(); - // auto decaylength = std::abs((track1.dcaXY() / TMath::Sin(diffangle)) / (Lambdac.P() / 2.286)); - // auto dcasum = TMath::Sqrt(track1.dcaXY() * track1.dcaXY() + v0.dcav0topv() * v0.dcav0topv()); - if (fillDefault && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { - if (fillDecayLength) { - histos.fill(HIST("hSparseV2SAMixedEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, dcasum); + + if (occupancy1 < cfgOccupancyCut && occupancy2 < cfgOccupancyCut && Lambdac.M() > cMinLambdaMass && Lambdac.M() <= cMaxLambdaMass && TMath::Abs(Lambdac.Rapidity()) < confRapidity && Lambdac.Pt() > 2.0 && Lambdac.Pt() <= 6.0) { + if (fillDefault) { + histos.fill(HIST("hSparseV2SAMixedEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, TMath::Abs(track1.dcaXY()), Proton.Pt()); } - histos.fill(HIST("hSparseV2SAMixedEvent_V2_new"), Lambdac.M(), Lambdac.Pt(), v2, std::abs(track1.dcaXY()), Proton.Pt()); - } - if (fillOccupancy && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { if (fillDecayLength) { - histos.fill(HIST("hSparseV2SAMixedEvent_V2_occupancy"), Lambdac.M(), Lambdac.Pt(), v2, dcasum, std::abs(track1.dcaXY()), occupancy); + histos.fill(HIST("hSparseV2SAMixedEvent_V2_dcatopv"), Lambdac.M(), Lambdac.Pt(), v2, v0.dcav0topv(), Proton.Pt()); } - histos.fill(HIST("hSparseV2SAMixedEvent_V2_new_occupancy"), Lambdac.M(), Lambdac.Pt(), v2, std::abs(track1.dcaXY()), Proton.Pt(), occupancy); - } - ROOT::Math::Boost boost{Lambdac.BoostToCM()}; - fourVecDauCM = boost(Kshort); - threeVecDauCM = fourVecDauCM.Vect(); - threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); - beamvector = ROOT::Math::XYZVector(0, 0, 1); - auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); - auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + } if (fillPolarization) { + ROOT::Math::Boost boost{Lambdac.BoostToCM()}; + fourVecDauCM = boost(Kshort); + threeVecDauCM = fourVecDauCM.Vect(); + threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); + beamvector = ROOT::Math::XYZVector(0, 0, 1); + auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); + auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + if (track1.sign() > 0) { histos.fill(HIST("hSparseV2SAMixedEventplus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); histos.fill(HIST("hSparseV2SAMixedEventplus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); diff --git a/PWGLF/Tasks/Resonances/highmasslambdasvx.cxx b/PWGLF/Tasks/Resonances/highmasslambdasvx.cxx new file mode 100644 index 00000000000..d6405483d13 --- /dev/null +++ b/PWGLF/Tasks/Resonances/highmasslambdasvx.cxx @@ -0,0 +1,927 @@ +// Copyright 2019-2020 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. +// Phi meson spin alignment task +// sourav.kundu@cern.ch + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TRandom3.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" +#include "TF1.h" + +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "Framework/runDataProcessing.h" +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/Core/TrackSelection.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/V0.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +struct highmasslambdasvx { + + int mRunNumber; + int multEstimator; + float d_bz; + Service ccdb; + Service pdg; + + o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + int runNumber{0}; + double bz = 0.; + + // CCDB options + // Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + // Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + // Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + // Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + // Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + + // fill output + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; + Configurable useSP{"useSP", false, "useSP"}; + Configurable additionalEvSel{"additionalEvSel", true, "additionalEvSel"}; + Configurable additionalEvSel2{"additionalEvSel2", false, "additionalEvSel2"}; + // events + Configurable cnfabsdca{"cnfabsdca", false, "Use Abs DCA for secondary vertex fitting"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 50.0f, "Accepted maximum Centrality"}; + Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 30.0f, "Accepted minimum Centrality"}; + // proton track cut + Configurable useDecayLengthxy{"useDecayLengthxy", true, "use decay length xy"}; + Configurable ispTdifferentialDCA{"ispTdifferentialDCA", true, "is pT differential DCA"}; + Configurable confMinRot{"confMinRot", 5.0 * TMath::Pi() / 6.0, "Minimum of rotation"}; + Configurable confMaxRot{"confMaxRot", 7.0 * TMath::Pi() / 6.0, "Maximum of rotation"}; + Configurable confRapidity{"confRapidity", 0.8, "cut on Rapidity"}; + Configurable cfgCutPT{"cfgCutPT", 0.3, "PT cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + Configurable cfgCutDCAxymin1{"cfgCutDCAxymin1", 0.005f, "Minimum DCAxy range for tracks pt 0 to 0.5"}; + Configurable cfgCutDCAxymin2{"cfgCutDCAxymin2", 0.003f, "Minimum DCAxy range for tracks pt 0.5 to 1"}; + Configurable cfgCutDCAxymin3{"cfgCutDCAxymin3", 0.003f, "Minimum DCAxy range for tracks pt 1.0 to 1.5"}; + Configurable cfgCutDCAxymin4{"cfgCutDCAxymin4", 0.002f, "Minimum DCAxy range for tracks pt 1.5 to 2.0"}; + Configurable cfgCutDCAxymin5{"cfgCutDCAxymin5", 0.001f, "Minimum DCAxy range for tracks pt 2.0 to 2.5"}; + Configurable cfgCutDCAxymin6{"cfgCutDCAxymin6", 0.0003f, "Minimum DCAxy range for tracks pt 2.5 to 3.0"}; + Configurable cfgCutDCAxymin7{"cfgCutDCAxymin7", 0.0003f, "Minimum DCAxy range for tracks pt 3.0 to 4.0"}; + Configurable cfgCutDCAxymin8{"cfgCutDCAxymin8", 0.0003f, "Minimum DCAxy range for tracks pt 4.0 to 10.0"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 0.1f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 1.0f, "DCAz range for tracks"}; + Configurable cfgITScluster{"cfgITScluster", 5, "Number of ITS cluster"}; + Configurable cfgITSclusterInnerlayer{"cfgITSclusterInnerlayer", 1, "Minimum Number of ITS cluster in inner barrel"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable PIDstrategy{"PIDstrategy", 0, "0: TOF Veto, 1: TOF Veto opti, 2: TOF, 3: TOF loose 1, 4: TOF loose 2, 5: old pt dep"}; + Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "TPC TOF combined PID"}; + Configurable nsigmaCutTPCPre{"nsigmacutTPCPre", 3.0, "Value of the TPC Nsigma cut Pre filter"}; + // Configs for V0 + Configurable ConfV0DCADaughMax{"ConfV0DCADaughMax", 0.2f, "Maximum DCA between the V0 daughters"}; + Configurable ConfV0CPAMin{"ConfV0CPAMin", 0.9998f, "Minimum CPA of V0"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 0.1, "Maximum V0 DCA to PV"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; + Configurable cSigmaMassKs0{"cSigmaMassKs0", 0.006, "Sigma cut on KS0 mass"}; + Configurable cMinLambdaMass{"cMinLambdaMass", 2.18, "Minimum lambda mass"}; + Configurable cMaxLambdaMass{"cMaxLambdaMass", 2.42, "Maximum lambda mass"}; + + // config for V0 daughters + Configurable ConfDaughPt{"ConfDaughPt", 0.1f, "V0 Daugh sel: min pt"}; + Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 50.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable ConfDaughDCAMin{"ConfDaughDCAMin", 0.08f, "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; + Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for KS0 daughters"}; + // Fill strategy + // Configurable cfgSelectDaughterTopology{"cfgSelectDaughterTopology", 2, "Select daughter for topology"}; + // Mixed event + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 1, "Number of mixed events per event"}; + /// activate rotational background + Configurable nBkgRotations{"nBkgRotations", 9, "Number of rotated copies (background) per each original candidate"}; + Configurable cutchi2PCA{"cutchi2PCA", 0.1f, "cut on chi2PCA"}; + // THnsparse bining + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {60, 2.15, 2.45}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisV2{"configThnAxisV2", {80, -1, 1}, "V2"}; + ConfigurableAxis configThnAxisSA{"configThnAxisSA", {100, -1, 1}, "SA"}; + ConfigurableAxis configThnAxisPhiminusPsi{"configThnAxisPhiminusPsi", {6, 0.0, TMath::Pi()}, "#phi - #psi"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {1, 30., 50}, "Centrality"}; + ConfigurableAxis configThnAxisDecayLength{"configThnAxisDecayLength", {60, 0.0, 0.06}, "Decay length"}; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); + Filter dcaCutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter pidFilter = nabs(aod::pidtpc::tpcNSigmaPr) < nsigmaCutTPCPre; + + using EventCandidates = soa::Filtered>; + // using TrackCandidates = soa::Filtered>; + // using AllTrackCandidates = soa::Join; + + using TrackCandidates = soa::Filtered>; + using AllTrackCandidates = soa::Join; + using ResoV0s = soa::Join; + + SliceCache cache; + // Partition posTracks = aod::track::signed1Pt > cfgCutCharge; + // Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; + std::vector dcaBinning = {0.0, 0.0005, 0.001, 0.002, 0.003, 0.004, 0.006, 0.3}; + std::vector ptProtonBinning = {0.0, 0.3, 0.5, 0.8, 1.2, 6.0}; + std::vector ptLambdaBinning = {2.0, 3.0, 4.0, 5.0, 6.0}; + + AxisSpec phiAxis = {500, -6.28, 6.28, "phi"}; + AxisSpec decaylengthAxis = {configThnAxisDecayLength, "decaylength"}; + AxisSpec resAxis = {1000, -10, 10, "Res"}; + AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; + const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisV2{configThnAxisV2, "V2"}; + const AxisSpec thnAxisCentrality{configThnAxisCentrality, "Centrality (%)"}; + const AxisSpec thnAxisPhiminusPsi{configThnAxisPhiminusPsi, "#phi - #psi"}; + AxisSpec occupancyAxis = {occupancyBinning, "occupancy"}; + AxisSpec ptAxis = {ptLambdaBinning, "pt"}; + AxisSpec dcaAxis = {dcaBinning, "dca"}; + AxisSpec ptProtonAxis = {ptProtonBinning, "daughter pt"}; + histos.add("hSparseV2SASameEvent_V2_EP", "hSparseV2SASameEvent_V2_EP", HistType::kTHnSparseF, {thnAxisInvMass, ptAxis, thnAxisV2, ptProtonAxis, decaylengthAxis, dcaAxis}); + histos.add("hSparseV2SASameEventRotational_V2_EP", "hSparseV2SASameEventRotational_V2_EP", HistType::kTHnSparseF, {thnAxisInvMass, ptAxis, thnAxisV2, ptProtonAxis, decaylengthAxis, dcaAxis}); + histos.add("hV0decaylength", "hV0decaylength", kTH1F, {{1000, 0.0f, 1000.0f}}); + histos.add("hMomCorr", "hMomCorr", kTH3F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}, {8, 0.0f, 80.0f}}); + histos.add("hInvMassKs0", "hInvMassKs0", kTH1F, {{200, 0.4f, 0.6f}}); + histos.add("hchi2PCA", "hchi2PCA", kTH1F, {{1000, 0.0f, 1.f}}); + histos.add("hFTOCvsTPCNoCut", "Mult correlation FT0C vs. TPC without any cut", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hCentrality", "Centrality distribution", kTH1F, {{200, 0.0, 200.0}}); + histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); + histos.add("hOccupancy", "Occupancy", kTH1F, {{5000, 0.0, 50000.0}}); + histos.add("hRotation", "hRotation", kTH1F, {{360, 0.0, 2.0 * TMath::Pi()}}); + + histos.add("hNsigmaProtonTPCDiff", "Difference NsigmaProton NsigmaKaon TPC distribution", kTH3F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}, {80, 0.0f, 8.0f}}); + histos.add("hNsigmaProtonTPC", "NsigmaProton TPC distribution", kTH2F, {{100, -5.0f, 5.0f}, {80, 0.0f, 8.0f}}); + histos.add("hNsigmaProtonTOF", "NsigmaProton TOF distribution", kTH2F, {{100, -5.0f, 5.0f}, {80, 0.0f, 8.0f}}); + + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{1000, -0.5f, 0.5f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{1000, -0.5f, 0.5f}}); + histos.add("hsignprotonDca", "hsignprotonDca", kTH1F, {{2000, -1.0f, 1.0f}}); + histos.add("hunsignprotonDca", "hunsignprotonDca", kTH1F, {{2000, -1.0f, 1.0f}}); + histos.add("hsignCPALambdac", "hsignCPALambdac", kTH1F, {{2000, -1.0f, 1.0f}}); + + histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, phiAxis, occupancyAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, phiAxis, occupancyAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, phiAxis, occupancyAxis}); + histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, phiAxis, occupancyAxis}); + histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, phiAxis, occupancyAxis}); + + // histogram for resolution + histos.add("ResFT0CTPC", "ResFT0CTPC", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH2F, {centAxis, resAxis}); + histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0ATPC", "ResFT0ATPC", kTH2F, {centAxis, resAxis}); + + df.setPropagateToPCA(true); + df.setMaxR(200); + df.setMaxDZIni(4); + df.setMinParamChange(1.e-3); + df.setMinRelChi2Change(0.9); + df.setUseAbsDCA(cnfabsdca); + df.setWeightedFinalPCA(true); + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); + runNumber = 0; + } + template + bool selectionTrack(const T& candidate) + { + if (!(candidate.isGlobalTrackWoDCA() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster && candidate.itsNClsInnerBarrel() >= cfgITSclusterInnerlayer)) { + return false; + } + if (candidate.pt() > 0.0 && candidate.pt() < 0.5 && TMath::Abs(candidate.dcaXY()) < cfgCutDCAxymin1) { + return false; + } + if (candidate.pt() >= 0.5 && candidate.pt() < 1.0 && TMath::Abs(candidate.dcaXY()) < cfgCutDCAxymin2) { + return false; + } + if (candidate.pt() >= 1.0 && candidate.pt() < 1.5 && TMath::Abs(candidate.dcaXY()) < cfgCutDCAxymin3) { + return false; + } + if (candidate.pt() >= 1.5 && candidate.pt() < 2.0 && TMath::Abs(candidate.dcaXY()) < cfgCutDCAxymin4) { + return false; + } + if (candidate.pt() >= 2.0 && candidate.pt() < 3.0 && TMath::Abs(candidate.dcaXY()) < cfgCutDCAxymin5) { + return false; + } + if (candidate.pt() >= 3.0 && TMath::Abs(candidate.dcaXY()) < cfgCutDCAxymin6) { + return false; + } + return true; + } + + template + bool rejectPi(const T& candidate) + { + if (candidate.tpcInnerParam() > 0.9 && candidate.tpcInnerParam() < 1.0 && candidate.tpcNSigmaPi() < 6.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.0 && candidate.tpcInnerParam() < 1.1 && candidate.tpcNSigmaPi() < 4.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.1 && candidate.tpcInnerParam() < 1.2 && candidate.tpcNSigmaPi() < 3.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.2 && candidate.tpcInnerParam() < 1.4 && candidate.tpcNSigmaPi() < 1.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.4 && candidate.tpcInnerParam() < 1.5 && candidate.tpcNSigmaPi() < 0.5) { + return false; + } + return true; + } + + template + bool rejectEl(const T& candidate) + { + + if (candidate.tpcInnerParam() > 0.7 && candidate.tpcInnerParam() < 0.8 && candidate.tpcNSigmaEl() < 2.0) { + return false; + } + if (candidate.tpcInnerParam() > 0.8 && candidate.tpcInnerParam() < 0.9 && candidate.tpcNSigmaEl() < 0.0) { + return false; + } + if (candidate.tpcInnerParam() > 0.9 && candidate.tpcInnerParam() < 1.0 && candidate.tpcNSigmaEl() < -1.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.0 && candidate.tpcInnerParam() < 1.1 && candidate.tpcNSigmaEl() < -2.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.1 && candidate.tpcInnerParam() < 1.2 && candidate.tpcNSigmaEl() < -3.0) { + return false; + } + + return true; + } + + template + bool rejectKa(const T& candidate) + { + if (candidate.tpcInnerParam() > 0.7 && candidate.tpcInnerParam() < 0.8 && candidate.tpcNSigmaKa() < 7.5) { + return false; + } + if (candidate.tpcInnerParam() > 0.8 && candidate.tpcInnerParam() < 0.9 && candidate.tpcNSigmaKa() < 6.0) { + return false; + } + if (candidate.tpcInnerParam() > 0.9 && candidate.tpcInnerParam() < 1.1 && candidate.tpcNSigmaKa() < 5.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.1 && candidate.tpcInnerParam() < 1.2 && candidate.tpcNSigmaKa() < 3.5) { + return false; + } + if (candidate.tpcInnerParam() > 1.2 && candidate.tpcInnerParam() < 1.4 && candidate.tpcNSigmaKa() < 3.0) { + return false; + } + if (candidate.tpcInnerParam() > 1.4 && candidate.tpcInnerParam() < 1.5 && candidate.tpcNSigmaKa() < 2.5) { + return false; + } + return true; + } + + // TPC TOF + template + bool selectionPID1(const T& candidate) + { + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 0.7) { + // printf("I am here: %.3f\n", candidate.tpcInnerParam()); + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + // printf("combine PIDA: %.3f\n", combinedPID); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + if (!candidate.hasTOF()) { + if (candidate.tpcInnerParam() < 1.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 1.5 && candidate.tpcNSigmaPr() > -2.0 && candidate.tpcNSigmaPr() < 2.0) { + return true; + } + } + } + return false; + } + + // TOF Veto + template + bool selectionPID2(const T& candidate) + { + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 0.7) { + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + } + return false; + } + + // TOF veto loose + template + bool selectionPID3(const T& candidate) + { + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 0.7) { + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + if (!candidate.hasTOF()) { + if (candidate.tpcInnerParam() < 1.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + } + } + return false; + } + + // TOF veto very loose + template + bool selectionPID4(const T& candidate) + { + if (candidate.tpcInnerParam() < 0.7 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 0.7) { + if (candidate.hasTOF()) { + auto combinedPID = TMath::Sqrt(candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) / TMath::Sqrt(2.0); + if (combinedPID < nsigmaCutCombined) { + return true; + } + } + if (!candidate.hasTOF()) { + if (candidate.tpcInnerParam() < 1.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.tpcInnerParam() >= 1.5 && candidate.tpcInnerParam() < 1.8 && candidate.tpcNSigmaPr() > -1.5 && candidate.tpcNSigmaPr() < 2.0) { + return true; + } + } + } + return false; + } + + template + bool SelectionV0(Collision const& collision, V0 const& candidate) + { + // const float pT = candidate.pt(); + const std::vector decVtx = {candidate.x(), candidate.y(), candidate.z()}; + const float tranRad = candidate.v0radius(); + const double dcaDaughv0 = TMath::Abs(candidate.dcaV0daughters()); + const double cpav0 = candidate.v0cosPA(); + float decaylength = TMath::Sqrt(TMath::Power(collision.posX() - candidate.x(), 2.0) + TMath::Power(collision.posY() - candidate.y(), 2.0) + TMath::Power(collision.posZ() - candidate.z(), 2.0)); + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); // FIXME: Get from the common header + float lowmasscutks0 = 0.497 - 2.0 * cSigmaMassKs0; + float highmasscutks0 = 0.497 + 2.0 * cSigmaMassKs0; + + if (TMath::Abs(CtauK0s) < 2.0 || TMath::Abs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + return false; + } + if (dcaDaughv0 > ConfV0DCADaughMax) { + return false; + } + if (TMath::Abs(candidate.dcav0topv()) > cMaxV0DCA) { + return false; + } + if (cpav0 < ConfV0CPAMin) { + return false; + } + if (decaylength > 100) { + return false; + } + if (tranRad > 100) { + return false; + } + return true; + } + template + bool isSelectedV0Daughter(T const& track, float charge) + { + const auto eta = track.eta(); + const auto pt = track.pt(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto dcaXY = track.dcaXY(); + const auto sign = track.sign(); + if (charge < 0 && sign > 0) { + return false; + } + if (charge > 0 && sign < 0) { + return false; + } + if (TMath::Abs(eta) > 0.8) { + return false; + } + if (TMath::Abs(pt) < ConfDaughPt) { + return false; + } + if (tpcNClsF < ConfDaughTPCnclsMin) { + return false; + } + if (TMath::Abs(dcaXY) < ConfDaughDCAMin) { + return false; + } + if (TMath::Abs(track.tpcNSigmaPi()) > ConfDaughPIDCuts) { + return false; + } + return true; + } + + double GetPhiInRange(double phi) + { + double result = phi; + while (result < 0) { + result = result + 2. * TMath::Pi() / 2; + } + while (result > 2. * TMath::Pi() / 2) { + result = result - 2. * TMath::Pi() / 2; + } + return result; + } + + ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for bin"}; + ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {10, 0, 100}, "multiplicity percentile for bin"}; + ConfigurableAxis axisEPAngle{"axisEPAngle", {1, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; + + using BinningTypeVertexContributor = ColumnBinningPolicy; + ROOT::Math::PxPyPzMVector Lambdac, Proton, Kshort, LambdacRot, KshortRot; + // ROOT::Math::PxPyPzMVector fourVecDauCM; + // ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY, eventplaneVec, eventplaneVecNorm, beamvector; + double massPr = TDatabasePDG::Instance()->GetParticle(kProton)->Mass(); // FIXME: Get from the common header + double massK0s = TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); // FIXME: Get from the common header + double v2, v2Rot; + void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, AllTrackCandidates const&, ResoV0s const& V0s, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) { + return; + } + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + // df.setBz(bz); /// put it outside the 'if'! Otherwise we have a difference wrt bz Configurable (< 1 permille) in Run2 conv. data + } + df.setBz(bz); + auto centrality = collision.centFT0C(); + auto multTPC = collision.multNTracksPV(); + histos.fill(HIST("hFTOCvsTPCNoCut"), centrality, multTPC); + if (!collision.triggereventep()) { + return; + } + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + return; + } + if (additionalEvSel2 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + return; + } + int occupancy = collision.trackOccupancyInTimeRange(); + auto psiFT0C = collision.psiFT0C(); + auto psiFT0A = collision.psiFT0A(); + auto psiTPC = collision.psiTPC(); + auto psiTPCR = collision.psiTPCR(); + auto psiTPCL = collision.psiTPCL(); + + // auto QFT0C = collision.qFT0C(); + // auto QFT0A = collision.qFT0A(); + // auto QTPC = collision.qTPC(); + // auto QTPCR = collision.qTPCR(); + // auto QTPCL = collision.qTPCL(); + + histos.fill(HIST("hFTOCvsTPC"), centrality, multTPC); + histos.fill(HIST("hFTOCvsTPCSelected"), centrality, multTPC); + histos.fill(HIST("hPsiFT0C"), centrality, psiFT0C, occupancy); + histos.fill(HIST("hPsiFT0A"), centrality, psiFT0A, occupancy); + histos.fill(HIST("hPsiTPC"), centrality, psiTPC, occupancy); + histos.fill(HIST("hPsiTPCR"), centrality, psiTPCR, occupancy); + histos.fill(HIST("hPsiTPCL"), centrality, psiTPCL, occupancy); + histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC))); + histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCR))); + histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCL))); + histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(2.0 * (psiTPCR - psiTPCL))); + histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); + histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiTPC - psiFT0A))); + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hVtxZ"), collision.posZ()); + histos.fill(HIST("hOccupancy"), occupancy); + auto firstprimarytrack = 0; + for (auto track1 : tracks) { + if (!selectionTrack(track1)) { + continue; + } + + if (!track1.hasTOF()) { + if (!rejectPi(track1)) { + continue; + } + if (!rejectEl(track1)) { + continue; + } + if (!rejectKa(track1)) { + continue; + } + } + + // PID check + if (PIDstrategy == 0 && !selectionPID1(track1)) { + continue; + } + if (PIDstrategy == 1 && !selectionPID2(track1)) { + continue; + } + if (PIDstrategy == 2 && !selectionPID3(track1)) { + continue; + } + if (PIDstrategy == 3 && !selectionPID4(track1)) { + continue; + } + histos.fill(HIST("hMomCorr"), track1.p() / track1.sign(), track1.p() - track1.tpcInnerParam(), centrality); + histos.fill(HIST("hEta"), track1.eta()); + histos.fill(HIST("hDcaz"), track1.dcaZ()); + histos.fill(HIST("hNsigmaProtonTPCDiff"), track1.tpcNSigmaPr(), track1.tpcNSigmaKa(), track1.pt()); + histos.fill(HIST("hNsigmaProtonTPC"), track1.tpcNSigmaPr(), track1.pt()); + histos.fill(HIST("hNsigmaProtonTOF"), track1.tofNSigmaPr(), track1.pt()); + auto track1ID = track1.globalIndex(); + auto trackParCovBach = getTrackParCov(track1); + for (auto v0 : V0s) { + if (!SelectionV0(collision, v0)) { + continue; + } + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + if (!isSelectedV0Daughter(postrack, 1)) { + continue; + } + if (!isSelectedV0Daughter(negtrack, -1)) { + continue; + } + if (track1ID == postrack.globalIndex()) { + continue; + } + if (track1ID == negtrack.globalIndex()) { + continue; + } + auto v0decaylength = TMath::Sqrt(TMath::Power(collision.posX() - v0.x(), 2.0) + TMath::Power(collision.posY() - v0.y(), 2.0) + TMath::Power(collision.posZ() - v0.z(), 2.0)); + if (firstprimarytrack == 0) { + histos.fill(HIST("hV0decaylength"), v0decaylength); + } + float v0x, v0y, v0z, v0px, v0py, v0pz; + // float v0PosPx, v0PosPy, v0PosPz, v0NegPx, v0NegPy, v0NegPz; + // float dcaV0dau, dcaPosToPV, dcaNegToPV, v0cosPA; + float posTrackX, negTrackX; + o2::track::TrackParCov trackParCovV0DaughPos; + o2::track::TrackParCov trackParCovV0DaughNeg; + + // const auto& trackV0DaughPos = v0.posTrack_as(); + // const auto& trackV0DaughNeg = v0.negTrack_as(); + + trackParCovV0DaughPos = getTrackParCov(postrack); // check that aod::TracksWCov does not need TracksDCA! + trackParCovV0DaughNeg = getTrackParCov(negtrack); // check that aod::TracksWCov does not need TracksDCA! + + posTrackX = v0.posX(); + negTrackX = v0.negX(); + v0x = v0.x(); + v0y = v0.y(); + v0z = v0.z(); + const std::array vertexV0 = {v0x, v0y, v0z}; + + v0px = v0.px(); + v0py = v0.py(); + v0pz = v0.pz(); + const std::array momentumV0 = {v0px, v0py, v0pz}; + + std::array covV0Pos = {0.}; + for (int i = 0; i < 6; i++) { + covV0Pos[i] = v0.positionCovMat()[i]; + } + // dcaV0dau = v0.dcaV0daughters(); + // dcaPosToPV = v0.dcapostopv(); + // dcaNegToPV = v0.dcanegtopv(); + // v0cosPA = v0.v0cosPA(); + + trackParCovV0DaughPos.propagateTo(posTrackX, bz); // propagate the track to the X closest to the V0 vertex + trackParCovV0DaughNeg.propagateTo(negTrackX, bz); // propagate the track to the X closest to the V0 vertex + + // we build the neutral track to then build the cascade + // auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, {0, 0, 0, 0, 0, 0}, trackParCovV0DaughPos, trackParCovV0DaughNeg); // build the V0 track (indices for v0 daughters set to 0 for now) + auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, covV0Pos, trackParCovV0DaughPos, trackParCovV0DaughNeg); // build the V0 track (indices for v0 daughters set to 0 for now) + std::array pVecV0 = {0., 0., 0.}; + std::array pVecBach = {0., 0., 0.}; + std::array pVecCand = {0., 0., 0.}; + + try { + if (df.process(trackV0, trackParCovBach) == 0) { + continue; + } else { + // LOG(info) << "Vertexing succeeded for Lc candidate"; + } + } catch (const std::runtime_error& error) { + // LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + continue; + } + if (firstprimarytrack == 0) { + histos.fill(HIST("hInvMassKs0"), v0.mK0Short()); + } + + df.propagateTracksToVertex(); // propagate the bachelor and V0 to the Lambdac vertex + trackV0.getPxPyPzGlo(pVecV0); // momentum of D0 at the Lambdac vertex + trackParCovBach.getPxPyPzGlo(pVecBach); // momentum of proton at the Lambdac vertex + pVecCand = RecoDecay::pVec(pVecV0, pVecBach); + + const auto& secondaryVertex = df.getPCACandidate(); + auto chi2PCA = df.getChi2AtPCACandidate(); + if (chi2PCA > cutchi2PCA) { + continue; + } + // auto covMatrixPCA = df.calcPCACovMatrixFlat(); + if (firstprimarytrack == 0) { + histos.fill(HIST("hchi2PCA"), chi2PCA); + } + // get track impact parameters + // This modifies track momenta! + auto primaryVertex = getPrimaryVertex(collision); + // auto covMatrixPV = primaryVertex.getCov(); + o2::dataformats::DCA impactParameter0; + o2::dataformats::DCA impactParameter1; + trackV0.propagateToDCA(primaryVertex, bz, &impactParameter0); + trackParCovBach.propagateToDCA(primaryVertex, bz, &impactParameter1); + + // get uncertainty of the decay length + double phi, theta; + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, phi, theta); + // auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + // auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + Kshort = ROOT::Math::PxPyPzMVector(pVecV0[0], pVecV0[1], pVecV0[2], massK0s); + Proton = ROOT::Math::PxPyPzMVector(pVecBach[0], pVecBach[1], pVecBach[2], massPr); + Lambdac = Proton + Kshort; + + double protonimpactparameter = impactParameter1.getY(); + // double kshortimpactparameter=impactParameter0.getY(); + + double decaylengthx = secondaryVertex[0] - collision.posX(); + double decaylengthy = secondaryVertex[1] - collision.posY(); + double decaylengthz = secondaryVertex[2] - collision.posZ(); + double decaylength = TMath::Sqrt(decaylengthx * decaylengthx + decaylengthy * decaylengthy + decaylengthz * decaylengthz); + double decaylengthxy = TMath::Sqrt(decaylengthx * decaylengthx + decaylengthy * decaylengthy); + // double lambdaclifetime = (decaylength * Lambdac.M()) / Lambdac.P(); + // if (lambdaclifetime > cutmaxctaulambdac) { + // continue; + // } + double anglesign = decaylengthx * Lambdac.Px() + decaylengthy * Lambdac.Py() + decaylengthz * Lambdac.Pz(); + double CPAlambdac = anglesign / (decaylength * Lambdac.P()); + anglesign = anglesign / TMath::Abs(anglesign); + auto signprotonimpactparameter = protonimpactparameter * anglesign; + if (firstprimarytrack == 0) { + histos.fill(HIST("hDcaxy"), track1.dcaXY()); + histos.fill(HIST("hunsignprotonDca"), protonimpactparameter); + histos.fill(HIST("hsignCPALambdac"), TMath::Abs(CPAlambdac)); + histos.fill(HIST("hsignprotonDca"), signprotonimpactparameter); + } + firstprimarytrack = firstprimarytrack + 1; + auto phiminuspsi = GetPhiInRange(Lambdac.Phi() - psiFT0C); + v2 = TMath::Cos(2.0 * phiminuspsi); + // if (TMath::Abs(CPAlambdac) > cutCPAlambdac && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { + if (Lambdac.M() > 2.18 && Lambdac.M() <= 2.42 && TMath::Abs(Lambdac.Rapidity()) < confRapidity && Lambdac.Pt() > 2 && Lambdac.Pt() <= 6.0) { + if (!useDecayLengthxy) { + histos.fill(HIST("hSparseV2SASameEvent_V2_EP"), Lambdac.M(), Lambdac.Pt(), v2, Proton.Pt(), decaylength, TMath::Abs(track1.dcaXY())); + } + if (useDecayLengthxy) { + histos.fill(HIST("hSparseV2SASameEvent_V2_EP"), Lambdac.M(), Lambdac.Pt(), v2, Proton.Pt(), decaylengthxy, TMath::Abs(track1.dcaXY())); + } + } + for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { + auto anglestart = confMinRot; + auto angleend = confMaxRot; + auto anglestep = (angleend - anglestart) / (1.0 * (nBkgRotations - 1)); + auto rotangle = anglestart + nrotbkg * anglestep; + histos.fill(HIST("hRotation"), rotangle); + auto rotKshortPx = Kshort.Px() * std::cos(rotangle) - Kshort.Py() * std::sin(rotangle); + auto rotKshortPy = Kshort.Px() * std::sin(rotangle) + Kshort.Py() * std::cos(rotangle); + KshortRot = ROOT::Math::PxPyPzMVector(rotKshortPx, rotKshortPy, Kshort.pz(), massK0s); + LambdacRot = Proton + KshortRot; + auto phiminuspsiRot = GetPhiInRange(LambdacRot.Phi() - psiFT0C); + v2Rot = TMath::Cos(2.0 * phiminuspsiRot); + // double CPAlambdacRot = (decaylengthx * LambdacRot.Px() + decaylengthy * LambdacRot.Py() + decaylengthz * LambdacRot.Pz()) / (decaylength * LambdacRot.P()); + // if (TMath::Abs(CPAlambdacRot) > cutCPAlambdac && LambdacRot.M() > 2.18 && LambdacRot.M() <= 2.42) { + if (LambdacRot.M() > 2.18 && LambdacRot.M() <= 2.42 && TMath::Abs(LambdacRot.Rapidity()) < confRapidity && LambdacRot.Pt() > 2 && LambdacRot.Pt() <= 6.0) { + if (!useDecayLengthxy) { + histos.fill(HIST("hSparseV2SASameEventRotational_V2_EP"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, Proton.Pt(), decaylength, TMath::Abs(track1.dcaXY())); + } + if (useDecayLengthxy) { + histos.fill(HIST("hSparseV2SASameEventRotational_V2_EP"), LambdacRot.M(), LambdacRot.Pt(), v2Rot, Proton.Pt(), decaylengthxy, TMath::Abs(track1.dcaXY())); + } + } + } + + // ROOT::Math::Boost boost{Lambdac.BoostToCM()}; + // fourVecDauCM = boost(Kshort); + // threeVecDauCM = fourVecDauCM.Vect(); + // threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); + // beamvector = ROOT::Math::XYZVector(0, 0, 1); + // auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); + // auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + // if (fillPolarization) { + // if (track1.sign() > 0) { + // histos.fill(HIST("hSparseV2SASameEventplus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + // histos.fill(HIST("hSparseV2SASameEventplus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + // histos.fill(HIST("hSparseV2SASameEventplus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + // } + // if (track1.sign() < 0) { + // histos.fill(HIST("hSparseV2SASameEventminus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + // histos.fill(HIST("hSparseV2SASameEventminus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + // histos.fill(HIST("hSparseV2SASameEventminus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + // } + // } + } + } + } + PROCESS_SWITCH(highmasslambdasvx, processSameEvent, "Process Same event", true); + /* void processMixedEventOpti(EventCandidates const& collisions, TrackCandidates const& tracks, AllTrackCandidates const&, ResoV0s const& V0s) + { + auto tracksV0sTuple = std::make_tuple(tracks, V0s); + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + Pair pairs{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksV0sTuple, &cache}; // -1 is the number of the bin to skip + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (!collision1.sel8() || !collision2.sel8()) { + continue; + } + if (!collision1.triggereventep() || !collision2.triggereventep()) { + continue; + } + if (additionalEvSel && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel2 && (!collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + return; + } + if (additionalEvSel2 && (!collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + return; + } + auto centrality = collision1.centFT0C(); + auto psiFT0C = collision1.psiFT0C(); + auto QFT0C = collision1.qFT0C(); + int occupancy = collision1.trackOccupancyInTimeRange(); + for (auto& [track1, v0] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!selectionTrack(track1)) { + continue; + } + // PID check + if (ispTdepPID && !selectionPIDNew(track1)) { + continue; + } + if (!ispTdepPID && !selectionPID(track1)) { + continue; + } + if (!SelectionV0(collision2, v0)) { + continue; + } + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + if (!isSelectedV0Daughter(postrack, 1)) { + continue; + } + if (!isSelectedV0Daughter(negtrack, -1)) { + continue; + } + + Proton = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPr); + Kshort = ROOT::Math::PxPyPzMVector(v0.px(), v0.py(), v0.pz(), massK0s); + Lambdac = Proton + Kshort; + if (TMath::Abs(Lambdac.Rapidity()) > confRapidity) { + continue; + } + auto phiminuspsi = GetPhiInRange(Lambdac.Phi() - psiFT0C); + if (useSP) { + v2 = TMath::Cos(2.0 * phiminuspsi) * QFT0C; + } + if (!useSP) { + v2 = TMath::Cos(2.0 * phiminuspsi); + } + auto anglesign = (v0.x() - collision1.posX()) * v0.px() + (v0.y() - collision1.posY()) * v0.py() + (v0.z() - collision1.posZ()) * v0.pz(); + anglesign = anglesign / TMath::Abs(anglesign); + auto dcasum = 0.0; + if (useSignDCAV0) { + dcasum = anglesign * (v0.dcav0topv()) - track1.dcaXY(); + } + if (!useSignDCAV0) { + dcasum = TMath::Sqrt((track1.dcaXY() + (v0.dcav0topv())) * (track1.dcaXY() + (v0.dcav0topv()))); + } + // auto diffangle = Proton.Phi() - Lambdac.Phi(); + // auto decaylength = TMath::Abs((track1.dcaXY() / TMath::Sin(diffangle)) / (Lambdac.P() / 2.286)); + // auto dcasum = TMath::Sqrt(track1.dcaXY() * track1.dcaXY() + v0.dcav0topv() * v0.dcav0topv()); + if (fillDefault && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { + if (fillDecayLength) { + histos.fill(HIST("hSparseV2SAMixedEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, dcasum); + } + histos.fill(HIST("hSparseV2SAMixedEvent_V2_new"), Lambdac.M(), Lambdac.Pt(), v2, TMath::Abs(track1.dcaXY()), Proton.Pt()); + } + if (fillOccupancy && Lambdac.M() > 2.18 && Lambdac.M() <= 2.42) { + if (fillDecayLength) { + histos.fill(HIST("hSparseV2SAMixedEvent_V2_occupancy"), Lambdac.M(), Lambdac.Pt(), v2, dcasum, TMath::Abs(track1.dcaXY()), occupancy); + } + histos.fill(HIST("hSparseV2SAMixedEvent_V2_new_occupancy"), Lambdac.M(), Lambdac.Pt(), v2, TMath::Abs(track1.dcaXY()), Proton.Pt(), occupancy); + } + ROOT::Math::Boost boost{Lambdac.BoostToCM()}; + fourVecDauCM = boost(Kshort); + threeVecDauCM = fourVecDauCM.Vect(); + threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); + beamvector = ROOT::Math::XYZVector(0, 0, 1); + auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); + auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + if (fillPolarization) { + if (track1.sign() > 0) { + histos.fill(HIST("hSparseV2SAMixedEventplus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventplus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventplus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + } + if (track1.sign() < 0) { + histos.fill(HIST("hSparseV2SAMixedEventminus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventminus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventminus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + } + } + } + } + } + PROCESS_SWITCH(highmasslambdasvx, processMixedEventOpti, "Process Mixed event new", true);*/ +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"highmasslambdasvx"})}; +} diff --git a/PWGLF/Tasks/Resonances/k892analysis.cxx b/PWGLF/Tasks/Resonances/k892analysis.cxx index 14e5f4e496e..7e02c354e89 100644 --- a/PWGLF/Tasks/Resonances/k892analysis.cxx +++ b/PWGLF/Tasks/Resonances/k892analysis.cxx @@ -17,6 +17,7 @@ #include #include "TF1.h" +#include "TRandom3.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Centrality.h" @@ -54,6 +55,9 @@ struct k892analysis { Configurable cPIDBins{"cPIDBins", 65, "PID binning"}; Configurable cPIDQALimit{"cPIDQALimit", 6.5, "PID QA limit"}; Configurable cDCABins{"cDCABins", 150, "DCA binning"}; + Configurable invmass1D{"invmass1D", false, "Invariant mass 1D"}; + Configurable study_antiparticle{"study_antiparticle", false, "Study anti-particles separately"}; + Configurable PIDplots{"PIDplots", false, "Make TPC and TOF PID plots"}; /// Event Mixing Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; @@ -99,6 +103,12 @@ struct k892analysis { Configurable cfgHasITS{"cfgHasITS", false, "Require ITS"}; Configurable cfgHasTPC{"cfgHasTPC", false, "Require TPC"}; Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + + // Rotational background + Configurable IsCalcRotBkg{"IsCalcRotBkg", true, "Calculate rotational background"}; + Configurable rotational_cut{"rotational_cut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable c_nof_rotations{"c_nof_rotations", 3, "Number of random rotations in the rotational background"}; + // MC Event selection Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; @@ -149,11 +159,15 @@ struct k892analysis { } // Mass QA (quick check) - histos.add("k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH1F, {invMassAxis}); - histos.add("k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTH1F, {invMassAxis}); - histos.add("k892invmassLS", "Invariant mass of K(892)0 like sign", kTH1F, {invMassAxis}); - histos.add("k892invmassLSAnti", "Invariant mass of Anti-K(892)0 like sign", kTH1F, {invMassAxis}); - histos.add("k892invmassME", "Invariant mass of K(892)0 mixed event", kTH1F, {invMassAxis}); + if (invmass1D) { + histos.add("k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH1F, {invMassAxis}); + histos.add("k892invmassLS", "Invariant mass of K(892)0 like sign", kTH1F, {invMassAxis}); + histos.add("k892invmassME", "Invariant mass of K(892)0 mixed event", kTH1F, {invMassAxis}); + if (study_antiparticle) { + histos.add("k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTH1F, {invMassAxis}); + histos.add("k892invmassLSAnti", "Invariant mass of Anti-K(892)0 like sign", kTH1F, {invMassAxis}); + } + } if (additionalMEPlots) { histos.add("k892invmassME_DS", "Invariant mass of K(892)0 mixed event DS", kTH1F, {invMassAxis}); @@ -194,19 +208,21 @@ struct k892analysis { histos.add("QAafter/trkpT_pi", "pT distribution of pion track candidates", kTH1F, {ptAxis}); histos.add("QAafter/trkpT_ka", "pT distribution of kaon track candidates", kTH1F, {ptAxis}); // PID QA before cuts - histos.add("QAbefore/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAbefore/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAbefore/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_Nsigma_ka_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAbefore/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - // PID QA after cuts - histos.add("QAafter/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAafter/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAafter/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAafter/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAafter/TOF_Nsigma_ka_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAafter/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + if (PIDplots) { + histos.add("QAbefore/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QAbefore/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAbefore/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAbefore/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QAbefore/TOF_Nsigma_ka_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAbefore/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + // PID QA after cuts + histos.add("QAafter/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QAafter/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAafter/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAafter/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QAafter/TOF_Nsigma_ka_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAafter/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + } // eta phi QA if (cfgCutsOnDaughters) { @@ -231,11 +247,16 @@ struct k892analysis { } // 3d histogram - histos.add("h3k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("h3k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("h3k892invmassLS", "Invariant mass of K(892)0 same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("h3k892invmassLSAnti", "Invariant mass of Anti-K(892)0 same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("h3k892invmassME", "Invariant mass of K(892)0 mixed event", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassLS", "Invariant mass of K(892)0 same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassME", "Invariant mass of K(892)0 mixed event", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + if (study_antiparticle) { + histos.add("h3k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassLSAnti", "Invariant mass of Anti-K(892)0 same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + } + if (IsCalcRotBkg) { + histos.add("h3K892InvMassRotation", "Invariant mass of K(892)0 rotation", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + } if (additionalMEPlots) { histos.add("h3k892invmassME_DS", "Invariant mass of K(892)0 mixed event DS", kTH3F, {centAxis, ptAxis, invMassAxis}); @@ -248,14 +269,16 @@ struct k892analysis { histos.add("QAMCTrue/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); histos.add("QAMCTrue/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); histos.add("QAMCTrue/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); - histos.add("QAMCTrue/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAMCTrue/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAMCTrue/TOF_Nsigma_ka_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("QAMCTrue/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); - histos.add("h3Reck892invmass", "Invariant mass of Reconstructed MC K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("h3Reck892invmassAnti", "Invariant mass of Reconstructed MC Anti-K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("k892Gen", "pT distribution of True MC K(892)0", kTH3F, {mcLabelAxis, ptAxis, centAxis}); - histos.add("k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTH3F, {mcLabelAxis, ptAxis, centAxis}); + if (PIDplots) { + histos.add("QAMCTrue/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAMCTrue/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAMCTrue/TOF_Nsigma_ka_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAMCTrue/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + } + histos.add("h3Reck892invmass", "Invariant mass of Reconstructed MC K(892)0", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + histos.add("h3Reck892invmassAnti", "Invariant mass of Reconstructed MC Anti-K(892)0", kTHnSparseF, {centAxis, ptAxis, invMassAxis}); + histos.add("k892Gen", "pT distribution of True MC K(892)0", kTHnSparseF, {mcLabelAxis, ptAxis, centAxis}); + histos.add("k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTHnSparseF, {mcLabelAxis, ptAxis, centAxis}); histos.add("k892Rec", "pT distribution of Reconstructed MC K(892)0", kTH2F, {ptAxis, centAxis}); histos.add("k892RecAnti", "pT distribution of Reconstructed MC Anti-K(892)0", kTH2F, {ptAxis, centAxis}); histos.add("k892Recinvmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {invMassAxis}); @@ -446,7 +469,7 @@ struct k892analysis { histos.fill(HIST("MultCalib/GloPVpi_after"), dTracks1.size(), collision.multNTracksPV()); // global tracks vs PV tracks after the multiplicity calibration cuts } - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance, ldaughter_rot, lresonance_rot; for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { // Full index policy is needed to consider all possible combinations @@ -483,16 +506,18 @@ struct k892analysis { if constexpr (!IsMix) { //// QA plots before the selection // --- PID QA Pion - histos.fill(HIST("QAbefore/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } - // --- PID QA Kaon - histos.fill(HIST("QAbefore/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + if (PIDplots) { + histos.fill(HIST("QAbefore/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAbefore/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + // --- PID QA Kaon + histos.fill(HIST("QAbefore/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAbefore/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } } histos.fill(HIST("QAbefore/trkpT_pi"), trk1ptPi); histos.fill(HIST("QAbefore/trkpT_ka"), trk2ptKa); @@ -528,16 +553,18 @@ struct k892analysis { if constexpr (!IsMix) { //// QA plots after the selection // --- PID QA Pion - histos.fill(HIST("QAafter/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAafter/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } - // --- PID QA Kaon - histos.fill(HIST("QAafter/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + if (PIDplots) { + histos.fill(HIST("QAafter/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAafter/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAafter/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + // --- PID QA Kaon + histos.fill(HIST("QAafter/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAafter/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } } histos.fill(HIST("QAafter/trkpT_pi"), trk1ptPi); histos.fill(HIST("QAafter/trkpT_ka"), trk2ptKa); @@ -558,9 +585,10 @@ struct k892analysis { } //// Resonance reconstruction - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + lDecayDaughter1.SetPtEtaPhiM(trk1.pt(), trk1.eta(), trk1.phi(), massPi); + lDecayDaughter2.SetPtEtaPhiM(trk2.pt(), trk2.eta(), trk2.phi(), massKa); lResonance = lDecayDaughter1 + lDecayDaughter2; + TRandom* rn = new TRandom(); // Rapidity cut if (abs(lResonance.Rapidity()) >= 0.5) continue; @@ -590,22 +618,41 @@ struct k892analysis { //// Un-like sign pair only if (trk1.sign() * trk2.sign() < 0) { if constexpr (!IsMix) { - if (trk1.sign() < 0) { - histos.fill(HIST("k892invmassDS"), lResonance.M()); + if (IsCalcRotBkg) { + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + ldaughter_rot.SetPtEtaPhiM(trk2.pt(), trk2.eta(), trk2.phi() + theta2, massKa); // for rotated background + lresonance_rot = lDecayDaughter1 + ldaughter_rot; + histos.fill(HIST("h3K892InvMassRotation"), multiplicity, lresonance_rot.Pt(), lresonance_rot.M()); + } + } + if (study_antiparticle) { + if (trk1.sign() < 0) { + if (invmass1D) + histos.fill(HIST("k892invmassDS"), lResonance.M()); + histos.fill(HIST("h3k892invmassDS"), multiplicity, lResonance.Pt(), lResonance.M()); + } else if (trk1.sign() > 0) { + if (invmass1D) + histos.fill(HIST("k892invmassDSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassDSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + } + } else { + if (invmass1D) + histos.fill(HIST("k892invmassDS"), lResonance.M()); histos.fill(HIST("h3k892invmassDS"), multiplicity, lResonance.Pt(), lResonance.M()); - } else if (trk1.sign() > 0) { - histos.fill(HIST("k892invmassDSAnti"), lResonance.M()); - histos.fill(HIST("h3k892invmassDSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); } } else { - histos.fill(HIST("k892invmassME"), lResonance.M()); + if (invmass1D) + histos.fill(HIST("k892invmassME"), lResonance.M()); histos.fill(HIST("h3k892invmassME"), multiplicity, lResonance.Pt(), lResonance.M()); if (additionalMEPlots) { if (trk1.sign() < 0) { - histos.fill(HIST("k892invmassME_DS"), lResonance.M()); + if (invmass1D) + histos.fill(HIST("k892invmassME_DS"), lResonance.M()); histos.fill(HIST("h3k892invmassME_DS"), multiplicity, lResonance.Pt(), lResonance.M()); } else if (trk1.sign() > 0) { - histos.fill(HIST("k892invmassME_DSAnti"), lResonance.M()); + if (invmass1D) + histos.fill(HIST("k892invmassME_DSAnti"), lResonance.M()); histos.fill(HIST("h3k892invmassME_DSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); } } @@ -625,13 +672,15 @@ struct k892analysis { histos.fill(HIST("QAMCTrue/trkDCAxy_ka"), trk2.dcaXY()); histos.fill(HIST("QAMCTrue/trkDCAz_pi"), trk1.dcaZ()); histos.fill(HIST("QAMCTrue/trkDCAz_ka"), trk2.dcaZ()); - histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAMCTrue/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); - } - histos.fill(HIST("QAMCTrue/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QAMCTrue/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + if (PIDplots) { + histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMCTrue/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); + } + histos.fill(HIST("QAMCTrue/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMCTrue/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + } } // MC histograms @@ -647,12 +696,20 @@ struct k892analysis { } } else if (trk1.sign() * trk2.sign() > 0) { if constexpr (!IsMix) { - if (trk1.sign() < 0) { - histos.fill(HIST("k892invmassLS"), lResonance.M()); + if (study_antiparticle) { + if (trk1.sign() < 0) { + if (invmass1D) + histos.fill(HIST("k892invmassLS"), lResonance.M()); + histos.fill(HIST("h3k892invmassLS"), multiplicity, lResonance.Pt(), lResonance.M()); + } else if (trk1.sign() > 0) { + if (invmass1D) + histos.fill(HIST("k892invmassLSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassLSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + } + } else { + if (invmass1D) + histos.fill(HIST("k892invmassLS"), lResonance.M()); histos.fill(HIST("h3k892invmassLS"), multiplicity, lResonance.Pt(), lResonance.M()); - } else if (trk1.sign() > 0) { - histos.fill(HIST("k892invmassLSAnti"), lResonance.M()); - histos.fill(HIST("h3k892invmassLSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); } } } diff --git a/PWGLF/Tasks/Resonances/k892pmanalysis.cxx b/PWGLF/Tasks/Resonances/k892pmanalysis.cxx index 16d9da6fe0c..0f161bfc694 100644 --- a/PWGLF/Tasks/Resonances/k892pmanalysis.cxx +++ b/PWGLF/Tasks/Resonances/k892pmanalysis.cxx @@ -60,6 +60,9 @@ struct k892pmanalysis { Configurable cLambdaAntiLambdaMassBins{"cLambdaAntiLambdaMassBins", 250, "V0 mass (in the (Anti)Lambda0 hypothesis) binning"}; Configurable cDCABinsQA{"cDCABinsQA", 150, "DCA binning"}; + + Configurable cTpcNsigmaPionBinsQA{"cTpcNsigmaPionBinsQA", 140, "tpcNSigmaPi binning"}; + // Pre-selection cuts Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minimum pt cut"}; Configurable cMaxEtacut{"cMaxEtacut", 0.8, "Track maximum eta cut"}; @@ -72,10 +75,7 @@ struct k892pmanalysis { /// PID Selections Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF - Configurable cMaxTPCnSigmaV0Pion{"cMaxTPCnSigmaV0Pion", 5.0, "TPC nSigma cut for V0 Pion"}; // TPC, secondary pions - Configurable cMaxTOFnSigmaV0Pion{"cMaxTOFnSigmaV0Pion", 5.0, "TOF nSigma cut for V0 Pion"}; // TOF, secondary pions Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined - Configurable nsigmaCutCombinedV0Pion{"nsigmaCutCombinedV0Pion", -999, "Combined nSigma cut for V0 Pion"}; // Combined, secondary pions Configurable cUseOnlyTOFTrackPi{"cUseOnlyTOFTrackPi", false, "Use only TOF track for PID selection"}; // Use only TOF track for Pion PID selection Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection // Track selections @@ -86,7 +86,7 @@ struct k892pmanalysis { Configurable cV0MinCosPA{"cV0MinCosPA", 0.97, "V0 minimum pointing angle cosine"}; Configurable cV0MaxDaughDCA{"cV0MaxDaughDCA", 1.0, "V0 daughter DCA Maximum"}; // Competing V0 rejection - Configurable cV0MassWindow{"cV0MassWindow", 0.004, "Mass window for competing Lambda0 rejection"}; + Configurable cV0MassWindow{"cV0MassWindow", 0.0043, "Mass window for competing Lambda0 rejection"}; // Resonance selection // Configurable cMaxResRapidity{"cMaxResRapidity", 0.5, "Maximum pseudo-rapidity value of reconstructed K*(892)pm resonance"}; // Event mixing @@ -102,6 +102,7 @@ struct k892pmanalysis { AxisSpec dcazAxisQA = {cDCABinsQA, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; AxisSpec daughdcaAxisQa = {cDCABinsQA, 0.0, 3.0, "V0 daughters DCA (cm)"}; AxisSpec CosPointAngleAxisQA = {binsV0CosPointAngleQA, "CosPA"}; + AxisSpec tpcNSigmaPiAxisQA = {cTpcNsigmaPionBinsQA, -7.0, 7.0, "N#sigma_{TPC}"}; AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxisQA = {binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^2)"}; @@ -112,11 +113,11 @@ struct k892pmanalysis { // Mass QA (quick check) // QA before - histos.add("QAbefore/k0shortmass", "Invariant mass of K0Short", kTH1F, {k0sMassAxisQA}); + histos.add("QAbefore/k0shortmassPt", "Invariant mass of K0Short vs K0Short Pt", kTH2F, {ptAxisQA, k0sMassAxisQA}); histos.add("QAbefore/lambda0mass", "Invariant mass of V0 in Lambda0 hypothesis", kTH1F, {lambdaAntilambdaMassAxisQA}); histos.add("QAbefore/antilambda0mass", "Invariant mass of V0 in AntiLambda0 hypothesis", kTH1F, {lambdaAntilambdaMassAxisQA}); // QA after - histos.add("QAafter/k0shortmass", "Invariant mass of K0Short", kTH1F, {k0sMassAxisQA}); + histos.add("QAafter/k0shortmassPt", "Invariant mass of K0Short vs K0Short Pt", kTH2F, {ptAxisQA, k0sMassAxisQA}); histos.add("QAafter/lambda0mass", "Invariant mass of V0 in Lambda0 hypothesis", kTH1F, {lambdaAntilambdaMassAxisQA}); histos.add("QAafter/antilambda0mass", "Invariant mass of V0 in AntiLambda0 hypothesis", kTH1F, {lambdaAntilambdaMassAxisQA}); histos.add("k892pminvmass", "Invariant mass of charged K*(892)", kTH1F, {invMassAxis}); @@ -152,6 +153,11 @@ struct k892pmanalysis { // QA after histos.add("QAafter/trkpT_pi", "pT distribution of pion track candidates", kTH1F, {ptAxisQA}); histos.add("QAafter/trkpT_k0s", "pT distribution of k0short track candidates", kTH1F, {ptAxisQA}); + // Primary pion TPC PID + // QA before + histos.add("QAbefore/tpcNsigmaPionQA", "NsigmaTPC distribution of primary pion candidates", kTH2F, {ptAxisQA, tpcNSigmaPiAxisQA}); + // QA after + histos.add("QAafter/tpcNsigmaPionQA", "NsigmaTPC distribution of primary pion candidates", kTH2F, {ptAxisQA, tpcNSigmaPiAxisQA}); // Good tracks and V0 counts QA histos.add("QAafter/hGoodTracksV0s", "Number of good track and V0 passed", kTH1F, {goodTrackCountAxis}); // Mass vs Pt vs Multiplicity 3-dimensional histogram @@ -244,30 +250,6 @@ struct k892pmanalysis { return false; } - // Secondary PID selection tools - template - bool selectionPIDSecondaryPion(const T& candidate) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaV0Pion) { - tpcPIDPassed = true; - } - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaV0Pion) { - tofPIDPassed = true; - } - if ((nsigmaCutCombinedPion > 0) && (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < nsigmaCutCombinedV0Pion * nsigmaCutCombinedV0Pion)) { - tofPIDPassed = true; - } - } else { - tofPIDPassed = true; - } - if (tpcPIDPassed && tofPIDPassed) { - return true; - } - return false; - } - /*// Resonance candidate selection template bool selectionResoK892pm(const ResoCandidate& resoCandidate) @@ -311,6 +293,8 @@ struct k892pmanalysis { histos.fill(HIST("QAbefore/trkEta_pi"), trketaPi); // pT QA (before cuts) histos.fill(HIST("QAbefore/trkpT_pi"), trkptPi); + // TPC PID (before cuts) + histos.fill(HIST("QAbefore/tpcNsigmaPionQA"), trkptPi, trk.tpcNSigmaPi()); } // apply the track cut @@ -329,6 +313,8 @@ struct k892pmanalysis { histos.fill(HIST("QAafter/trkEta_pi"), trketaPi); // pT QA (after cuts) histos.fill(HIST("QAafter/trkpT_pi"), trk.pt()); + // TPC PID (after cuts) + histos.fill(HIST("QAafter/tpcNsigmaPionQA"), trkptPi, trk.tpcNSigmaPi()); } for (auto& v0 : dV0s) { @@ -350,7 +336,7 @@ struct k892pmanalysis { // pT QA (before cuts) histos.fill(HIST("QAbefore/trkpT_k0s"), v0ptK0s); // K0s mass QA (before cuts) - histos.fill(HIST("QAbefore/k0shortmass"), v0.mK0Short()); + histos.fill(HIST("QAbefore/k0shortmassPt"), v0ptK0s, v0.mK0Short()); } // apply the track cut @@ -381,7 +367,7 @@ struct k892pmanalysis { // pt QA (after cuts) histos.fill(HIST("QAafter/trkpT_k0s"), v0ptK0s); // K0s mass QA (after cuts) - histos.fill(HIST("QAafter/k0shortmass"), v0.mK0Short()); + histos.fill(HIST("QAafter/k0shortmassPt"), v0ptK0s, v0.mK0Short()); histos.fill(HIST("QAafter/lambda0mass"), v0.mLambda()); histos.fill(HIST("QAafter/antilambda0mass"), v0.mAntiLambda()); } diff --git a/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx b/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx index 14e98174c48..f899bf27ed1 100644 --- a/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx +++ b/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx @@ -29,11 +29,14 @@ #include #include #include -#include #include #include #include #include "TF1.h" +#include "TRandom3.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -67,6 +70,8 @@ struct kaonkaonAnalysisRun3 { Configurable timFrameEvsel{"timFrameEvsel", true, "TPC Time frame boundary cut"}; Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; Configurable otherQAplots{"otherQAplots", true, "Other QA plots"}; + Configurable QAPID{"QAPID", true, "QA PID plots"}; + Configurable QAevents{"QAevents", true, "QA events"}; Configurable cfgMultFT0M{"cfgMultFT0M", true, "true for pp (FT0M estimator) and false for PbPb (FT0C estimator)"}; // Event selection cuts - Alex (Temporary, need to fix!) @@ -77,6 +82,7 @@ struct kaonkaonAnalysisRun3 { TF1* fMultMultPVCut = nullptr; // track + Configurable rotational_cut{"rotational_cut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; Configurable cfgCutPT{"cfgCutPT", 0.2, "PT cut on daughter track"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; @@ -102,47 +108,91 @@ struct kaonkaonAnalysisRun3 { Configurable cMasslow{"cMasslow", 0.9f, "Low mass"}; Configurable cMasshigh{"cMasshigh", 2.5f, "High mass"}; Configurable cMassbins{"cMassbins", 320, "Number of mass bins"}; + Configurable c_nof_rotations{"c_nof_rotations", 3, "Number of random rotations in the rotational background"}; + ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; + ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; + ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; + + // different frames + Configurable activateTHnSparseCosThStarHelicity{"activateTHnSparseCosThStarHelicity", true, "Activate the THnSparse with cosThStar w.r.t. helicity axis"}; + Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; + Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; + Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; + ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + // MC Configurable isMC{"isMC", false, "Run MC"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", false, "avoid split track in MC"}; + void init(o2::framework::InitContext&) { - AxisSpec axisMult{cmultBins, cmultLow, cmultHigh}; - AxisSpec axisPt{cpTbins, cpTlow, cpThigh}; - AxisSpec axisMass{cMassbins, cMasslow, cMasshigh}; - histos.add("hCentrality", "Centrality distribution", kTH1F, {axisMult}); - histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); - histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hNsigmaKaonTPC_before", "NsigmaKaon TPC distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF_before", "NsigmaKaon TOF distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTPC_after", "NsigmaKaon TPC distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF_after", "NsigmaKaon TOF distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF_TPC_before", "NsigmaKaon TOF-TPC distribution", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF_TPC_after", "NsigmaKaon TOF-TPC distribution", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}); + AxisSpec axisMult{cmultBins, cmultLow, cmultHigh, "Multiplicity"}; + AxisSpec axisPt{cpTbins, cpTlow, cpThigh, "pT (GeV/c)"}; + AxisSpec axisMass{cMassbins, cMasslow, cMasshigh, "Invariant mass (GeV/c^2)"}; + const AxisSpec thnAxisPOL{configThnAxisPOL, "Frame axis"}; + + // THnSparses + std::array sparses = {activateTHnSparseCosThStarHelicity, activateTHnSparseCosThStarProduction, activateTHnSparseCosThStarBeam, activateTHnSparseCosThStarRandom}; + + // std::array sparses = {activateTHnSparseCosThStarHelicity}; + + if (std::accumulate(sparses.begin(), sparses.end(), 0) == 0) { + LOGP(fatal, "No output THnSparses enabled"); + } else { + if (activateTHnSparseCosThStarHelicity) { + LOGP(info, "THnSparse with cosThStar w.r.t. helicity axis active."); + } + if (activateTHnSparseCosThStarProduction) { + LOGP(info, "THnSparse with cosThStar w.r.t. production axis active."); + } + if (activateTHnSparseCosThStarBeam) { + LOGP(info, "THnSparse with cosThStar w.r.t. beam axis active. (Gottified jackson frame)"); + } + if (activateTHnSparseCosThStarRandom) { + LOGP(info, "THnSparse with cosThStar w.r.t. random axis active."); + } + } + + if (QAevents) { + histos.add("hmutiplicity", "Multiplicity percentile distribution", kTH1F, {axisMult}); + histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); + histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); + histos.add("multdist_FT0M", "FT0M Multiplicity distribution", kTH1F, {axisMultdist}); + histos.add("multdist_FT0A", "FT0A Multiplicity distribution", kTH1F, {axisMultdist}); + histos.add("multdist_FT0C", "FT0C Multiplicity distribution", kTH1F, {axisMultdist}); + } + + if (QAPID) { + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hNsigmaKaonTPC_before", "NsigmaKaon TPC distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF_before", "NsigmaKaon TOF distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaKaonTPC_after", "NsigmaKaon TPC distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaKaonTOF_after", "NsigmaKaon TOF distribution", kTH2F, {{axisPt}, {200, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF_TPC_before", "NsigmaKaon TOF-TPC distribution", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaKaonTOF_TPC_after", "NsigmaKaon TOF-TPC distribution", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}); + histos.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {axisPtfordEbydx, axisdEdx}); + } + if (otherQAplots) { + histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); + histos.add("hFTOCvsTPCNoCut", "Mult correlation FT0C vs. TPC without any cut", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + + // chi2 plots histos.add("Chi2perclusterITS", "Chi2 / cluster for the ITS track segment", kTH1F, {{50, 0.0f, 50.0f}}); histos.add("Chi2perclusterTPC", "Chi2 / cluster for the TPC track segment", kTH1F, {{50, 0.0f, 50.0f}}); histos.add("Chi2perclusterTRD", "Chi2 / cluster for the TRD track segment", kTH1F, {{50, 0.0f, 50.0f}}); histos.add("Chi2perclusterTOF", "Chi2 / cluster for the TOF track segment", kTH1F, {{50, 0.0f, 50.0f}}); - histos.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {{100, 0.0f, 100.0f}, {axisPt}}); } if (!isMC) { - histos.add("h3PhiInvMassUnlikeSign", "Invariant mass of Phi meson Unlike Sign", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassLikeSignPP", "Invariant mass of Phi meson Like Sign positive", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassLikeSignMM", "Invariant mass of Phi meson Like Sign negative", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassMixed", "Invariant mass of Phi meson Mixed", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassRotation", "Invariant mass of Phi meson Rotation", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - if (isEtaAssym) { - histos.add("h3PhiInvMassUnlikeSignAside", "Invariant mass of Phi meson Unlike Sign A side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassLikeSignAside", "Invariant mass of Phi meson Like Sign A side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassMixedAside", "Invariant mass of Phi meson Mixed A side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassUnlikeSignCside", "Invariant mass of Phi meson Unlike Sign C side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassLikeSignCside", "Invariant mass of Phi meson Like Sign C side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - histos.add("h3PhiInvMassMixedCside", "Invariant mass of Phi meson Mixed C side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); - } + histos.add("h3PhiInvMassUnlikeSign", "KK Unlike Sign", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + histos.add("h3PhiInvMassLikeSignPP", "KK Like Sign +", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + histos.add("h3PhiInvMassLikeSignMM", "KK Like Sign -", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + histos.add("h3PhiInvMassMixed", "KK Mixed", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + histos.add("h3PhiInvMassRotation", "KK Rotation", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); } else if (isMC) { histos.add("hMC", "MC Event statistics", kTH1F, {{6, 0.0f, 6.0f}}); histos.add("h1PhiGen", "Phi meson Gen", kTH1F, {axisPt}); @@ -174,6 +224,7 @@ struct kaonkaonAnalysisRun3 { array pvec1; array pvec1rotation; array pvec2rotation; + ROOT::Math::PxPyPzMVector daughter1, daughter2; template bool eventselection(Collision const& collision, const float& multiplicity) @@ -258,44 +309,19 @@ struct kaonkaonAnalysisRun3 { } return true; } - template - void FillinvMass(const T1& candidate1, const T2& candidate2, float multiplicity, bool unlike, bool mix, bool likesign, bool rotation, float massd1, float massd2) + template + void FillinvMass(const T1& candidate1, const T2& candidate2, const T3& framecalculation, float multiplicity, bool unlike, bool mix, bool likesign, bool rotation, float massd1, float massd2) { - pvec0 = array{candidate1.px(), candidate1.py(), candidate1.pz()}; - pvec1 = array{candidate2.px(), candidate2.py(), candidate2.pz()}; - pvec1rotation = array{-candidate2.px(), -candidate2.py(), candidate2.pz()}; - pvec2rotation = array{-candidate1.px(), -candidate1.py(), candidate1.pz()}; - auto arrMom = array{pvec0, pvec1}; - auto arrMomrotation1 = array{pvec0, pvec1rotation}; - auto arrMomrotation2 = array{pvec1, pvec2rotation}; + TRandom* rn = new TRandom(); int track1Sign = candidate1.sign(); int track2Sign = candidate2.sign(); - mass = RecoDecay::m(arrMom, array{massd1, massd2}); - massrotation1 = RecoDecay::m(arrMomrotation1, array{massd1, massd2}); - massrotation2 = RecoDecay::m(arrMomrotation2, array{massd1, massd2}); - pT = RecoDecay::pt(array{candidate1.px() + candidate2.px(), candidate1.py() + candidate2.py()}); - rapidity = RecoDecay::y(array{candidate1.px() + candidate2.px(), candidate1.py() + candidate2.py(), candidate1.pz() + candidate2.pz()}, mass); - if (isEtaAssym && unlike && track1Sign * track2Sign < 0) { - if (candidate1.eta() > 0.2 && candidate1.eta() < 0.8 && candidate2.eta() > 0.2 && candidate2.eta() < 0.8) { - histos.fill(HIST("h3PhiInvMassUnlikeSignAside"), multiplicity, pT, mass); - } else if (candidate1.eta() > -0.6 && candidate1.eta() < 0.0 && candidate2.eta() > -0.6 && candidate2.eta() < 0.0) { - histos.fill(HIST("h3PhiInvMassUnlikeSignCside"), multiplicity, pT, mass); - } - } - if (isEtaAssym && mix && track1Sign * track2Sign < 0) { - if (candidate1.eta() > 0.2 && candidate1.eta() < 0.8 && candidate2.eta() > 0.2 && candidate2.eta() < 0.8) { - histos.fill(HIST("h3PhiInvMassMixedAside"), multiplicity, pT, mass); - } else if (candidate1.eta() > -0.6 && candidate1.eta() < 0.0 && candidate2.eta() > -0.6 && candidate2.eta() < 0.0) { - histos.fill(HIST("h3PhiInvMassMixedCside"), multiplicity, pT, mass); - } - } - if (isEtaAssym && likesign && track1Sign * track2Sign > 0) { - if (candidate1.eta() > 0.2 && candidate1.eta() < 0.8 && candidate2.eta() > 0.2 && candidate2.eta() < 0.8) { - histos.fill(HIST("h3PhiInvMassLikeSignAside"), multiplicity, pT, mass); - } else if (candidate1.eta() > -0.6 && candidate1.eta() < 0.0 && candidate2.eta() > -0.6 && candidate2.eta() < 0.0) { - histos.fill(HIST("h3PhiInvMassLikeSignCside"), multiplicity, pT, mass); - } - } + TLorentzVector vec1, vec2, vec3, vec4, vec5; + vec1.SetPtEtaPhiM(candidate1.pt(), candidate1.eta(), candidate1.phi(), massd1); + vec2.SetPtEtaPhiM(candidate2.pt(), candidate2.eta(), candidate2.phi(), massd2); + vec3 = vec1 + vec2; + // daughter1 = ROOT::Math::PxPyPzMVector(candidate1.px(), candidate1.py(), candidate1.pz(), massd1); // Kplus + // daughter2 = ROOT::Math::PxPyPzMVector(candidate2.px(), candidate2.py(), candidate2.pz(), massd2); // Kminus + double rapidity = vec3.Rapidity(); if (otherQAplots) { histos.fill(HIST("Chi2perclusterITS"), candidate1.itsChi2NCl()); @@ -306,30 +332,51 @@ struct kaonkaonAnalysisRun3 { histos.fill(HIST("Chi2perclusterTRD"), candidate2.trdChi2()); histos.fill(HIST("Chi2perclusterTOF"), candidate1.tofChi2()); histos.fill(HIST("Chi2perclusterTOF"), candidate2.tofChi2()); - histos.fill(HIST("dE_by_dx_TPC"), candidate1.tpcSignal(), candidate1.pt()); - histos.fill(HIST("dE_by_dx_TPC"), candidate2.tpcSignal(), candidate2.pt()); + } + if (QAPID) { + histos.fill(HIST("dE_by_dx_TPC"), candidate1.p(), candidate1.tpcSignal()); + histos.fill(HIST("dE_by_dx_TPC"), candidate2.p(), candidate2.tpcSignal()); } + // polarization calculations + // auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + // auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + // ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massd1); // Kaon + + // ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(vec3.Px(), vec3.Py(), vec3.Pz(), vec3.M()); // mass of KaonKaon pair + // ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + // ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + // ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + // default filling - if (std::abs(rapidity) < 0.5 && !isEtaAssym && track1Sign * track2Sign < 0) { + // if (activateTHnSparseCosThStarHelicity) { + // ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + // auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + if (std::abs(rapidity) < 0.5 && track1Sign * track2Sign < 0) { if (unlike) { - histos.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, pT, mass); + histos.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); } if (mix) { - histos.fill(HIST("h3PhiInvMassMixed"), multiplicity, pT, mass); + histos.fill(HIST("h3PhiInvMassMixed"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); } + if (rotation) { - histos.fill(HIST("h3PhiInvMassRotation"), multiplicity, pT, massrotation1); - histos.fill(HIST("h3PhiInvMassRotation"), multiplicity, pT, massrotation2); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + vec4.SetPtEtaPhiM(candidate1.pt(), candidate1.eta(), candidate1.phi() + theta2, massd1); // for rotated background + vec5 = vec4 + vec2; + histos.fill(HIST("h3PhiInvMassRotation"), multiplicity, vec5.Pt(), vec5.M(), framecalculation); + } } } - if (std::abs(rapidity) < 0.5 && !isEtaAssym && track1Sign * track2Sign > 0 && likesign) { + if (std::abs(rapidity) < 0.5 && track1Sign * track2Sign > 0 && likesign) { if (track1Sign > 0 && track2Sign > 0) { - histos.fill(HIST("h3PhiInvMassLikeSignPP"), multiplicity, pT, mass); + histos.fill(HIST("h3PhiInvMassLikeSignPP"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); } else { - histos.fill(HIST("h3PhiInvMassLikeSignMM"), multiplicity, pT, mass); + histos.fill(HIST("h3PhiInvMassLikeSignMM"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); } } + // } } Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -353,19 +400,26 @@ struct kaonkaonAnalysisRun3 { multiplicity = collision.centFT0M(); else multiplicity = collision.centFT0C(); - histos.fill(HIST("hCentrality"), multiplicity); - histos.fill(HIST("hNcontributor"), collision.numContrib()); - histos.fill(HIST("hVtxZ"), collision.posZ()); + if (QAevents) { + histos.fill(HIST("hmutiplicity"), multiplicity); + histos.fill(HIST("hVtxZ"), collision.posZ()); + histos.fill(HIST("hNcontributor"), collision.numContrib()); + histos.fill(HIST("multdist_FT0M"), collision.multFT0M()); + histos.fill(HIST("multdist_FT0A"), collision.multFT0A()); + histos.fill(HIST("multdist_FT0C"), collision.multFT0C()); + } for (auto track1 : tracks) { if (!selectionTrack(track1)) { continue; } - histos.fill(HIST("hEta"), track1.eta()); - histos.fill(HIST("hDcaxy"), track1.dcaXY()); - histos.fill(HIST("hDcaz"), track1.dcaZ()); - histos.fill(HIST("hNsigmaKaonTPC_before"), track1.pt(), track1.tpcNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF_before"), track1.pt(), track1.tofNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF_TPC_before"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); + if (QAPID) { + histos.fill(HIST("hEta"), track1.eta()); + histos.fill(HIST("hDcaxy"), track1.dcaXY()); + histos.fill(HIST("hDcaz"), track1.dcaZ()); + histos.fill(HIST("hNsigmaKaonTPC_before"), track1.pt(), track1.tpcNSigmaKa()); + histos.fill(HIST("hNsigmaKaonTOF_before"), track1.pt(), track1.tofNSigmaKa()); + histos.fill(HIST("hNsigmaKaonTOF_TPC_before"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); + } auto track1ID = track1.index(); for (auto track2 : tracks) { if (!selectionTrack(track2)) { @@ -379,19 +433,74 @@ struct kaonkaonAnalysisRun3 { continue; } + // calculation of event planes + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); // Kplus + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); // Kminus + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massKa); // Kaon + TLorentzVector lv1, lv2, lv3; + lv1.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi(), massKa); + lv2.SetPtEtaPhiM(track2.pt(), track2.eta(), track2.phi(), massKa); + lv3 = lv1 + lv2; + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KaonKaon pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + bool unlike = true; bool mix = false; bool likesign = true; bool rotation = true; - if (isITSOnlycut) { - FillinvMass(track1, track2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { - FillinvMass(track1, track2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - histos.fill(HIST("hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + + if (isITSOnlycut) { + FillinvMass(track1, track2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { + FillinvMass(track1, track2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + + if (isITSOnlycut) { + FillinvMass(track1, track2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { + FillinvMass(track1, track2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (isITSOnlycut) { + FillinvMass(track1, track2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { + FillinvMass(track1, track2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (isITSOnlycut) { + FillinvMass(track1, track2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { + FillinvMass(track1, track2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } } + + // if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { + // // histos.fill(HIST("hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); + // // histos.fill(HIST("hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); + // // histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); + // } } } } @@ -436,12 +545,77 @@ struct kaonkaonAnalysisRun3 { if (!selectionPair(t1, t2)) { continue; } - if (isITSOnlycut) { - FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + + // calculation of event planes + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); // Kplus + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); // Kminus + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massKa); // Kaon + TLorentzVector lv1, lv2, lv3; + lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); + lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massKa); + lv3 = lv1 + lv2; + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KaonKaon pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } } + + // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + // histos.fill(HIST("hNsigmaKaonTPC_after"), t1.pt(), t1.tpcNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTOF_after"), t1.pt(), t1.tofNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), t1.tofNSigmaKa(), t1.tpcNSigmaKa()); + // } + // if (isITSOnlycut) { + // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + // } + // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + // } } } } else { @@ -468,12 +642,78 @@ struct kaonkaonAnalysisRun3 { if (!selectionPair(t1, t2)) { continue; } - if (isITSOnlycut) { - FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + + // calculation of event planes + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); // Kplus + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); // Kminus + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massKa); // Kaon + TLorentzVector lv1, lv2, lv3; + lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); + lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massKa); + lv3 = lv1 + lv2; + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KaonKaon pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (isITSOnlycut) { + FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } + if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + } } + + // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + // histos.fill(HIST("hNsigmaKaonTPC_after"), t1.pt(), t1.tpcNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTOF_after"), t1.pt(), t1.tofNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), t1.tofNSigmaKa(), t1.tpcNSigmaKa()); + // } + + // if (isITSOnlycut) { + // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + // } + // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { + // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); + // } } } } diff --git a/PWGLF/Tasks/Resonances/kstar892analysis.cxx b/PWGLF/Tasks/Resonances/kstar892analysis.cxx new file mode 100644 index 00000000000..ba456d46532 --- /dev/null +++ b/PWGLF/Tasks/Resonances/kstar892analysis.cxx @@ -0,0 +1,912 @@ +// Copyright 2019-2020 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. + +/// \file kstar892analysis.cxx +/// \brief Reconstruction of track-track decay resonance candidates +/// +/// +/// adaped from k892analysis.cxx by Bong-Hwi Lim , Sawan Sawan +/// \author Marta Urioni + +#include +#include "TF1.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" +#include "DataFormatsParameters/GRPObject.h" +#include "CommonConstants/PhysicsConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::constants::physics; + +struct kstar892analysis { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + ///// Configurables + /// Histograms + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15.0}, "Binning of the pT axis"}; + ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0}, "Binning of the pT axis"}; + ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0}, "Binning of the centrality axis"}; + ConfigurableAxis binsImpactPar{"binsImpactPar", {VARIABLE_WIDTH, 0.0, 3.00065, 4.28798, 6.14552, 7.6196, 8.90942, 10.0897, 11.2002, 12.2709, 13.3167, 14.4173, 23.2518}, "Binning of the impact parameter axis"}; + + Configurable cInvMassStart{"cInvMassStart", 0.6, "Invariant mass start"}; + Configurable cInvMassEnd{"cInvMassEnd", 1.5, "Invariant mass end"}; + Configurable cInvMassBins{"cInvMassBins", 900, "Invariant mass binning"}; + Configurable cPIDBins{"cPIDBins", 65, "PID binning"}; + Configurable cPIDQALimit{"cPIDQALimit", 6.5, "PID QA limit"}; + Configurable cDCABins{"cDCABins", 150, "DCA binning"}; + /// Event Mixing + Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 1.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 110.0f}, "Mixing bins - z-vertex"}; + + /// Pre-selection cuts + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; + /// DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; + /// PID Selections + Configurable cfgHighPt{"cfgHighPt", 999.0, "Minimum Pt to apply tighter PID selections on Mixed Event"}; + // Pion + Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cMaxTPCnSigmaPionHighPtME{"cMaxTPCnSigmaPionHighPtME", 2.0, "TPC nSigma cut for Pion at high pt for Mixed Event"}; // TPC + Configurable cMaxTOFnSigmaPionHighPtME{"cMaxTOFnSigmaPionHighPtME", 2.0, "TOF nSigma cut for Pion at high pt for Mixed Event"}; // TOF + Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined + // Kaon + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC + Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF + Configurable cMaxTPCnSigmaKaonHighPtME{"cMaxTPCnSigmaKaonHighPtME", 2.0, "TPC nSigma cut for Kaon at pt>3GeV for Mixed Event"}; // TPC + Configurable cMaxTOFnSigmaKaonHighPtME{"cMaxTOFnSigmaKaonHighPtME", 2.0, "TOF nSigma cut for Kaon at pt>3GeV for Mixed Event"}; // TOF + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", -999, "Combined nSigma cut for Kaon"}; // Combined + + Configurable cByPassTOF{"cByPassTOF", false, "By pass TOF PID selection"}; // By pass TOF PID selection + Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable additionalQAeventPlots{"additionalQAeventPlots", false, "Additional QA event plots"}; + Configurable additionalMEPlots{"additionalMEPlots", false, "Additional Mixed event plots"}; + + Configurable tof_at_high_pt{"tof_at_high_pt", false, "Use TOF at high pT"}; + Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; + Configurable cfgRatioTPCRowsOverFindableCls{"cfgRatioTPCRowsOverFindableCls", 0.0f, "TPC Crossed Rows to Findable Clusters"}; + Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 999.0, "ITS Chi2/NCl"}; + Configurable cfgTPCChi2NCl{"cfgTPCChi2NCl", 999.0, "TPC Chi2/NCl"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + + // MC Event selection + Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; + + // cuts on mother + Configurable cfgCutsOnMother{"cfgCutsOnMother", false, "Enamble additional cuts on mother"}; + Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 15.0, "Maximum pt of mother cut"}; + Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 1.5, "Maximum Minv of mother cut"}; + + // configurables for partitions + Configurable cMaxPtTPC{"cMaxPtTPC", 1.2, "maximum pt to apply TPC PID and TOF if available"}; + Configurable cMinPtTOF{"cMinPtTOF", 0.8, "minimum pt to require TOF PID in addition to TPC"}; + + void init(o2::framework::InitContext&) + { + + // LOG(info) << "\n cfgITScluster ============>"<< static_cast(cfgITScluster); + // LOG(info)<< "\n cfgTPCcluster ============>"<< static_cast(cfgTPCcluster); + + AxisSpec centAxis = {binsCent, "V0M (%)"}; + AxisSpec ImpactParAxis = {binsImpactPar, "Impact Parameter"}; + AxisSpec dcaxyAxis = {cDCABins, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {cDCABins, 0.0, 3.0, "DCA_{#it{z}} (cm)"}; + AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; + AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisQA = {binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec pidQAAxis = {cPIDBins, -cPIDQALimit, cPIDQALimit}; + + if (additionalQAeventPlots) { + // Test on Mixed event + histos.add("TestME/hCollisionIndexSameE", "coll index sameE", HistType::kTH1F, {{500, 0.0f, 500.0f}}); + histos.add("TestME/hCollisionIndexMixedE", "coll index mixedE", HistType::kTH1F, {{500, 0.0f, 500.0f}}); + histos.add("TestME/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); + histos.add("TestME/hnTrksMixedE", "n tracks per event MixedE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); + histos.add("TestME/hPairsCounterSameE", "tot n pairs sameE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + histos.add("TestME/hPairsCounterMixedE", "tot n pairs mixedE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + + // event histograms + histos.add("QAevent/hEvtCounterSameE", "Number of analyzed Same Events", HistType::kTH1F, {{1, 0.5, 1.5}}); + histos.add("QAevent/hVertexZSameE", "Collision Vertex Z position", HistType::kTH1F, {{100, -15., 15.}}); + histos.add("QAevent/hMultiplicityPercentSameE", "Multiplicity percentile of collision", HistType::kTH1F, {{120, 0.0f, 120.0f}}); + + histos.add("QAevent/hEvtCounterMixedE", "Number of analyzed Mixed Events", HistType::kTH1F, {{1, 0.5, 1.5}}); + histos.add("QAevent/hVertexZMixedE", "Collision Vertex Z position", HistType::kTH1F, {{100, -15., 15.}}); + histos.add("QAevent/hMultiplicityPercentMixedE", "Multiplicity percentile of collision", HistType::kTH1F, {{120, 0.0f, 120.0f}}); + } + + // Mass QA (quick check) + histos.add("k892invmassDS", "Invariant mass of K(892)0 different sign", kTH1F, {invMassAxis}); + histos.add("k892invmassDSAnti", "Invariant mass of Anti-K(892)0 different sign", kTH1F, {invMassAxis}); + histos.add("k892invmassLS", "Invariant mass of K(892)0 like sign", kTH1F, {invMassAxis}); + histos.add("k892invmassLSAnti", "Invariant mass of Anti-K(892)0 like sign", kTH1F, {invMassAxis}); + if (doprocessMELight || doprocessMELightWithTof || doprocessMELightTPCLowPt || doprocessMELightTOFHighPt) { + histos.add("k892invmassME", "Invariant mass of K(892)0 mixed event", kTH1F, {invMassAxis}); + if (additionalMEPlots) { + histos.add("k892invmassME_DS", "Invariant mass of K(892)0 mixed event DS", kTH1F, {invMassAxis}); + histos.add("k892invmassME_DSAnti", "Invariant mass of K(892)0 mixed event DSAnti", kTH1F, {invMassAxis}); + } + } + + if (additionalQAplots) { + // TPC ncluster distirbutions + histos.add("TPCncluster/TPCnclusterpi", "TPC ncluster distribution", kTH1F, {{160, 0, 160, "TPC nCluster"}}); + histos.add("TPCncluster/TPCnclusterka", "TPC ncluster distribution", kTH1F, {{160, 0, 160, "TPC nCluster"}}); + histos.add("TPCncluster/TPCnclusterPhipi", "TPC ncluster vs phi", kTH2F, {{160, 0, 160, "TPC nCluster"}, {63, 0, 6.28, "#phi"}}); + histos.add("TPCncluster/TPCnclusterPhika", "TPC ncluster vs phi", kTH2F, {{160, 0, 160, "TPC nCluster"}, {63, 0, 6.28, "#phi"}}); + } + + // DCA QA + histos.add("QA/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QA/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + // pT QA + histos.add("QA/trkpT_pi", "pT distribution of pion track candidates", kTH1F, {ptAxis}); + histos.add("QA/trkpT_ka", "pT distribution of kaon track candidates", kTH1F, {ptAxis}); + // PID QA + histos.add("QA/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QA/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QA/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QA/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QA/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QA/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + + // 3d histogram + histos.add("h3k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassLS", "Invariant mass of K(892)0 same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassLSAnti", "Invariant mass of Anti-K(892)0 same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + if (doprocessMELight || doprocessMELightWithTof || doprocessMELightTPCLowPt || doprocessMELightTOFHighPt) { + histos.add("h3k892invmassME", "Invariant mass of K(892)0 mixed event", kTH3F, {centAxis, ptAxis, invMassAxis}); + + if (additionalMEPlots) { + histos.add("QAME/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QAME/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAME/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAME/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QAME/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAME/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + + histos.add("h3k892invmassME_DS", "Invariant mass of K(892)0 mixed event DS", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassME_DSAnti", "Invariant mass of K(892)0 mixed event DSAnti", kTH3F, {centAxis, ptAxis, invMassAxis}); + } + } + + if (doprocessMCLight || doprocessMCLightWithTof || doprocessMCLightTPCLowPt || doprocessMCLightTOFHighPt) { + // MC QA + histos.add("QAMCTrue/ImpactParameter", "Impact parameter of event", HistType::kTH1F, {ImpactParAxis}); + histos.add("QAMCTrue/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMCTrue/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMCTrue/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAMCTrue/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAMCTrue/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAMCTrue/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAMCTrue/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + histos.add("QAMCTrue/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); + + histos.add("k892Recinvmass", "Inv mass distribution of Reconstructed MC K(892)", kTH1F, {invMassAxis}); + histos.add("k892GenInvmass", "Invariant mass of generated K(892)0", kTH1F, {invMassAxis}); + histos.add("k892GenInvmassAnti", "Invariant mass of generated Anti-K(892)0", kTH1F, {invMassAxis}); + + histos.add("h3Reck892invmass", "Invariant mass of Reconstructed MC K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3Reck892invmassAnti", "Invariant mass of Reconstructed MC Anti-K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("k892Gen", "pT distribution of True MC K(892)0", kTH3F, {mcLabelAxis, ptAxis, centAxis}); + histos.add("k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTH3F, {mcLabelAxis, ptAxis, centAxis}); + histos.add("k892Rec", "pT distribution of Reconstructed MC K(892)0", kTH2F, {ptAxis, centAxis}); + histos.add("k892RecAnti", "pT distribution of Reconstructed MC Anti-K(892)0", kTH2F, {ptAxis, centAxis}); + histos.add("h3k892GenInvmass", "Invariant mass of generated K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892GenInvmassAnti", "Invariant mass of generated Anti-K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); + + histos.add("ImpactParPlots/h3Reck892invmass", "Invariant mass of Reconstructed MC K(892)0", kTH3F, {ImpactParAxis, ptAxis, invMassAxis}); + histos.add("ImpactParPlots/h3Reck892invmassAnti", "Invariant mass of Reconstructed MC Anti-K(892)0", kTH3F, {ImpactParAxis, ptAxis, invMassAxis}); + histos.add("ImpactParPlots/k892Gen", "pT distribution of True MC K(892)0", kTH3F, {mcLabelAxis, ptAxis, ImpactParAxis}); + histos.add("ImpactParPlots/k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTH3F, {mcLabelAxis, ptAxis, ImpactParAxis}); + histos.add("ImpactParPlots/k892Rec", "pT distribution of Reconstructed MC K(892)0", kTH2F, {ptAxis, ImpactParAxis}); + histos.add("ImpactParPlots/k892RecAnti", "pT distribution of Reconstructed MC Anti-K(892)0", kTH2F, {ptAxis, ImpactParAxis}); + histos.add("ImpactParPlots/h3k892GenInvmass", "Invariant mass of generated K(892)0", kTH3F, {ImpactParAxis, ptAxis, invMassAxis}); + histos.add("ImpactParPlots/h3k892GenInvmassAnti", "Invariant mass of generated Anti-K(892)0", kTH3F, {ImpactParAxis, ptAxis, invMassAxis}); + } + // Print output histograms statistics + LOG(info) << "Size of the histograms in spectraTOF"; + histos.print(); + } + + /////////////////////////////////////////////////////// + + SliceCache cache; + Preslice perRCol = aod::resodaughter::resoCollisionId; + Preslice perCollision = aod::track::collisionId; + + // Filters + Filter acceptanceFilter = nabs(aod::resodaughter::pt) >= cMinPtcut; + Filter qualityFilter = (aod::track::itsChi2NCl <= cfgITSChi2NCl) && (aod::track::tpcChi2NCl <= cfgTPCChi2NCl) && (aod::resodaughter::tpcCrossedRowsOverFindableCls >= cfgRatioTPCRowsOverFindableCls); + Filter DCAcutFilter = (nabs(aod::track::dcaXY) <= cMaxDCArToPVcut) && (nabs(aod::track::dcaZ) <= cMaxDCAzToPVcut); + Filter hasTPCfilter = aod::resodaughter::hasTPC == true; + Filter primarytrackFilter = aod::resodaughter::isPVContributor && aod::resodaughter::isPrimaryTrack && aod::resodaughter::isGlobalTrackWoDCA; + + // partitions for data + Partition> resoKaWithTof = (nabs(aod::pidtof::tofNSigmaKa) <= cMaxTOFnSigmaKaon) && (aod::resodaughter::hasTOF == true); + Partition> resoPiWithTof = (nabs(aod::pidtof::tofNSigmaPi) <= cMaxTOFnSigmaPion) && (aod::resodaughter::hasTOF == true); + Partition> resoKa = (nabs(aod::pidtpc::tpcNSigmaKa) <= cMaxTPCnSigmaKaon); + Partition> resoPi = (nabs(aod::pidtpc::tpcNSigmaPi) <= cMaxTPCnSigmaPion); + Partition> resoKaTPClowPt = (nabs(aod::pidtpc::tpcNSigmaKa) <= cMaxTPCnSigmaKaon) && (nabs(aod::resodaughter::pt) < cMaxPtTPC); + Partition> resoPiTPClowPt = (nabs(aod::pidtpc::tpcNSigmaPi) <= cMaxTPCnSigmaPion) && (nabs(aod::resodaughter::pt) < cMaxPtTPC); + Partition> resoKaTOFhighPt = (nabs(aod::pidtof::tofNSigmaKa) <= cMaxTOFnSigmaKaon) && (aod::resodaughter::hasTOF == true) && (nabs(aod::resodaughter::pt) >= cMinPtTOF); + Partition> resoPiTOFhighPt = (nabs(aod::pidtof::tofNSigmaPi) <= cMaxTOFnSigmaPion) && (aod::resodaughter::hasTOF == true) && (nabs(aod::resodaughter::pt) >= cMinPtTOF); + + // Partitions for mc + Partition>> resoMCrecKaWithTof = (nabs(aod::pidtof::tofNSigmaKa) <= cMaxTOFnSigmaKaon) && (aod::resodaughter::hasTOF == true); + Partition>> resoMCrecPiWithTof = (nabs(aod::pidtof::tofNSigmaPi) <= cMaxTOFnSigmaPion) && (aod::resodaughter::hasTOF == true); + Partition>> resoMCrecKa = (nabs(aod::pidtpc::tpcNSigmaKa) <= cMaxTPCnSigmaKaon); + Partition>> resoMCrecPi = (nabs(aod::pidtpc::tpcNSigmaPi) <= cMaxTPCnSigmaPion); + Partition>> resoMCrecKaTPClowPt = (nabs(aod::pidtpc::tpcNSigmaKa) <= cMaxTPCnSigmaKaon) && (nabs(aod::resodaughter::pt) < cMaxPtTPC); + Partition>> resoMCrecPiTPClowPt = (nabs(aod::pidtpc::tpcNSigmaPi) <= cMaxTPCnSigmaPion) && (nabs(aod::resodaughter::pt) < cMaxPtTPC); + Partition>> resoMCrecKaTOFhighPt = (nabs(aod::pidtof::tofNSigmaKa) <= cMaxTOFnSigmaKaon) && (aod::resodaughter::hasTOF == true) && (nabs(aod::resodaughter::pt) >= cMinPtTOF); + Partition>> resoMCrecPiTOFhighPt = (nabs(aod::pidtof::tofNSigmaPi) <= cMaxTOFnSigmaPion) && (aod::resodaughter::hasTOF == true) && (nabs(aod::resodaughter::pt) >= cMinPtTOF); + + using ResoMCCols = soa::Join; + + //****************************************** + + float massKa = MassKaonCharged; + float massPi = MassPionCharged; + + template + bool trackCut(const TrackType track) + { + if (track.itsNCls() < cfgITScluster) + return false; + if (track.tpcNClsFound() < cfgTPCcluster) + return false; + + if (cfgUseITSRefit && !track.passedITSRefit()) + return false; + if (cfgUseTPCRefit && !track.passedTPCRefit()) + return false; + + if (cfgGlobalTrack && !track.isGlobalTrack()) + return false; + + return true; + } + // PID selection tools + + template + bool selectionPIDPion(const T& candidate) + { + if (tof_at_high_pt) { + if (candidate.hasTOF() && (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaPion)) { + return true; + } + if (!candidate.hasTOF() && (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion)) { + return true; + } + } else { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { + tpcPIDPassed = true; + } + if (cByPassTOF && tpcPIDPassed) { + return true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaPion) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedPion > 0) && (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < nsigmaCutCombinedPion * nsigmaCutCombinedPion)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } + return false; + } + template + bool selectionPIDKaon(const T& candidate) + { + if (tof_at_high_pt) { + if (candidate.hasTOF() && (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon)) { + return true; + } + if (!candidate.hasTOF() && (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon)) { + return true; + } + } else { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + tpcPIDPassed = true; + } + if (cByPassTOF && tpcPIDPassed) { + return true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } + return false; + } + + template + bool selectionPIDPionME(const T& candidate) + { + float NsigmaTOF; + float NsigmaTPC; + + if (std::abs(candidate.pt()) < cfgHighPt) { + NsigmaTOF = cMaxTOFnSigmaPion; + NsigmaTPC = cMaxTPCnSigmaPion; + } else { + NsigmaTOF = cMaxTOFnSigmaPionHighPtME; + NsigmaTPC = cMaxTPCnSigmaPionHighPtME; + } + + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaPi()) < NsigmaTPC) { + tpcPIDPassed = true; + } + if (cByPassTOF && tpcPIDPassed) { + return true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < NsigmaTOF) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + template + bool selectionPIDKaonME(const T& candidate) + { + float NsigmaTOF; + float NsigmaTPC; + + if (std::abs(candidate.pt()) < cfgHighPt) { + NsigmaTOF = cMaxTOFnSigmaKaon; + NsigmaTPC = cMaxTPCnSigmaKaon; + } else { + NsigmaTOF = cMaxTOFnSigmaKaonHighPtME; + NsigmaTPC = cMaxTPCnSigmaKaonHighPtME; + } + + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < NsigmaTPC) { + tpcPIDPassed = true; + } + if (cByPassTOF && tpcPIDPassed) { + return true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < NsigmaTOF) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + // auto multNTracksPV = collision.multNTracksPV(); + float impactpar = -999.0; + if constexpr (IsMC) { + impactpar = collision.impactParameter(); + } + auto multiplicity = collision.cent(); + + if (additionalQAeventPlots) { + if constexpr (!IsMix) { + histos.fill(HIST("QAevent/hVertexZSameE"), collision.posZ()); + histos.fill(HIST("QAevent/hMultiplicityPercentSameE"), collision.cent()); + histos.fill(HIST("TestME/hCollisionIndexSameE"), collision.globalIndex()); + histos.fill(HIST("TestME/hnTrksSameE"), dTracks1.size()); + } else { + histos.fill(HIST("QAevent/hVertexZMixedE"), collision.posZ()); + histos.fill(HIST("QAevent/hMultiplicityPercentMixedE"), collision.cent()); + histos.fill(HIST("TestME/hCollisionIndexMixedE"), collision.globalIndex()); + histos.fill(HIST("TestME/hnTrksMixedE"), dTracks1.size()); + } + } + + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { + + // Full index policy is needed to consider all possible combinations + if (trk1.index() == trk2.index()) + continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + + if (additionalQAeventPlots) { + if constexpr (!IsMix) { + histos.fill(HIST("TestME/hPairsCounterSameE"), 1.0); + } else { + histos.fill(HIST("TestME/hPairsCounterMixedE"), 1.0); + } + } + + //// Initialize variables + // Trk1: Pion, Trk2: Kaon + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); + auto trk1ptPi = trk1.pt(); + auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; + auto trk2ptKa = trk2.pt(); + auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); + auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; + + if constexpr (!IsMix) { + if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) + continue; + } else { + if (!selectionPIDPionME(trk1) || !selectionPIDKaonME(trk2)) + continue; + } + + if (additionalQAplots) { + // TPCncluster distributions + histos.fill(HIST("TPCncluster/TPCnclusterpi"), trk1.tpcNClsFound()); + histos.fill(HIST("TPCncluster/TPCnclusterka"), trk2.tpcNClsFound()); + histos.fill(HIST("TPCncluster/TPCnclusterPhipi"), trk1.tpcNClsFound(), trk1.phi()); + histos.fill(HIST("TPCncluster/TPCnclusterPhika"), trk2.tpcNClsFound(), trk2.phi()); + } + + if constexpr (!IsMix) { + //// QA plots after the selection + // --- PID QA Pion + histos.fill(HIST("QA/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QA/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + // --- PID QA Kaon + histos.fill(HIST("QA/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + histos.fill(HIST("QA/trkpT_pi"), trk1ptPi); + histos.fill(HIST("QA/trkpT_ka"), trk2ptKa); + histos.fill(HIST("QA/trkDCAxy_pi"), trk1.dcaXY()); + histos.fill(HIST("QA/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QA/trkDCAz_pi"), trk1.dcaZ()); + histos.fill(HIST("QA/trkDCAz_ka"), trk2.dcaZ()); + } else if (additionalMEPlots) { + // --- PID QA Pion + histos.fill(HIST("QAME/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAME/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAME/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + // --- PID QA Kaon + histos.fill(HIST("QAME/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAME/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QAME/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + } + + //// Resonance reconstruction + lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + lResonance = lDecayDaughter1 + lDecayDaughter2; + // Rapidity cut + if (abs(lResonance.Rapidity()) >= 0.5) + continue; + if (cfgCutsOnMother) { + if (lResonance.Pt() >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (lResonance.M() >= cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + + //// Un-like sign pair only + if (trk1.sign() * trk2.sign() < 0) { + if constexpr (!IsMix) { + if (trk1.sign() < 0) { + histos.fill(HIST("k892invmassDS"), lResonance.M()); + histos.fill(HIST("h3k892invmassDS"), multiplicity, lResonance.Pt(), lResonance.M()); + } else if (trk1.sign() > 0) { + histos.fill(HIST("k892invmassDSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassDSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + } + } else { + histos.fill(HIST("k892invmassME"), lResonance.M()); + histos.fill(HIST("h3k892invmassME"), multiplicity, lResonance.Pt(), lResonance.M()); + if (additionalMEPlots) { + if (trk1.sign() < 0) { + histos.fill(HIST("k892invmassME_DS"), lResonance.M()); + histos.fill(HIST("h3k892invmassME_DS"), multiplicity, lResonance.Pt(), lResonance.M()); + } else if (trk1.sign() > 0) { + histos.fill(HIST("k892invmassME_DSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassME_DSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + } + } + } + + // MC + if constexpr (IsMC) { + if (abs(trk1.pdgCode()) != 211 || abs(trk2.pdgCode()) != 321) + continue; + if (trk1.motherId() != trk2.motherId()) // Same mother + continue; + if (abs(trk1.motherPDG()) != 313) + continue; + + // Track selection check. + histos.fill(HIST("QAMCTrue/trkDCAxy_pi"), trk1.dcaXY()); + histos.fill(HIST("QAMCTrue/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QAMCTrue/trkDCAz_pi"), trk1.dcaZ()); + histos.fill(HIST("QAMCTrue/trkDCAz_ka"), trk2.dcaZ()); + histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMCTrue/TOF_Nsigma_pi_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); + } + histos.fill(HIST("QAMCTrue/TPC_Nsigmaka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMCTrue/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); + } + + // MC histograms + if (trk1.motherPDG() < 0) { + histos.fill(HIST("k892Rec"), lResonance.Pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892Rec"), lResonance.Pt(), impactpar); + histos.fill(HIST("k892Recinvmass"), lResonance.M()); + histos.fill(HIST("h3Reck892invmass"), multiplicity, lResonance.Pt(), lResonance.M()); + histos.fill(HIST("ImpactParPlots/h3Reck892invmass"), impactpar, lResonance.Pt(), lResonance.M()); + } else { + histos.fill(HIST("k892RecAnti"), lResonance.Pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892RecAnti"), lResonance.Pt(), impactpar); + histos.fill(HIST("k892Recinvmass"), lResonance.M()); + histos.fill(HIST("h3Reck892invmassAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + histos.fill(HIST("ImpactParPlots/h3Reck892invmassAnti"), impactpar, lResonance.Pt(), lResonance.M()); + } + } + } else if (trk1.sign() * trk2.sign() > 0) { + if constexpr (!IsMix) { + if (trk1.sign() < 0) { + histos.fill(HIST("k892invmassLS"), lResonance.M()); + histos.fill(HIST("h3k892invmassLS"), multiplicity, lResonance.Pt(), lResonance.M()); + } else if (trk1.sign() > 0) { + histos.fill(HIST("k892invmassLSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassLSAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + } + } + } + } + } // end of fillHistograms + + /////////////////////////////////////////////////////////////////////////////// + ///// ///// + ///// PROCESS FUNCTIONS ///// + ///// ///// + /////////////////////////////////////////////////////////////////////////////// + + void processDataLight(aod::ResoCollision& collision, + soa::Filtered const&) + { + // LOG(info) << "new collision, zvtx: " << collision.posZ(); + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterSameE"), 1.0); + + auto candPi = resoPi->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKa = resoKa->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPi, candKa); + } + PROCESS_SWITCH(kstar892analysis, processDataLight, "Process Event for data", false); + + void processDataLightWithTof(aod::ResoCollision& collision, + soa::Filtered const&) + { + // LOG(info) << "new collision, zvtx: " << collision.posZ(); + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterSameE"), 1.0); + + auto candPiwithtof = resoPiWithTof->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKawithtof = resoKaWithTof->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPiwithtof, candKawithtof); + } + PROCESS_SWITCH(kstar892analysis, processDataLightWithTof, "Process Event for data, tracks with TOF", false); + + void processDataTPCLowPt(aod::ResoCollision& collision, + soa::Filtered const&) + { + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterSameE"), 1.0); + + auto candPi = resoPiTPClowPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKa = resoKaTPClowPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPi, candKa); + } + PROCESS_SWITCH(kstar892analysis, processDataTPCLowPt, "Process Event for data, TPC at low pt", false); + + void processDataTOFHighPt(aod::ResoCollision& collision, + soa::Filtered const&) + { + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterSameE"), 1.0); + + auto candPi = resoPiTOFhighPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKa = resoKaTOFhighPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPi, candKa); + } + PROCESS_SWITCH(kstar892analysis, processDataTOFHighPt, "Process Event for data, TOF at high pt", false); + + void processMCLight(ResoMCCols::iterator const& collision, + soa::Filtered> const&) + { + if (!collision.isInAfterAllCuts() || (abs(collision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + return; + + auto candPi = resoMCrecPi->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKa = resoMCrecKa->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPi, candKa); + } + PROCESS_SWITCH(kstar892analysis, processMCLight, "Process Event for MC (Reconstructed)", false); + + void processMCLightWithTof(ResoMCCols::iterator const& collision, + soa::Filtered> const&) + { + if (!collision.isInAfterAllCuts() || (abs(collision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + return; + + auto candPiwithtof = resoMCrecPiWithTof->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKawithtof = resoMCrecKaWithTof->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPiwithtof, candKawithtof); + } + PROCESS_SWITCH(kstar892analysis, processMCLightWithTof, "Process Event for MC (Reconstructed), tracks with TOF", false); + + void processMCLightTPCLowPt(ResoMCCols::iterator const& collision, + soa::Filtered> const&) + { + if (!collision.isInAfterAllCuts() || (abs(collision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + return; + + auto candPi = resoMCrecPiTPClowPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKa = resoMCrecKaTPClowPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPi, candKa); + } + PROCESS_SWITCH(kstar892analysis, processMCLightTPCLowPt, "Process Event for MC (reconstructed), TPC at low pt", false); + + void processMCLightTOFHighPt(ResoMCCols::iterator const& collision, + soa::Filtered> const&) + { + if (!collision.isInAfterAllCuts() || (abs(collision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + return; + + auto candPi = resoMCrecPiTOFhighPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + auto candKa = resoMCrecKaTOFhighPt->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); + + fillHistograms(collision, candPi, candKa); + } + PROCESS_SWITCH(kstar892analysis, processMCLightTOFHighPt, "Process Event for MC (reconstructed), TOF at high pt", false); + + void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents& resoParents, aod::McParticles& mcparticles) + { + auto multiplicity = collision.cent(); + float impactpar = collision.impactParameter(); + histos.fill(HIST("QAMCTrue/ImpactParameter"), impactpar); + + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (abs(part.pdgCode()) != 313 || abs(part.y()) >= 0.5) + continue; + bool pass1 = abs(part.daughterPDG1()) == 211 || abs(part.daughterPDG2()) == 211; + bool pass2 = abs(part.daughterPDG1()) == 321 || abs(part.daughterPDG2()) == 321; + + if (!pass1 || !pass2) + continue; + + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + + std::vector listDaughters{}; + std::array dauPdgs = {211, 321}; + + auto mcparticle = part.mcParticle_as(); + + RecoDecay::getDaughters(mcparticle, &listDaughters, dauPdgs, 1); + + for (const auto& dauIdx : listDaughters) { + auto dauPart = mcparticles.rawIteratorAt(dauIdx - mcparticles.offset()); + + if (std::abs(dauPart.pdgCode()) == 211) { + lDecayDaughter1.SetXYZM(dauPart.px(), dauPart.py(), dauPart.pz(), massPi); + } else if (std::abs(dauPart.pdgCode()) == 321) { + lDecayDaughter2.SetXYZM(dauPart.px(), dauPart.py(), dauPart.pz(), massKa); + } + } + lResonance = lDecayDaughter1 + lDecayDaughter2; + + if (part.pdgCode() > 0) { // no cuts, purely generated + histos.fill(HIST("k892GenInvmass"), lResonance.M()); + histos.fill(HIST("h3k892GenInvmass"), multiplicity, lResonance.Pt(), lResonance.M()); + histos.fill(HIST("ImpactParPlots/h3k892GenInvmass"), impactpar, lResonance.Pt(), lResonance.M()); + } else { + histos.fill(HIST("k892GenInvmassAnti"), lResonance.M()); + histos.fill(HIST("h3k892GenInvmassAnti"), multiplicity, lResonance.Pt(), lResonance.M()); + histos.fill(HIST("ImpactParPlots/h3k892GenInvmassAnti"), impactpar, lResonance.Pt(), lResonance.M()); + } + + if (collision.isVtxIn10()) // INEL10 + { + if (part.pdgCode() > 0) { + histos.fill(HIST("k892Gen"), 0, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892Gen"), 0, part.pt(), impactpar); + } else { + histos.fill(HIST("k892GenAnti"), 0, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892GenAnti"), 0, part.pt(), impactpar); + } + } + if (collision.isVtxIn10() && collision.isInSel8()) // INEL>10, vtx10 + { + if (part.pdgCode() > 0) { + histos.fill(HIST("k892Gen"), 1, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892Gen"), 1, part.pt(), impactpar); + } else { + histos.fill(HIST("k892GenAnti"), 1, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892GenAnti"), 1, part.pt(), impactpar); + } + } + if (collision.isVtxIn10() && collision.isTriggerTVX()) // vtx10, TriggerTVX + { + if (part.pdgCode() > 0) { + histos.fill(HIST("k892Gen"), 2, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892Gen"), 2, part.pt(), impactpar); + } else { + histos.fill(HIST("k892GenAnti"), 2, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892GenAnti"), 2, part.pt(), impactpar); + } + } + if (collision.isInAfterAllCuts()) // after all event selection + { + if (part.pdgCode() > 0) { + histos.fill(HIST("k892Gen"), 3, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892Gen"), 3, part.pt(), impactpar); + } else { + histos.fill(HIST("k892GenAnti"), 3, part.pt(), multiplicity); + histos.fill(HIST("ImpactParPlots/k892GenAnti"), 3, part.pt(), impactpar); + } + } + } + } + PROCESS_SWITCH(kstar892analysis, processMCTrue, "Process Event for MC (Generated)", false); + + // Processing Event Mixing + using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processMELight(o2::aod::ResoCollisions& collisions, soa::Filtered const& resotracks) + { + auto tracksTuple = std::make_tuple(resotracks); + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair, BinningTypeVtxZT0M> pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterMixedE"), 1.0); + + auto candPi = resoPi->sliceByCached(aod::resodaughter::resoCollisionId, collision1.globalIndex(), cache); + auto candKa = resoKa->sliceByCached(aod::resodaughter::resoCollisionId, collision2.globalIndex(), cache); + + fillHistograms(collision1, candPi, candKa); + } + } + PROCESS_SWITCH(kstar892analysis, processMELight, "Process EventMixing light without partition", false); + + void processMELightWithTof(o2::aod::ResoCollisions& collisions, soa::Filtered const& resotracks) + { + auto tracksTuple = std::make_tuple(resotracks); + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair, BinningTypeVtxZT0M> pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterMixedE"), 1.0); + + auto candPiwithtof = resoPiWithTof->sliceByCached(aod::resodaughter::resoCollisionId, collision1.globalIndex(), cache); + auto candKawithtof = resoKaWithTof->sliceByCached(aod::resodaughter::resoCollisionId, collision2.globalIndex(), cache); + + fillHistograms(collision1, candPiwithtof, candKawithtof); + } + } + PROCESS_SWITCH(kstar892analysis, processMELightWithTof, "Process EventMixing light with tof", false); + + void processMELightTPCLowPt(o2::aod::ResoCollisions& collisions, soa::Filtered const& resotracks) + { + auto tracksTuple = std::make_tuple(resotracks); + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair, BinningTypeVtxZT0M> pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterMixedE"), 1.0); + + auto candPi = resoPiTPClowPt->sliceByCached(aod::resodaughter::resoCollisionId, collision1.globalIndex(), cache); + auto candKa = resoKaTPClowPt->sliceByCached(aod::resodaughter::resoCollisionId, collision2.globalIndex(), cache); + + fillHistograms(collision1, candPi, candKa); + } + } + PROCESS_SWITCH(kstar892analysis, processMELightTPCLowPt, "Process EventMixing light with TPC at low pt", false); + + void processMELightTOFHighPt(o2::aod::ResoCollisions& collisions, soa::Filtered const& resotracks) + { + auto tracksTuple = std::make_tuple(resotracks); + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair, BinningTypeVtxZT0M> pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (additionalQAeventPlots) + histos.fill(HIST("QAevent/hEvtCounterMixedE"), 1.0); + + auto candPi = resoPiTOFhighPt->sliceByCached(aod::resodaughter::resoCollisionId, collision1.globalIndex(), cache); + auto candKa = resoKaTOFhighPt->sliceByCached(aod::resodaughter::resoCollisionId, collision2.globalIndex(), cache); + + fillHistograms(collision1, candPi, candKa); + } + } + PROCESS_SWITCH(kstar892analysis, processMELightTOFHighPt, "Process EventMixing light with TOF at high pt", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-kstar892analysis"})}; +} diff --git a/PWGLF/Tasks/Resonances/kstarpbpb.cxx b/PWGLF/Tasks/Resonances/kstarpbpb.cxx index 7770e46a0f6..6a402f29ec7 100644 --- a/PWGLF/Tasks/Resonances/kstarpbpb.cxx +++ b/PWGLF/Tasks/Resonances/kstarpbpb.cxx @@ -73,8 +73,10 @@ struct kstarpbpb { // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Accepted maximum Centrality"}; // track Configurable cfgCutCharge{"cfgCutCharge", 0.0, "cut on Charge"}; + Configurable additionalEvSel2{"additionalEvSel2", true, "Additional evsel2"}; Configurable cfgCutPT{"cfgCutPT", 0.2, "PT cut on daughter track"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; @@ -86,18 +88,27 @@ struct kstarpbpb { Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; Configurable confRapidity{"confRapidity", 0.5, "Rapidity cut"}; - ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {120, 0.66, 1.2}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {180, 0.6, 1.5}, "#it{M} (GeV/#it{c}^{2})"}; ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0., 80}, "Centrality"}; + Configurable removefaketrak{"removefaketrack", true, "Remove fake track from momentum difference"}; + Configurable ConfFakeKaonCut{"ConfFakeKaonCut", 0.1, "Cut based on track from momentum difference"}; ConfigurableAxis configThnAxisPhiminusPsi{"configThnAxisPhiminusPsi", {6, 0.0, TMath::Pi()}, "#phi - #psi"}; ConfigurableAxis configThnAxisV2{"configThnAxisV2", {200, -1, 1}, "V2"}; Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; Configurable ispTdepPID{"ispTdepPID", true, "pT dependent PID"}; Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable confMinRot{"confMinRot", 5.0 * TMath::Pi() / 6.0, "Minimum of rotation"}; + Configurable confMaxRot{"confMaxRot", 7.0 * TMath::Pi() / 6.0, "Maximum of rotation"}; Configurable nBkgRotations{"nBkgRotations", 9, "Number of rotated copies (background) per each original candidate"}; + Configurable fillRotation{"fillRotation", true, "fill rotation"}; + Configurable fillRotation1{"fillRotation1", true, "fill rotation"}; + Configurable fillOccupancy{"fillOccupancy", true, "fill Occupancy"}; + Configurable cfgOccupancyCut{"cfgOccupancyCut", 500, "Occupancy cut"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter centralityFilter = nabs(aod::cent::centFT0C) < cfgCutCentrality; Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); @@ -130,18 +141,23 @@ struct kstarpbpb { AxisSpec phiAxis = {500, -6.28, 6.28, "phi"}; AxisSpec resAxis = {400, -2, 2, "Res"}; AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; + AxisSpec occupancyAxis = {1500, 0, 1500, "Occupancy"}; histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{200, 0.0, 200.0}}); + histos.add("hOccupancy", "Occupancy distribution", kTH1F, {occupancyAxis}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hPsiFT0C", "PsiFT0C", kTH2F, {centAxis, phiAxis}); - histos.add("hPsiFT0A", "PsiFT0A", kTH2F, {centAxis, phiAxis}); - histos.add("hPsiTPC", "PsiTPC", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); histos.add("hSparseV2SAMixedEvent_V2", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEvent2_V2", "hSparseV2SAMixedEvent2_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); histos.add("hSparseV2SASameEventRotational_V2", "hSparseV2SASameEventRotational_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2SASameEventRotational1_V2", "hSparseV2SASameEventRotational1_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hMC", "MC Event statistics", kTH1F, {{6, 0.0f, 6.0f}}); // histogram for resolution histos.add("ResFT0CTPC", "ResFT0CTPC", kTH2F, {centAxis, resAxis}); @@ -176,6 +192,12 @@ struct kstarpbpb { histos.add("QAafter/TOF_Nsigma_allpi", "TOF NSigma for pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{pion};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); histos.add("QAafter/TPC_Nsigma_allpi", "TPC NSigma for pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{pion};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); } + if (fillRotation) { + histos.add("hRotation", "hRotation", kTH1F, {{360, 0.0, 2.0 * TMath::Pi()}}); + } + if (fillRotation1) { + histos.add("hRotation1", "hRotation1", kTH1F, {{360, 0.0, 2.0 * TMath::Pi()}}); + } // Event selection cut additional - Alex if (additionalEvsel) { fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); @@ -195,7 +217,7 @@ struct kstarpbpb { double massPi = o2::constants::physics::MassPiMinus; template - bool eventSelected(TCollision collision, const int& /*multTrk*/, const float& centrality) + bool eventSelected(TCollision collision, const float& centrality) { if (collision.alias_bit(kTVXinTRD)) { // TRD triggered @@ -215,7 +237,6 @@ struct kstarpbpb { return 1; } - template bool selectionTrack(const T& candidate) { @@ -229,20 +250,20 @@ struct kstarpbpb { } template - bool selectionPIDpTdependent(const T& candidate, int PID) + bool selectionPIDNew(const T& candidate, int PID) { if (PID == 0) { - if (candidate.p() < 0.5 && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (candidate.pt() < 0.5 && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { return true; } - if (candidate.p() >= 0.5 && candidate.hasTOF() && ((candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) + (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa())) < (nsigmaCutCombined * nsigmaCutCombined)) { + if (candidate.pt() >= 0.5 && candidate.hasTOF() && ((candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) + (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa())) < (nsigmaCutCombined * nsigmaCutCombined)) { return true; } } else if (PID == 1) { - if (candidate.p() < 0.5 && TMath::Abs(candidate.tpcNSigmaPi()) < nsigmaCutTPC) { + if (candidate.pt() < 0.5 && TMath::Abs(candidate.tpcNSigmaPi()) < nsigmaCutTPC) { return true; } - if (candidate.p() >= 0.5 && candidate.hasTOF() && ((candidate.tofNSigmaPi() * candidate.tofNSigmaPi()) + (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi())) < (nsigmaCutCombined * nsigmaCutCombined)) { + if (candidate.pt() >= 0.5 && candidate.hasTOF() && ((candidate.tofNSigmaPi() * candidate.tofNSigmaPi()) + (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi())) < (nsigmaCutCombined * nsigmaCutCombined)) { return true; } } @@ -271,20 +292,20 @@ struct kstarpbpb { } template - bool selectionPIDNew(const T& candidate, int PID) + bool selectionPIDpTdependent(const T& candidate, int PID) { if (PID == 0) { - if (candidate.p() < 0.6 && TMath::Abs(candidate.tpcNSigmaKa()) < 2.0) { + if (candidate.pt() < 0.6 && TMath::Abs(candidate.tpcNSigmaKa()) < 2.0) { return true; } - if (candidate.p() >= 0.6 && candidate.p() < 3.0 && candidate.hasTOF() && candidate.tpcNSigmaKa() > -2.0 && candidate.tpcNSigmaKa() < 3.0 && TMath::Abs(candidate.tofNSigmaKa()) < 2.0) { + if (candidate.pt() >= 0.6 && candidate.pt() < 3.0 && candidate.hasTOF() && candidate.tpcNSigmaKa() > -2.0 && candidate.tpcNSigmaKa() < 3.0 && TMath::Abs(candidate.tofNSigmaKa()) < 2.0) { return true; } } else if (PID == 1) { - if (candidate.p() < 1.0 && TMath::Abs(candidate.tpcNSigmaPi()) < 2.0) { + if (candidate.pt() < 1.0 && TMath::Abs(candidate.tpcNSigmaPi()) < 2.0) { return true; } - if (candidate.p() >= 1.0 && candidate.p() < 3.0 && candidate.hasTOF() && candidate.tpcNSigmaPi() > -2.0 && candidate.tpcNSigmaPi() < 3.0 && TMath::Abs(candidate.tofNSigmaPi()) < 2.0) { + if (candidate.pt() >= 1.0 && candidate.pt() < 3.0 && candidate.hasTOF() && candidate.tpcNSigmaPi() > -2.0 && candidate.tpcNSigmaPi() < 3.0 && TMath::Abs(candidate.tofNSigmaPi()) < 2.0) { return true; } } @@ -302,45 +323,63 @@ struct kstarpbpb { } return result; } - + template + bool isFakeKaon(T const& track, int PID) + { + const auto pglobal = track.p(); + const auto ptpc = track.tpcInnerParam(); + if (TMath::Abs(pglobal - ptpc) > ConfFakeKaonCut) { + return true; + } + return false; + } ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; ConfigurableAxis axisEPAngle{"axisEPAngle", {6, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; + ConfigurableAxis axisOccup{"axisOccup", {20, 0.0, 40000.0}, "occupancy axis"}; - using BinningTypeVertexContributor = ColumnBinningPolicy; - ROOT::Math::PxPyPzMVector KstarMother, daughter1, daughter2, kaonrot, kstarrot; + using BinningTypeVertexContributor = ColumnBinningPolicy; + ROOT::Math::PxPyPzMVector KstarMother, daughter1, daughter2, kaonrot, kstarrot, pionrot, kstarrot1; void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { if (!collision.sel8()) { return; } - + auto centrality = collision.centFT0C(); + auto multTPC = collision.multNTracksPV(); if (!collision.triggereventep()) { return; } if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { return; } + if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + return; + } auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto centrality = collision.centFT0C(); - auto multTPC = collision.multNTracksPV(); auto psiFT0C = collision.psiFT0C(); auto psiFT0A = collision.psiFT0A(); auto psiTPC = collision.psiTPC(); + int occupancy = collision.trackOccupancyInTimeRange(); + if (fillOccupancy && occupancy >= cfgOccupancyCut) // occupancy info is available for this collision (*) + { + return; + } histos.fill(HIST("hFTOCvsTPC"), centrality, multTPC); - if (additionalEvsel && !eventSelected(collision, tracks.size(), centrality)) { + if (additionalEvsel && !eventSelected(collision, centrality)) { return; } histos.fill(HIST("hFTOCvsTPCSelected"), centrality, multTPC); - histos.fill(HIST("hPsiFT0C"), centrality, psiFT0C); - histos.fill(HIST("hPsiFT0A"), centrality, psiFT0A); - histos.fill(HIST("hPsiTPC"), centrality, psiTPC); + histos.fill(HIST("hPsiFT0C"), centrality, occupancy, psiFT0C); + histos.fill(HIST("hPsiFT0A"), centrality, occupancy, psiFT0A); + histos.fill(HIST("hPsiTPC"), centrality, occupancy, psiTPC); histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC))); histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiTPC - psiFT0A))); histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hOccupancy"), occupancy); histos.fill(HIST("hVtxZ"), collision.posZ()); for (auto track1 : posThisColl) { @@ -357,7 +396,7 @@ struct kstarpbpb { bool track1pion = false; bool track1kaon = false; - if (ispTdepPID && !(selectionPIDNew(track1, 0) || selectionPIDNew(track1, 1))) { + if (ispTdepPID && !(selectionPIDpTdependent(track1, 0) || selectionPIDpTdependent(track1, 1))) { continue; } if (!ispTdepPID && !(selectionPID(track1, 0) || selectionPID(track1, 1))) { @@ -376,7 +415,7 @@ struct kstarpbpb { histos.fill(HIST("QAbefore/trkDCAxypi"), track2.dcaXY()); histos.fill(HIST("QAbefore/trkDCAzpi"), track2.dcaZ()); } - if (ispTdepPID && !(selectionPIDNew(track2, 0) || selectionPIDNew(track2, 1))) { + if (ispTdepPID && !(selectionPIDpTdependent(track2, 0) || selectionPIDpTdependent(track2, 1))) { continue; } if (!ispTdepPID && !(selectionPID(track2, 0) || selectionPID(track2, 1))) { @@ -387,23 +426,35 @@ struct kstarpbpb { } if (ispTdepPID) { - if (selectionPIDNew(track1, 1) && selectionPIDNew(track2, 0)) { + if (selectionPIDpTdependent(track1, 1) && selectionPIDpTdependent(track2, 0)) { track1pion = true; track2kaon = true; + if (removefaketrak && isFakeKaon(track2, 0)) { + continue; + } } - if (selectionPIDNew(track2, 1) && selectionPIDNew(track1, 0)) { + if (selectionPIDpTdependent(track2, 1) && selectionPIDpTdependent(track1, 0)) { track2pion = true; track1kaon = true; + if (removefaketrak && isFakeKaon(track1, 0)) { + continue; + } } } if (!ispTdepPID) { if (selectionPID(track1, 1) && selectionPID(track2, 0)) { track1pion = true; track2kaon = true; + if (removefaketrak && isFakeKaon(track2, 0)) { + continue; + } } if (selectionPID(track2, 1) && selectionPID(track1, 0)) { track2pion = true; track1kaon = true; + if (removefaketrak && isFakeKaon(track1, 0)) { + continue; + } } } @@ -438,34 +489,178 @@ struct kstarpbpb { auto v2 = TMath::Cos(2.0 * phiminuspsi); histos.fill(HIST("hSparseV2SASameEvent_V2"), KstarMother.M(), KstarMother.Pt(), v2, centrality); - for (int nrotbkg = 1; nrotbkg < nBkgRotations; nrotbkg++) { - auto anglestep = nrotbkg * (2.0 * TMath::Pi() / nBkgRotations); - if (track1kaon && track2pion) { - auto rotkaonPx = track1.px() * std::cos(anglestep) - track1.py() * std::sin(anglestep); - auto rotkaonPy = track1.px() * std::sin(anglestep) + track1.py() * std::cos(anglestep); - kaonrot = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track1.pz(), massKa); - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); - } else if (track1pion && track2kaon) { - auto rotkaonPx = track2.px() * std::cos(anglestep) - track2.py() * std::sin(anglestep); - auto rotkaonPy = track2.px() * std::sin(anglestep) + track2.py() * std::cos(anglestep); - kaonrot = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track2.pz(), massKa); - daughter2 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPi); - } else { - continue; + if (fillRotation) { + for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { + auto anglestart = confMinRot; + auto angleend = confMaxRot; + auto anglestep = (angleend - anglestart) / (1.0 * (nBkgRotations - 1)); + auto rotangle = anglestart + nrotbkg * anglestep; + histos.fill(HIST("hRotation"), rotangle); + if (track1kaon && track2pion) { + auto rotkaonPx = track1.px() * std::cos(rotangle) - track1.py() * std::sin(rotangle); + auto rotkaonPy = track1.px() * std::sin(rotangle) + track1.py() * std::cos(rotangle); + kaonrot = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); + } else if (track1pion && track2kaon) { + auto rotkaonPx = track2.px() * std::cos(rotangle) - track2.py() * std::sin(rotangle); + auto rotkaonPy = track2.px() * std::sin(rotangle) + track2.py() * std::cos(rotangle); + kaonrot = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track2.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPi); + } else { + continue; + } + kstarrot = kaonrot + daughter2; + auto phiminuspsiRot = GetPhiInRange(kstarrot.Phi() - psiFT0C); + auto v2Rot = TMath::Cos(2.0 * phiminuspsiRot); + histos.fill(HIST("hSparseV2SASameEventRotational_V2"), kstarrot.M(), kstarrot.Pt(), v2Rot, centrality); + } + } + if (fillRotation1) { + for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { + auto anglestart = confMinRot; + auto angleend = confMaxRot; + auto anglestep = (angleend - anglestart) / (1.0 * (nBkgRotations - 1)); + auto rotangle = anglestart + nrotbkg * anglestep; + histos.fill(HIST("hRotation1"), rotangle); + if (track1kaon && track2pion) { + auto rotpionPx = track2.px() * std::cos(rotangle) - track2.py() * std::sin(rotangle); + auto rotpionPy = track2.px() * std::sin(rotangle) + track2.py() * std::cos(rotangle); + pionrot = ROOT::Math::PxPyPzMVector(rotpionPx, rotpionPy, track2.pz(), massPi); + daughter2 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + } else if (track1pion && track2kaon) { + auto rotpionPx = track1.px() * std::cos(rotangle) - track1.py() * std::sin(rotangle); + auto rotpionPy = track1.px() * std::sin(rotangle) + track1.py() * std::cos(rotangle); + pionrot = ROOT::Math::PxPyPzMVector(rotpionPx, rotpionPy, track2.pz(), massPi); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } else { + continue; + } + kstarrot1 = pionrot + daughter2; + auto phiminuspsiRot1 = GetPhiInRange(kstarrot1.Phi() - psiFT0C); + auto v2Rot1 = TMath::Cos(2.0 * phiminuspsiRot1); + histos.fill(HIST("hSparseV2SASameEventRotational1_V2"), kstarrot1.M(), kstarrot1.Pt(), v2Rot1, centrality); } - kstarrot = kaonrot + daughter2; - auto phiminuspsiRot = GetPhiInRange(kstarrot.Phi() - psiFT0C); - auto v2Rot = TMath::Cos(2.0 * phiminuspsiRot); - histos.fill(HIST("hSparseV2SASameEventRotational_V2"), kstarrot.M(), kstarrot.Pt(), v2Rot, centrality); } } } } PROCESS_SWITCH(kstarpbpb, processSameEvent, "Process Same event", true); - void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& /*tracks*/) + { + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisOccup}, true}; + for (auto const& [collision1, collision2] : o2::soa::selfCombinations(binningOnPositions, cfgNoMixedEvents, -1, collisions, collisions)) { + if (!collision1.sel8() || !collision2.sel8()) { + // printf("Mix = %d\n", 1); + continue; + } + if (!collision1.triggereventep() || !collision2.triggereventep()) { + // printf("Mix = %d\n", 2); + continue; + } + if (timFrameEvsel && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + // printf("Mix = %d\n", 3); + continue; + } + if (additionalEvSel2 && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel2 && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + int occupancy = collision1.trackOccupancyInTimeRange(); + auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + auto centrality = collision1.centFT0C(); + auto centrality2 = collision2.centFT0C(); + auto psiFT0C = collision1.psiFT0C(); + auto QFT0C = collision1.qFT0C(); + bool track1pion = false; + bool track1kaon = false; + bool track2pion = false; + bool track2kaon = false; + if (additionalEvsel && !eventSelected(collision1, centrality)) { + // printf("Mix = %d\n", 4); + continue; + } + if (additionalEvsel && !eventSelected(collision2, centrality2)) { + // printf("Mix = %d\n", 5); + continue; + } + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(posThisColl, negThisColl))) { + // track selection + if (!selectionTrack(track1) || !selectionTrack(track2)) { + // printf("Mix = %d\n", 6); + continue; + } + if (ispTdepPID && !(selectionPIDpTdependent(track1, 0) || selectionPIDpTdependent(track1, 1))) { + continue; + } + if (ispTdepPID && !(selectionPIDpTdependent(track2, 1) || selectionPIDpTdependent(track2, 0))) { + continue; + } + if (!ispTdepPID && !(selectionPID(track1, 0) || selectionPID(track1, 1))) { + continue; + } + if (!ispTdepPID && !(selectionPID(track2, 1) || selectionPID(track2, 0))) { + continue; + } + + if (ispTdepPID) { + if (selectionPIDpTdependent(track1, 1) && selectionPIDpTdependent(track2, 0)) { + track1pion = true; + track2kaon = true; + if (removefaketrak && isFakeKaon(track2, 0)) { + continue; + } + } + if (selectionPIDpTdependent(track2, 1) && selectionPIDpTdependent(track1, 0)) { + track2pion = true; + track1kaon = true; + if (removefaketrak && isFakeKaon(track1, 0)) { + continue; + } + } + } + if (!ispTdepPID) { + if (selectionPID(track1, 1) && selectionPID(track2, 0)) { + track1pion = true; + track2kaon = true; + if (removefaketrak && isFakeKaon(track2, 0)) { + continue; + } + } + if (selectionPID(track2, 1) && selectionPID(track1, 0)) { + track2pion = true; + track1kaon = true; + if (removefaketrak && isFakeKaon(track1, 0)) { + continue; + } + } + } + if (track1kaon && track2pion) { + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); + } else if (track1pion && track2kaon) { + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPi); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } else { + continue; + } + KstarMother = daughter1 + daughter2; + if (TMath::Abs(KstarMother.Rapidity()) > confRapidity) { + continue; + } + auto phiminuspsi = GetPhiInRange(KstarMother.Phi() - psiFT0C); + auto v2 = TMath::Cos(2.0 * phiminuspsi); + histos.fill(HIST("hSparseV2SAMixedEvent_V2"), KstarMother.M(), KstarMother.Pt(), v2, centrality); + } + } + } + PROCESS_SWITCH(kstarpbpb, processMixedEvent, "Process Mixed event", true); + void processMixedEvent2(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisOccup}, true}; SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; for (auto& [collision1, tracks1, collision2, tracks2] : pair) { if (!collision1.sel8() || !collision2.sel8()) { @@ -474,9 +669,20 @@ struct kstarpbpb { if (!collision1.triggereventep() || !collision2.triggereventep()) { continue; } + if (additionalEvSel2 && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel2 && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } if (timFrameEvsel && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { continue; } + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + if (fillOccupancy && (occupancy1 >= cfgOccupancyCut || occupancy2 >= cfgOccupancyCut)) { + continue; + } auto centrality = collision1.centFT0C(); auto centrality2 = collision2.centFT0C(); auto psiFT0C = collision1.psiFT0C(); @@ -485,10 +691,12 @@ struct kstarpbpb { bool track2pion = false; bool track2kaon = false; - if (additionalEvsel && !eventSelected(collision1, tracks.size(), centrality)) { + if (additionalEvsel && !eventSelected(collision1, centrality)) { + // printf("Mix = %d\n", 4); continue; } - if (additionalEvsel && !eventSelected(collision2, tracks.size(), centrality2)) { + if (additionalEvsel && !eventSelected(collision2, centrality2)) { + // printf("Mix = %d\n", 5); continue; } @@ -499,10 +707,10 @@ struct kstarpbpb { if (!selectionTrack(track1) || !selectionTrack(track2)) { continue; } - if (ispTdepPID && !(selectionPIDNew(track1, 0) || selectionPIDNew(track1, 1))) { + if (ispTdepPID && !(selectionPIDpTdependent(track1, 0) || selectionPIDpTdependent(track1, 1))) { continue; } - if (ispTdepPID && !(selectionPIDNew(track2, 1) || selectionPIDNew(track2, 0))) { + if (ispTdepPID && !(selectionPIDpTdependent(track2, 1) || selectionPIDpTdependent(track2, 0))) { continue; } if (!ispTdepPID && !(selectionPID(track1, 0) || selectionPID(track1, 1))) { @@ -513,23 +721,35 @@ struct kstarpbpb { } if (ispTdepPID) { - if (selectionPIDNew(track1, 1) && selectionPIDNew(track2, 0)) { + if (selectionPIDpTdependent(track1, 1) && selectionPIDpTdependent(track2, 0)) { track1pion = true; track2kaon = true; + if (removefaketrak && isFakeKaon(track2, 0)) { + continue; + } } - if (selectionPIDNew(track2, 1) && selectionPIDNew(track1, 0)) { + if (selectionPIDpTdependent(track2, 1) && selectionPIDpTdependent(track1, 0)) { track2pion = true; track1kaon = true; + if (removefaketrak && isFakeKaon(track1, 0)) { + continue; + } } } if (!ispTdepPID) { if (selectionPID(track1, 1) && selectionPID(track2, 0)) { track1pion = true; track2kaon = true; + if (removefaketrak && isFakeKaon(track2, 0)) { + continue; + } } if (selectionPID(track2, 1) && selectionPID(track1, 0)) { track2pion = true; track1kaon = true; + if (removefaketrak && isFakeKaon(track1, 0)) { + continue; + } } } if (track1kaon && track2pion) { @@ -538,8 +758,6 @@ struct kstarpbpb { } else if (track1pion && track2kaon) { daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPi); daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); - } else { - continue; } KstarMother = daughter1 + daughter2; if (TMath::Abs(KstarMother.Rapidity()) > confRapidity) { @@ -547,11 +765,11 @@ struct kstarpbpb { } auto phiminuspsi = GetPhiInRange(KstarMother.Phi() - psiFT0C); auto v2 = TMath::Cos(2.0 * phiminuspsi); - histos.fill(HIST("hSparseV2SAMixedEvent_V2"), KstarMother.M(), KstarMother.Pt(), v2, centrality); + histos.fill(HIST("hSparseV2SAMixedEvent2_V2"), KstarMother.M(), KstarMother.Pt(), v2, centrality); } } } - PROCESS_SWITCH(kstarpbpb, processMixedEvent, "Process Mixed event", true); + PROCESS_SWITCH(kstarpbpb, processMixedEvent2, "Process Mixed event", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index 1606a75ac8b..7bf410a3451 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -23,11 +23,10 @@ #include #include #include - -#include -#include -#include - +#include "TRandom3.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" #include "Common/Core/TrackSelection.h" @@ -50,15 +49,11 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::soa; using std::array; struct kstarqa { - // Connect to ccdb - Service ccdb; - Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; - Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; - SliceCache cache; // Histograms are defined with HistogramRegistry @@ -66,14 +61,19 @@ struct kstarqa { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Confugrable for QA histograms + Configurable CalcLikeSign{"CalcLikeSign", true, "Calculate Like Sign"}; + Configurable CalcRotational{"CalcRotational", true, "Calculate Rotational"}; Configurable QA{"QA", false, "QA"}; Configurable QAbefore{"QAbefore", true, "QAbefore"}; Configurable QAafter{"QAafter", true, "QAafter"}; + Configurable QAevents{"QAevents", true, "Multiplicity dist, DCAxy, DCAz"}; Configurable onlyTOF{"onlyTOF", false, "only TOF tracks"}; Configurable onlyTOFHIT{"onlyTOFHIT", false, "accept only TOF hit tracks at high pt"}; Configurable onlyTPC{"onlyTPC", true, "only TPC tracks"}; + Configurable cfgFT0M{"cfgFT0M", true, "1: pp, 0: PbPb"}; // Configurables for track selections + Configurable rotational_cut{"rotational_cut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; Configurable cfgCutPT{"cfgCutPT", 0.2f, "PT cut on daughter track"}; Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; @@ -112,6 +112,19 @@ struct kstarqa { ConfigurableAxis binsMultPlot{"binsCent", {201, -0.5f, 200.5f}, "Binning of the centrality axis for plots"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", true, "avoid split track in MC"}; Configurable AllGenCollisions{"AllGenCollisions", true, "To fill all generated collisions for the signal loss calculations"}; + ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; + ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; + ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; + + // Event plane configurables + Configurable boost_daugter1{"boost_daugter1", false, "Boost daughter Kaon in the COM frame"}; + Configurable boost_daugter2{"boost_daugter2", true, "Boost daughter Pion in the COM frame"}; + Configurable activateTHnSparseCosThStarHelicity{"activateTHnSparseCosThStarHelicity", true, "Activate the THnSparse with cosThStar w.r.t. helicity axis"}; + Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; + Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; + Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; + Configurable c_nof_rotations{"c_nof_rotations", 3, "Number of random rotations in the rotational background"}; + ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; void init(InitContext const&) { @@ -119,35 +132,36 @@ struct kstarqa { AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm] for plots"}; AxisSpec ptAxis = {nBinspT, pTbinlow, pTbinhigh, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec invmassAxis = {nBinsinvMass, invMassbinlow, invMassbinhigh, "Invariant mass (GeV/#it{c}^{2})"}; + AxisSpec thnAxisPOL{configThnAxisPOL, "cos(#theta)"}; // Histograms // Event selection rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - rEventSelection.add("hmult", "Centrality distribution", kTH1F, {{binsMultPlot}}); + rEventSelection.add("hmult", "Multiplicity percentile", kTH1F, {{binsMultPlot}}); // for primary tracks if (QAbefore && QAafter) { - histos.add("hNsigmaPionTPC_before", "NsigmaPion TPC distribution before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaPionTOF_before", "NsigmaPion TOF distribution before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTPC_before", "NsigmaKaon TPC distribution before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF_before", "NsigmaKaon TOF distribution before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("deoverdx_tpc", "dE/dx TPC distribution", kTH2F, {{ptAxis}, {250, 0, 500}}); + histos.add("hNsigmaTPC_before", "NsigmaKaon TPC distribution before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); + histos.add("hNsigmaTOF_before", "NsigmaKaon TOF distribution before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); + histos.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {axisPtfordEbydx, axisdEdx}); histos.add("hphi", "Phi distribution", kTH1F, {{65, 0, 6.5}}); histos.add("hEta_after", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); histos.add("hCRFC_after", "CRFC after distribution", kTH1F, {{100, 0.0f, 10.0f}}); histos.add("hCRFC_before", "CRFC before distribution", kTH1F, {{100, 0.0f, 10.0f}}); - histos.add("hNsigmaPionTPC_after", "NsigmaPion TPC distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaPionTOF_after", "NsigmaPion TOF distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTPC_after", "NsigmaKaon TPC distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF_after", "NsigmaKaon TOF distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaPionTPC_after", "NsigmaPion TPC distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaPionTOF_after", "NsigmaPion TOF distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaKaonTPC_after", "NsigmaKaon TPC distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); + // histos.add("hNsigmaKaonTOF_after", "NsigmaKaon TOF distribution", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); } // KStar histograms - histos.add("h3KstarInvMassUnlikeSign", "Invariant mass of kstar meson Unlike Sign", kTHnSparseF, {{binsMultPlot}, {ptAxis}, {invmassAxis}}, true); - histos.add("h3KstarInvMasslikeSign", "Invariant mass of kstar meson like Sign", kTHnSparseF, {{binsMultPlot}, {ptAxis}, {invmassAxis}}, true); - histos.add("h3KstarInvMassRotated", "Invariant mass of kstar meson rotated", kTHnSparseF, {{binsMultPlot}, {ptAxis}, {invmassAxis}}, true); - histos.add("h3KstarInvMassMixed", "Invariant mass of kstar meson Mixed", kTHnSparseF, {{binsMultPlot}, {ptAxis}, {invmassAxis}}, true); + histos.add("h3KstarInvMassUnlikeSign", "kstar Unlike Sign", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}, true); + histos.add("h3KstarInvMassMixed", "kstar Mixed", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}, true); + if (CalcLikeSign) + histos.add("h3KstarInvMasslikeSign", "kstar like Sign", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}, true); + if (CalcRotational) + histos.add("h3KstarInvMassRotated", "kstar rotated", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}, true); // MC generated histograms histos.add("k892Gen", "pT distribution of True MC K(892)0", kTH1D, {ptAxis}); @@ -158,15 +172,20 @@ struct kstarqa { histos.add("h1KstarRecpt", "pT of kstar meson", kTH1F, {ptAxis}); histos.add("h1genmass", "Invariant mass of generated kstar meson", kTH1D, {invmassAxis}); histos.add("h1recpt", "pT of generated kstar meson", kTH1F, {ptAxis}); - histos.add("events_check", "No. of events in the generated MC", kTH1F, {{20, 0, 20}}); - histos.add("events_checkrec", "No. of events in the reconstructed MC", kTH1F, {{20, 0, 20}}); + histos.add("events_check_data", "No. of events in the data", kTH1I, {{20, 0, 20}}); + histos.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); + histos.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); histos.add("h1KSRecsplit", "KS meson Rec split", kTH1F, {{100, 0.0f, 10.0f}}); // Multplicity distribution - histos.add("multdist", "FT0M multiplicity distribution", kTH1F, {{1000, 0, 10000}}); - histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); - histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); + if (QAevents) { + histos.add("multdist_FT0M", "FT0M Multiplicity distribution", kTH1F, {axisMultdist}); + histos.add("multdist_FT0A", "FT0A Multiplicity distribution", kTH1F, {axisMultdist}); + histos.add("multdist_FT0C", "FT0C Multiplicity distribution", kTH1F, {axisMultdist}); + histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); + } } double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); // FIXME: Get from the common header @@ -362,261 +381,351 @@ struct kstarqa { using TrackCandidates = soa::Filtered>; using V0TrackCandidate = aod::V0Datas; using EventCandidatesMC = soa::Join; - // using TrackCandidatesMC = soa::Filtered>; - using TrackCandidatesMC = soa::Filtered>; - - ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for ME mixing"}; - // ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {10, 0, 100}, "multiplicity percentile for ME mixing"}; - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin for ME mixing"}; - using BinningTypeTPCMultiplicity = ColumnBinningPolicy; - // using BinningTypeVertexContributor = - // ColumnBinningPolicy; - using BinningTypeCentralityM = ColumnBinningPolicy; - using BinningTypeVertexContributor = ColumnBinningPolicy; + using TrackCandidatesMC = soa::Filtered>; - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicity}, true}; + template + void fillInvMass(const T1& track1, const T2& track2, const T3& lv2, const T4& lv3, float multiplicity, bool isMix) + { + ROOT::Math::PxPyPzMVector daughter1, daughter2, daughter_selected; + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); // Kaon + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); // Pion + daughter_selected = (boost_daugter1) ? daughter1 : daughter2; + auto selected_dau_mass = (boost_daugter1) ? massKa : massPi; + + TLorentzVector lv4, lv5; + // polarization calculations + + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + ROOT::Math::PxPyPzMVector fourVecDau1 = ROOT::Math::PxPyPzMVector(daughter_selected.Px(), daughter_selected.Py(), daughter_selected.Pz(), selected_dau_mass); // Kaon or Pion + + ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame + ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter same as mother + ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + + TRandom* rn = new TRandom(); + + if (TMath::Abs(lv3.Rapidity() < 0.5)) { + + if (activateTHnSparseCosThStarHelicity) { + ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame + auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + histos.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); + lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background + lv5 = lv2 + lv4; + if (CalcRotational) + histos.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity); + } + } else { + histos.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + } + } else { + if (!isMix) { + if (CalcLikeSign) + histos.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + } + } - SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; + } else if (activateTHnSparseCosThStarProduction) { + ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); - double totmomka = 0.0; - double totmompi = 0.0; - double totmomkamix = 0.0; - double totmompimix = 0.0; - // double openingangle = 0.0; - // double openinganglemix = 0.0; + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + histos.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(0, TMath::Pi()); + lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background + lv5 = lv2 + lv4; + if (CalcRotational) + histos.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction); + } + } else { + histos.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + } + } else { + if (!isMix) { + if (CalcLikeSign) + histos.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + } + } + } else if (activateTHnSparseCosThStarBeam) { + ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + histos.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(0, TMath::Pi()); + lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background + lv5 = lv2 + lv4; + if (CalcRotational) + histos.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam); + } + } else { + histos.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + } + } else { + if (CalcLikeSign) + histos.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + } + } else if (activateTHnSparseCosThStarRandom) { + ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + histos.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + for (int i = 0; i < c_nof_rotations; i++) { + float theta2 = rn->Uniform(0, TMath::Pi()); + lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background + lv5 = lv2 + lv4; + if (CalcRotational) + histos.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom); + } + } else { + histos.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + } + } else { + if (!isMix) { + if (CalcLikeSign) + histos.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + } + } + } + } + } void processSE(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { + histos.fill(HIST("events_check_data"), 0.5); - if (!collision.sel8()) { + if (TVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { return; } + histos.fill(HIST("events_check_data"), 1.5); if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { return; } + histos.fill(HIST("events_check_data"), 2.5); - if (TVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + if (!collision.sel8()) { return; } - - std::vector pions, kaons, pionsrot, kaonsrot; - std::vector PionIndex = {}; - std::vector KaonIndex = {}; - std::vector PioncollIndex = {}; - std::vector KaoncollIndex = {}; - std::vector PionSign = {}; - std::vector KaonSign = {}; - - std::vector PionPx = {}; - std::vector KaonPx = {}; - std::vector PionPy = {}; - std::vector KaonPy = {}; - std::vector PionPz = {}; - std::vector KaonPz = {}; - std::vector PionP = {}; - std::vector KaonP = {}; + histos.fill(HIST("events_check_data"), 3.5); float multiplicity = 0.0f; - multiplicity = collision.centFT0M(); - // multiplicity = collision.centFT0C(); - // Fill the event counter - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - rEventSelection.fill(HIST("hmult"), multiplicity); - histos.fill(HIST("multdist"), collision.multFT0M()); - histos.fill(HIST("hNcontributor"), collision.numContrib()); + multiplicity = (cfgFT0M) ? collision.centFT0M() : collision.centFT0C(); - for (auto track1 : tracks) { + // Fill the event counter + if (QAevents) { + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + rEventSelection.fill(HIST("hmult"), multiplicity); + histos.fill(HIST("multdist_FT0M"), collision.multFT0M()); + histos.fill(HIST("multdist_FT0A"), collision.multFT0A()); + histos.fill(HIST("multdist_FT0C"), collision.multFT0C()); + histos.fill(HIST("hNcontributor"), collision.numContrib()); + } + for (auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { if (QAbefore) { - histos.fill(HIST("hNsigmaKaonTPC_before"), track1.pt(), track1.tpcNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF_before"), track1.pt(), track1.tofNSigmaKa()); + histos.fill(HIST("hNsigmaTPC_before"), track1.pt(), track1.tpcNSigmaKa()); + histos.fill(HIST("hNsigmaTOF_before"), track1.pt(), track1.tofNSigmaKa()); histos.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("deoverdx_tpc"), track1.pt(), track1.tpcSignal()); + histos.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); histos.fill(HIST("hphi"), track1.phi()); } + histos.fill(HIST("events_check_data"), 4.5); if (!selectionTrack(track1)) { continue; } - histos.fill(HIST("hDcaxy"), track1.dcaXY()); - histos.fill(HIST("hDcaz"), track1.dcaZ()); - if (!selectionPID(track1, 1)) // kaon + if (!selectionTrack(track2)) { continue; + } + histos.fill(HIST("events_check_data"), 5.5); + if (QAevents) { + histos.fill(HIST("hDcaxy"), track1.dcaXY()); + histos.fill(HIST("hDcaz"), track1.dcaZ()); + } + + // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with pion + if (!selectionPID(track1, 1)) // Track 1 is checked with Kaon + continue; + if (!selectionPID(track2, 0)) // Track 2 is checked with Pion + continue; + + histos.fill(HIST("events_check_data"), 6.5); if (MID) { - if (MIDselectionPID(track1, 0)) // misidentified as pion + if (MIDselectionPID(track1, 0)) // Kaon misidentified as pion continue; - - if (MIDselectionPID(track1, 2)) // misidentified as proton + if (MIDselectionPID(track1, 2)) // Kaon misidentified as proton + continue; + if (MIDselectionPID(track2, 1)) // Pion misidentified as kaon continue; } + histos.fill(HIST("events_check_data"), 7.5); + if (QAafter) { histos.fill(HIST("hEta_after"), track1.eta()); histos.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); + // histos.fill(HIST("hNsigmaPionTPC_after"), track2.pt(), track2.tpcNSigmaPi()); + // histos.fill(HIST("hNsigmaPionTOF_after"), track2.pt(), track2.tofNSigmaPi()); } - totmomka = TMath::Sqrt(track1.px() * track1.px() + track1.py() * track1.py() + track1.pz() * track1.pz()); + if (track1.globalIndex() == track2.globalIndex()) + continue; - ROOT::Math::PtEtaPhiMVector temp1(track1.pt(), track1.eta(), track1.phi(), massKa); - ROOT::Math::PtEtaPhiMVector temp1rot(track1.pt(), track1.eta(), track1.phi() + TMath::Pi(), massKa); - kaons.push_back(temp1); - kaonsrot.push_back(temp1rot); - KaonIndex.push_back(track1.globalIndex()); - KaoncollIndex.push_back(track1.collisionId()); - KaonSign.push_back(track1.sign()); - KaonPx.push_back(track1.px()); - KaonPy.push_back(track1.py()); - KaonPz.push_back(track1.pz()); - KaonP.push_back(totmomka); + histos.fill(HIST("events_check_data"), 8.5); - } // track loop ends + TLorentzVector lv1, lv2, lv3; + lv1.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi(), massKa); + lv2.SetPtEtaPhiM(track2.pt(), track2.eta(), track2.phi(), massPi); + lv3 = lv1 + lv2; + bool isMix = false; + fillInvMass(track1, track2, lv2, lv3, multiplicity, isMix); + } + } - for (auto track2 : tracks) { + PROCESS_SWITCH(kstarqa, processSE, "Process Same event", true); - if (QAbefore) { - histos.fill(HIST("hNsigmaPionTPC_before"), track2.pt(), track2.tpcNSigmaPi()); - histos.fill(HIST("hNsigmaPionTOF_before"), track2.pt(), track2.tofNSigmaPi()); - } + ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for ME mixing"}; + ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {10, 0, 100}, "multiplicity percentile for ME mixing"}; + // ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin for ME mixing"}; - if (!selectionTrack(track2)) { - continue; - } + using BinningTypeTPCMultiplicity = ColumnBinningPolicy; + using BinningTypeCentralityM = ColumnBinningPolicy; + using BinningTypeVertexContributor = ColumnBinningPolicy; - if (!selectionPID(track2, 0)) // pion - continue; + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; + BinningTypeCentralityM binningOnCentrality{{axisVertex, axisMultiplicityClass}, true}; - if (MID) { - if (MIDselectionPID(track2, 1)) // misidentified as kaon + SameKindPair pair1{binningOnPositions, cfgNoMixedEvents, -1, &cache}; + SameKindPair pair2{binningOnCentrality, cfgNoMixedEvents, -1, &cache}; + + void processME(EventCandidates const&, TrackCandidates const&) + { + if (cfgFT0M) { + for (auto& [c1, tracks1, c2, tracks2] : pair1) { + + if (!c1.sel8()) { continue; - } - if (QAafter) { - histos.fill(HIST("hNsigmaPionTPC_after"), track2.pt(), track2.tpcNSigmaPi()); - histos.fill(HIST("hNsigmaPionTOF_after"), track2.pt(), track2.tofNSigmaPi()); - } + } + if (!c2.sel8()) { + continue; + } - totmompi = TMath::Sqrt(track2.px() * track2.px() + track2.py() * track2.py() + track2.pz() * track2.pz()); - - ROOT::Math::PtEtaPhiMVector temp2(track2.pt(), track2.eta(), track2.phi(), massPi); - ROOT::Math::PtEtaPhiMVector temp2rot(track2.pt(), track2.eta(), track2.phi() + TMath::Pi(), massPi); - pions.push_back(temp2); - pionsrot.push_back(temp2rot); - PionIndex.push_back(track2.globalIndex()); - PioncollIndex.push_back(track2.collisionId()); - PionSign.push_back(track2.sign()); - PionPx.push_back(track2.px()); - PionPy.push_back(track2.py()); - PionPz.push_back(track2.pz()); - PionP.push_back(totmompi); - } // track loop ends - - if (!QA) { - if (pions.size() != 0 && kaons.size() != 0) { - for (auto ikaon = kaons.begin(); ikaon != kaons.end(); ++ikaon) { - auto i1 = std::distance(kaons.begin(), ikaon); - for (auto ipion = pions.begin(); ipion != pions.end(); ++ipion) { - auto i3 = std::distance(pions.begin(), ipion); - - if (PionIndex.at(i3) <= KaonIndex.at(i1)) - continue; - CKSVector = kaons.at(i1) + pions.at(i3); - CKSVectorRot1 = kaonsrot.at(i1) + pions.at(i3); - CKSVectorRot2 = kaons.at(i1) + pionsrot.at(i3); - - // openingangle = TMath::Abs((PionPx.at(i3) * KaonPx.at(i1) + PionPy.at(i3) * KaonPy.at(i1) + PionPz.at(i3) * KaonPz.at(i1)) / (PionP.at(i3) * KaonP.at(i1))); - - // openingangle = (PionPx.at(i3)*KaonPx.at(i1) + PionPy.at(i3)*KaonPy.at(i1) + PionPz.at(i3)*KaonPz.at(i1)); - // LOG(info) << "opening angle" << openingangle; - - if (TMath::Abs(CKSVector.Rapidity()) < 0.5) { - if (PionSign.at(i3) * KaonSign.at(i1) < 0) { - histos.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, CKSVector.Pt(), CKSVector.M()); - histos.fill(HIST("h3KstarInvMassRotated"), multiplicity, CKSVectorRot1.Pt(), CKSVectorRot1.M()); - histos.fill(HIST("h3KstarInvMassRotated"), multiplicity, CKSVectorRot2.Pt(), CKSVectorRot2.M()); - } else if (PionSign.at(i3) * KaonSign.at(i1) > 0) { - histos.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, CKSVector.Pt(), CKSVector.M()); - } - } - } + if (timFrameEvsel && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; } - } - } - } - PROCESS_SWITCH(kstarqa, processSE, "Process Same event", true); + if (TVXEvsel && (!c1.selection_bit(aod::evsel::kIsTriggerTVX) || !c2.selection_bit(aod::evsel::kIsTriggerTVX))) { + return; + } - void processME(EventCandidates const&, TrackCandidates const&) + auto multiplicity = c1.centFT0M(); - { + for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - for (auto& [c1, tracks1, c2, tracks2] : pair) { + if (!selectionTrack(t1)) // Kaon + continue; + if (!selectionTrack(t2)) // Pion + continue; + if (!selectionPID(t1, 1)) // Kaon + continue; + if (!selectionPID(t2, 0)) // Pion + continue; + if (MID) { + if (MIDselectionPID(t1, 0)) // misidentified as pion + continue; + if (MIDselectionPID(t1, 2)) // misidentified as proton + continue; + if (MIDselectionPID(t2, 1)) // misidentified as kaon + continue; + } - if (!c1.sel8()) { - continue; - } - if (!c2.sel8()) { - continue; - } + TLorentzVector KAON; + KAON.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); + TLorentzVector PION; + PION.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); - if (timFrameEvsel && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { - continue; - } + TLorentzVector Kstar = KAON + PION; + bool isMix = true; - if (TVXEvsel && (!c1.selection_bit(aod::evsel::kIsTriggerTVX) || !c2.selection_bit(aod::evsel::kIsTriggerTVX))) { - return; + if (!QA) { + if (TMath::Abs(Kstar.Rapidity()) < 0.5) { + fillInvMass(t1, t2, PION, Kstar, multiplicity, isMix); + } + } + } } + } else { + for (auto& [c1, tracks1, c2, tracks2] : pair2) { - // float multiplicity = 0.0f; - /* if (cfgMultFT0) - multiplicity = c1.multZeqFT0A() + c1.multZeqFT0C(); - if (cfgMultFT0 == 0 && cfgCentFT0C == 1) - multiplicity = c1.centFT0C(); - if (cfgMultFT0 == 0 && cfgCentFT0C == 0)*/ - auto multiplicity = c1.centFT0M(); - - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - - if (!selectionTrack(t1)) - continue; - if (!selectionTrack(t2)) + if (!c1.sel8()) { continue; - if (!selectionPID(t1, 1)) + } + if (!c2.sel8()) { continue; - if (!selectionPID(t2, 0)) + } + + if (timFrameEvsel && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { continue; - if (MID) { - if (MIDselectionPID(t1, 0)) // misidentified as pion - continue; - if (MIDselectionPID(t1, 2)) // misidentified as proton - continue; - if (MIDselectionPID(t2, 1)) // misidentified as kaon - continue; } - TLorentzVector KAON; - KAON.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - TLorentzVector PION; - PION.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); + if (TVXEvsel && (!c1.selection_bit(aod::evsel::kIsTriggerTVX) || !c2.selection_bit(aod::evsel::kIsTriggerTVX))) { + return; + } - // totmompimix = TMath::Sqrt(t2.px() * t2.px() + t2.py() * t2.py() + t2.pz() * t2.pz()); - // totmomkamix = TMath::Sqrt(t1.px() * t1.px() + t1.py() * t1.py() + t1.pz() * t1.pz()); + auto multiplicity = c1.centFT0M(); - // openinganglemix = TMath::Abs((t1.px() * t2.px() + t1.py() * t2.py() + t1.pz() * t2.pz()) / (totmomkamix * totmompimix)); + for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + if (!selectionTrack(t1)) // Kaon + continue; + if (!selectionTrack(t2)) // Pion + continue; + if (!selectionPID(t1, 1)) // Kaon + continue; + if (!selectionPID(t2, 0)) // Pion + continue; + if (MID) { + if (MIDselectionPID(t1, 0)) // misidentified as pion + continue; + if (MIDselectionPID(t1, 2)) // misidentified as proton + continue; + if (MIDselectionPID(t2, 1)) // misidentified as kaon + continue; + } - // LOG(info) << "mix angle" << openinganglemix; + TLorentzVector KAON; + KAON.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); + TLorentzVector PION; + PION.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); - TLorentzVector CKSmix = KAON + PION; + TLorentzVector Kstar = KAON + PION; + bool isMix = true; - if (!QA) { - if (TMath::Abs(CKSmix.Rapidity()) < 0.5) { - if (t1.sign() * t2.sign() < 0) - histos.fill(HIST("h3KstarInvMassMixed"), multiplicity, CKSmix.Pt(), CKSmix.M()); + if (!QA) { + if (TMath::Abs(Kstar.Rapidity()) < 0.5) { + fillInvMass(t1, t2, PION, Kstar, multiplicity, isMix); + } } } } diff --git a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx index 5e7ced3a94a..63f1c7d58d5 100644 --- a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -61,10 +62,24 @@ struct lambdaAnalysis_pb { Configurable cPVContributor{"cPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor // PID Selections - Configurable cUseOnlyTOFTrackPr{"cUseOnlyTOFTrackPr", false, "Use only TOF track for PID selection"}; // Use only TOF track for Proton PID selection - Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection - Configurable cUseTpcOnly{"cUseTpcOnly", false, "Use TPC Only selection"}; // TPC And TOF tracks - Configurable cRejNsigmaTpc{"cRejNsigmaTpc", 3.0, "Reject tracks to improve purity of TPC PID"}; // Reject missidentified particles when tpc bands merge + Configurable cUseOnlyTOFTrackPr{"cUseOnlyTOFTrackPr", false, "Use only TOF track for PID selection"}; // Use only TOF track for Proton PID selection + Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection + Configurable cUseTpcOnly{"cUseTpcOnly", false, "Use TPC Only selection"}; // TPC And TOF tracks + Configurable cRejNsigmaTpc{"cRejNsigmaTpc", 3.0, "Reject tracks to improve purity of TPC PID"}; // Reject missidentified particles when tpc bands merge + Configurable cRejNsigmaTpcPi{"cRejNsigmaTpcPi", 3.0, "Reject tracks to improve purity of TPC PID"}; // TPC And TOF tracks + // Configurable cRejNsigmaTpcPr{"cRejNsigmaTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmaTpcKa{"cRejNsigmaTpcKa", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmaTpcEl{"cRejNsigmaTpcEl", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmakTpcPi{"cRejNsigmakTpcPi", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmakTpcPr{"cRejNsigmakTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmakTpcEl{"cRejNsigmakTpcEl", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatpcKa{"minnsigmatpcKa", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatpcPr{"minnsigmatpcPr", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatofKa{"minnsigmatofKa", -6.0, "Reject tracks to improve purity of TofPID"}; + Configurable minnsigmatofPr{"minnsigmatofPr", -6.0, "Reject tracks to improve purity of Tof PID"}; + Configurable minnsigmatpctofKa{"minnsigmatpctofKa", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatpctofPr{"minnsigmatpctofPr", -6.0, "Reject tracks to improve purity of TPC PID"}; + // Configurable cRejNsigmaTpcPr{"cRejNsigmaTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; Configurable cRejNsigmaTpcVeto{"cRejNsigmaTpcVeto", 3.0, "Reject tracks to improve purity of TPC PID"}; // Reject missidentified particles when tpc bands merge Configurable cRejNsigmaTof{"cRejNsigmaTof", 3.0, "Reject tracks to improve purity of TOF PID"}; // Reject missidentified particles when tpc bands merge // Proton @@ -107,11 +122,12 @@ struct lambdaAnalysis_pb { const AxisSpec axisTOFNsigma(401, -10.025, 10.025, {"n#sigma^{TOF}"}); const AxisSpec axisdEdx(380, 10, 200, {"#frac{dE}{dx}"}); const AxisSpec axisVz(120, -12, 12, {"vz"}); + const AxisSpec axisEP(120, -3.14, 3.14, {"#theta"}); const AxisSpec axisInvM(nBinsInvM, 1.44, 2.04, {"M_{inv} (GeV/c^{2})"}); histos.add("Event/h1d_ft0_mult_percentile", "FT0 (%)", kTH1F, {axisCent}); if (doprocessMix || doprocessMixDF || doprocessMixepDF) { - histos.add("Event/mixing_vzVsmultpercentile", "FT0(%)", kTH2F, {axisCent, axisVz}); + histos.add("Event/mixing_vzVsmultpercentile", "FT0(%)", kTH3F, {axisCent, axisVz, axisEP}); } // QA Before histos.add("QAbefore/Proton/h2d_pr_nsigma_tpc_p", "n#sigma^{TPC} Protons", kTH2F, {axisP_pid, axisTPCNsigma}); @@ -122,7 +138,7 @@ struct lambdaAnalysis_pb { histos.add("QAbefore/Kaon/h2d_ka_nsigma_tof_vs_tpc", "n#sigma^{TPC} vs n#sigma^{TOF} Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); // QA After - histos.add("QAafter/Proton/h1d_pr_pt", "p_{T}-spectra Protons", kTH1F, {axisPt_pid}); + histos.add("QAafter/Proton/hd_pr_pt", "p_{T}-spectra Protons", kTH1F, {axisPt_pid}); histos.add("QAafter/Proton/h2d_pr_dca_z", "dca_{z} Protons", kTH2F, {axisPt_pid, axisDCAz}); histos.add("QAafter/Proton/h2d_pr_dca_xy", "dca_{xy} Protons", kTH2F, {axisPt_pid, axisDCAxy}); histos.add("QAafter/Proton/h2d_pr_dEdx_p", "TPC Signal Protons", kTH2F, {axisP_pid, axisdEdx}); @@ -137,7 +153,7 @@ struct lambdaAnalysis_pb { histos.add("QAafter/Proton/h2d_Prka_nsigma_tof_p", " Protons kaon", kTH2F, {axisP_pid, axisTOFNsigma}); histos.add("QAafter/Proton/h2d_Prel_nsigma_tof_p", " Protons electron", kTH2F, {axisP_pid, axisTOFNsigma}); histos.add("QAafter/Proton/h2d_pr_nsigma_tof_vs_tpc", "n#sigma(TOF) vs n#sigma(TPC) Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); - histos.add("QAafter/Kaon/h1d_ka_pt", "p_{T}-spectra Kaons", kTH1F, {axisPt_pid}); + histos.add("QAafter/Kaon/hd_ka_pt", "p_{T}-spectra Kaons", kTH1F, {axisPt_pid}); histos.add("QAafter/Kaon/h2d_ka_dca_z", "dca_{z} Kaons", kTH2F, {axisPt_pid, axisDCAz}); histos.add("QAafter/Kaon/h2d_ka_dca_xy", "dca_{xy} Kaons", kTH2F, {axisPt_pid, axisDCAxy}); histos.add("QAafter/Kaon/h2d_ka_dEdx_p", "TPC Signal Kaon", kTH2F, {axisP_pid, axisdEdx}); @@ -237,11 +253,16 @@ struct lambdaAnalysis_pb { float combinedRejCut = cRejNsigmaTof * cRejNsigmaTpc; if (!cUseTpcOnly && candidate.hasTOF()) { + if (candidate.tofNSigmaPr() < minnsigmatofPr) + return false; if (nsigmaCutCombinedProton < 0 && p >= cPMin) { + for (int i = 0; i < nitrtof - 1; ++i) { if (p >= tofPIDp[i] && p < tofPIDp[i + 1] && (tofNsigmaPr < tofPIDcut[i] && tofNsigmaPi > cRejNsigmaTof && tofNsigmaKa > cRejNsigmaTof && tofNsigmaEl > cRejNsigmaTof)) tofPIDPassed = true; } + if (candidate.tpcNSigmaPr() < minnsigmatpctofPr) + return false; if (tpcNsigmaPr < cMaxTPCnSigmaProton && tpcNsigmaPi > cRejNsigmaTpcVeto && tpcNsigmaKa > cRejNsigmaTpcVeto && tpcNsigmaEl > cRejNsigmaTpcVeto) tpcPIDPassed = true; } @@ -259,8 +280,10 @@ struct lambdaAnalysis_pb { } } else { tofPIDPassed = true; + if (candidate.tpcNSigmaPr() < minnsigmatpcPr) + return false; for (int i = 0; i < nitr - 1; ++i) { - if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaPr < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmaTpc && tpcNsigmaKa > cRejNsigmaTpc && tpcNsigmaEl > cRejNsigmaTpc)) { + if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaPr < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmaTpcPi && tpcNsigmaKa > cRejNsigmaTpcKa && tpcNsigmaEl > cRejNsigmaTpcEl)) { tpcPIDPassed = true; } } @@ -298,11 +321,16 @@ struct lambdaAnalysis_pb { float combinedRejCut = cRejNsigmaTpc * cRejNsigmaTof; if (!cUseTpcOnly && candidate.hasTOF()) { + if (candidate.tofNSigmaKa() < minnsigmatofKa) + return false; if (nsigmaCutCombinedKaon < 0 && p >= cPMin) { + for (int i = 0; i < nitrtof - 1; ++i) { if (p >= tofPIDp[i] && p < tofPIDp[i + 1] && (tofNsigmaKa < tofPIDcut[i] && tofNsigmaPi > cRejNsigmaTof && tofNsigmaPr > cRejNsigmaTof && tofNsigmaEl > cRejNsigmaTof)) tofPIDPassed = true; } + if (candidate.tpcNSigmaKa() < minnsigmatpctofKa) + return false; if (tpcNsigmaKa < cMaxTPCnSigmaKaon && tpcNsigmaPi > cRejNsigmaTpcVeto && tpcNsigmaPr > cRejNsigmaTpcVeto && tpcNsigmaEl > cRejNsigmaTpcVeto) tpcPIDPassed = true; } @@ -321,8 +349,10 @@ struct lambdaAnalysis_pb { } else { tofPIDPassed = true; + if (candidate.tpcNSigmaKa() < minnsigmatpcKa) + return false; for (int i = 0; i < nitr - 1; ++i) { - if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaKa < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmaTpc && tpcNsigmaPr > cRejNsigmaTpc && tpcNsigmaEl > cRejNsigmaTpc)) { + if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaKa < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmakTpcPi && tpcNsigmaPr > cRejNsigmakTpcPr && tpcNsigmaEl > cRejNsigmakTpcEl)) { tpcPIDPassed = true; } } @@ -397,7 +427,7 @@ struct lambdaAnalysis_pb { auto _tpcnsigmaPr = trkPr.tpcNSigmaPr(); // Proton - histos.fill(HIST("QAafter/Proton/h1d_pr_pt"), _ptPr); + histos.fill(HIST("QAafter/Proton/hd_pr_pt"), _ptPr); histos.fill(HIST("QAafter/Proton/h2d_pr_dca_z"), _ptPr, trkPr.dcaZ()); histos.fill(HIST("QAafter/Proton/h2d_pr_dca_xy"), _ptPr, trkPr.dcaXY()); histos.fill(HIST("QAafter/Proton/h2d_pr_dEdx_p"), p_ptot, trkPr.tpcSignal()); @@ -419,7 +449,7 @@ struct lambdaAnalysis_pb { auto _tpcnsigmaKa = trkKa.tpcNSigmaKa(); // Kaon - histos.fill(HIST("QAafter/Kaon/h1d_ka_pt"), _ptKa); + histos.fill(HIST("QAafter/Kaon/hd_ka_pt"), _ptKa); histos.fill(HIST("QAafter/Kaon/h2d_ka_dca_z"), _ptKa, trkKa.dcaZ()); histos.fill(HIST("QAafter/Kaon/h2d_ka_dca_xy"), _ptKa, trkKa.dcaXY()); histos.fill(HIST("QAafter/Kaon/h2d_ka_dEdx_p"), k_ptot, trkKa.tpcSignal()); @@ -609,7 +639,7 @@ struct lambdaAnalysis_pb { for (auto& [c1, t1, c2, t2] : pairs) { // LOGF(info, "processMCMixedDerived: Mixed collisions : %d (%.3f, %.3f,%d), %d (%.3f, %.3f,%d)",c1.globalIndex(), c1.posZ(), c1.cent(),c1.mult(), c2.globalIndex(), c2.posZ(), c2.cent(),c2.mult()); - histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ()); + histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); fillDataHistos(t1, t2, c1.cent()); } } @@ -648,7 +678,7 @@ struct lambdaAnalysis_pb { for (auto& [c1, t1, c2, t2] : pairs) { // LOGF(info, "processMCMixedDerived: Mixed collisions : %d (%.3f, %.3f,%d), %d (%.3f, %.3f,%d)",c1.globalIndex(), c1.posZ(), c1.cent(),c1.mult(), c2.globalIndex(), c2.posZ(), c2.cent(),c2.mult()); - histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ()); + histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); fillDataHistos(t1, t2, c1.cent()); } } @@ -669,7 +699,7 @@ struct lambdaAnalysis_pb { for (auto& [c1, t1, c2, t2] : pairs) { // LOGF(info, "processMCMixedDerived: Mixed collisions : %d (%.3f, %.3f,%.3f), %d (%.3f, %.3f, %.3f)",c1.globalIndex(), c1.posZ(), c1.cent(),c1.evtPl(), c2.globalIndex(), c2.posZ(), c2.cent(),c2.evtPl()); - histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ()); + histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); fillDataHistos(t1, t2, c1.cent()); } } diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx index 504f41e5e92..2a728d33bf4 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx @@ -27,17 +27,23 @@ #include #include #include -#include #include #include #include +#include "TRandom3.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" +#include "TF1.h" + +#include "PWGLF/DataModel/EPCalibrationTables.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/HistogramRegistry.h" #include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" @@ -47,13 +53,17 @@ #include "CommonConstants/PhysicsConstants.h" #include "Common/Core/TrackSelection.h" #include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; struct phianalysisrun3_PbPb { - SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; @@ -62,17 +72,24 @@ struct phianalysisrun3_PbPb { Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutTPC{"nsigmacutTPC", 2.0, "Value of the TPC Nsigma cut"}; Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "Value of the TOF Nsigma cut"}; Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + Configurable fillOccupancy{"fillOccupancy", true, "fill Occupancy"}; + Configurable cfgOccupancyCut{"cfgOccupancyCut", 2500, "Occupancy cut"}; + Configurable isNoTOF{"isNoTOF", false, "isNoTOF"}; Configurable isEtaAssym{"isEtaAssym", false, "isEtaAssym"}; Configurable cfgMultFT0{"cfgMultFT0", true, "cfgMultFT0"}; Configurable iscustomDCAcut{"iscustomDCAcut", false, "iscustomDCAcut"}; Configurable ismanualDCAcut{"ismanualDCAcut", true, "ismanualDCAcut"}; Configurable isITSOnlycut{"isITSOnlycut", true, "isITSOnlycut"}; Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; + Configurable confRapidity{"confRapidity", 0.5, "Rapidity cut"}; + Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; + Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; // MC Configurable isMC{"isMC", false, "Run MC"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", false, "avoid split track in MC"}; @@ -101,18 +118,33 @@ struct phianalysisrun3_PbPb { histos.add("h3PhiInvMassMixedCside", "Invariant mass of Phi meson Mixed C side", kTH3F, {{200, 0.0, 200.0}, {200, 0.0f, 20.0f}, {200, 0.9, 1.1}}); } } else if (isMC) { - histos.add("hMC", "MC Event statistics", kTH1F, {{6, 0.0f, 6.0f}}); + histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); histos.add("h1PhiGen", "Phi meson Gen", kTH1F, {{200, 0.0f, 20.0f}}); histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {{200, 0.0f, 20.0f}}); histos.add("Centrec", "MC Centrality", kTH1F, {{200, 0.0, 200.0}}); - histos.add("Centgen", "MC Centrality", kTH1F, {{200, 0.0, 200.0}}); histos.add("h2PhiRec2", "Phi meson Rec", kTH2F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}}); + histos.add("h3PhiRec3", "Phi meson Rec", kTH3F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}, {200, 0.9, 1.1}}); histos.add("h2PhiGen2", "Phi meson gen", kTH2F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}}); histos.add("h1PhiRec1", "Phi meson Rec", kTH1F, {{200, 0.0f, 20.0f}}); histos.add("h1Phimassgen", "Phi meson gen", kTH1F, {{200, 0.9, 1.1}}); histos.add("h1Phimassrec", "Phi meson Rec", kTH1F, {{200, 0.9, 1.1}}); histos.add("h1Phipt", "Phi meson Rec", kTH1F, {{200, 0.0f, 20.0f}}); } + if (additionalQAplots) { + // DCA QA + histos.add("QAbefore/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + histos.add("QAbefore/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + histos.add("QAafter/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + histos.add("QAafter/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + // PID QA before cuts + histos.add("QAbefore/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); + histos.add("QAbefore/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + histos.add("QAbefore/TPC_Nsigma_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + // PID QA after cuts + histos.add("QAafter/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); + histos.add("QAafter/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + histos.add("QAafter/TPC_Nsigma_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + } } double massKa = o2::constants::physics::MassKPlus; @@ -142,14 +174,18 @@ struct phianalysisrun3_PbPb { template bool selectionPID(const T& candidate) { - if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (nsigmaCutCombined * nsigmaCutCombined)) { + if (!isNoTOF && candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (nsigmaCutCombined * nsigmaCutCombined)) { + return true; + } + if (!isNoTOF && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { return true; } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (isNoTOF && std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { return true; } return false; } + // deep angle cut on pair to remove photon conversion template bool selectionPair(const T1& candidate1, const T2& candidate2) @@ -237,11 +273,20 @@ struct phianalysisrun3_PbPb { using TrackCandidatesMC = soa::Filtered>; + using CollisionMCTrueTable = aod::McCollisions; + using TrackMCTrueTable = aod::McParticles; + using CollisionMCRecTableCentFT0C = soa::SmallGroups>; + using TrackMCRecTable = soa::Join; + using FilTrackMCRecTable = soa::Filtered; ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin"}; + Preslice perCollision = aod::track::collisionId; + + SliceCache cache; + // using BinningType = BinningPolicy>; // BinningType binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; @@ -251,12 +296,17 @@ struct phianalysisrun3_PbPb { // using BinningType = ColumnBinningPolicy; // BinningType binningOnPositions{{axisVertex, axisMultiplicity}, true}; - + ROOT::Math::PxPyPzMVector PhiMesonMother, KaonPlus, KaonMinus; void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { if (!collision.sel8()) { return; } + int occupancy = collision.trackOccupancyInTimeRange(); + if (fillOccupancy && occupancy < cfgOccupancyCut) // occupancy info is available for this collision (*) + { + return; + } float multiplicity; if (cfgMultFT0) multiplicity = collision.centFT0C(); @@ -269,6 +319,12 @@ struct phianalysisrun3_PbPb { if (!selectionTrack(track1)) { continue; } + histos.fill(HIST("QAbefore/TPC_Nsigma_all"), track1.pt(), track1.tpcNSigmaKa()); + histos.fill(HIST("QAbefore/TOF_Nsigma_all"), track1.pt(), track1.tofNSigmaKa()); + histos.fill(HIST("QAbefore/trkDCAxy"), track1.dcaXY()); + histos.fill(HIST("QAbefore/trkDCAz"), track1.dcaZ()); + histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); + histos.fill(HIST("hEta"), track1.eta()); histos.fill(HIST("hDcaxy"), track1.dcaXY()); histos.fill(HIST("hDcaz"), track1.dcaZ()); @@ -291,9 +347,19 @@ struct phianalysisrun3_PbPb { bool likesign = true; bool rotation = true; if (isITSOnlycut) { + histos.fill(HIST("QAafter/TPC_Nsigma_all"), track1.pt(), track1.tpcNSigmaKa()); + histos.fill(HIST("QAafter/TOF_Nsigma_all"), track1.pt(), track1.tofNSigmaKa()); + histos.fill(HIST("QAafter/trkDCAxy"), track1.dcaXY()); + histos.fill(HIST("QAafter/trkDCAz"), track1.dcaZ()); + histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); FillinvMass(track1, track2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); } if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { + histos.fill(HIST("QAafter/TPC_Nsigma_all"), track1.pt(), track1.tpcNSigmaKa()); + histos.fill(HIST("QAafter/TOF_Nsigma_all"), track1.pt(), track1.tofNSigmaKa()); + histos.fill(HIST("QAafter/trkDCAxy"), track1.dcaXY()); + histos.fill(HIST("QAafter/trkDCAz"), track1.dcaZ()); + histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); FillinvMass(track1, track2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); } } @@ -314,7 +380,11 @@ struct phianalysisrun3_PbPb { if (!c2.sel8()) { continue; } - + int occupancy = c1.trackOccupancyInTimeRange(); + if (fillOccupancy && occupancy < cfgOccupancyCut) // occupancy info is available for this collision (*) + { + return; + } float multiplicity; if (cfgMultFT0) multiplicity = c1.centFT0C(); @@ -346,167 +416,172 @@ struct phianalysisrun3_PbPb { } PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent, "Process Mixed event", false); - void processGen(aod::McCollision const& mcCollision, aod::McParticles& mcParticles, const soa::SmallGroups& collisions) - { - histos.fill(HIST("hMC"), 0.5); - if (std::abs(mcCollision.posZ()) < cfgCutVertex) { - histos.fill(HIST("hMC"), 1.5); - } - int Nchinel = 0; - for (auto& mcParticle : mcParticles) { - auto pdgcode = std::abs(mcParticle.pdgCode()); - if (mcParticle.isPhysicalPrimary() && (pdgcode == 211 || pdgcode == 321 || pdgcode == 2212 || pdgcode == 11 || pdgcode == 13)) { - if (std::abs(mcParticle.eta()) < 1.0) { - Nchinel = Nchinel + 1; - } - } - } - if (Nchinel > 0 && std::abs(mcCollision.posZ()) < cfgCutVertex) - histos.fill(HIST("hMC"), 2.5); - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - auto multiplicity = 0; - for (const auto& collision : collisions) { - if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cfgCutVertex) { - continue; - } - multiplicity = collision.centFT0C(); - histos.fill(HIST("Centgen"), multiplicity); - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); - } - SelectedEvents.resize(nevts); - const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); - histos.fill(HIST("hMC"), 3.5); - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection - return; - } - histos.fill(HIST("hMC"), 4.5); - for (auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.y()) >= 0.5) { - continue; - } - if (mcParticle.pdgCode() != 333) { - continue; - } - auto kDaughters = mcParticle.daughters_as(); - if (kDaughters.size() != 2) { - continue; - } - auto daughtp = false; - auto daughtm = false; - for (auto kCurrentDaughter : kDaughters) { - if (!kCurrentDaughter.isPhysicalPrimary()) { - continue; - } - if (kCurrentDaughter.pdgCode() == +321) { - daughtp = true; - } else if (kCurrentDaughter.pdgCode() == -321) { - daughtm = true; - } - } - if (daughtp && daughtm) { - histos.fill(HIST("h1PhiGen"), mcParticle.pt()); - histos.fill(HIST("h2PhiGen2"), mcParticle.pt(), multiplicity); - } - } - } - PROCESS_SWITCH(phianalysisrun3_PbPb, processGen, "Process Generated", false); - void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) + void processMC(CollisionMCTrueTable::iterator const& /*TrueCollision*/, CollisionMCRecTableCentFT0C const& RecCollisions, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { - if (!collision.has_mcCollision()) { + histos.fill(HIST("hMC"), 0); + if (RecCollisions.size() == 0) { + histos.fill(HIST("hMC"), 1); return; } - if (std::abs(collision.mcCollision().posZ()) > cfgCutVertex || !collision.sel8()) { + if (RecCollisions.size() > 1) { + histos.fill(HIST("hMC"), 2); return; } - auto multiplicity = collision.centFT0C(); - histos.fill(HIST("Centrec"), multiplicity); - histos.fill(HIST("hMC"), 5.5); - auto oldindex = -999; - for (auto track1 : tracks) { - if (!selectionTrack(track1)) { + for (auto& RecCollision : RecCollisions) { + histos.fill(HIST("hMC"), 3); + if (!RecCollision.sel8()) { + histos.fill(HIST("hMC"), 4); continue; } - if (!track1.has_mcParticle()) { + if (timFrameEvsel && (!RecCollision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !RecCollision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + histos.fill(HIST("hMC"), 5); continue; } - auto track1ID = track1.index(); - for (auto track2 : tracks) { - if (!track2.has_mcParticle()) { - continue; - } - if (!selectionTrack(track2)) { + if (TMath::Abs(RecCollision.posZ()) > cfgCutVertex) { + histos.fill(HIST("hMC"), 6); + continue; + } + histos.fill(HIST("hMC"), 7); + auto centrality = RecCollision.centFT0C(); + histos.fill(HIST("Centrec"), centrality); + auto oldindex = -999; + auto Rectrackspart = RecTracks.sliceBy(perCollision, RecCollision.globalIndex()); + // loop over reconstructed particle + for (auto track1 : Rectrackspart) { + if (!selectionTrack(track1)) { continue; } - auto track2ID = track2.index(); - if (track2ID <= track1ID) { + if (!selectionPID(track1)) { continue; } - if (!selectionPair(track1, track2)) { + if (!track1.has_mcParticle()) { continue; } - if (track1.sign() * track2.sign() > 0) { - continue; + auto track1ID = track1.index(); + for (auto track2 : Rectrackspart) { + auto track2ID = track2.index(); + if (track2ID <= track1ID) { + continue; + } + if (!selectionTrack(track2)) { + continue; + } + if (!selectionPID(track2)) { + continue; + } + if (!track2.has_mcParticle()) { + continue; + } + if (!selectionPair(track1, track2)) { + continue; + } + if (track1.sign() * track2.sign() > 0) { + continue; + } + const auto mctrack1 = track1.mcParticle(); + const auto mctrack2 = track2.mcParticle(); + int track1PDG = TMath::Abs(mctrack1.pdgCode()); + int track2PDG = TMath::Abs(mctrack2.pdgCode()); + if (!mctrack1.isPhysicalPrimary()) { + continue; + } + if (!mctrack2.isPhysicalPrimary()) { + continue; + } + if (!(track1PDG == 321 && track2PDG == 321)) { + continue; + } + for (auto& mothertrack1 : mctrack1.mothers_as()) { + for (auto& mothertrack2 : mctrack2.mothers_as()) { + if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { + continue; + } + if (mothertrack1 != mothertrack2) { + continue; + } + if (TMath::Abs(mothertrack1.y()) > confRapidity) { + continue; + } + if (TMath::Abs(mothertrack1.pdgCode()) != 333) { + continue; + } + if (!selectionPID(track1) || !selectionPID(track2)) { + continue; + } + if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { + histos.fill(HIST("h1PhiRecsplit"), mothertrack1.pt()); + continue; + } + oldindex = mothertrack1.globalIndex(); + if (track1.sign() > 0 && track2.sign() < 0) { + KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } + if (track1.sign() < 0 && track2.sign() > 0) { + KaonMinus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonPlus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } + PhiMesonMother = KaonPlus + KaonMinus; + + if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + continue; + } + histos.fill(HIST("h1PhiRec1"), PhiMesonMother.pt()); + histos.fill(HIST("h2PhiRec2"), PhiMesonMother.pt(), centrality); + histos.fill(HIST("h1Phimassrec"), PhiMesonMother.M()); + histos.fill(HIST("h3PhiRec3"), PhiMesonMother.pt(), centrality, PhiMesonMother.M()); + } + } } - const auto mctrack1 = track1.mcParticle(); - const auto mctrack2 = track2.mcParticle(); - int track1PDG = std::abs(mctrack1.pdgCode()); - int track2PDG = std::abs(mctrack2.pdgCode()); - if (!mctrack1.isPhysicalPrimary()) { + } + // loop over generated particle + for (auto& mcParticle : GenParticles) { + if (TMath::Abs(mcParticle.y()) > confRapidity) { continue; } - if (!mctrack2.isPhysicalPrimary()) { + if (mcParticle.pdgCode() != 333) { continue; } - if (!(track1PDG == 321 && track2PDG == 321)) { + auto kDaughters = mcParticle.daughters_as(); + if (kDaughters.size() != 2) { continue; } - for (auto& mothertrack1 : mctrack1.mothers_as()) { - for (auto& mothertrack2 : mctrack2.mothers_as()) { - if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { - continue; - } - if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) { - continue; - } - if (!mothertrack1.producedByGenerator()) { - continue; - } - if (std::abs(mothertrack1.y()) >= 0.5) { - continue; + auto daughtp = false; + auto daughtm = false; + for (auto kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { + continue; + } + if (kCurrentDaughter.pdgCode() == +321) { + if (genacceptancecut && kCurrentDaughter.pt() > cfgCutPT && TMath::Abs(kCurrentDaughter.eta()) < cfgCutEta) { + daughtp = true; } - if (std::abs(mothertrack1.pdgCode()) != 333) { - continue; + if (!genacceptancecut) { + daughtp = true; } - if (!isITSOnlycut && !(selectionPID(track1) && selectionPID(track2))) { - continue; + KaonPlus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + } else if (kCurrentDaughter.pdgCode() == -321) { + if (genacceptancecut && kCurrentDaughter.pt() > cfgCutPT && TMath::Abs(kCurrentDaughter.eta()) < cfgCutEta) { + daughtm = true; } - if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { - histos.fill(HIST("h1PhiRecsplit"), mothertrack1.pt()); - continue; + if (!genacceptancecut) { + daughtm = true; } - oldindex = mothertrack1.globalIndex(); - pvec0 = array{track1.px(), track1.py(), track1.pz()}; - pvec1 = array{track2.px(), track2.py(), track2.pz()}; - auto arrMomrec = array{pvec0, pvec1}; - auto motherP = mothertrack1.p(); - auto motherE = mothertrack1.e(); - genMass = std::sqrt(motherE * motherE - motherP * motherP); - recMass = RecoDecay::m(arrMomrec, array{massKa, massKa}); - auto recpt = TMath::Sqrt((track1.px() + track2.px()) * (track1.px() + track2.px()) + (track1.py() + track2.py()) * (track1.py() + track2.py())); - histos.fill(HIST("h1PhiRec1"), mothertrack1.pt()); - histos.fill(HIST("h2PhiRec2"), mothertrack1.pt(), multiplicity); - histos.fill(HIST("h1Phimassgen"), genMass); - histos.fill(HIST("h1Phimassrec"), recMass); - histos.fill(HIST("h1Phipt"), recpt); + KaonMinus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); } } + if (daughtp && daughtm) { + PhiMesonMother = KaonPlus + KaonMinus; + histos.fill(HIST("h1PhiGen"), PhiMesonMother.pt()); + histos.fill(HIST("h2PhiGen2"), PhiMesonMother.pt(), centrality); + histos.fill(HIST("h1Phimassgen"), PhiMesonMother.M()); + } } - } - } + } // rec collision loop - PROCESS_SWITCH(phianalysisrun3_PbPb, processRec, "Process Reconstructed", false); + } // process MC + PROCESS_SWITCH(phianalysisrun3_PbPb, processMC, "Process Reconstructed", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Resonances/phipbpb.cxx b/PWGLF/Tasks/Resonances/phipbpb.cxx index a97cb412127..79b4e42f6b8 100644 --- a/PWGLF/Tasks/Resonances/phipbpb.cxx +++ b/PWGLF/Tasks/Resonances/phipbpb.cxx @@ -145,8 +145,8 @@ struct phipbpb { void init(o2::framework::InitContext&) { - std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; // std::vector occupancyBinning = {0.0, 500.0, 1000.0, 3000.0, 6000.0, 50000.0}; + std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec thnAxisCosThetaStarOP{configThnAxisCosThetaStar, "cos(#vartheta_{OP})"}; @@ -175,11 +175,11 @@ struct phipbpb { histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); - histos.add("hPsiFT0C", "PsiFT0C", kTH2F, {centAxis, phiAxis}); - histos.add("hPsiFT0A", "PsiFT0A", kTH2F, {centAxis, phiAxis}); - histos.add("hPsiTPC", "PsiTPC", kTH2F, {centAxis, phiAxis}); - histos.add("hPsiTPCR", "PsiTPCR", kTH2F, {centAxis, phiAxis}); - histos.add("hPsiTPCL", "PsiTPCL", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, occupancyAxis, phiAxis}); if (!fillRapidity) { histos.add("hSparseV2SASameEvent_costhetastarOP", "hSparseV2SASameEvent_costhetastarOP", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStarOP, thnAxisPhiminusPsi, thnAxisCentrality}); histos.add("hSparseV2SASameEvent_costhetastarIP", "hSparseV2SASameEvent_costhetastarIP", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStarOP, thnAxisPhiminusPsi, thnAxisCentrality}); @@ -211,19 +211,19 @@ struct phipbpb { histos.add("hSparseV2SAMixedEvent_V2", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); } // histogram for resolution - histos.add("ResFT0CTPC", "ResFT0CTPC", kTH2F, {centAxis, resAxis}); - histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH2F, {centAxis, resAxis}); - histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH2F, {centAxis, resAxis}); - histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH2F, {centAxis, resAxis}); - histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH2F, {centAxis, resAxis}); - histos.add("ResFT0ATPC", "ResFT0ATPC", kTH2F, {centAxis, resAxis}); - - histos.add("ResSPFT0CTPC", "ResSPFT0CTPC", kTH2F, {centAxis, resAxis}); - histos.add("ResSPFT0CTPCR", "ResSPFT0CTPCR", kTH2F, {centAxis, resAxis}); - histos.add("ResSPFT0CTPCL", "ResSPFT0CTPCL", kTH2F, {centAxis, resAxis}); - histos.add("ResSPTPCRTPCL", "ResSPTPCRTPCL", kTH2F, {centAxis, resAxis}); - histos.add("ResSPFT0CFT0A", "ResSPFT0CFT0A", kTH2F, {centAxis, resAxis}); - histos.add("ResSPFT0ATPC", "ResSPFT0ATPC", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CTPC", "ResFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0ATPC", "ResFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("ResSPFT0CTPC", "ResSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CTPCR", "ResSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CTPCL", "ResSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPTPCRTPCL", "ResSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CFT0A", "ResSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0ATPC", "ResSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); // MC histogram if (isMC) { @@ -318,10 +318,10 @@ struct phipbpb { template bool selectionPIDpTdependent(const T& candidate) { - if (candidate.p() < 0.5 && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (candidate.pt() < 0.5 && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { return true; } - if (candidate.p() >= 0.5 && candidate.hasTOF() && ((candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) + (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa())) < (nsigmaCutCombined * nsigmaCutCombined)) { + if (candidate.pt() >= 0.5 && candidate.hasTOF() && ((candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) + (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa())) < (nsigmaCutCombined * nsigmaCutCombined)) { return true; } if (!useGlobalTrack && !candidate.hasTPC()) { @@ -389,7 +389,7 @@ struct phipbpb { { const auto pglobal = track.p(); const auto ptpc = track.tpcInnerParam(); - if (std::abs(pglobal - ptpc) > ConfFakeKaonCut) { + if (TMath::Abs(pglobal - ptpc) > ConfFakeKaonCut) { return true; } return false; @@ -398,8 +398,9 @@ struct phipbpb { ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; ConfigurableAxis axisEPAngle{"axisEPAngle", {6, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; + ConfigurableAxis axisOccup{"axisOccup", {20, 0.0, 40000.0}, "occupancy axis"}; - using BinningTypeVertexContributor = ColumnBinningPolicy; + using BinningTypeVertexContributor = ColumnBinningPolicy; ROOT::Math::PxPyPzMVector PhiMesonMother, KaonPlus, KaonMinus, fourVecDauCM; ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY, eventplaneVec, eventplaneVecNorm, beamvector; @@ -441,25 +442,25 @@ struct phipbpb { return; } histos.fill(HIST("hFTOCvsTPCSelected"), centrality, multTPC); - histos.fill(HIST("hPsiFT0C"), centrality, psiFT0C); - histos.fill(HIST("hPsiFT0A"), centrality, psiFT0A); - histos.fill(HIST("hPsiTPC"), centrality, psiTPC); - histos.fill(HIST("hPsiTPCR"), centrality, psiTPCR); - histos.fill(HIST("hPsiTPCL"), centrality, psiTPCL); - - histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC))); - histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCR))); - histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCL))); - histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(2.0 * (psiTPCR - psiTPCL))); - histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); - histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiTPC - psiFT0A))); - - histos.fill(HIST("ResSPFT0CTPC"), centrality, QFT0C * QTPC * TMath::Cos(2.0 * (psiFT0C - psiTPC))); - histos.fill(HIST("ResSPFT0CTPCR"), centrality, QFT0C * QTPCR * TMath::Cos(2.0 * (psiFT0C - psiTPCR))); - histos.fill(HIST("ResSPFT0CTPCL"), centrality, QFT0C * QTPCL * TMath::Cos(2.0 * (psiFT0C - psiTPCL))); - histos.fill(HIST("ResSPTPCRTPCL"), centrality, QTPCR * QTPCL * TMath::Cos(2.0 * (psiTPCR - psiTPCL))); - histos.fill(HIST("ResSPFT0CFT0A"), centrality, QFT0C * QFT0A * TMath::Cos(2.0 * (psiFT0C - psiFT0A))); - histos.fill(HIST("ResSPFT0ATPC"), centrality, QTPC * QFT0A * TMath::Cos(2.0 * (psiTPC - psiFT0A))); + histos.fill(HIST("hPsiFT0C"), centrality, occupancy, psiFT0C); + histos.fill(HIST("hPsiFT0A"), centrality, occupancy, psiFT0A); + histos.fill(HIST("hPsiTPC"), centrality, occupancy, psiTPC); + histos.fill(HIST("hPsiTPCR"), centrality, occupancy, psiTPCR); + histos.fill(HIST("hPsiTPCL"), centrality, occupancy, psiTPCL); + + histos.fill(HIST("ResFT0CTPC"), centrality, occupancy, TMath::Cos(2.0 * (psiFT0C - psiTPC))); + histos.fill(HIST("ResFT0CTPCR"), centrality, occupancy, TMath::Cos(2.0 * (psiFT0C - psiTPCR))); + histos.fill(HIST("ResFT0CTPCL"), centrality, occupancy, TMath::Cos(2.0 * (psiFT0C - psiTPCL))); + histos.fill(HIST("ResTPCRTPCL"), centrality, occupancy, TMath::Cos(2.0 * (psiTPCR - psiTPCL))); + histos.fill(HIST("ResFT0CFT0A"), centrality, occupancy, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); + histos.fill(HIST("ResFT0ATPC"), centrality, occupancy, TMath::Cos(2.0 * (psiTPC - psiFT0A))); + + histos.fill(HIST("ResSPFT0CTPC"), centrality, occupancy, QFT0C * QTPC * TMath::Cos(2.0 * (psiFT0C - psiTPC))); + histos.fill(HIST("ResSPFT0CTPCR"), centrality, occupancy, QFT0C * QTPCR * TMath::Cos(2.0 * (psiFT0C - psiTPCR))); + histos.fill(HIST("ResSPFT0CTPCL"), centrality, occupancy, QFT0C * QTPCL * TMath::Cos(2.0 * (psiFT0C - psiTPCL))); + histos.fill(HIST("ResSPTPCRTPCL"), centrality, occupancy, QTPCR * QTPCL * TMath::Cos(2.0 * (psiTPCR - psiTPCL))); + histos.fill(HIST("ResSPFT0CFT0A"), centrality, occupancy, QFT0C * QFT0A * TMath::Cos(2.0 * (psiFT0C - psiFT0A))); + histos.fill(HIST("ResSPFT0ATPC"), centrality, occupancy, QTPC * QFT0A * TMath::Cos(2.0 * (psiTPC - psiFT0A))); histos.fill(HIST("hCentrality"), centrality); histos.fill(HIST("hVtxZ"), collision.posZ()); @@ -561,7 +562,7 @@ struct phipbpb { PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", true); void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& /*tracks*/) { - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisOccup}, true}; for (auto const& [collision1, collision2] : o2::soa::selfCombinations(binningOnPositions, cfgNoMixedEvents, -1, collisions, collisions)) { if (!collision1.sel8() || !collision2.sel8()) { // printf("Mix = %d\n", 1); @@ -668,7 +669,7 @@ struct phipbpb { void processMixedEventOpti(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisOccup}, true}; SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; for (auto& [collision1, tracks1, collision2, tracks2] : pair) { if (!collision1.sel8() || !collision2.sel8()) { @@ -798,7 +799,7 @@ struct phipbpb { histos.fill(HIST("hMC"), 5); continue; } - if (std::abs(RecCollision.posZ()) > cfgCutVertex) { + if (TMath::Abs(RecCollision.posZ()) > cfgCutVertex) { histos.fill(HIST("hMC"), 6); continue; } @@ -847,8 +848,8 @@ struct phipbpb { } const auto mctrack1 = track1.mcParticle(); const auto mctrack2 = track2.mcParticle(); - int track1PDG = std::abs(mctrack1.pdgCode()); - int track2PDG = std::abs(mctrack2.pdgCode()); + int track1PDG = TMath::Abs(mctrack1.pdgCode()); + int track2PDG = TMath::Abs(mctrack2.pdgCode()); if (!mctrack1.isPhysicalPrimary()) { continue; } @@ -866,10 +867,10 @@ struct phipbpb { if (mothertrack1 != mothertrack2) { continue; } - if (std::abs(mothertrack1.y()) > confRapidity) { + if (TMath::Abs(mothertrack1.y()) > confRapidity) { continue; } - if (std::abs(mothertrack1.pdgCode()) != 333) { + if (TMath::Abs(mothertrack1.pdgCode()) != 333) { continue; } if (!selectionPID(track1) || !selectionPID(track2)) { @@ -934,7 +935,7 @@ struct phipbpb { } // loop over generated particle for (auto& mcParticle : GenParticles) { - if (std::abs(mcParticle.y()) > confRapidity) { + if (TMath::Abs(mcParticle.y()) > confRapidity) { continue; } if (mcParticle.pdgCode() != 333) { diff --git a/PWGLF/Tasks/Strangeness/CMakeLists.txt b/PWGLF/Tasks/Strangeness/CMakeLists.txt index 32a70cfb412..961f7511cd5 100644 --- a/PWGLF/Tasks/Strangeness/CMakeLists.txt +++ b/PWGLF/Tasks/Strangeness/CMakeLists.txt @@ -16,7 +16,7 @@ o2physics_add_dpl_workflow(hyperon-reco-test o2physics_add_dpl_workflow(derivedlambdakzeroanalysis SOURCES derivedlambdakzeroanalysis.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lambdakzeroanalysis-mc @@ -98,3 +98,13 @@ o2physics_add_dpl_workflow(strangeness-in-jets SOURCES strangeness_in_jets.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(v0topologicalcuts + SOURCES v0topologicalcuts.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(v0ptinvmassplots + SOURCES v0ptinvmassplots.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Strangeness/cascadeanalysisMC.cxx b/PWGLF/Tasks/Strangeness/cascadeanalysisMC.cxx index 05df2504e4e..896d366a1fa 100644 --- a/PWGLF/Tasks/Strangeness/cascadeanalysisMC.cxx +++ b/PWGLF/Tasks/Strangeness/cascadeanalysisMC.cxx @@ -78,16 +78,23 @@ struct cascadeGenerated { Configurable maxPt{"maxPt", 20.0, "max generated pT"}; Configurable nPtBins{"nPtBins", 200, "number of pT bins"}; + Configurable rapidityCut{"rapidityCut", 0.5, "max (absolute) rapidity of generated cascade"}; + Configurable nRapidityBins{"nRapidityBins", 200, "number of pT bins"}; void init(InitContext const&) { - AxisSpec ptAxis = {nPtBins, 0.0f, maxPt, "it{p}_{T} (GeV/c)"}; + AxisSpec ptAxis = {nPtBins, 0.0f, maxPt, "#it{p}_{T} (GeV/c)"}; + AxisSpec rapidityAxis = {nRapidityBins, -rapidityCut, rapidityCut, "y"}; registry.add("hEventCounter", "hEventCounter", {HistType::kTH1F, {{10, 0.0f, 10.0f}}}); registry.add("hPtXiMinus", "hPtXiMinus", {HistType::kTH1F, {ptAxis}}); registry.add("hPtXiPlus", "hPtXiPlus", {HistType::kTH1F, {ptAxis}}); registry.add("hPtOmegaMinus", "hPtOmegaMinus", {HistType::kTH1F, {ptAxis}}); registry.add("hPtOmegaPlus", "hPtOmegaPlus", {HistType::kTH1F, {ptAxis}}); + registry.add("h2DXiMinus", "h2DXiMinus", {HistType::kTH2F, {ptAxis, rapidityAxis}}); + registry.add("h2DXiPlus", "h2DXiPlus", {HistType::kTH2F, {ptAxis, rapidityAxis}}); + registry.add("h2DOmegaMinus", "h2DOmegaMinus", {HistType::kTH2F, {ptAxis, rapidityAxis}}); + registry.add("h2DOmegaPlus", "h2DOmegaPlus", {HistType::kTH2F, {ptAxis, rapidityAxis}}); } void process(aod::McCollision const& /*collision*/, aod::McParticles const& mcparts) @@ -99,16 +106,24 @@ struct cascadeGenerated { // Count all generated MC particles // WARNING: event-level losses have to be understood too for (auto& particle : mcparts) { - if (TMath::Abs(particle.y()) > 0.5) + if (TMath::Abs(particle.y()) > rapidityCut) continue; - if (particle.pdgCode() == 3312) + if (particle.pdgCode() == 3312) { registry.fill(HIST("hPtXiMinus"), particle.pt()); - if (particle.pdgCode() == -3312) + registry.fill(HIST("h2DXiMinus"), particle.pt(), particle.y()); + } + if (particle.pdgCode() == -3312) { registry.fill(HIST("hPtXiPlus"), particle.pt()); - if (particle.pdgCode() == 3334) + registry.fill(HIST("h2DXiPlus"), particle.pt(), particle.y()); + } + if (particle.pdgCode() == 3334) { registry.fill(HIST("hPtOmegaMinus"), particle.pt()); - if (particle.pdgCode() == -3334) + registry.fill(HIST("h2DOmegaMinus"), particle.pt(), particle.y()); + } + if (particle.pdgCode() == -3334) { registry.fill(HIST("hPtOmegaPlus"), particle.pt()); + registry.fill(HIST("h2DOmegaPlus"), particle.pt(), particle.y()); + } } } }; @@ -184,9 +199,13 @@ struct cascadeAnalysisMC { {}, }; + Configurable rapidityCut{"rapidityCut", 0.5, "max (absolute) rapidity of cascade candidate"}; + Configurable nRapidityBins{"nRapidityBins", 200, "number of pT bins"}; + void init(InitContext const&) { - AxisSpec ptAxis = {200, 0.0f, 10.0f, "it{p}_{T} (GeV/c)"}; + AxisSpec ptAxis = {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}; + AxisSpec rapidityAxis = {nRapidityBins, -rapidityCut, rapidityCut, "y"}; AxisSpec massAxisXi = {200, 1.222f, 1.422f, "Inv. Mass (GeV/c^{2})"}; AxisSpec massAxisOmega = {200, 1.572f, 1.772f, "Inv. Mass (GeV/c^{2})"}; @@ -195,6 +214,10 @@ struct cascadeAnalysisMC { registry.add("h2dMassXiPlus", "h2dMassXiPlus", {HistType::kTH2F, {ptAxis, massAxisXi}}); registry.add("h2dMassOmegaMinus", "h2dMassOmegaMinus", {HistType::kTH2F, {ptAxis, massAxisOmega}}); registry.add("h2dMassOmegaPlus", "h2dMassOmegaPlus", {HistType::kTH2F, {ptAxis, massAxisOmega}}); + registry.add("hPtYMassXiMinus", "hPtYMassXiMinus", {HistType::kTH3F, {ptAxis, rapidityAxis, massAxisXi}}); + registry.add("hPtYMassXiPlus", "hPtYMassXiPlus", {HistType::kTH3F, {ptAxis, rapidityAxis, massAxisXi}}); + registry.add("hPtYMassOmegaMinus", "hPtYMassOmegaMinus", {HistType::kTH3F, {ptAxis, rapidityAxis, massAxisOmega}}); + registry.add("hPtYMassOmegaPlus", "hPtYMassOmegaPlus", {HistType::kTH3F, {ptAxis, rapidityAxis, massAxisOmega}}); } // Selection criteria @@ -347,14 +370,16 @@ struct cascadeAnalysisMC { TMath::Abs(casc.mLambda() - 1.115683) < cascadesetting_v0masswindow) { registry.fill(HIST("hCandidateCounter"), 3.5); // pass cascade selections if (casc.sign() < 0) { // FIXME: could be done better... - if (TMath::Abs(casc.yXi()) < 0.5 && lCompatiblePID_Xi && ((!assocMC) || (lPDG == 3312))) { + if (TMath::Abs(casc.yXi()) < rapidityCut && lCompatiblePID_Xi && ((!assocMC) || (lPDG == 3312))) { + registry.fill(HIST("hPtYMassXiMinus"), casc.pt(), casc.yXi(), casc.mXi()); if (!doCentralityStudy) { registry.fill(HIST("h2dMassXiMinus"), casc.pt(), casc.mXi()); } else { registry.fill(HIST("h3dMassXiMinus"), lPercentile, casc.pt(), casc.mXi()); } } - if (TMath::Abs(casc.yOmega()) < 0.5 && lCompatiblePID_Om && ((!assocMC) || (lPDG == 3334))) { + if (TMath::Abs(casc.yOmega()) < rapidityCut && lCompatiblePID_Om && ((!assocMC) || (lPDG == 3334))) { + registry.fill(HIST("hPtYMassOmegaMinus"), casc.pt(), casc.yOmega(), casc.mOmega()); if (!doCentralityStudy) { registry.fill(HIST("h2dMassOmegaMinus"), casc.pt(), casc.mOmega()); } else { @@ -362,14 +387,16 @@ struct cascadeAnalysisMC { } } } else { - if (TMath::Abs(casc.yXi()) < 0.5 && lCompatiblePID_Xi && ((!assocMC) || (lPDG == -3312))) { + if (TMath::Abs(casc.yXi()) < rapidityCut && lCompatiblePID_Xi && ((!assocMC) || (lPDG == -3312))) { + registry.fill(HIST("hPtYMassXiPlus"), casc.pt(), casc.yXi(), casc.mXi()); if (!doCentralityStudy) { registry.fill(HIST("h2dMassXiPlus"), casc.pt(), casc.mXi()); } else { registry.fill(HIST("h3dMassXiPlus"), lPercentile, casc.pt(), casc.mXi()); } } - if (TMath::Abs(casc.yOmega()) < 0.5 && lCompatiblePID_Om && ((!assocMC) || (lPDG == -3334))) { + if (TMath::Abs(casc.yOmega()) < rapidityCut && lCompatiblePID_Om && ((!assocMC) || (lPDG == -3334))) { + registry.fill(HIST("hPtYMassOmegaPlus"), casc.pt(), casc.yOmega(), casc.mOmega()); if (!doCentralityStudy) { registry.fill(HIST("h2dMassOmegaPlus"), casc.pt(), casc.mOmega()); } else { diff --git a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx index 152ca106846..2d02d8c2111 100644 --- a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx +++ b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx @@ -34,7 +34,10 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "CCDB/BasicCCDBManager.h" + #include +#include #include #include #include @@ -263,17 +266,50 @@ struct cascadeSelector { }; // struct struct cascadeCorrelations { + Service ccdb; Configurable zVertexCut{"zVertexCut", 10, "Cut on PV position"}; + Configurable nMixedEvents{"nMixedEvents", 10, "Number of events to be mixed"}; + Configurable doEfficiencyCorrection{"doEfficiencyCorrection", true, "flag to do efficiency corrections"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "CCDB url"}; + Configurable efficiencyCCDBPath{"efficiencyCCDBPath", "Users/r/rspijker/test/EffTest", "Path of the efficiency corrections"}; AxisSpec invMassAxis = {2000, 1.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}; AxisSpec deltaPhiAxis = {100, -PI / 2, 1.5 * PI, "#Delta#varphi"}; - AxisSpec deltaEtaAxis = {40, -2, 2, "#Delta#eta"}; + AxisSpec deltaYAxis = {40, -2, 2, "#Delta y"}; // TODO: narrower range? AxisSpec ptAxis = {200, 0, 15, "#it{p}_{T}"}; AxisSpec selectionFlagAxis = {4, -0.5f, 3.5f, "Selection flag of casc candidate"}; AxisSpec vertexAxis = {200, -10.0f, 10.0f, "cm"}; AxisSpec multiplicityAxis{100, 0, 100, "Multiplicity (MultFT0M?)"}; + // initialize efficiency maps + TH1D* hEffXiMin; + TH1D* hEffXiPlus; + TH1D* hEffOmegaMin; + TH1D* hEffOmegaPlus; + + void init(InitContext const&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + if (doEfficiencyCorrection) { + TList* effList = ccdb->getForTimeStamp(efficiencyCCDBPath, 1); + if (!effList) { + LOGF(fatal, "null ptr in efficiency list!"); + } + hEffXiMin = static_cast(effList->FindObject("hXiMinEff")); + hEffXiPlus = static_cast(effList->FindObject("hXiPlusEff")); + hEffOmegaMin = static_cast(effList->FindObject("hOmegaMinEff")); + hEffOmegaPlus = static_cast(effList->FindObject("hOmegaPlusEff")); + } + } + + double getEfficiency(TH1D* h, double pT) + { // TODO: make 2D (rapidity) + // This function returns the value of histogram h corresponding to the x-coordinate pT + return h->GetBinContent(h->GetXaxis()->FindFixBin(pT)); + } + HistogramRegistry registry{ "registry", { @@ -301,34 +337,37 @@ struct cascadeCorrelations { {"hAutoCorrelationOS", "hAutoCorrelationOS", {HistType::kTH1I, {{2, -1.f, 1.f, "Charge of OS autocorrelated track"}}}}, {"hPhi", "hPhi", {HistType::kTH1F, {{100, 0, 2 * PI, "#varphi"}}}}, {"hEta", "hEta", {HistType::kTH1F, {{100, -2, 2, "#eta"}}}}, + {"hRapidityXi", "hRapidityXi", {HistType::kTH1F, {{100, -2, 2, "y"}}}}, + {"hRapidityOmega", "hRapidityOmega", {HistType::kTH1F, {{100, -2, 2, "y"}}}}, // correlation histos {"hDeltaPhiSS", "hDeltaPhiSS", {HistType::kTH1F, {deltaPhiAxis}}}, {"hDeltaPhiOS", "hDeltaPhiOS", {HistType::kTH1F, {deltaPhiAxis}}}, - // THnSparses containing all relevant dimensions, to be extended with e.g. multiplicity - // TODO: maybe use a seperate table/tree for this? - {"hXiXiOS", "hXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hXiXiSS", "hXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hXiOmOS", "hXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hXiOmSS", "hXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hOmXiOS", "hOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hOmXiSS", "hOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hOmOmOS", "hOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"hOmOmSS", "hOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - - // ad hoc mixed events + + {"hXiXiOS", "hXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hXiXiSS", "hXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hXiOmOS", "hXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hXiOmSS", "hXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hOmXiOS", "hOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hOmXiSS", "hOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hOmOmOS", "hOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"hOmOmSS", "hOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + + // Mixed events {"MixedEvents/hMEVz1", "hMEVz1", {HistType::kTH1F, {vertexAxis}}}, {"MixedEvents/hMEVz2", "hMEVz2", {HistType::kTH1F, {vertexAxis}}}, {"MixedEvents/hMEDeltaPhiSS", "hMEDeltaPhiSS", {HistType::kTH1F, {deltaPhiAxis}}}, {"MixedEvents/hMEDeltaPhiOS", "hMEDeltaPhiOS", {HistType::kTH1F, {deltaPhiAxis}}}, - {"MixedEvents/hMEXiXiOS", "hMEXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEXiXiSS", "hMEXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEXiOmOS", "hMEXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEXiOmSS", "hMEXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEOmXiOS", "hMEOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEOmXiSS", "hMEOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEOmOmOS", "hMEOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, - {"MixedEvents/hMEOmOmSS", "hMEOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEQA", "hMEQA", {HistType::kTH1I, {{2, 0, 2, "QA for exceptions in ME (this histogram should have 0 entries!)"}}}}, + + {"MixedEvents/hMEXiXiOS", "hMEXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEXiXiSS", "hMEXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEXiOmOS", "hMEXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEXiOmSS", "hMEXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEOmXiOS", "hMEOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEOmXiSS", "hMEOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEOmOmOS", "hMEOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, + {"MixedEvents/hMEOmOmSS", "hMEOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}}, }, }; @@ -345,7 +384,7 @@ struct cascadeCorrelations { using BinningType = ColumnBinningPolicy>; BinningType colBinning{{axisVtxZ, axisMult}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. // Preslice collisionSliceCascades = aod::CascDataExtSelected::collisionId; - SameKindPair pair{colBinning, 5, -1, &cache}; + SameKindPair pair{colBinning, nMixedEvents, -1, &cache}; void processSameEvent(myCollisions::iterator const& collision, myCascades const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, FullTracksExtIU const&) { @@ -361,6 +400,7 @@ struct cascadeCorrelations { } else { registry.fill(HIST("hMassXiPlus"), casc.mXi(), casc.pt()); } + registry.fill(HIST("hRapidityXi"), casc.yXi()); } if (casc.isSelected() >= 2) { // consistent with Omega or both if (casc.sign() < 0) { @@ -368,6 +408,7 @@ struct cascadeCorrelations { } else { registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt()); } + registry.fill(HIST("hRapidityOmega"), casc.yOmega()); } registry.fill(HIST("hV0Radius"), casc.v0radius()); registry.fill(HIST("hCascRadius"), casc.cascradius()); @@ -404,7 +445,6 @@ struct cascadeCorrelations { int negIdAssoc = assoc.negTrackId(); // calculate angular correlations - double deta = trigger.eta() - assoc.eta(); double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -0.5 * PI); double invMassXiTrigg = trigger.mXi(); @@ -412,9 +452,10 @@ struct cascadeCorrelations { double invMassXiAssoc = assoc.mXi(); double invMassOmAssoc = assoc.mOmega(); - double weight = 1.; // Will be changed by Efficiency-correction + double weightTrigg = 1.; + double weightAssoc = 1.; - // Fill the correct histograms based on same-sign or opposite-sign + // split into opposite-sign or same-sign if (trigger.sign() * assoc.sign() < 0) { // opposite-sign // check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic? if (trigger.isSelected() >= 2) { @@ -441,12 +482,36 @@ struct cascadeCorrelations { continue; } } - registry.fill(HIST("hDeltaPhiOS"), dphi); - registry.fill(HIST("hXiXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); - registry.fill(HIST("hXiOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); - registry.fill(HIST("hOmXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); - registry.fill(HIST("hOmOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); + // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) + if (trigger.isSelected() <= 2) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffXiMin, trigger.pt()) : 1. / getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("hXiXiOS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hXiOmOS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + } + if (trigger.isSelected() >= 2) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, trigger.pt()) : 1. / getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("hOmXiOS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hOmOmOS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + } } else { // same-sign // make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct) if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) { @@ -482,10 +547,35 @@ struct cascadeCorrelations { } } registry.fill(HIST("hDeltaPhiSS"), dphi); - registry.fill(HIST("hXiXiSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); - registry.fill(HIST("hXiOmSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); - registry.fill(HIST("hOmXiSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); - registry.fill(HIST("hOmOmSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M(), weight); + // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) + if (trigger.isSelected() <= 2) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffXiMin, trigger.pt()) : 1. / getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("hXiXiSS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hXiOmSS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + } + if (trigger.isSelected() >= 2) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, trigger.pt()) : 1. / getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("hOmXiSS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hOmOmSS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); + } + } } } // correlations } // process same event @@ -500,6 +590,10 @@ struct cascadeCorrelations { continue; if (TMath::Abs(col1.posZ()) > zVertexCut || TMath::Abs(col2.posZ()) > zVertexCut) continue; + if (col1.globalIndex() == col2.globalIndex()) { + registry.fill(HIST("hMEQA"), 0.5); + continue; + } registry.fill(HIST("MixedEvents/hMEVz1"), col1.posZ()); registry.fill(HIST("MixedEvents/hMEVz2"), col2.posZ()); @@ -514,7 +608,11 @@ struct cascadeCorrelations { auto trigger = *triggerAddress; auto assoc = *assocAddress; - double deta = trigger.eta() - assoc.eta(); + if (trigger.collisionId() == assoc.collisionId()) { + registry.fill(HIST("hMEQA"), 1.5); + continue; + } + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -0.5 * PI); double invMassXiTrigg = trigger.mXi(); @@ -522,21 +620,140 @@ struct cascadeCorrelations { double invMassXiAssoc = assoc.mXi(); double invMassOmAssoc = assoc.mOmega(); - double weight = 1.; // Will be changed by Efficiency-correction + // V0 daughter track ID's used for autocorrelation check + int posIdTrigg = trigger.posTrackId(); + int negIdTrigg = trigger.negTrackId(); + int posIdAssoc = assoc.posTrackId(); + int negIdAssoc = assoc.negTrackId(); + + double weightTrigg = 1.; + double weightAssoc = 1.; if (trigger.sign() * assoc.sign() < 0) { // opposite-sign + + // check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic? + if (trigger.isSelected() >= 2) { + if (trigger.sign() > 0 && trigger.bachelorId() == posIdAssoc) { + // K+ from trigger Omega is the same as proton from assoc lambda + registry.fill(HIST("hAutoCorrelationOS"), 1); + continue; + } + if (trigger.sign() < 0 && trigger.bachelorId() == negIdAssoc) { + // K- from trigger Omega is the same as antiproton from assoc antilambda + registry.fill(HIST("hAutoCorrelationOS"), -1); + continue; + } + } + if (assoc.isSelected() >= 2) { + if (assoc.sign() > 0 && assoc.bachelorId() == posIdTrigg) { + // K+ from assoc Omega is the same as proton from trigger lambda + registry.fill(HIST("hAutoCorrelationOS"), 1); + continue; + } + if (assoc.sign() < 0 && assoc.bachelorId() == negIdTrigg) { + // K- from assoc Omega is the same as antiproton from trigger antilambda + registry.fill(HIST("hAutoCorrelationOS"), -1); + continue; + } + } + registry.fill(HIST("MixedEvents/hMEDeltaPhiOS"), dphi); - registry.fill(HIST("MixedEvents/hMEXiXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - registry.fill(HIST("MixedEvents/hMEXiOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - registry.fill(HIST("MixedEvents/hMEOmXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - registry.fill(HIST("MixedEvents/hMEOmOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); + + // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) + if (trigger.isSelected() <= 2) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffXiMin, trigger.pt()) : 1. / getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiXiOS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiOmOS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + } + if (trigger.isSelected() >= 2) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, trigger.pt()) : 1. / getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEOmXiOS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEOmOmOS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + } } else { // same sign + // make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct) + if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) { + // LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id()); + registry.fill(HIST("hAutoCorrelation"), 0); + continue; + } + int bachIdTrigg = trigger.bachelorId(); + int bachIdAssoc = assoc.bachelorId(); + + if (bachIdTrigg == bachIdAssoc) { + // LOGF(info, "same bachelor in SS correlation! %d %d", bachIdTrigg, bachIdAssoc); + registry.fill(HIST("hAutoCorrelation"), 1); + continue; + } + // check for same tracks in v0's of cascades + if (negIdTrigg == negIdAssoc || posIdTrigg == posIdAssoc) { + // LOGF(info, "cascades have a v0-track in common in SS correlation!"); + registry.fill(HIST("hAutoCorrelation"), 2); + continue; + } + if (trigger.sign() < 0) { // neg cascade + if (negIdTrigg == bachIdAssoc || negIdAssoc == bachIdTrigg) { + // LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!"); + registry.fill(HIST("hAutoCorrelation"), 3); + continue; + } + } else { // pos cascade + if (posIdTrigg == bachIdAssoc || posIdAssoc == bachIdTrigg) { + // LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!"); + registry.fill(HIST("hAutoCorrelation"), 3); + continue; + } + } + registry.fill(HIST("MixedEvents/hMEDeltaPhiSS"), dphi); - registry.fill(HIST("MixedEvents/hMEXiXiSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - registry.fill(HIST("MixedEvents/hMEXiOmSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - registry.fill(HIST("MixedEvents/hMEOmXiSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - registry.fill(HIST("MixedEvents/hMEOmOmSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), col1.posZ(), col1.multFT0M(), weight); - } + + if (trigger.isSelected() <= 2) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffXiMin, trigger.pt()) : 1. / getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiXiSS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiOmSS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + } + if (trigger.isSelected() >= 2) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, trigger.pt()) : 1. / getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffXiMin, assoc.pt()) : 1. / getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEOmXiSS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? 1. / getEfficiency(hEffOmegaMin, assoc.pt()) : 1. / getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEOmOmSS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); + } + } + } // same sign } // correlations } // collisions } // process mixed events diff --git a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx index c51eaaa7725..3bbff7b117a 100644 --- a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx +++ b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx @@ -158,8 +158,8 @@ struct cascpostprocessing { registry.add("hPt", "hPt", {HistType::kTH1F, {ptAxis}}); registry.add("hCascMinusInvMassvsPt", "hCascMinusInvMassvsPt", HistType::kTH2F, {ptAxis, massAxis}); registry.add("hCascPlusInvMassvsPt", "hCascPlusInvMassvsPt", HistType::kTH2F, {ptAxis, massAxis}); - registry.add("hCascMinusInvMassvsPt_FT0M", "hCascMinusInvMassvsPt_FT0M", HistType::kTH3F, {isMC ? nChargedFT0MGenAxis : centFT0MAxis, ptAxis, massAxis}); - registry.add("hCascPlusInvMassvsPt_FT0M", "hCascPlusInvMassvsPt_FT0M", HistType::kTH3F, {isMC ? nChargedFT0MGenAxis : centFT0MAxis, ptAxis, massAxis}); + registry.add("hCascMinusInvMassvsPt_FT0M", "hCascMinusInvMassvsPt_FT0M", HistType::kTH3F, {centFT0MAxis, ptAxis, massAxis}); + registry.add("hCascPlusInvMassvsPt_FT0M", "hCascPlusInvMassvsPt_FT0M", HistType::kTH3F, {centFT0MAxis, ptAxis, massAxis}); registry.add("hCascMinusInvMassvsPt_FV0A", "hCascMinusInvMassvsPt_FV0A", HistType::kTH3F, {centFV0AAxis, ptAxis, massAxis}); registry.add("hCascPlusInvMassvsPt_FV0A", "hCascPlusInvMassvsPt_FV0A", HistType::kTH3F, {centFV0AAxis, ptAxis, massAxis}); registry.add("hXiMinusInvMassvsPt_BefSels", "hXiMinusInvMassvsPt_BefSels", HistType::kTH2F, {ptAxis, ximassAxis}); @@ -213,22 +213,22 @@ struct cascpostprocessing { registry.add("hCascMinusEtaBach", "hCascMinusEtaBach", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); // Info for eff x acc from MC - registry.add("hPtCascPlusTrueRec", "hPtCascPlusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtCascMinusTrueRec", "hPtCascMinusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtCascPlusTrueRec", "hPtCascPlusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtCascMinusTrueRec", "hPtCascMinusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); registry.add("hCascMinusMassvsPtTrueRec", "hCascMinusMassvsPtTrueRec", {HistType::kTH2F, {ptAxis, massAxis}}); registry.add("hCascPlusMassvsPtTrueRec", "hCascPlusMassvsPtTrueRec", {HistType::kTH2F, {ptAxis, massAxis}}); registry.add("hCascMinusMassvsPtBG", "hCascMinusMassvsPtBG", {HistType::kTH2F, {ptAxis, massAxis}}); registry.add("hCascPlusMassvsPtBG", "hCascPlusMassvsPtBG", {HistType::kTH2F, {ptAxis, massAxis}}); if (isMC) { - registry.add("hPtXiPlusTrue", "hPtXiPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtXiMinusTrue", "hPtXiMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtOmegaPlusTrue", "hPtOmegaPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtOmegaMinusTrue", "hPtOmegaMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtXiPlusTrueAssocWithSelColl", "hPtXiPlusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtXiMinusTrueAssocWithSelColl", "hPtXiMinusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtOmegaPlusTrueAssocWithSelColl", "hPtOmegaPlusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); - registry.add("hPtOmegaMinusTrueAssocWithSelColl", "hPtOmegaMinusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtXiPlusTrue", "hPtXiPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtXiMinusTrue", "hPtXiMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtOmegaPlusTrue", "hPtOmegaPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtOmegaMinusTrue", "hPtOmegaMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtXiPlusTrueAssocWithSelColl", "hPtXiPlusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtXiMinusTrueAssocWithSelColl", "hPtXiMinusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtOmegaPlusTrueAssocWithSelColl", "hPtOmegaPlusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtOmegaMinusTrueAssocWithSelColl", "hPtOmegaMinusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); } } @@ -488,25 +488,25 @@ struct cascpostprocessing { if (candidate.sign() < 0) { if (isCorrectlyRec) { - registry.fill(HIST("hPtCascMinusTrueRec"), candidate.pt(), rapidity, candidate.multFT0M()); // 3rd axis is N charged in FT0M region from gen. MC + registry.fill(HIST("hPtCascMinusTrueRec"), candidate.pt(), rapidity, candidate.centFT0M()); // 3rd axis is from MC calibration registry.fill(HIST("hCascMinusMassvsPtTrueRec"), candidate.pt(), invmass); } else { registry.fill(HIST("hCascMinusMassvsPtBG"), candidate.pt(), invmass); } registry.fill(HIST("hCascMinusInvMassvsPt"), candidate.pt(), invmass); - registry.fill(HIST("hCascMinusInvMassvsPt_FT0M"), candidate.multFT0M(), candidate.pt(), invmass); - registry.fill(HIST("hCascMinusInvMassvsPt_FV0A"), isMC ? 0 : candidate.multFV0A(), candidate.pt(), invmass); + registry.fill(HIST("hCascMinusInvMassvsPt_FT0M"), candidate.centFT0M(), candidate.pt(), invmass); + registry.fill(HIST("hCascMinusInvMassvsPt_FV0A"), candidate.centFV0A(), candidate.pt(), invmass); } if (candidate.sign() > 0) { if (isCorrectlyRec) { - registry.fill(HIST("hPtCascPlusTrueRec"), candidate.pt(), rapidity, candidate.multFT0M()); // 3rd axis is N charged in FT0M region from gen. MC + registry.fill(HIST("hPtCascPlusTrueRec"), candidate.pt(), rapidity, candidate.centFT0M()); // 3rd axis is from MC calibration registry.fill(HIST("hCascPlusMassvsPtTrueRec"), candidate.pt(), invmass); } else { registry.fill(HIST("hCascPlusMassvsPtBG"), candidate.pt(), invmass); } registry.fill(HIST("hCascPlusInvMassvsPt"), candidate.pt(), invmass); - registry.fill(HIST("hCascPlusInvMassvsPt_FT0M"), candidate.multFT0M(), candidate.pt(), invmass); - registry.fill(HIST("hCascPlusInvMassvsPt_FV0A"), isMC ? 0 : candidate.multFV0A(), candidate.pt(), invmass); + registry.fill(HIST("hCascPlusInvMassvsPt_FT0M"), candidate.centFT0M(), candidate.pt(), invmass); + registry.fill(HIST("hCascPlusInvMassvsPt_FV0A"), candidate.centFV0A(), candidate.pt(), invmass); } } } @@ -545,16 +545,16 @@ struct cascpostprocessing { // Histos of generated cascades from generated events with accepted z vrtx + chosen event type (evSelFlag) (for signal loss correction) if (genCascade.pdgCode() == -3312) { - registry.fill(HIST("hPtXiPlusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtXiPlusTrue"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } if (genCascade.pdgCode() == 3312) { - registry.fill(HIST("hPtXiMinusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtXiMinusTrue"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } if (genCascade.pdgCode() == -3334) { - registry.fill(HIST("hPtOmegaPlusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtOmegaPlusTrue"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } if (genCascade.pdgCode() == 3334) { - registry.fill(HIST("hPtOmegaMinusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtOmegaMinusTrue"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } // Histos of generated cascades from generated events with good z vrtx + chosen event type (evSelFlag) + associated to the accepted reconstructed event of the same type (for signal loss + efficiency x acceptance correction) @@ -580,16 +580,16 @@ struct cascpostprocessing { } if (genCascade.pdgCode() == -3312) { - registry.fill(HIST("hPtXiPlusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtXiPlusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } if (genCascade.pdgCode() == 3312) { - registry.fill(HIST("hPtXiMinusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtXiMinusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } if (genCascade.pdgCode() == -3334) { - registry.fill(HIST("hPtOmegaPlusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtOmegaPlusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } if (genCascade.pdgCode() == 3334) { - registry.fill(HIST("hPtOmegaMinusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + registry.fill(HIST("hPtOmegaMinusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.centFT0M()); } } } diff --git a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx index 26350264959..861f820e157 100644 --- a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx @@ -71,6 +71,7 @@ struct derivedCascadeAnalysis { Configurable doITSFrameBorderCut{"doITSFrameBorderCut", false, "Enable ITSFrame event cut"}; Configurable doMultiplicityCorrCut{"doMultiplicityCorrCut", false, "Enable multiplicity vs centrality correlation cut"}; Configurable doOccupancyCheck{"doOccupancyCheck", true, ""}; + Configurable doTimeRangeStandardCut{"doTimeRangeStandardCut", true, "It rejects a given collision if there are other events nearby in |dt|< 10 ÎŒs"}; Configurable centMin{"centMin", 0, "Minimal accepted centrality"}; Configurable centMax{"centMax", 100, "Maximal accepted centrality"}; @@ -154,7 +155,7 @@ struct derivedCascadeAnalysis { { histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {vertexZ}); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{101, 0, 101}}); - histos.add("hEventSelection", "hEventSelection", kTH1F, {{12, 0, 12}}); + histos.add("hEventSelection", "hEventSelection", kTH1F, {{13, 0, 13}}); histos.add("hOccupancyVsCentrality", "", kTH2F, {axisOccupancy, {100, 0, 100}}); histos.add("hEventNchCorrelationAfCuts", "hEventNchCorrelationAfCuts", kTH2F, {{5000, 0, 5000}, {5000, 0, 2500}}); @@ -460,6 +461,13 @@ struct derivedCascadeAnalysis { } histos.fill(HIST("hEventSelection"), 11.5 /* Remove outlyers */); } + + if (doTimeRangeStandardCut && !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + histos.fill(HIST("hEventSelection"), 12.5 /* Rejection of events too close in time */); + int occupancy = coll.trackOccupancyInTimeRange(); histos.fill(HIST("hOccupancyVsCentrality"), occupancy, coll.centFT0C()); histos.fill(HIST("hEventCentrality"), coll.centFT0C()); @@ -625,7 +633,7 @@ struct derivedCascadeAnalysis { return true; } - void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) + void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) { if (!IsEventAccepted(coll, coll.sel8())) @@ -899,7 +907,7 @@ struct derivedCascadeAnalysis { } } } - void processCascadesMCrec(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) + void processCascadesMCrec(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) { if (!IsEventAccepted(coll, coll.sel8())) return; @@ -1101,6 +1109,14 @@ struct derivedCascadeAnalysis { if (casc.sign() < 0) { histos.fill(HIST("InvMassAfterSel/hNegativeCascade"), casc.pt(), invmass, coll.centFT0C()); + if (doOccupancyCheck) { + static_for<0, 9>([&](auto i) { + constexpr int index = i.value; + if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { + histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/hNegativeCascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); + } + }); + } if (!doBachelorBaryonCut && doPtDepCutStudy) histos.fill(HIST("PtDepCutStudy/hNegativeBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); if (!doDCAV0ToPVCut && doPtDepCutStudy) @@ -1156,6 +1172,14 @@ struct derivedCascadeAnalysis { } } else { histos.fill(HIST("InvMassAfterSel/hPositiveCascade"), casc.pt(), invmass, coll.centFT0C()); + if (doOccupancyCheck) { + static_for<0, 9>([&](auto i) { + constexpr int index = i.value; + if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { + histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/hPositiveCascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); + } + }); + } if (!doBachelorBaryonCut && doPtDepCutStudy) histos.fill(HIST("PtDepCutStudy/hPositiveBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); if (!doDCAV0ToPVCut && doPtDepCutStudy) diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index 9f425d78b9e..e144687c52d 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -42,6 +42,7 @@ #include "CommonConstants/PhysicsConstants.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -49,6 +50,9 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" +#include "PWGUD/Core/SGSelector.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" using namespace o2; using namespace o2::framework; @@ -57,8 +61,9 @@ using std::array; using dauTracks = soa::Join; using dauMCTracks = soa::Join; -using v0Candidates = soa::Join; -using v0MCCandidates = soa::Join; +using v0Candidates = soa::Join; +// using v0MCCandidates = soa::Join; +using v0MCCandidates = soa::Join; // simple checkers, but ensure 64 bit integers #define bitset(var, nbit) ((var) |= (static_cast(1) << static_cast(nbit))) @@ -72,52 +77,57 @@ struct derivedlambdakzeroanalysis { Configurable analyseLambda{"analyseLambda", true, "process Lambda-like candidates"}; Configurable analyseAntiLambda{"analyseAntiLambda", true, "process AntiLambda-like candidates"}; Configurable calculateFeeddownMatrix{"calculateFeeddownMatrix", true, "fill feeddown matrix if MC"}; + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border"}; Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border"}; - Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track"}; Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", true, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference"}; Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF"}; Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD"}; Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; - Configurable requireNoHighOccupancyAgressive{"requireNoHighOccupancyAgressive", false, "reject collisions with high occupancies according to the aggressive cuts"}; - Configurable requireNoHighOccupancyStrict{"requireNoHighOccupancyStrict", false, "reject collisions with high occupancies according to the strict cuts"}; - Configurable requireNoHighOccupancyMedium{"requireNoHighOccupancyMedium", false, "reject collisions with high occupancies according to the medium cuts"}; - Configurable requireNoHighOccupancyRelaxed{"requireNoHighOccupancyRelaxed", false, "reject collisions with high occupancies according to the relaxed cuts"}; - Configurable requireNoHighOccupancyGentle{"requireNoHighOccupancyGentle", false, "reject collisions with high occupancies according to the gentle cuts"}; Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", true, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds"}; Configurable requireNoCollInTimeRangeNarrow{"requireNoCollInTimeRangeNarrow", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds"}; - Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; - - // Selection criteria: acceptance - Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; - Configurable daughterEtaCut{"daughterEtaCut", 0.8, "max eta for daughters"}; - - // Standard 5 topological criteria - Configurable v0cospa{"v0cospa", 0.97, "min V0 CosPA"}; - Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; - Configurable dcanegtopv{"dcanegtopv", .05, "min DCA Neg To PV (cm)"}; - Configurable dcapostopv{"dcapostopv", .05, "min DCA Pos To PV (cm)"}; - Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; - Configurable v0radiusMax{"v0radiusMax", 1E5, "maximum V0 radius (cm)"}; - - // Additional selection on the AP plot (exclusive for K0Short) - // original equation: lArmPt*5>TMath::Abs(lArmAlpha) - Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; - - // Track quality - Configurable minTPCrows{"minTPCrows", 70, "minimum TPC crossed rows"}; - Configurable minITSclusters{"minITSclusters", -1, "minimum ITS clusters"}; - Configurable skipTPConly{"skipTPConly", false, "skip V0s comprised of at least one TPC only prong"}; - Configurable requirePosITSonly{"requirePosITSonly", false, "require that positive track is ITSonly (overrides TPC quality)"}; - Configurable requireNegITSonly{"requireNegITSonly", false, "require that negative track is ITSonly (overrides TPC quality)"}; - - // PID (TPC/TOF) - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - Configurable TofPidNsigmaCutLaPr{"TofPidNsigmaCutLaPr", 1e+6, "TofPidNsigmaCutLaPr"}; - Configurable TofPidNsigmaCutLaPi{"TofPidNsigmaCutLaPi", 1e+6, "TofPidNsigmaCutLaPi"}; - Configurable TofPidNsigmaCutK0Pi{"TofPidNsigmaCutK0Pi", 1e+6, "TofPidNsigmaCutK0Pi"}; + // fast check on occupancy + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + + struct : ConfigurableGroup { + Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + + // Selection criteria: acceptance + Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; + Configurable daughterEtaCut{"daughterEtaCut", 0.8, "max eta for daughters"}; + + // Standard 5 topological criteria + Configurable v0cospa{"v0cospa", 0.97, "min V0 CosPA"}; + Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable dcanegtopv{"dcanegtopv", .05, "min DCA Neg To PV (cm)"}; + Configurable dcapostopv{"dcapostopv", .05, "min DCA Pos To PV (cm)"}; + Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; + Configurable v0radiusMax{"v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + + // Additional selection on the AP plot (exclusive for K0Short) + // original equation: lArmPt*5>TMath::Abs(lArmAlpha) + Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; + + // Track quality + Configurable minTPCrows{"minTPCrows", 70, "minimum TPC crossed rows"}; + Configurable minITSclusters{"minITSclusters", -1, "minimum ITS clusters"}; + Configurable skipTPConly{"skipTPConly", false, "skip V0s comprised of at least one TPC only prong"}; + Configurable requirePosITSonly{"requirePosITSonly", false, "require that positive track is ITSonly (overrides TPC quality)"}; + Configurable requireNegITSonly{"requireNegITSonly", false, "require that negative track is ITSonly (overrides TPC quality)"}; + + // PID (TPC/TOF) + Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; + Configurable TofPidNsigmaCutLaPr{"TofPidNsigmaCutLaPr", 1e+6, "TofPidNsigmaCutLaPr"}; + Configurable TofPidNsigmaCutLaPi{"TofPidNsigmaCutLaPi", 1e+6, "TofPidNsigmaCutLaPi"}; + Configurable TofPidNsigmaCutK0Pi{"TofPidNsigmaCutK0Pi", 1e+6, "TofPidNsigmaCutK0Pi"}; + + // PID (TOF) + Configurable maxDeltaTimeProton{"maxDeltaTimeProton", 1e+9, "check maximum allowed time"}; + Configurable maxDeltaTimePion{"maxDeltaTimePion", 1e+9, "check maximum allowed time"}; + } v0Selections; Configurable doCompleteTopoQA{"doCompleteTopoQA", false, "do topological variable QA histograms"}; Configurable doTPCQA{"doTPCQA", false, "do TPC QA histograms"}; @@ -129,17 +139,56 @@ struct derivedlambdakzeroanalysis { Configurable qaMaxPt{"qaMaxPt", 1000.0f, "maximum pT for QA plots"}; Configurable qaCentrality{"qaCentrality", false, "qa centrality flag: check base raw values"}; - // PID (TOF) - Configurable maxDeltaTimeProton{"maxDeltaTimeProton", 1e+9, "check maximum allowed time"}; - Configurable maxDeltaTimePion{"maxDeltaTimePion", 1e+9, "check maximum allowed time"}; - // for MC Configurable doMCAssociation{"doMCAssociation", true, "if MC, do MC association"}; Configurable doCollisionAssociationQA{"doCollisionAssociationQA", true, "check collision association"}; - // fast check on occupancy - Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; - Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + // Machine learning evaluation for pre-selection and corresponding information generation + o2::ml::OnnxModel mlCustomModelK0Short; + o2::ml::OnnxModel mlCustomModelLambda; + o2::ml::OnnxModel mlCustomModelAntiLambda; + o2::ml::OnnxModel mlCustomModelGamma; + + struct : ConfigurableGroup { + // ML classifiers: master flags to control whether we should use custom ML classifiers or the scores in the derived data + Configurable useK0ShortScores{"mlConfigurations.useK0ShortScores", false, "use ML scores to select K0Short"}; + Configurable useLambdaScores{"mlConfigurations.useLambdaScores", false, "use ML scores to select Lambda"}; + Configurable useAntiLambdaScores{"mlConfigurations.useAntiLambdaScores", false, "use ML scores to select AntiLambda"}; + + Configurable calculateK0ShortScores{"mlConfigurations.calculateK0ShortScores", false, "calculate K0Short ML scores"}; + Configurable calculateLambdaScores{"mlConfigurations.calculateLambdaScores", false, "calculate Lambda ML scores"}; + Configurable calculateAntiLambdaScores{"mlConfigurations.calculateAntiLambdaScores", false, "calculate AntiLambda ML scores"}; + + // ML input for ML calculation + Configurable customModelPathCCDB{"mlConfigurations.customModelPathCCDB", "", "Custom ML Model path in CCDB"}; + Configurable timestampCCDB{"mlConfigurations.timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadCustomModelsFromCCDB{"mlConfigurations.loadCustomModelsFromCCDB", false, "Flag to enable or disable the loading of custom models from CCDB"}; + Configurable enableOptimizations{"mlConfigurations.enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + + // Local paths for test purposes + Configurable localModelPathLambda{"mlConfigurations.localModelPathLambda", "Lambda_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathAntiLambda{"mlConfigurations.localModelPathAntiLambda", "AntiLambda_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathK0Short{"mlConfigurations.localModelPathK0Short", "KZeroShort_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + + // Thresholds for choosing to populate V0Cores tables with pre-selections + Configurable thresholdLambda{"mlConfigurations.thresholdLambda", -1.0f, "Threshold to keep Lambda candidates"}; + Configurable thresholdAntiLambda{"mlConfigurations.thresholdAntiLambda", -1.0f, "Threshold to keep AntiLambda candidates"}; + Configurable thresholdK0Short{"mlConfigurations.thresholdK0Short", -1.0f, "Threshold to keep K0Short candidates"}; + } mlConfigurations; + + // CCDB options + struct : ConfigurableGroup { + Configurable ccdburl{"ccdbConfigurations.ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"ccdbConfigurations.grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"ccdbConfigurations.grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"ccdbConfigurations.lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"ccdbConfigurations.geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable mVtxPath{"ccdbConfigurations.mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + } ccdbConfigurations; + + o2::ccdb::CcdbApi ccdbApi; + int mRunNumber; + std::map metadata; static constexpr float defaultLifetimeCuts[1][2] = {{30., 20.}}; Configurable> lifetimecut{"lifetimecut", {defaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0S"}}, "lifetimecut"}; @@ -165,6 +214,19 @@ struct derivedlambdakzeroanalysis { ConfigurableAxis axisTPCsignal{"axisTPCsignal", {200, 0.0f, 200.0f}, "TPC signal"}; ConfigurableAxis axisTOFdeltaT{"axisTOFdeltaT", {200, -5000.0f, 5000.0f}, "TOF Delta T (ps)"}; + // UPC axes + ConfigurableAxis axisSelGap{"axisSelGap", {4, -1.5, 2.5}, "Gap side"}; + + // UPC selections + SGSelector sgSelector; + struct : ConfigurableGroup { + Configurable FV0cut{"FV0cut", 100., "FV0A threshold"}; + Configurable FT0Acut{"FT0Acut", 200., "FT0A threshold"}; + Configurable FT0Ccut{"FT0Ccut", 100., "FT0C threshold"}; + Configurable ZDCcut{"ZDCcut", 10., "ZDC threshold"}; + // Configurable gapSel{"gapSel", 2, "Gap selection"}; + } upcCuts; + // AP plot axes ConfigurableAxis axisAPAlpha{"axisAPAlpha", {220, -1.1f, 1.1f}, "V0 AP alpha"}; ConfigurableAxis axisAPQt{"axisAPQt", {220, 0.0f, 0.5f}, "V0 AP alpha"}; @@ -174,12 +236,16 @@ struct derivedlambdakzeroanalysis { ConfigurableAxis axisITSclus{"axisITSclus", {7, 0.0f, 7.0f}, "N ITS Clusters"}; ConfigurableAxis axisITScluMap{"axisITSMap", {128, -0.5f, 127.5f}, "ITS Cluster map"}; ConfigurableAxis axisDetMap{"axisDetMap", {16, -0.5f, 15.5f}, "Detector use map"}; - ConfigurableAxis axisITScluMapCoarse{"axisITScluMapCoarse", {13, -0.5f, 12.5f}, "ITS Coarse cluster map"}; + ConfigurableAxis axisITScluMapCoarse{"axisITScluMapCoarse", {16, -3.5f, 12.5f}, "ITS Coarse cluster map"}; ConfigurableAxis axisDetMapCoarse{"axisDetMapCoarse", {5, -0.5f, 4.5f}, "Detector Coarse user map"}; // MC coll assoc QA axis ConfigurableAxis axisMonteCarloNch{"axisMonteCarloNch", {300, 0.0f, 3000.0f}, "N_{ch} MC"}; + // For manual sliceBy + // Preslice> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + enum selection : uint64_t { selCosPA = 0, selRadius, selRadiusMax, @@ -258,44 +324,44 @@ struct derivedlambdakzeroanalysis { // ask for specific TPC/TOF PID selections maskTrackProperties = 0; - if (requirePosITSonly) { + if (v0Selections.requirePosITSonly) { maskTrackProperties = maskTrackProperties | (uint64_t(1) << selPosItsOnly) | (uint64_t(1) << selPosGoodITSTrack); } else { maskTrackProperties = maskTrackProperties | (uint64_t(1) << selPosGoodTPCTrack) | (uint64_t(1) << selPosGoodITSTrack); // TPC signal is available: ask for positive track PID - if (TpcPidNsigmaCut < 1e+5) { // safeguard for no cut + if (v0Selections.TpcPidNsigmaCut < 1e+5) { // safeguard for no cut maskK0ShortSpecific = maskK0ShortSpecific | (uint64_t(1) << selTPCPIDPositivePion); maskLambdaSpecific = maskLambdaSpecific | (uint64_t(1) << selTPCPIDPositiveProton); maskAntiLambdaSpecific = maskAntiLambdaSpecific | (uint64_t(1) << selTPCPIDPositivePion); } // TOF PID - if (TofPidNsigmaCutK0Pi < 1e+5) // safeguard for no cut + if (v0Selections.TofPidNsigmaCutK0Pi < 1e+5) // safeguard for no cut maskK0ShortSpecific = maskK0ShortSpecific | (uint64_t(1) << selTOFNSigmaPositivePionK0Short) | (uint64_t(1) << selTOFDeltaTPositivePionK0Short); - if (TofPidNsigmaCutLaPr < 1e+5) // safeguard for no cut + if (v0Selections.TofPidNsigmaCutLaPr < 1e+5) // safeguard for no cut maskLambdaSpecific = maskLambdaSpecific | (uint64_t(1) << selTOFNSigmaPositiveProtonLambda) | (uint64_t(1) << selTOFDeltaTPositiveProtonLambda); - if (TofPidNsigmaCutLaPi < 1e+5) // safeguard for no cut + if (v0Selections.TofPidNsigmaCutLaPi < 1e+5) // safeguard for no cut maskAntiLambdaSpecific = maskAntiLambdaSpecific | (uint64_t(1) << selTOFNSigmaPositivePionLambda) | (uint64_t(1) << selTOFDeltaTPositivePionLambda); } - if (requireNegITSonly) { + if (v0Selections.requireNegITSonly) { maskTrackProperties = maskTrackProperties | (uint64_t(1) << selNegItsOnly) | (uint64_t(1) << selNegGoodITSTrack); } else { maskTrackProperties = maskTrackProperties | (uint64_t(1) << selNegGoodTPCTrack) | (uint64_t(1) << selNegGoodITSTrack); // TPC signal is available: ask for negative track PID - if (TpcPidNsigmaCut < 1e+5) { // safeguard for no cut + if (v0Selections.TpcPidNsigmaCut < 1e+5) { // safeguard for no cut maskK0ShortSpecific = maskK0ShortSpecific | (uint64_t(1) << selTPCPIDNegativePion); maskLambdaSpecific = maskLambdaSpecific | (uint64_t(1) << selTPCPIDNegativePion); maskAntiLambdaSpecific = maskAntiLambdaSpecific | (uint64_t(1) << selTPCPIDNegativeProton); } // TOF PID - if (TofPidNsigmaCutK0Pi < 1e+5) // safeguard for no cut + if (v0Selections.TofPidNsigmaCutK0Pi < 1e+5) // safeguard for no cut maskK0ShortSpecific = maskK0ShortSpecific | (uint64_t(1) << selTOFNSigmaNegativePionK0Short) | (uint64_t(1) << selTOFDeltaTNegativePionK0Short); - if (TofPidNsigmaCutLaPr < 1e+5) // safeguard for no cut + if (v0Selections.TofPidNsigmaCutLaPi < 1e+5) // safeguard for no cut maskLambdaSpecific = maskLambdaSpecific | (uint64_t(1) << selTOFNSigmaNegativePionLambda) | (uint64_t(1) << selTOFDeltaTNegativePionLambda); - if (TofPidNsigmaCutLaPi < 1e+5) // safeguard for no cut + if (v0Selections.TofPidNsigmaCutLaPr < 1e+5) // safeguard for no cut maskAntiLambdaSpecific = maskAntiLambdaSpecific | (uint64_t(1) << selTOFNSigmaNegativeProtonLambda) | (uint64_t(1) << selTOFDeltaTNegativeProtonLambda); } - if (skipTPConly) { + if (v0Selections.skipTPConly) { maskK0ShortSpecific = maskK0ShortSpecific | (uint64_t(1) << selPosNotTPCOnly) | (uint64_t(1) << selNegNotTPCOnly); maskLambdaSpecific = maskLambdaSpecific | (uint64_t(1) << selPosNotTPCOnly) | (uint64_t(1) << selNegNotTPCOnly); maskAntiLambdaSpecific = maskAntiLambdaSpecific | (uint64_t(1) << selPosNotTPCOnly) | (uint64_t(1) << selNegNotTPCOnly); @@ -322,15 +388,10 @@ struct derivedlambdakzeroanalysis { histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(11, "kNoHighOccupancyAgressive"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(12, "kNoHighOccupancyStrict"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(13, "kNoHighOccupancyMedium"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(14, "kNoHighOccupancyRelaxed"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(15, "kNoHighOccupancyGentle"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(16, "kNoCollInTimeRangeStd"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(17, "kNoCollInTimeRangeNarrow"); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(18, "Below min occup."); - histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(19, "Above max occup."); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(11, "kNoCollInTimeRangeStd"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(12, "kNoCollInTimeRangeNarrow"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(13, "Below min occup."); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(14, "Above max occup."); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{100, 0.0f, +100.0f}}); histos.add("hCentralityVsNch", "hCentralityVsNch", kTH2F, {axisCentrality, axisNch}); @@ -338,6 +399,9 @@ struct derivedlambdakzeroanalysis { histos.add("hEventOccupancy", "hEventOccupancy", kTH1F, {axisOccupancy}); histos.add("hCentralityVsOccupancy", "hCentralityVsOccupancy", kTH2F, {axisCentrality, axisOccupancy}); + histos.add("hGapSide", "Gap side; Entries", kTH1F, {{5, -0.5, 4.5}}); + histos.add("hSelGapSide", "Selected gap side; Entries", kTH1F, {axisSelGap}); + // for QA and test purposes auto hRawCentrality = histos.add("hRawCentrality", "hRawCentrality", kTH1F, {axisRawCentrality}); @@ -349,6 +413,12 @@ struct derivedlambdakzeroanalysis { // histograms versus mass if (analyseK0Short) { histos.add("h3dMassK0Short", "h3dMassK0Short", kTH3F, {axisCentrality, axisPt, axisK0Mass}); + // Non-UPC info + histos.add("h3dMassK0ShortHadronic", "h3dMassK0ShortHadronic", kTH3F, {axisCentrality, axisPt, axisK0Mass}); + // UPC info + histos.add("h3dMassK0ShortSGA", "h3dMassK0ShortSGA", kTH3F, {axisCentrality, axisPt, axisK0Mass}); + histos.add("h3dMassK0ShortSGC", "h3dMassK0ShortSGC", kTH3F, {axisCentrality, axisPt, axisK0Mass}); + histos.add("h3dMassK0ShortDG", "h3dMassK0ShortDG", kTH3F, {axisCentrality, axisPt, axisK0Mass}); if (doTPCQA) { histos.add("K0Short/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3F, {axisCentrality, axisPtCoarse, axisNsigmaTPC}); histos.add("K0Short/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3F, {axisCentrality, axisPtCoarse, axisNsigmaTPC}); @@ -388,6 +458,12 @@ struct derivedlambdakzeroanalysis { } if (analyseLambda) { histos.add("h3dMassLambda", "h3dMassLambda", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + // Non-UPC info + histos.add("h3dMassLambdaHadronic", "h3dMassLambdaHadronic", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + // UPC info + histos.add("h3dMassLambdaSGA", "h3dMassLambdaSGA", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("h3dMassLambdaSGC", "h3dMassLambdaSGC", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("h3dMassLambdaDG", "h3dMassLambdaDG", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); if (doTPCQA) { histos.add("Lambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3F, {axisCentrality, axisPtCoarse, axisNsigmaTPC}); histos.add("Lambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3F, {axisCentrality, axisPtCoarse, axisNsigmaTPC}); @@ -427,6 +503,12 @@ struct derivedlambdakzeroanalysis { } if (analyseAntiLambda) { histos.add("h3dMassAntiLambda", "h3dMassAntiLambda", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + // Non-UPC info + histos.add("h3dMassAntiLambdaHadronic", "h3dMassAntiLambdaHadronic", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + // UPC info + histos.add("h3dMassAntiLambdaSGA", "h3dMassAntiLambdaSGA", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("h3dMassAntiLambdaSGC", "h3dMassAntiLambdaSGC", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("h3dMassAntiLambdaDG", "h3dMassAntiLambdaDG", kTH3F, {axisCentrality, axisPt, axisLambdaMass}); if (doTPCQA) { histos.add("AntiLambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3F, {axisCentrality, axisPtCoarse, axisNsigmaTPC}); histos.add("AntiLambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3F, {axisCentrality, axisPtCoarse, axisNsigmaTPC}); @@ -542,7 +624,17 @@ struct derivedlambdakzeroanalysis { histos.add("GeneralQA/h2dArmenterosSelected", "h2dArmenterosSelected", kTH2F, {axisAPAlpha, axisAPQt}); // Creation of histograms: MC generated - if (doprocessBinnedGenerated) { + if (doprocessGenerated) { + histos.add("hGenEvents", "hGenEvents", kTH2F, {{axisNch}, {2, -0.5f, +1.5f}}); + histos.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(1, "All gen. events"); + histos.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(2, "Gen. with at least 1 rec. events"); + histos.add("hGenEventCentrality", "hGenEventCentrality", kTH1F, {{100, 0.0f, +100.0f}}); + + histos.add("hCentralityVsNcoll_beforeEvSel", "hCentralityVsNcoll_beforeEvSel", kTH2F, {axisCentrality, {50, -0.5f, 49.5f}}); + histos.add("hCentralityVsNcoll_afterEvSel", "hCentralityVsNcoll_afterEvSel", kTH2F, {axisCentrality, {50, -0.5f, 49.5f}}); + + histos.add("hCentralityVsMultMC", "hCentralityVsMultMC", kTH2F, {{100, 0.0f, 100.0f}, axisNch}); + histos.add("h2dGenK0Short", "h2dGenK0Short", kTH2D, {axisCentrality, axisPt}); histos.add("h2dGenLambda", "h2dGenLambda", kTH2D, {axisCentrality, axisPt}); histos.add("h2dGenAntiLambda", "h2dGenAntiLambda", kTH2D, {axisCentrality, axisPt}); @@ -550,92 +642,128 @@ struct derivedlambdakzeroanalysis { histos.add("h2dGenXiPlus", "h2dGenXiPlus", kTH2D, {axisCentrality, axisPt}); histos.add("h2dGenOmegaMinus", "h2dGenOmegaMinus", kTH2D, {axisCentrality, axisPt}); histos.add("h2dGenOmegaPlus", "h2dGenOmegaPlus", kTH2D, {axisCentrality, axisPt}); + + histos.add("h2dGenK0ShortVsMultMC", "h2dGenK0ShortVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenLambdaVsMultMC", "h2dGenLambdaVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenAntiLambdaVsMultMC", "h2dGenAntiLambdaVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenXiMinusVsMultMC", "h2dGenXiMinusVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenXiPlusVsMultMC", "h2dGenXiPlusVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenOmegaMinusVsMultMC", "h2dGenOmegaMinusVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenOmegaPlusVsMultMC", "h2dGenOmegaPlusVsMultMC", kTH2D, {axisNch, axisPt}); + } + if (doprocessBinnedGenerated) { + histos.add("h2dGeneratedK0Short", "h2dGeneratedK0Short", kTH2D, {axisCentrality, axisPt}); + histos.add("h2dGeneratedLambda", "h2dGeneratedLambda", kTH2D, {axisCentrality, axisPt}); + histos.add("h2dGeneratedAntiLambda", "h2dGeneratedAntiLambda", kTH2D, {axisCentrality, axisPt}); + histos.add("h2dGeneratedXiMinus", "h2dGeneratedXiMinus", kTH2D, {axisCentrality, axisPt}); + histos.add("h2dGeneratedXiPlus", "h2dGeneratedXiPlus", kTH2D, {axisCentrality, axisPt}); + histos.add("h2dGeneratedOmegaMinus", "h2dGeneratedOmegaMinus", kTH2D, {axisCentrality, axisPt}); + histos.add("h2dGeneratedOmegaPlus", "h2dGeneratedOmegaPlus", kTH2D, {axisCentrality, axisPt}); } // inspect histogram sizes, please histos.print(); } + void initCCDB(soa::Join::iterator const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + mRunNumber = collision.runNumber(); + + // machine learning initialization if requested + if (mlConfigurations.calculateK0ShortScores || + mlConfigurations.calculateLambdaScores || + mlConfigurations.calculateAntiLambdaScores) { + int64_t timeStampML = collision.timestamp(); + if (mlConfigurations.timestampCCDB.value != -1) + timeStampML = mlConfigurations.timestampCCDB.value; + LoadMachines(timeStampML); + } + } + template uint64_t computeReconstructionBitmap(TV0 v0, TCollision collision, float rapidityLambda, float rapidityK0Short, float /*pT*/) // precalculate this information so that a check is one mask operation, not many { uint64_t bitMap = 0; // Base topological variables - if (v0.v0radius() > v0radius) + if (v0.v0radius() > v0Selections.v0radius) bitset(bitMap, selRadius); - if (v0.v0radius() < v0radiusMax) + if (v0.v0radius() < v0Selections.v0radiusMax) bitset(bitMap, selRadiusMax); - if (TMath::Abs(v0.dcapostopv()) > dcapostopv) + if (TMath::Abs(v0.dcapostopv()) > v0Selections.dcapostopv) bitset(bitMap, selDCAPosToPV); - if (TMath::Abs(v0.dcanegtopv()) > dcanegtopv) + if (TMath::Abs(v0.dcanegtopv()) > v0Selections.dcanegtopv) bitset(bitMap, selDCANegToPV); - if (v0.v0cosPA() > v0cospa) + if (v0.v0cosPA() > v0Selections.v0cospa) bitset(bitMap, selCosPA); - if (v0.dcaV0daughters() < dcav0dau) + if (v0.dcaV0daughters() < v0Selections.dcav0dau) bitset(bitMap, selDCAV0Dau); // rapidity - if (TMath::Abs(rapidityLambda) < rapidityCut) + if (TMath::Abs(rapidityLambda) < v0Selections.rapidityCut) bitset(bitMap, selLambdaRapidity); - if (TMath::Abs(rapidityK0Short) < rapidityCut) + if (TMath::Abs(rapidityK0Short) < v0Selections.rapidityCut) bitset(bitMap, selK0ShortRapidity); auto posTrackExtra = v0.template posTrackExtra_as(); auto negTrackExtra = v0.template negTrackExtra_as(); // ITS quality flags - if (posTrackExtra.itsNCls() >= minITSclusters) + if (posTrackExtra.itsNCls() >= v0Selections.minITSclusters) bitset(bitMap, selPosGoodITSTrack); - if (negTrackExtra.itsNCls() >= minITSclusters) + if (negTrackExtra.itsNCls() >= v0Selections.minITSclusters) bitset(bitMap, selNegGoodITSTrack); // TPC quality flags - if (posTrackExtra.tpcCrossedRows() >= minTPCrows) + if (posTrackExtra.tpcCrossedRows() >= v0Selections.minTPCrows) bitset(bitMap, selPosGoodTPCTrack); - if (negTrackExtra.tpcCrossedRows() >= minTPCrows) + if (negTrackExtra.tpcCrossedRows() >= v0Selections.minTPCrows) bitset(bitMap, selNegGoodTPCTrack); // TPC PID - if (fabs(posTrackExtra.tpcNSigmaPi()) < TpcPidNsigmaCut) + if (fabs(posTrackExtra.tpcNSigmaPi()) < v0Selections.TpcPidNsigmaCut) bitset(bitMap, selTPCPIDPositivePion); - if (fabs(posTrackExtra.tpcNSigmaPr()) < TpcPidNsigmaCut) + if (fabs(posTrackExtra.tpcNSigmaPr()) < v0Selections.TpcPidNsigmaCut) bitset(bitMap, selTPCPIDPositiveProton); - if (fabs(negTrackExtra.tpcNSigmaPi()) < TpcPidNsigmaCut) + if (fabs(negTrackExtra.tpcNSigmaPi()) < v0Selections.TpcPidNsigmaCut) bitset(bitMap, selTPCPIDNegativePion); - if (fabs(negTrackExtra.tpcNSigmaPr()) < TpcPidNsigmaCut) + if (fabs(negTrackExtra.tpcNSigmaPr()) < v0Selections.TpcPidNsigmaCut) bitset(bitMap, selTPCPIDNegativeProton); // TOF PID in DeltaT // Positive track - if (fabs(v0.posTOFDeltaTLaPr()) < maxDeltaTimeProton) + if (fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) bitset(bitMap, selTOFDeltaTPositiveProtonLambda); - if (fabs(v0.posTOFDeltaTLaPi()) < maxDeltaTimePion) + if (fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) bitset(bitMap, selTOFDeltaTPositivePionLambda); - if (fabs(v0.posTOFDeltaTK0Pi()) < maxDeltaTimePion) + if (fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) bitset(bitMap, selTOFDeltaTPositivePionK0Short); // Negative track - if (fabs(v0.negTOFDeltaTLaPr()) < maxDeltaTimeProton) + if (fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) bitset(bitMap, selTOFDeltaTNegativeProtonLambda); - if (fabs(v0.negTOFDeltaTLaPi()) < maxDeltaTimePion) + if (fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) bitset(bitMap, selTOFDeltaTNegativePionLambda); - if (fabs(v0.negTOFDeltaTK0Pi()) < maxDeltaTimePion) + if (fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) bitset(bitMap, selTOFDeltaTNegativePionK0Short); // TOF PID in NSigma // Positive track - if (fabs(v0.tofNSigmaLaPr()) < TofPidNsigmaCutLaPr) + if (fabs(v0.tofNSigmaLaPr()) < v0Selections.TofPidNsigmaCutLaPr) bitset(bitMap, selTOFNSigmaPositiveProtonLambda); - if (fabs(v0.tofNSigmaALaPi()) < TofPidNsigmaCutLaPi) + if (fabs(v0.tofNSigmaALaPi()) < v0Selections.TofPidNsigmaCutLaPi) bitset(bitMap, selTOFNSigmaPositivePionLambda); - if (fabs(v0.tofNSigmaK0PiPlus()) < TofPidNsigmaCutK0Pi) + if (fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.TofPidNsigmaCutK0Pi) bitset(bitMap, selTOFNSigmaPositivePionK0Short); // Negative track - if (fabs(v0.tofNSigmaALaPr()) < TofPidNsigmaCutLaPr) + if (fabs(v0.tofNSigmaALaPr()) < v0Selections.TofPidNsigmaCutLaPr) bitset(bitMap, selTOFNSigmaNegativeProtonLambda); - if (fabs(v0.tofNSigmaLaPi()) < TofPidNsigmaCutLaPi) + if (fabs(v0.tofNSigmaLaPi()) < v0Selections.TofPidNsigmaCutLaPi) bitset(bitMap, selTOFNSigmaNegativePionLambda); - if (fabs(v0.tofNSigmaK0PiMinus()) < TofPidNsigmaCutK0Pi) + if (fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.TofPidNsigmaCutK0Pi) bitset(bitMap, selTOFNSigmaNegativePionK0Short); // ITS only tag @@ -657,7 +785,7 @@ struct derivedlambdakzeroanalysis { bitset(bitMap, selK0ShortCTau); // armenteros - if (v0.qtarm() * armPodCut > TMath::Abs(v0.alpha()) || armPodCut < 1e-4) + if (v0.qtarm() * v0Selections.armPodCut > TMath::Abs(v0.alpha()) || v0Selections.armPodCut < 1e-4) bitset(bitMap, selK0ShortArmenteros); return bitMap; @@ -693,10 +821,10 @@ struct derivedlambdakzeroanalysis { return (bitmap & mask) == mask; } - uint computeITSclusBitmap(uint8_t itsClusMap) + int computeITSclusBitmap(uint8_t itsClusMap, bool fromAfterburner) // Focus on the 12 dominant ITS cluster configurations { - uint bitMap = 0; + int bitMap = 0; if (verifyMask(itsClusMap, ((uint8_t(1) << 0) | (uint8_t(1) << 1) | (uint8_t(1) << 2) | (uint8_t(1) << 3) | (uint8_t(1) << 4) | (uint8_t(1) << 5) | (uint8_t(1) << 6)))) { // ITS : IB OB @@ -718,16 +846,22 @@ struct derivedlambdakzeroanalysis { // ITS : L0 L1 L2 L3 L4 L5 L6 // ITS : x x x x bitMap = 9; + if (fromAfterburner) + bitMap = -3; } else if (verifyMask(itsClusMap, ((uint8_t(1) << 4) | (uint8_t(1) << 5) | (uint8_t(1) << 6)))) { // ITS : IB OB // ITS : L0 L1 L2 L3 L4 L5 L6 // ITS : x x x bitMap = 8; + if (fromAfterburner) + bitMap = -2; } else if (verifyMask(itsClusMap, ((uint8_t(1) << 5) | (uint8_t(1) << 6)))) { // ITS : IB OB // ITS : L0 L1 L2 L3 L4 L5 L6 // ITS : x x bitMap = 7; + if (fromAfterburner) + bitMap = -1; } else if (verifyMask(itsClusMap, ((uint8_t(1) << 0) | (uint8_t(1) << 1) | (uint8_t(1) << 2) | (uint8_t(1) << 3) | (uint8_t(1) << 4) | (uint8_t(1) << 5)))) { // ITS : IB OB // ITS : L0 L1 L2 L3 L4 L5 L6 @@ -793,17 +927,118 @@ struct derivedlambdakzeroanalysis { return bitMap; } + // function to load models for ML-based classifiers + void LoadMachines(int64_t timeStampML) + { + if (mlConfigurations.loadCustomModelsFromCCDB) { + ccdbApi.init(ccdbConfigurations.ccdburl); + LOG(info) << "Fetching models for timestamp: " << timeStampML; + + if (mlConfigurations.calculateLambdaScores) { + bool retrieveSuccessLambda = ccdbApi.retrieveBlob(mlConfigurations.customModelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathLambda.value); + if (retrieveSuccessLambda) { + mlCustomModelLambda.initModel(mlConfigurations.localModelPathLambda.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Lambda model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateAntiLambdaScores) { + bool retrieveSuccessAntiLambda = ccdbApi.retrieveBlob(mlConfigurations.customModelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathAntiLambda.value); + if (retrieveSuccessAntiLambda) { + mlCustomModelAntiLambda.initModel(mlConfigurations.localModelPathAntiLambda.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the AntiLambda model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateK0ShortScores) { + bool retrieveSuccessKZeroShort = ccdbApi.retrieveBlob(mlConfigurations.customModelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathK0Short.value); + if (retrieveSuccessKZeroShort) { + mlCustomModelK0Short.initModel(mlConfigurations.localModelPathK0Short.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the K0Short model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + } else { + if (mlConfigurations.calculateLambdaScores) + mlCustomModelLambda.initModel(mlConfigurations.localModelPathLambda.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateAntiLambdaScores) + mlCustomModelAntiLambda.initModel(mlConfigurations.localModelPathAntiLambda.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateK0ShortScores) + mlCustomModelK0Short.initModel(mlConfigurations.localModelPathK0Short.value, mlConfigurations.enableOptimizations.value); + } + LOG(info) << "ML Models loaded."; + } + template - void analyseCandidate(TV0 v0, float pt, float centrality, uint64_t selMap) + void analyseCandidate(TV0 v0, float pt, float centrality, uint64_t selMap, uint8_t gapSide) // precalculate this information so that a check is one mask operation, not many { + bool passK0ShortSelections = false; + bool passLambdaSelections = false; + bool passAntiLambdaSelections = false; + + // machine learning is on, go for calculation of thresholds + // FIXME THIS NEEDS ADJUSTING + std::vector inputFeatures{pt, 0.0f, 0.0f, v0.v0radius(), v0.v0cosPA(), v0.dcaV0daughters(), v0.dcapostopv(), v0.dcanegtopv()}; + + if (mlConfigurations.useK0ShortScores) { + float k0shortScore = -1; + if (mlConfigurations.calculateK0ShortScores) { + // evaluate machine-learning scores + float* k0shortProbability = mlCustomModelK0Short.evalModel(inputFeatures); + k0shortScore = k0shortProbability[1]; + } else { + k0shortScore = v0.k0ShortBDTScore(); + } + if (k0shortScore > mlConfigurations.thresholdK0Short.value) { + passK0ShortSelections = true; + } + } else { + passK0ShortSelections = verifyMask(selMap, maskSelectionK0Short); + } + if (mlConfigurations.useLambdaScores) { + float lambdaScore = -1; + if (mlConfigurations.calculateLambdaScores) { + // evaluate machine-learning scores + float* lambdaProbability = mlCustomModelLambda.evalModel(inputFeatures); + lambdaScore = lambdaProbability[1]; + } else { + lambdaScore = v0.lambdaBDTScore(); + } + if (lambdaScore > mlConfigurations.thresholdK0Short.value) { + passLambdaSelections = true; + } + } else { + passLambdaSelections = verifyMask(selMap, maskSelectionLambda); + } + if (mlConfigurations.useLambdaScores) { + float antiLambdaScore = -1; + if (mlConfigurations.calculateAntiLambdaScores) { + // evaluate machine-learning scores + float* antilambdaProbability = mlCustomModelAntiLambda.evalModel(inputFeatures); + antiLambdaScore = antilambdaProbability[1]; + } else { + antiLambdaScore = v0.antiLambdaBDTScore(); + } + if (antiLambdaScore > mlConfigurations.thresholdK0Short.value) { + passAntiLambdaSelections = true; + } + } else { + passAntiLambdaSelections = verifyMask(selMap, maskSelectionAntiLambda); + } + auto posTrackExtra = v0.template posTrackExtra_as(); auto negTrackExtra = v0.template negTrackExtra_as(); + bool posIsFromAfterburner = posTrackExtra.itsChi2PerNcl() < 0; + bool negIsFromAfterburner = negTrackExtra.itsChi2PerNcl() < 0; + uint posDetMap = computeDetBitmap(posTrackExtra.detectorMap()); - uint posITSclusMap = computeITSclusBitmap(posTrackExtra.itsClusterMap()); + int posITSclusMap = computeITSclusBitmap(posTrackExtra.itsClusterMap(), posIsFromAfterburner); uint negDetMap = computeDetBitmap(negTrackExtra.detectorMap()); - uint negITSclusMap = computeITSclusBitmap(negTrackExtra.itsClusterMap()); + int negITSclusMap = computeITSclusBitmap(negTrackExtra.itsClusterMap(), negIsFromAfterburner); // __________________________________________ // fill with no selection if plain QA requested @@ -819,9 +1054,17 @@ struct derivedlambdakzeroanalysis { // __________________________________________ // main analysis - if (verifyMask(selMap, maskSelectionK0Short) && analyseK0Short) { + if (passK0ShortSelections && analyseK0Short) { histos.fill(HIST("GeneralQA/h2dArmenterosSelected"), v0.alpha(), v0.qtarm()); // cross-check histos.fill(HIST("h3dMassK0Short"), centrality, pt, v0.mK0Short()); + if (gapSide == 0) + histos.fill(HIST("h3dMassK0ShortSGA"), centrality, pt, v0.mK0Short()); + if (gapSide == 1) + histos.fill(HIST("h3dMassK0ShortSGC"), centrality, pt, v0.mK0Short()); + if (gapSide == 2) + histos.fill(HIST("h3dMassK0ShortDG"), centrality, pt, v0.mK0Short()); + if (gapSide > 2) + histos.fill(HIST("h3dMassK0ShortHadronic"), centrality, pt, v0.mK0Short()); histos.fill(HIST("hMassK0Short"), v0.mK0Short()); if (doPlainTopoQA) { histos.fill(HIST("K0Short/hPosDCAToPV"), v0.dcapostopv()); @@ -865,8 +1108,16 @@ struct derivedlambdakzeroanalysis { histos.fill(HIST("K0Short/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTK0Pi()); } } - if (verifyMask(selMap, maskSelectionLambda) && analyseLambda) { + if (passLambdaSelections && analyseLambda) { histos.fill(HIST("h3dMassLambda"), centrality, pt, v0.mLambda()); + if (gapSide == 0) + histos.fill(HIST("h3dMassLambdaSGA"), centrality, pt, v0.mLambda()); + if (gapSide == 1) + histos.fill(HIST("h3dMassLambdaSGC"), centrality, pt, v0.mLambda()); + if (gapSide == 2) + histos.fill(HIST("h3dMassLambdaDG"), centrality, pt, v0.mLambda()); + if (gapSide > 2) + histos.fill(HIST("h3dMassLambdaHadronic"), centrality, pt, v0.mLambda()); if (doPlainTopoQA) { histos.fill(HIST("Lambda/hPosDCAToPV"), v0.dcapostopv()); histos.fill(HIST("Lambda/hNegDCAToPV"), v0.dcanegtopv()); @@ -909,8 +1160,16 @@ struct derivedlambdakzeroanalysis { histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPi()); } } - if (verifyMask(selMap, maskSelectionAntiLambda) && analyseAntiLambda) { + if (passAntiLambdaSelections && analyseAntiLambda) { histos.fill(HIST("h3dMassAntiLambda"), centrality, pt, v0.mAntiLambda()); + if (gapSide == 0) + histos.fill(HIST("h3dMassAntiLambdaSGA"), centrality, pt, v0.mAntiLambda()); + if (gapSide == 1) + histos.fill(HIST("h3dMassAntiLambdaSGC"), centrality, pt, v0.mAntiLambda()); + if (gapSide == 2) + histos.fill(HIST("h3dMassAntiLambdaDG"), centrality, pt, v0.mAntiLambda()); + if (gapSide > 2) + histos.fill(HIST("h3dMassAntiLambdaHadronic"), centrality, pt, v0.mAntiLambda()); if (doPlainTopoQA) { histos.fill(HIST("AntiLambda/hPosDCAToPV"), v0.dcapostopv()); histos.fill(HIST("AntiLambda/hNegDCAToPV"), v0.dcanegtopv()); @@ -1046,8 +1305,15 @@ struct derivedlambdakzeroanalysis { // ______________________________________________________ // Real data processing - no MC subscription - void processRealData(soa::Join::iterator const& collision, v0Candidates const& fullV0s, dauTracks const&) + void processRealData(soa::Join::iterator const& collision, v0Candidates const& fullV0s, dauTracks const&) { + // Fire up CCDB + if ((mlConfigurations.useK0ShortScores && mlConfigurations.calculateK0ShortScores) || + (mlConfigurations.useLambdaScores && mlConfigurations.calculateLambdaScores) || + (mlConfigurations.useAntiLambdaScores && mlConfigurations.calculateAntiLambdaScores)) { + initCCDB(collision); + } + histos.fill(HIST("hEventSelection"), 0. /* all collisions */); if (!collision.sel8()) { return; @@ -1094,49 +1360,24 @@ struct derivedlambdakzeroanalysis { } histos.fill(HIST("hEventSelection"), 9 /* Not at same bunch pile-up */); - if (requireNoHighOccupancyAgressive && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyAgressive)) { - return; - } - histos.fill(HIST("hEventSelection"), 10 /* No occupancy according to the aggressive cuts */); - - if (requireNoHighOccupancyStrict && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyStrict)) { - return; - } - histos.fill(HIST("hEventSelection"), 11 /* No occupancy according to the strict cuts */); - - if (requireNoHighOccupancyMedium && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyMedium)) { - return; - } - histos.fill(HIST("hEventSelection"), 12 /* No occupancy according to the medium cuts */); - - if (requireNoHighOccupancyRelaxed && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyRelaxed)) { - return; - } - histos.fill(HIST("hEventSelection"), 13 /* No occupancy according to the relaxed cuts */); - - if (requireNoHighOccupancyGentle && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyGentle)) { - return; - } - histos.fill(HIST("hEventSelection"), 14 /* No occupancy according to the gentle cuts */); - if (requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return; } - histos.fill(HIST("hEventSelection"), 15 /* No other collision within +/- 10 microseconds */); + histos.fill(HIST("hEventSelection"), 10 /* No other collision within +/- 10 microseconds */); if (requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { return; } - histos.fill(HIST("hEventSelection"), 16 /* No other collision within +/- 4 microseconds */); + histos.fill(HIST("hEventSelection"), 11 /* No other collision within +/- 4 microseconds */); if (minOccupancy > 0 && collision.trackOccupancyInTimeRange() < minOccupancy) { return; } - histos.fill(HIST("hEventSelection"), 17 /* Below min occupancy */); + histos.fill(HIST("hEventSelection"), 12 /* Below min occupancy */); if (maxOccupancy > 0 && collision.trackOccupancyInTimeRange() > maxOccupancy) { return; } - histos.fill(HIST("hEventSelection"), 18 /* Above max occupancy */); + histos.fill(HIST("hEventSelection"), 13 /* Above max occupancy */); float centrality = collision.centFT0C(); if (qaCentrality) { @@ -1144,6 +1385,17 @@ struct derivedlambdakzeroanalysis { centrality = hRawCentrality->GetBinContent(hRawCentrality->FindBin(collision.multFT0C())); } + // gap side + int gapSide = collision.gapSide(); + int selGapSide = -1; + // -1 --> Hadronic + // 0 --> Single Gap - A side + // 1 --> Single Gap - C side + // 2 --> Double Gap - both A & C sides + selGapSide = sgSelector.trueGap(collision, upcCuts.FV0cut, upcCuts.FT0Acut, upcCuts.FT0Ccut, upcCuts.ZDCcut); + histos.fill(HIST("hGapSide"), gapSide); + histos.fill(HIST("hSelGapSide"), selGapSide); + histos.fill(HIST("hEventCentrality"), centrality); histos.fill(HIST("hCentralityVsNch"), centrality, collision.multNTracksPVeta1()); @@ -1154,10 +1406,10 @@ struct derivedlambdakzeroanalysis { // __________________________________________ // perform main analysis for (auto& v0 : fullV0s) { - if (std::abs(v0.negativeeta()) > daughterEtaCut || std::abs(v0.positiveeta()) > daughterEtaCut) + if (std::abs(v0.negativeeta()) > v0Selections.daughterEtaCut || std::abs(v0.positiveeta()) > v0Selections.daughterEtaCut) continue; // remove acceptance that's badly reproduced by MC / superfluous in future - if (v0.v0Type() != v0TypeSelection && v0TypeSelection > -1) + if (v0.v0Type() != v0Selections.v0TypeSelection && v0Selections.v0TypeSelection > -1) continue; // skip V0s that are not standard // fill AP plot for all V0s @@ -1169,13 +1421,13 @@ struct derivedlambdakzeroanalysis { selMap = selMap | (uint64_t(1) << selConsiderK0Short) | (uint64_t(1) << selConsiderLambda) | (uint64_t(1) << selConsiderAntiLambda); selMap = selMap | (uint64_t(1) << selPhysPrimK0Short) | (uint64_t(1) << selPhysPrimLambda) | (uint64_t(1) << selPhysPrimAntiLambda); - analyseCandidate(v0, v0.pt(), centrality, selMap); + analyseCandidate(v0, v0.pt(), centrality, selMap, selGapSide); } // end v0 loop } // ______________________________________________________ // Simulated processing (subscribes to MC information too) - void processMonteCarlo(soa::Join::iterator const& collision, v0MCCandidates const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const& /*mccollisions*/) + void processMonteCarlo(soa::Join::iterator const& collision, v0MCCandidates const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const& /*mccollisions*/, soa::Join const&) { histos.fill(HIST("hEventSelection"), 0. /* all collisions */); if (!collision.sel8()) { @@ -1223,49 +1475,24 @@ struct derivedlambdakzeroanalysis { } histos.fill(HIST("hEventSelection"), 9 /* Not at same bunch pile-up */); - if (requireNoHighOccupancyAgressive && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyAgressive)) { - return; - } - histos.fill(HIST("hEventSelection"), 10 /* No occupancy according to the aggressive cuts */); - - if (requireNoHighOccupancyStrict && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyStrict)) { - return; - } - histos.fill(HIST("hEventSelection"), 11 /* No occupancy according to the strict cuts */); - - if (requireNoHighOccupancyMedium && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyMedium)) { - return; - } - histos.fill(HIST("hEventSelection"), 12 /* No occupancy according to the medium cuts */); - - if (requireNoHighOccupancyRelaxed && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyRelaxed)) { - return; - } - histos.fill(HIST("hEventSelection"), 13 /* No occupancy according to the relaxed cuts */); - - if (requireNoHighOccupancyGentle && !collision.selection_bit(o2::aod::evsel::kNoHighOccupancyGentle)) { - return; - } - histos.fill(HIST("hEventSelection"), 14 /* No occupancy according to the gentle cuts */); - if (requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return; } - histos.fill(HIST("hEventSelection"), 15 /* No other collision within +/- 10 microseconds */); + histos.fill(HIST("hEventSelection"), 10 /* No other collision within +/- 10 microseconds */); if (requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { return; } - histos.fill(HIST("hEventSelection"), 16 /* No other collision within +/- 4 microseconds */); + histos.fill(HIST("hEventSelection"), 11 /* No other collision within +/- 4 microseconds */); if (minOccupancy > 0 && collision.trackOccupancyInTimeRange() < minOccupancy) { return; } - histos.fill(HIST("hEventSelection"), 17 /* Below min occupancy */); + histos.fill(HIST("hEventSelection"), 12 /* Below min occupancy */); if (maxOccupancy > 0 && collision.trackOccupancyInTimeRange() > maxOccupancy) { return; } - histos.fill(HIST("hEventSelection"), 18 /* Above max occupancy */); + histos.fill(HIST("hEventSelection"), 13 /* Above max occupancy */); float centrality = collision.centFT0C(); if (qaCentrality) { @@ -1273,6 +1500,17 @@ struct derivedlambdakzeroanalysis { centrality = hRawCentrality->GetBinContent(hRawCentrality->FindBin(collision.multFT0C())); } + // gap side + int gapSide = collision.gapSide(); + int selGapSide = -1; + // -1 --> Hadronic + // 0 --> Single Gap - A side + // 1 --> Single Gap - C side + // 2 --> Double Gap - both A & C sides + selGapSide = sgSelector.trueGap(collision, upcCuts.FV0cut, upcCuts.FT0Acut, upcCuts.FT0Ccut, upcCuts.ZDCcut); + histos.fill(HIST("hGapSide"), gapSide); + histos.fill(HIST("hSelGapSide"), selGapSide); + histos.fill(HIST("hEventCentrality"), centrality); histos.fill(HIST("hCentralityVsNch"), centrality, collision.multNTracksPVeta1()); @@ -1283,21 +1521,26 @@ struct derivedlambdakzeroanalysis { // __________________________________________ // perform main analysis for (auto& v0 : fullV0s) { - if (std::abs(v0.negativeeta()) > daughterEtaCut || std::abs(v0.positiveeta()) > daughterEtaCut) + if (std::abs(v0.negativeeta()) > v0Selections.daughterEtaCut || std::abs(v0.positiveeta()) > v0Selections.daughterEtaCut) continue; // remove acceptance that's badly reproduced by MC / superfluous in future + if (!v0.has_v0MCCore()) + continue; + + auto v0MC = v0.v0MCCore_as>(); + // fill AP plot for all V0s histos.fill(HIST("GeneralQA/h2dArmenterosAll"), v0.alpha(), v0.qtarm()); - float ptmc = RecoDecay::sqrtSumOfSquares(v0.pxPosMC() + v0.pxNegMC(), v0.pyPosMC() + v0.pyNegMC()); + float ptmc = RecoDecay::sqrtSumOfSquares(v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC()); float ymc = 1e-3; - if (v0.pdgCode() == 310) - ymc = RecoDecay::y(std::array{v0.pxPosMC() + v0.pxNegMC(), v0.pyPosMC() + v0.pyNegMC(), v0.pzPosMC() + v0.pzNegMC()}, o2::constants::physics::MassKaonNeutral); - else if (TMath::Abs(v0.pdgCode()) == 3122) - ymc = RecoDecay::y(std::array{v0.pxPosMC() + v0.pxNegMC(), v0.pyPosMC() + v0.pyNegMC(), v0.pzPosMC() + v0.pzNegMC()}, o2::constants::physics::MassLambda); + if (v0MC.pdgCode() == 310) + ymc = RecoDecay::y(std::array{v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC(), v0MC.pzPosMC() + v0MC.pzNegMC()}, o2::constants::physics::MassKaonNeutral); + else if (TMath::Abs(v0MC.pdgCode()) == 3122) + ymc = RecoDecay::y(std::array{v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC(), v0MC.pzPosMC() + v0MC.pzNegMC()}, o2::constants::physics::MassLambda); uint64_t selMap = computeReconstructionBitmap(v0, collision, ymc, ymc, ptmc); - selMap = selMap | computeMCAssociation(v0); + selMap = selMap | computeMCAssociation(v0MC); // feeddown matrix always with association if (calculateFeeddownMatrix) @@ -1309,7 +1552,7 @@ struct derivedlambdakzeroanalysis { selMap = selMap | (uint64_t(1) << selPhysPrimK0Short) | (uint64_t(1) << selPhysPrimLambda) | (uint64_t(1) << selPhysPrimAntiLambda); } - analyseCandidate(v0, ptmc, centrality, selMap); + analyseCandidate(v0, ptmc, centrality, selMap, selGapSide); if (doCollisionAssociationQA) { // check collision association explicitly @@ -1318,7 +1561,7 @@ struct derivedlambdakzeroanalysis { if (collision.has_straMCCollision()) { auto mcCollision = collision.straMCCollision_as>(); mcNch = mcCollision.multMCNParticlesEta05(); - correctCollision = (v0.straMCCollisionId() == mcCollision.globalIndex()); + correctCollision = (v0MC.straMCCollisionId() == mcCollision.globalIndex()); } analyseCollisionAssociation(v0, ptmc, mcNch, correctCollision, selMap); } @@ -1326,6 +1569,176 @@ struct derivedlambdakzeroanalysis { } // end v0 loop } + // ______________________________________________________ + // Simulated processing (subscribes to MC information too) + void processGenerated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& CascMCCores, soa::Join const& collisions) + { + std::vector listBestCollisionIdx = fillGenEventHist(mcCollisions, collisions); + for (auto const& v0MC : V0MCCores) { + if (!v0MC.has_straMCCollision()) + continue; + + if (!v0MC.isPhysicalPrimary()) + continue; + + float ptmc = RecoDecay::sqrtSumOfSquares(v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC()); + float ymc = 1e3; + if (v0MC.pdgCode() == 310) + ymc = RecoDecay::y(std::array{v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC(), v0MC.pzPosMC() + v0MC.pzNegMC()}, o2::constants::physics::MassKaonNeutral); + else if (TMath::Abs(v0MC.pdgCode()) == 3122) + ymc = RecoDecay::y(std::array{v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC(), v0MC.pzPosMC() + v0MC.pzNegMC()}, o2::constants::physics::MassLambda); + + if (TMath::Abs(ymc) > v0Selections.rapidityCut) + continue; + + auto mcCollision = v0MC.straMCCollision_as>(); + float centrality = 100.5f; + if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { + auto collision = collisions.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); + centrality = collision.centFT0C(); + } + + if (v0MC.pdgCode() == 310) { + histos.fill(HIST("h2dGenK0Short"), centrality, ptmc); + histos.fill(HIST("h2dGenK0ShortVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (v0MC.pdgCode() == 3122) { + histos.fill(HIST("h2dGenLambda"), centrality, ptmc); + histos.fill(HIST("h2dGenLambdaVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (v0MC.pdgCode() == -3122) { + histos.fill(HIST("h2dGenAntiLambda"), centrality, ptmc); + histos.fill(HIST("h2dGenAntiLambdaVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + } + + for (auto const& cascMC : CascMCCores) { + if (!cascMC.has_straMCCollision()) + continue; + + if (!cascMC.isPhysicalPrimary()) + continue; + + float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + float ymc = 1e3; + if (TMath::Abs(cascMC.pdgCode()) == 3312) + ymc = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, o2::constants::physics::MassXiMinus); + else if (TMath::Abs(cascMC.pdgCode()) == 3334) + ymc = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, o2::constants::physics::MassOmegaMinus); + + if (TMath::Abs(ymc) > v0Selections.rapidityCut) + continue; + + auto mcCollision = cascMC.straMCCollision_as>(); + float centrality = 100.5f; + if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { + auto collision = collisions.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); + centrality = collision.centFT0C(); + } + + if (cascMC.pdgCode() == 3312) { + histos.fill(HIST("h2dGenXiMinus"), centrality, ptmc); + histos.fill(HIST("h2dGenXiMinusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == -3312) { + histos.fill(HIST("h2dGenXiPlus"), centrality, ptmc); + histos.fill(HIST("h2dGenXiPlusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == 3334) { + histos.fill(HIST("h2dGenOmegaMinus"), centrality, ptmc); + histos.fill(HIST("h2dGenOmegaMinusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == -3334) { + histos.fill(HIST("h2dGenOmegaPlus"), centrality, ptmc); + histos.fill(HIST("h2dGenOmegaPlusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + } + } + + // ______________________________________________________ + // Simulated processing + // Fill event information (for event loss estimation) and return the index to the recoed collision associated to a given MC collision. + std::vector fillGenEventHist(soa::Join const& mcCollisions, soa::Join const& collisions) + { + std::vector listBestCollisionIdx(mcCollisions.size()); + for (auto const& mcCollision : mcCollisions) { + histos.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 0 /* all gen. events*/); + + auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex()); + // Check if there is at least one of the reconstructed collisions associated to this MC collision + // If so, we consider it + bool atLeastOne = false; + int biggestNContribs = -1; + int bestCollisionIndex = -1; + float centrality = 100.5f; + int nCollisions = 0; + for (auto const& collision : groupedCollisions) { + if (!collision.sel8()) { + continue; + } + if (std::abs(collision.posZ()) > 10.f) { + continue; + } + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + continue; + } + if (requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + continue; + } + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + continue; + } + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + continue; + } + if (requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + continue; + } + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + if (requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + continue; + } + + if (minOccupancy > 0 && collision.trackOccupancyInTimeRange() < minOccupancy) { + continue; + } + if (maxOccupancy > 0 && collision.trackOccupancyInTimeRange() > maxOccupancy) { + continue; + } + + if (biggestNContribs < collision.multPVTotalContributors()) { + biggestNContribs = collision.multPVTotalContributors(); + bestCollisionIndex = collision.globalIndex(); + centrality = collision.centFT0C(); + } + nCollisions++; + + atLeastOne = true; + } + listBestCollisionIdx[mcCollision.globalIndex()] = bestCollisionIndex; + + histos.fill(HIST("hCentralityVsNcoll_beforeEvSel"), centrality, groupedCollisions.size()); + histos.fill(HIST("hCentralityVsNcoll_afterEvSel"), centrality, nCollisions); + + histos.fill(HIST("hCentralityVsMultMC"), centrality, mcCollision.multMCNParticlesEta05()); + + if (atLeastOne) { + histos.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 1 /* at least 1 rec. event*/); + + histos.fill(HIST("hGenEventCentrality"), centrality); + } + } + return listBestCollisionIdx; + } + // ______________________________________________________ // Simulated processing (subscribes to MC information too) void processBinnedGenerated( @@ -1333,59 +1746,59 @@ struct derivedlambdakzeroanalysis { aod::GeXiMinus const& geXiMinus, aod::GeXiPlus const& geXiPlus, aod::GeOmegaMinus const& geOmegaMinus, aod::GeOmegaPlus const& geOmegaPlus) { - auto hK0Short = histos.get(HIST("h2dGenK0Short")); - auto hLambda = histos.get(HIST("h2dGenLambda")); - auto hAntiLambda = histos.get(HIST("h2dGenAntiLambda")); - auto hXiMinus = histos.get(HIST("h2dGenXiMinus")); - auto hXiPlus = histos.get(HIST("h2dGenXiPlus")); - auto hOmegaMinus = histos.get(HIST("h2dGenOmegaMinus")); - auto hOmegaPlus = histos.get(HIST("h2dGenOmegaPlus")); + auto hK0Short = histos.get(HIST("h2dGeneratedK0Short")); + auto hLambda = histos.get(HIST("h2dGeneratedLambda")); + auto hAntiLambda = histos.get(HIST("h2dGeneratedAntiLambda")); + auto hXiMinus = histos.get(HIST("h2dGeneratedXiMinus")); + auto hXiPlus = histos.get(HIST("h2dGeneratedXiPlus")); + auto hOmegaMinus = histos.get(HIST("h2dGeneratedOmegaMinus")); + auto hOmegaPlus = histos.get(HIST("h2dGeneratedOmegaPlus")); for (auto& gVec : geK0Short) { - if (gVec.generatedK0Short().size() != hK0Short->GetNcells()) + if (static_cast(gVec.generatedK0Short().size()) != hK0Short->GetNcells()) LOGF(fatal, "K0Short: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedK0Short().size(), hK0Short->GetNcells()); - for (uint64_t iv = 0; iv < hK0Short->GetNcells(); iv++) { + for (int iv = 0; iv < hK0Short->GetNcells(); iv++) { hK0Short->SetBinContent(iv, hK0Short->GetBinContent(iv) + gVec.generatedK0Short()[iv]); } } for (auto& gVec : geLambda) { - if (gVec.generatedLambda().size() != hLambda->GetNcells()) + if (static_cast(gVec.generatedLambda().size()) != hLambda->GetNcells()) LOGF(fatal, "Lambda: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedLambda().size(), hLambda->GetNcells()); - for (uint64_t iv = 0; iv < hLambda->GetNcells(); iv++) { + for (int iv = 0; iv < hLambda->GetNcells(); iv++) { hLambda->SetBinContent(iv, hLambda->GetBinContent(iv) + gVec.generatedLambda()[iv]); } } for (auto& gVec : geAntiLambda) { - if (gVec.generatedAntiLambda().size() != hAntiLambda->GetNcells()) + if (static_cast(gVec.generatedAntiLambda().size()) != hAntiLambda->GetNcells()) LOGF(fatal, "AntiLambda: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedAntiLambda().size(), hAntiLambda->GetNcells()); - for (uint64_t iv = 0; iv < hAntiLambda->GetNcells(); iv++) { + for (int iv = 0; iv < hAntiLambda->GetNcells(); iv++) { hAntiLambda->SetBinContent(iv, hAntiLambda->GetBinContent(iv) + gVec.generatedAntiLambda()[iv]); } } for (auto& gVec : geXiMinus) { - if (gVec.generatedXiMinus().size() != hXiMinus->GetNcells()) + if (static_cast(gVec.generatedXiMinus().size()) != hXiMinus->GetNcells()) LOGF(fatal, "XiMinus: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedXiMinus().size(), hXiMinus->GetNcells()); - for (uint64_t iv = 0; iv < hXiMinus->GetNcells(); iv++) { + for (int iv = 0; iv < hXiMinus->GetNcells(); iv++) { hXiMinus->SetBinContent(iv, hXiMinus->GetBinContent(iv) + gVec.generatedXiMinus()[iv]); } } for (auto& gVec : geXiPlus) { - if (gVec.generatedXiPlus().size() != hXiPlus->GetNcells()) + if (static_cast(gVec.generatedXiPlus().size()) != hXiPlus->GetNcells()) LOGF(fatal, "XiPlus: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedXiPlus().size(), hXiPlus->GetNcells()); - for (uint64_t iv = 0; iv < hXiPlus->GetNcells(); iv++) { + for (int iv = 0; iv < hXiPlus->GetNcells(); iv++) { hXiPlus->SetBinContent(iv, hXiPlus->GetBinContent(iv) + gVec.generatedXiPlus()[iv]); } } for (auto& gVec : geOmegaMinus) { - if (gVec.generatedOmegaMinus().size() != hOmegaMinus->GetNcells()) + if (static_cast(gVec.generatedOmegaMinus().size()) != hOmegaMinus->GetNcells()) LOGF(fatal, "OmegaMinus: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedOmegaMinus().size(), hOmegaMinus->GetNcells()); - for (uint64_t iv = 0; iv < hOmegaMinus->GetNcells(); iv++) { + for (int iv = 0; iv < hOmegaMinus->GetNcells(); iv++) { hOmegaMinus->SetBinContent(iv, hOmegaMinus->GetBinContent(iv) + gVec.generatedOmegaMinus()[iv]); } } for (auto& gVec : geOmegaPlus) { - if (gVec.generatedOmegaPlus().size() != hOmegaPlus->GetNcells()) + if (static_cast(gVec.generatedOmegaPlus().size()) != hOmegaPlus->GetNcells()) LOGF(fatal, "OmegaPlus: Number of elements in generated array and number of cells in receiving histogram differ: %i vs %i!", gVec.generatedOmegaPlus().size(), hOmegaPlus->GetNcells()); - for (uint64_t iv = 0; iv < hOmegaPlus->GetNcells(); iv++) { + for (int iv = 0; iv < hOmegaPlus->GetNcells(); iv++) { hOmegaPlus->SetBinContent(iv, hOmegaPlus->GetBinContent(iv) + gVec.generatedOmegaPlus()[iv]); } } @@ -1394,6 +1807,7 @@ struct derivedlambdakzeroanalysis { PROCESS_SWITCH(derivedlambdakzeroanalysis, processRealData, "process as if real data", true); PROCESS_SWITCH(derivedlambdakzeroanalysis, processMonteCarlo, "process as if MC", false); PROCESS_SWITCH(derivedlambdakzeroanalysis, processBinnedGenerated, "process MC generated", false); + PROCESS_SWITCH(derivedlambdakzeroanalysis, processGenerated, "process MC generated", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 9408bfe2a07..74014fdda7b 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -28,6 +28,7 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Framework/ASoAHelpers.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "Framework/StaticFor.h" @@ -42,13 +43,15 @@ using namespace o2::framework::expressions; #define bitset(var, nbit) ((var) |= (1 << (nbit))) #define bitcheck(var, nbit) ((var) & (1 << (nbit))) -using TracksComplete = soa::Join; +using TracksComplete = soa::Join; using V0DatasWithoutTrackX = soa::Join; struct correlateStrangeness { // for efficiency corrections if requested Service ccdb; + Service pdgDB; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable doCorrelationK0Short{"doCorrelationK0Short", true, "do K0Short correlation"}; @@ -59,12 +62,19 @@ struct correlateStrangeness { Configurable doCorrelationOmegaMinus{"doCorrelationOmegaMinus", false, "do OmegaMinus correlation"}; Configurable doCorrelationOmegaPlus{"doCorrelationOmegaPlus", false, "do OmegaPlus correlation"}; Configurable doCorrelationPion{"doCorrelationPion", false, "do Pion correlation"}; + Configurable doGenEventSelection{"doGenEventSelection", true, "use event selections when performing closure test for the gen events"}; + Configurable selectINELgtZERO{"selectINELgtZERO", true, "select INEL>0 events"}; Configurable zVertexCut{"zVertexCut", 10, "Cut on PV position"}; Configurable skipUnderOverflowInTHn{"skipUnderOverflowInTHn", false, "skip under/overflow in THns"}; Configurable mixingParameter{"mixingParameter", 10, "how many events are mixed"}; Configurable doMCassociation{"doMCassociation", false, "fill everything only for MC associated"}; + Configurable doTriggPhysicalPrimary{"doTriggPhysicalPrimary", false, "require physical primary for trigger particles"}; + Configurable doAssocPhysicalPrimary{"doAssocPhysicalPrimary", false, "require physical primary for associated particles"}; + Configurable doLambdaPrimary{"doLambdaPrimary", false, "do primary selection for lambda"}; Configurable doAutocorrelationRejection{"doAutocorrelationRejection", true, "reject pairs where trigger Id is the same as daughter particle Id"}; + Configurable triggerBinToSelect{"triggerBinToSelect", 0, "trigger bin to select on if processSelectEventWithTrigger enabled"}; + // Axes - configurable for smaller sizes ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0.0f, 0.01f, 1.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 100.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis axisVtxZ{"axisVtxZ", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; @@ -75,13 +85,61 @@ struct correlateStrangeness { ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt associated axis for histograms"}; ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.0, 1.0, 2.0, 3.0, 100}, "pt associated axis for histograms"}; ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + ConfigurableAxis axisMultCount{"axisMultCount", {VARIABLE_WIDTH, 0, 200, 400, 600, 800, 1000, 1400, 1800, 2300, 2800, 3300, 4000, 5000, 6000}, "Mixing bins - multiplicity"}; + ConfigurableAxis axisMassNSigma{"axisMassNSigma", {40, -2, 2}, "Axis for mass Nsigma"}; + + // for topo var QA + struct : ConfigurableGroup { + Configurable maxPeakNSigma{"maxPeakNSigma", 5, "Peak region edge definition (in sigma)"}; + Configurable minBgNSigma{"minBgNSigma", 5, "Bg region edge closest to peak (in sigma)"}; + Configurable maxBgNSigma{"maxBgNSigma", 10, "Bg region edge furthest to peak (in sigma)"}; + } massWindowConfigurations; // allows for gap between peak and bg in case someone wants to // Implementation of on-the-spot efficiency correction Configurable applyEfficiencyCorrection{"applyEfficiencyCorrection", false, "apply efficiency correction"}; + Configurable applyEfficiencyForTrigger{"applyEfficiencyForTrigger", false, "apply efficiency correction for the trigger particle"}; Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; Configurable efficiencyCCDBPath{"efficiencyCCDBPath", "GLO/Config/GeometryAligned", "Path of the efficiency corrections"}; + // Configurables for doing subwagon systematics + // Group all settings necessary for systematics in a specific ConfigurableGroup + struct : ConfigurableGroup { + std::string prefix = "systematics"; + // --- Track quality variations (single track, both trigger and assoc daughters) + Configurable minTPCNCrossedRowsTrigger{"minTPCNCrossedRowsTrigger", 70, "Minimum TPC crossed rows (trigger)"}; + Configurable minTPCNCrossedRowsAssociated{"minTPCNCrossedRowsAssociated", 70, "Minimum TPC crossed rows (associated)"}; + Configurable triggerRequireITS{"triggerRequireITS", true, "require ITS signal in trigger tracks"}; + Configurable triggerMaxTPCSharedClusters{"triggerMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive)"}; + Configurable triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"}; + + // --- Trigger: DCA variation from basic formula: |DCAxy| < 0.004f + (0.013f / pt) + Configurable dcaXYconstant{"dcaXYconstant", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"}; + Configurable dcaXYpTdep{"dcaXYpTdep", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"}; + + // --- Associated: topological variable variation (OK to vary all-at-once, at least for first study) + Configurable v0cospa{"v0cospa", 0.97, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable dcaV0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + Configurable dcanegtopv{"dcanegtopv", 0.06, "DCA Neg To PV"}; + Configurable dcapostopv{"dcapostopv", 0.06, "DCA Pos To PV"}; + Configurable v0RadiusMin{"v0radiusmin", 0.5, "v0radius"}; + Configurable v0RadiusMax{"v0radiusmax", 200, "v0radius"}; + + // cascade selections + Configurable casc_cospa{"casc_cospa", 0.95, "casc_cospa"}; + Configurable casc_dcacascdau{"casc_dcacascdau", 1.0, "casc_dcacascdau"}; + Configurable casc_dcabachtopv{"casc_dcabachtopv", 0.1, "casc_dcabachtopv"}; + Configurable casc_cascradius{"casc_cascradius", 0.5, "casc_cascradius"}; + Configurable casc_v0masswindow{"casc_v0masswindow", 0.01, "casc_v0masswindow"}; + Configurable casc_mindcav0topv{"casc_mindcav0topv", 0.01, "casc_mindcav0topv"}; + + // dE/dx for associated daughters + Configurable dEdxCompatibility{"dEdxCompatibility", 1, "0: loose, 1: normal, 2: tight. Defined in hStrangeCorrelationFilter"}; + + // (N.B.: sources that can be investigated in post are not listed!) + } systCuts; + // objects to use for efficiency corrections + TH2F* hEfficiencyTrigger; TH2F* hEfficiencyPion; TH2F* hEfficiencyK0Short; TH2F* hEfficiencyLambda; @@ -99,9 +157,11 @@ struct correlateStrangeness { Preslice collisionSliceV0s = aod::assocV0s::collisionId; Preslice collisionSliceCascades = aod::assocCascades::collisionId; Preslice collisionSlicePions = aod::assocPions::collisionId; + Preslice perCollision = aod::mcparticle::mcCollisionId; static constexpr std::string_view v0names[] = {"K0Short", "Lambda", "AntiLambda"}; static constexpr std::string_view cascadenames[] = {"XiMinus", "XiPlus", "OmegaMinus", "OmegaPlus"}; + static constexpr std::string_view particlenames[] = {"Pion", "K0Short", "Lambda", "AntiLambda", "XiMinus", "XiPlus", "OmegaMinus", "OmegaPlus"}; uint8_t doCorrelation; int mRunNumber; @@ -140,6 +200,7 @@ struct correlateStrangeness { LOG(fatal) << "Problem getting TList object with efficiencies!"; } + hEfficiencyTrigger = static_cast(listEfficiencies->FindObject("hEfficiencyTrigger")); hEfficiencyK0Short = static_cast(listEfficiencies->FindObject("hEfficiencyK0Short")); hEfficiencyLambda = static_cast(listEfficiencies->FindObject("hEfficiencyLambda")); hEfficiencyAntiLambda = static_cast(listEfficiencies->FindObject("hEfficiencyAntiLambda")); @@ -149,16 +210,57 @@ struct correlateStrangeness { hEfficiencyOmegaPlus = static_cast(listEfficiencies->FindObject("hEfficiencyOmegaPlus")); LOG(info) << "Efficiencies now loaded for " << mRunNumber; } - + template + bool isValidTrigger(TTrack track) + { + if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsTrigger) { + return false; // crossed rows + } + if (!track.hasITS() && systCuts.triggerRequireITS) { + return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) + } + if (track.tpcNClsShared() > systCuts.triggerMaxTPCSharedClusters) { + return false; // skip, has shared clusters + } + if (!(bitcheck(track.itsClusterMap(), 0)) && systCuts.triggerRequireL0) { + return false; // skip, doesn't have cluster in ITS L0 + } + // systematic variations: trigger DCAxy + if (std::abs(track.dcaXY()) > systCuts.dcaXYconstant + systCuts.dcaXYpTdep * std::abs(track.signed1Pt())) { + return false; + } + if (track.pt() > axisRanges[3][1] || track.pt() < axisRanges[3][0]) { + return false; + } + return true; + } void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvz, float mult) { for (auto& triggerTrack : triggers) { + if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + continue; auto trigg = triggerTrack.track_as(); - if (!mixing) - histos.fill(HIST("sameEvent/TriggerParticlesV0"), trigg.pt(), mult); + if (!isValidTrigger(trigg)) + continue; + + if (!mixing) { + float efficiency = 1.0f; + if (applyEfficiencyForTrigger) { + efficiency = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); + } + float weight = (applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; + histos.fill(HIST("sameEvent/TriggerParticlesV0"), trigg.pt(), mult, weight); + } + for (auto& assocCandidate : assocs) { auto assoc = assocCandidate.v0Core_as(); + //---] syst cuts [--- + if (assoc.v0radius() < systCuts.v0RadiusMin || assoc.v0radius() > systCuts.v0RadiusMax || + std::abs(assoc.dcapostopv()) < systCuts.dcapostopv || std::abs(assoc.dcanegtopv()) < systCuts.dcanegtopv || + assoc.v0cosPA() < systCuts.v0cospa || assoc.dcaV0daughters() > systCuts.dcaV0dau) + continue; + //---] removing autocorrelations [--- auto postrack = assoc.posTrack_as(); auto negtrack = assoc.negTrack_as(); @@ -173,6 +275,10 @@ struct correlateStrangeness { } } + //---] track quality check [--- + if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + continue; + float deltaphi = ComputeDeltaPhi(trigg.phi(), assoc.phi()); float deltaeta = trigg.eta() - assoc.eta(); float ptassoc = assoc.pt(); @@ -185,28 +291,34 @@ struct correlateStrangeness { continue; if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; - if (pttrigger < axisRanges[3][0] || pttrigger > axisRanges[3][1]) - continue; + TH2F* hEfficiencyV0[3]; hEfficiencyV0[0] = hEfficiencyK0Short; hEfficiencyV0[1] = hEfficiencyLambda; hEfficiencyV0[2] = hEfficiencyAntiLambda; static_for<0, 2>([&](auto i) { constexpr int index = i.value; - float efficiency = hEfficiencyV0[index]->GetBinContent(hEfficiencyV0[index]->GetXaxis()->FindBin(ptassoc), hEfficiencyV0[index]->GetYaxis()->FindBin(assoc.eta())); - float weight = applyEfficiencyCorrection ? 1. / efficiency : 1.0f; + float efficiency = 1.0f; + if (applyEfficiencyCorrection) { + efficiency = hEfficiencyV0[index]->Interpolate(ptassoc, assoc.eta()); + } + if (applyEfficiencyForTrigger) { + efficiency = efficiency * hEfficiencyTrigger->Interpolate(pttrigger, trigg.eta()); + } + + float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; if (bitcheck(doCorrelation, index) && (!applyEfficiencyCorrection || efficiency != 0)) { - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 1)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("sameEvent/LeftBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 2)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxPeakNSigma) histos.fill(HIST("sameEvent/Signal/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 3)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxBgNSigma) histos.fill(HIST("sameEvent/RightBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 1)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("mixedEvent/LeftBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 2)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxPeakNSigma) histos.fill(HIST("mixedEvent/Signal/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 3)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxBgNSigma) histos.fill(HIST("mixedEvent/RightBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); } }); @@ -214,15 +326,39 @@ struct correlateStrangeness { } } - void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvz, float mult) + void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult) { for (auto& triggerTrack : triggers) { + if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + continue; auto trigg = triggerTrack.track_as(); - if (!mixing) - histos.fill(HIST("sameEvent/TriggerParticlesCascade"), trigg.pt(), mult); + if (!isValidTrigger(trigg)) + continue; + + if (!mixing) { + float efficiency = 1.0f; + if (applyEfficiencyForTrigger) { + efficiency = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); + } + float weight = (applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; + histos.fill(HIST("sameEvent/TriggerParticlesCascade"), trigg.pt(), mult, weight); + } for (auto& assocCandidate : assocs) { auto assoc = assocCandidate.cascData(); + //---] syst cuts [--- + if (std::abs(assoc.dcapostopv()) < systCuts.dcapostopv || + std::abs(assoc.dcanegtopv()) < systCuts.dcanegtopv || + assoc.dcabachtopv() < systCuts.casc_dcabachtopv || + assoc.dcaV0daughters() > systCuts.dcaV0dau || + assoc.dcacascdaughters() > systCuts.casc_dcacascdau || + assoc.v0cosPA(pvx, pvy, pvz) < systCuts.v0cospa || + assoc.casccosPA(pvx, pvy, pvz) < systCuts.casc_cospa || + assoc.cascradius() < systCuts.casc_cascradius || + std::abs(assoc.dcav0topv(pvx, pvy, pvz)) < systCuts.casc_mindcav0topv || + std::abs(assoc.mLambda() - pdgDB->Mass(3122)) > systCuts.casc_v0masswindow) + continue; + //---] removing autocorrelations [--- auto postrack = assoc.posTrack_as(); auto negtrack = assoc.negTrack_as(); @@ -242,6 +378,10 @@ struct correlateStrangeness { } } + //---] track quality check [--- + if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + continue; + float deltaphi = ComputeDeltaPhi(trigg.phi(), assoc.phi()); float deltaeta = trigg.eta() - assoc.eta(); float ptassoc = assoc.pt(); @@ -254,8 +394,7 @@ struct correlateStrangeness { continue; if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; - if (pttrigger < axisRanges[3][0] || pttrigger > axisRanges[3][1]) - continue; + TH2F* hEfficiencyCascade[4]; hEfficiencyCascade[0] = hEfficiencyXiMinus; hEfficiencyCascade[1] = hEfficiencyXiPlus; @@ -264,20 +403,26 @@ struct correlateStrangeness { static_for<0, 3>([&](auto i) { constexpr int index = i.value; - float efficiency = hEfficiencyCascade[index]->GetBinContent(hEfficiencyCascade[index]->GetXaxis()->FindBin(ptassoc), hEfficiencyCascade[index]->GetYaxis()->FindBin(assoc.eta())); - float weight = applyEfficiencyCorrection ? 1. / efficiency : 1.0f; + float efficiency = 1.0f; + if (applyEfficiencyCorrection) { + efficiency = hEfficiencyCascade[index]->GetBinContent(hEfficiencyCascade[index]->GetXaxis()->FindBin(ptassoc), hEfficiencyCascade[index]->GetYaxis()->FindBin(assoc.eta())); + } + if (applyEfficiencyForTrigger) { + efficiency = efficiency * hEfficiencyTrigger->Interpolate(pttrigger, trigg.eta()); + } + float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; if (bitcheck(doCorrelation, index + 3) && (!applyEfficiencyCorrection || efficiency != 0)) { - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 1)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("sameEvent/LeftBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 2)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxPeakNSigma) histos.fill(HIST("sameEvent/Signal/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 3)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxBgNSigma) histos.fill(HIST("sameEvent/RightBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 1)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("mixedEvent/LeftBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 2)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxPeakNSigma) histos.fill(HIST("mixedEvent/Signal/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 3)) + if (assocCandidate.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(index) && assocCandidate.invMassNSigma(index) < +massWindowConfigurations.maxBgNSigma) histos.fill(HIST("mixedEvent/RightBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); } }); @@ -289,7 +434,12 @@ struct correlateStrangeness { { for (auto& triggerTrack : triggers) { + if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + continue; auto trigg = triggerTrack.track_as(); + if (!isValidTrigger(trigg)) + continue; + if (!mixing) histos.fill(HIST("sameEvent/TriggerParticlesPion"), trigg.pt(), mult); for (auto& assocTrack : assocs) { @@ -303,6 +453,10 @@ struct correlateStrangeness { } } + //---] track quality check [--- + if (assoc.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + continue; + float deltaphi = ComputeDeltaPhi(trigg.phi(), assoc.phi()); float deltaeta = trigg.eta() - assoc.eta(); float ptassoc = assoc.pt(); @@ -315,8 +469,6 @@ struct correlateStrangeness { continue; if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; - if (pttrigger < axisRanges[3][0] || pttrigger > axisRanges[3][1]) - continue; if (!mixing) histos.fill(HIST("sameEvent/Pion"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult); @@ -508,57 +660,42 @@ struct correlateStrangeness { const AxisSpec axisMultNDim{edgesMult, "mult percentile"}; if (bitcheck(doCorrelation, 0)) { - histos.add("h3dK0ShortSpectrum", "h3dK0ShortSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dK0ShortSpectrumY", "h3dK0ShortSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hK0ShortEtaVsPtVsPhi", "hK0ShortEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hK0ShortEtaVsPtVsPhiBg", "hK0ShortEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dK0ShortSpectrum", "h3dK0ShortSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dK0ShortSpectrumY", "h3dK0ShortSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/K0Short", "K0Short", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 1)) { - histos.add("h3dLambdaSpectrum", "h3dLambdaSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dLambdaSpectrumY", "h3dLambdaSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hLambdaEtaVsPtVsPhi", "hLambdaEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hLambdaEtaVsPtVsPhiBg", "hLambdaEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dLambdaSpectrum", "h3dLambdaSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dLambdaSpectrumY", "h3dLambdaSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/Lambda", "Lambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 2)) { - histos.add("h3dAntiLambdaSpectrum", "h3dAntiLambdaSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dAntiLambdaSpectrumY", "h3dAntiLambdaSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hAntiLambdaEtaVsPtVsPhi", "hAntiLambdaEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hAntiLambdaEtaVsPtVsPhiBg", "hAntiLambdaEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dAntiLambdaSpectrum", "h3dAntiLambdaSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dAntiLambdaSpectrumY", "h3dAntiLambdaSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/AntiLambda", "AntiLambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 3)) { - histos.add("h3dXiMinusSpectrum", "h3dXiMinusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dXiMinusSpectrumY", "h3dXiMinusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hXiMinusEtaVsPtVsPhi", "hXiMinusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hXiMinusEtaVsPtVsPhiBg", "hXiMinusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dXiMinusSpectrum", "h3dXiMinusSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dXiMinusSpectrumY", "h3dXiMinusSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/XiMinus", "XiMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 4)) { - histos.add("h3dXiPlusSpectrum", "h3dXiPlusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dXiPlusSpectrumY", "h3dXiPlusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hXiPlusEtaVsPtVsPhi", "hXiPlusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hXiPlusEtaVsPtVsPhiBg", "hXiPlusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dXiPlusSpectrum", "h3dXiPlusSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dXiPlusSpectrumY", "h3dXiPlusSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/XiPlus", "XiPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 5)) { - histos.add("h3dOmegaMinusSpectrum", "h3dOmegaMinusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dOmegaMinusSpectrumY", "h3dOmegaMinusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hOmegaMinusEtaVsPtVsPhi", "hOmegaMinusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hOmegaMinusEtaVsPtVsPhiBg", "hOmegaMinusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dOmegaMinusSpectrum", "h3dOmegaMinusSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dOmegaMinusSpectrumY", "h3dOmegaMinusSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/OmegaMinus", "OmegaMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 6)) { - histos.add("h3dOmegaPlusSpectrum", "h3dOmegaPlusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("h3dOmegaPlusSpectrumY", "h3dOmegaPlusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); - histos.add("hOmegaPlusEtaVsPtVsPhi", "hOmegaPlusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("hOmegaPlusEtaVsPtVsPhiBg", "hOmegaPlusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("h3dOmegaPlusSpectrum", "h3dOmegaPlusSpectrum", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); + histos.add("h3dOmegaPlusSpectrumY", "h3dOmegaPlusSpectrumY", kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add("sameEvent/Signal/OmegaPlus", "OmegaPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 7)) { histos.add("sameEvent/Pion", "Pion", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); - histos.add("hPionEtaVsPtVsPhi", "hPionEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); } LOGF(info, "Init THnFs done"); if (doCorrelationK0Short || doCorrelationLambda || doCorrelationAntiLambda || doCorrelationXiMinus || doCorrelationXiPlus || doCorrelationOmegaMinus || doCorrelationOmegaPlus) { @@ -572,7 +709,31 @@ struct correlateStrangeness { } // Some QA plots + histos.add("hGeneratedQAPtTrigger", "hGeneratedQAPtTrigger", kTH2F, {axisPtQA, {5, -0.5f, 4.5f}}); + histos.add("hGeneratedQAPtAssociatedK0", "hGeneratedQAPtAssociatedK0", kTH2F, {axisPtQA, {5, -0.5f, 4.5f}}); + histos.add("hClosureQAPtTrigger", "hClosureQAPtTrigger", kTH2F, {axisPtQA, {5, -0.5f, 4.5f}}); + histos.add("hClosureQAPtAssociatedK0", "hClosureQAPtAssociatedK0", kTH2F, {axisPtQA, {5, -0.5f, 4.5f}}); + histos.add("hTrackEtaVsPtVsPhi", "hTrackEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hK0ShortEtaVsPtVsPhi", "hK0ShortEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hK0ShortEtaVsPtVsPhiBg", "hK0ShortEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hLambdaEtaVsPtVsPhi", "hLambdaEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hLambdaEtaVsPtVsPhiBg", "hLambdaEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hAntiLambdaEtaVsPtVsPhi", "hAntiLambdaEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hAntiLambdaEtaVsPtVsPhiBg", "hAntiLambdaEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hXiMinusEtaVsPtVsPhi", "hXiMinusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hXiMinusEtaVsPtVsPhiBg", "hXiMinusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hXiPlusEtaVsPtVsPhi", "hXiPlusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hXiPlusEtaVsPtVsPhiBg", "hXiPlusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hOmegaMinusEtaVsPtVsPhi", "hOmegaMinusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hOmegaMinusEtaVsPtVsPhiBg", "hOmegaMinusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hOmegaPlusEtaVsPtVsPhi", "hOmegaPlusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hOmegaPlusEtaVsPtVsPhiBg", "hOmegaPlusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hPionEtaVsPtVsPhi", "hPionEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("hTriggerPrimaryEtaVsPt", "hTriggerPrimaryEtaVsPt", kTH3F, {axisPtQA, axisEta, axisMult}); + histos.add("hTriggerAllSelectedEtaVsPt", "hTriggerAllSelectedEtaVsPt", kTH3F, {axisPtQA, axisEta, axisMult}); + + histos.add("hClosureTestEventCounter", "hClosureTestEventCounter", kTH1F, {{10, 0, 10}}); histos.add("hNumberOfRejectedPairsV0", "hNumberOfRejectedPairsV0", kTH1F, {{1, 0, 1}}); histos.add("hNumberOfRejectedPairsCascades", "hNumberOfRejectedPairsCascades", kTH1F, {{1, 0, 1}}); @@ -592,9 +753,11 @@ struct correlateStrangeness { histos.add("EventQA/hMixingQA", "mixing QA", kTH1F, {{2, -0.5, 1.5}}); histos.add("EventQA/hMult", "Multiplicity", kTH1F, {axisMult}); histos.add("EventQA/hPvz", ";pvz;Entries", kTH1F, {{30, -15, 15}}); + histos.add("EventQA/hMultFT0vsTPC", ";centFT0M;multNTracksPVeta1", kTH2F, {{100, 0, 100}, {300, 0, 300}}); // MC generated plots if (doprocessMCGenerated) { + histos.add("Generated/hTrigger", "", kTH2F, {axisPtQA, axisEta}); histos.add("Generated/hPion", "", kTH2F, {axisPtQA, axisEta}); histos.add("Generated/hK0Short", "", kTH2F, {axisPtQA, axisEta}); histos.add("Generated/hLambda", "", kTH2F, {axisPtQA, axisEta}); @@ -625,6 +788,45 @@ struct correlateStrangeness { histos.add("GeneratedWithPV/hOmegaMinus_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); histos.add("GeneratedWithPV/hOmegaPlus_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); } + if (doprocessClosureTest) { + if (doCorrelationPion) { + histos.add("ClosureTest/sameEvent/Pion", "Pion", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hPion", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationK0Short) { + histos.add("ClosureTest/sameEvent/K0Short", "K0Short", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hK0Short", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationLambda) { + histos.add("ClosureTest/sameEvent/Lambda", "Lambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hLambda", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationAntiLambda) { + histos.add("ClosureTest/sameEvent/AntiLambda", "AntiLambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hAntiLambda", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationXiMinus) { + histos.add("ClosureTest/sameEvent/XiMinus", "XiMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hXiMinus", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationXiPlus) { + histos.add("ClosureTest/sameEvent/XiPlus", "XiPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/XiPlus", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationOmegaMinus) { + histos.add("ClosureTest/sameEvent/OmegaMinus", "OmegaMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hOmegaMinus", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + if (doCorrelationOmegaPlus) { + histos.add("ClosureTest/sameEvent/OmegaPlus", "OmegaPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add("ClosureTest/hOmegaPlus", "", kTH3F, {axisPtQA, axisEta, axisPhi}); + } + histos.add("ClosureTest/hTrigger", "Trigger Tracks", kTH3F, {axisPtQA, axisEta, axisMult}); + } + + // visual inspection of sizes + histos.print(); + // initialize CCDB *only* if efficiency correction requested // skip if not requested, saves a bit of time if (applyEfficiencyCorrection) { @@ -635,10 +837,60 @@ struct correlateStrangeness { } } - void processSameEventHV0s(soa::Join::iterator const& collision, + // if this process function is enabled, it will be such that only events with trigger particles within a given + // trigger pt bin are taken for the entire processing. This allows for the calculation of e.g. efficiencies + // within an event class that has a trigger (which may differ with respect to other cases, to be checked) + + // for map determining which trigger bins are present and which aren't + std::vector triggerPresenceMap; + + void processSelectEventWithTrigger(soa::Join const& collisions, + aod::TriggerTracks const& triggerTracks, TracksComplete const&, aod::BCsWithTimestamps const&) + { + // setup + triggerPresenceMap.clear(); + triggerPresenceMap.resize(collisions.size(), 0); + + for (auto const& collision : collisions) { + // ________________________________________________ + // Perform basic event selection + if (!collision.sel8()) { + continue; + } + if (TMath::Abs(collision.posZ()) > zVertexCut) { + continue; + } + if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { + continue; + } + if (!collision.isInelGt0() && selectINELgtZERO) { + continue; + } + + // do not forget to re-group ... + auto slicedTriggerTracks = triggerTracks.sliceBy(collisionSliceTracks, collision.globalIndex()); + + for (auto const& triggerTrack : slicedTriggerTracks) { + auto track = triggerTrack.track_as(); + if (!isValidTrigger(track)) { + continue; + } + auto binNumber = histos.get(HIST("axes/hPtTriggerAxis"))->FindFixBin(track.pt()) - 1; + bitset(triggerPresenceMap[collision.globalIndex()], binNumber); + } + } + } + + void processSameEventHV0s(soa::Join::iterator const& collision, aod::AssocV0s const& associatedV0s, aod::TriggerTracks const& triggerTracks, V0DatasWithoutTrackX const&, aod::V0sLinked const&, TracksComplete const&, aod::BCsWithTimestamps const&) { + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !bitcheck(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + // ________________________________________________ // Perform basic event selection if (!collision.sel8()) { @@ -650,15 +902,22 @@ struct correlateStrangeness { if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return; } + if (!collision.isInelGt0() && selectINELgtZERO) { + return; + } // ________________________________________________ if (!doprocessSameEventHCascades) { histos.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({collision.posZ(), collision.centFT0M()})); histos.fill(HIST("EventQA/hMult"), collision.centFT0M()); histos.fill(HIST("EventQA/hPvz"), collision.posZ()); + histos.fill(HIST("EventQA/hMultFT0vsTPC"), collision.centFT0M(), collision.multNTracksPVeta1()); } // Do basic QA - auto bc = collision.bc_as(); - initEfficiencyFromCCDB(bc); + + if (applyEfficiencyCorrection) { + auto bc = collision.bc_as(); + initEfficiencyFromCCDB(bc); + } TH2F* hEfficiencyV0[3]; hEfficiencyV0[0] = hEfficiencyK0Short; hEfficiencyV0[1] = hEfficiencyLambda; @@ -666,25 +925,49 @@ struct correlateStrangeness { for (auto const& v0 : associatedV0s) { auto v0Data = v0.v0Core_as(); + + //---] track quality check [--- + auto postrack = v0Data.posTrack_as(); + auto negtrack = v0Data.negTrack_as(); + if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + continue; + + //---] syst cuts [--- + if (v0Data.v0radius() < systCuts.v0RadiusMin || v0Data.v0radius() > systCuts.v0RadiusMax || + std::abs(v0Data.dcapostopv()) < systCuts.dcapostopv || std::abs(v0Data.dcanegtopv()) < systCuts.dcanegtopv || + v0Data.v0cosPA() < systCuts.v0cospa || v0Data.dcaV0daughters() > systCuts.dcaV0dau) + continue; + static_for<0, 2>([&](auto i) { constexpr int index = i.value; - float efficiency = hEfficiencyV0[index]->GetBinContent(hEfficiencyV0[index]->GetXaxis()->FindBin(v0Data.pt()), hEfficiencyV0[index]->GetYaxis()->FindBin(v0Data.eta())); + float efficiency = 1.0f; + if (applyEfficiencyCorrection) { + efficiency = hEfficiencyV0[index]->Interpolate(v0Data.pt(), v0Data.eta()); + } float weight = applyEfficiencyCorrection ? 1. / efficiency : 1.0f; - if (v0.compatible(index) && (!doMCassociation || v0.mcTrue(index)) && bitcheck(doCorrelation, index) && (!applyEfficiencyCorrection || efficiency != 0)) { - histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("Spectrum"), v0Data.pt(), collision.centFT0M(), v0.invMassRegion(index), weight); - if (std::abs(v0Data.rapidity(index)) < 0.5) { - histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("SpectrumY"), v0Data.pt(), collision.centFT0M(), v0.invMassRegion(index), weight); + if (v0.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || v0.mcTrue(index)) && (!doAssocPhysicalPrimary || v0.mcPhysicalPrimary()) && (!applyEfficiencyCorrection || efficiency != 0)) { + if (-massWindowConfigurations.maxPeakNSigma < v0.invMassNSigma(index) && v0.invMassNSigma(index) < +massWindowConfigurations.maxPeakNSigma) + histos.fill(HIST("h") + HIST(v0names[index]) + HIST("EtaVsPtVsPhi"), v0Data.pt(), v0Data.eta(), v0Data.phi(), weight); + if ((-massWindowConfigurations.maxBgNSigma < v0.invMassNSigma(index) && v0.invMassNSigma(index) < -massWindowConfigurations.minBgNSigma) || (+massWindowConfigurations.minBgNSigma < v0.invMassNSigma(index) && v0.invMassNSigma(index) < +massWindowConfigurations.maxBgNSigma)) + histos.fill(HIST("h") + HIST(v0names[index]) + HIST("EtaVsPtVsPhiBg"), v0Data.pt(), v0Data.eta(), v0Data.phi(), weight); + if (bitcheck(doCorrelation, index)) { + histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("Spectrum"), v0Data.pt(), collision.centFT0M(), v0.invMassNSigma(index), weight); + if (std::abs(v0Data.rapidity(index)) < 0.5) { + histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("SpectrumY"), v0Data.pt(), collision.centFT0M(), v0.invMassNSigma(index), weight); + } } - if (v0.invMassRegionCheck(index, 2)) - histos.fill(HIST("h") + HIST(v0names[index]) + HIST("EtaVsPtVsPhi"), v0Data.pt(), v0Data.eta(), v0Data.phi()); - if (v0.invMassRegionCheck(index, 1) || v0.invMassRegionCheck(index, 3)) - histos.fill(HIST("h") + HIST(v0names[index]) + HIST("EtaVsPtVsPhiBg"), v0Data.pt(), v0Data.eta(), v0Data.phi()); } }); } if (!doprocessSameEventHCascades) { for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); + if (!isValidTrigger(track)) + continue; + histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); + if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + continue; + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTrackEtaVsPtVsPhi"), track.pt(), track.eta(), track.phi()); } } @@ -694,10 +977,16 @@ struct correlateStrangeness { fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posZ(), collision.centFT0M()); } - void processSameEventHCascades(soa::Join::iterator const& collision, + void processSameEventHCascades(soa::Join::iterator const& collision, aod::AssocV0s const&, aod::AssocCascades const& associatedCascades, aod::TriggerTracks const& triggerTracks, V0DatasWithoutTrackX const&, aod::V0sLinked const&, aod::CascDatas const&, TracksComplete const&, aod::BCsWithTimestamps const&) { + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !bitcheck(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + // ________________________________________________ // Perform basic event selection if (!collision.sel8()) { @@ -709,13 +998,18 @@ struct correlateStrangeness { if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return; } + if (!collision.isInelGt0() && selectINELgtZERO) { + return; + } // ________________________________________________ histos.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({collision.posZ(), collision.centFT0M()})); histos.fill(HIST("EventQA/hMult"), collision.centFT0M()); histos.fill(HIST("EventQA/hPvz"), collision.posZ()); // Do basic QA - auto bc = collision.bc_as(); - initEfficiencyFromCCDB(bc); + if (applyEfficiencyCorrection) { + auto bc = collision.bc_as(); + initEfficiencyFromCCDB(bc); + } TH2F* hEfficiencyCascade[4]; hEfficiencyCascade[0] = hEfficiencyXiMinus; hEfficiencyCascade[1] = hEfficiencyXiPlus; @@ -724,35 +1018,73 @@ struct correlateStrangeness { for (auto const& casc : associatedCascades) { auto cascData = casc.cascData(); + + //---] syst cuts [--- + if (std::abs(cascData.dcapostopv()) < systCuts.dcapostopv || + std::abs(cascData.dcanegtopv()) < systCuts.dcanegtopv || + cascData.dcabachtopv() < systCuts.casc_dcabachtopv || + cascData.dcaV0daughters() > systCuts.dcaV0dau || + cascData.dcacascdaughters() > systCuts.casc_dcacascdau || + cascData.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0cospa || + cascData.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.casc_cospa || + cascData.cascradius() < systCuts.casc_cascradius || + std::abs(cascData.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.casc_mindcav0topv || + std::abs(cascData.mLambda() - pdgDB->Mass(3122)) > systCuts.casc_v0masswindow) + continue; + + //---] track quality check [--- + auto postrack = cascData.posTrack_as(); + auto negtrack = cascData.negTrack_as(); + auto bachtrack = cascData.bachelor_as(); + if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + continue; + static_for<0, 3>([&](auto i) { constexpr int index = i.value; - float efficiency = hEfficiencyCascade[index]->GetBinContent(hEfficiencyCascade[index]->GetXaxis()->FindBin(cascData.pt()), hEfficiencyCascade[index]->GetYaxis()->FindBin(cascData.eta())); + float efficiency = 1.0f; + if (applyEfficiencyCorrection) { + efficiency = hEfficiencyCascade[index]->Interpolate(cascData.pt(), cascData.eta()); + } float weight = applyEfficiencyCorrection ? 1. / efficiency : 1.0f; - if (casc.compatible(index) && (!doMCassociation || casc.mcTrue(index)) && bitcheck(doCorrelation, index + 3) && (!applyEfficiencyCorrection || efficiency != 0)) { - histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("Spectrum"), cascData.pt(), collision.centFT0M(), casc.invMassRegion(index), weight); - if (std::abs(cascData.rapidity(index)) < 0.5) { - histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("SpectrumY"), cascData.pt(), collision.centFT0M(), casc.invMassRegion(index), weight); + if (casc.compatible(index, systCuts.dEdxCompatibility) && (!doMCassociation || casc.mcTrue(index)) && (!doAssocPhysicalPrimary || casc.mcPhysicalPrimary()) && (!applyEfficiencyCorrection || efficiency != 0)) { + if (bitcheck(doCorrelation, index + 3)) { + histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("Spectrum"), cascData.pt(), collision.centFT0M(), casc.invMassNSigma(index), weight); + if (std::abs(cascData.rapidity(index)) < 0.5) { + histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("SpectrumY"), cascData.pt(), collision.centFT0M(), casc.invMassNSigma(index), weight); + } } - if (casc.invMassRegionCheck(index, 2)) - histos.fill(HIST("h") + HIST(cascadenames[index]) + HIST("EtaVsPtVsPhi"), cascData.pt(), cascData.eta(), cascData.phi()); - if (casc.invMassRegionCheck(index, 1) || casc.invMassRegionCheck(index, 3)) - histos.fill(HIST("h") + HIST(cascadenames[index]) + HIST("EtaVsPtVsPhiBg"), cascData.pt(), cascData.eta(), cascData.phi()); + if (-massWindowConfigurations.maxPeakNSigma < casc.invMassNSigma(index) && casc.invMassNSigma(index) < +massWindowConfigurations.maxPeakNSigma) + histos.fill(HIST("h") + HIST(cascadenames[index]) + HIST("EtaVsPtVsPhi"), cascData.pt(), cascData.eta(), cascData.phi(), weight); + if ((-massWindowConfigurations.maxBgNSigma < casc.invMassNSigma(index) && casc.invMassNSigma(index) < -massWindowConfigurations.minBgNSigma) || (+massWindowConfigurations.minBgNSigma < casc.invMassNSigma(index) && casc.invMassNSigma(index) < +massWindowConfigurations.maxBgNSigma)) + histos.fill(HIST("h") + HIST(cascadenames[index]) + HIST("EtaVsPtVsPhiBg"), cascData.pt(), cascData.eta(), cascData.phi(), weight); } }); } for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); + if (!isValidTrigger(track)) + continue; + histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); + if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + continue; + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTrackEtaVsPtVsPhi"), track.pt(), track.eta(), track.phi()); } // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posZ(), collision.centFT0M()); + fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), collision.centFT0M()); } - void processSameEventHPions(soa::Join::iterator const& collision, + void processSameEventHPions(soa::Join::iterator const& collision, aod::AssocPions const& associatedPions, aod::TriggerTracks const& triggerTracks, TracksComplete const&, aod::BCsWithTimestamps const&) { + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !bitcheck(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + // ________________________________________________ // Perform basic event selection if (!collision.sel8()) { @@ -764,6 +1096,9 @@ struct correlateStrangeness { if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return; } + if (!collision.isInelGt0() && selectINELgtZERO) { + return; + } // ________________________________________________ if (!doprocessSameEventHCascades && !doprocessSameEventHV0s) { histos.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({collision.posZ(), collision.centFT0M()})); @@ -778,6 +1113,12 @@ struct correlateStrangeness { if (!doprocessSameEventHCascades && !doprocessSameEventHV0s) { for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); + if (!isValidTrigger(track)) + continue; + histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); + if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + continue; + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTrackEtaVsPtVsPhi"), track.pt(), track.eta(), track.phi()); } } @@ -786,14 +1127,22 @@ struct correlateStrangeness { // Do hadron - Pion correlations fillCorrelationsPion(triggerTracks, associatedPions, false, collision.posZ(), collision.centFT0M()); } - void processMixedEventHV0s(soa::Join const& collisions, + void processMixedEventHV0s(soa::Join const& collisions, aod::AssocV0s const& associatedV0s, aod::TriggerTracks const& triggerTracks, V0DatasWithoutTrackX const&, aod::V0sLinked const&, TracksComplete const&, aod::BCsWithTimestamps const&) { for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { // ________________________________________________ - auto bc = collision1.bc_as(); - initEfficiencyFromCCDB(bc); + if (applyEfficiencyCorrection) { + auto bc = collision1.bc_as(); + initEfficiencyFromCCDB(bc); + } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && (!bitcheck(triggerPresenceMap[collision1.globalIndex()], triggerBinToSelect) || !bitcheck(triggerPresenceMap[collision2.globalIndex()], triggerBinToSelect))) { + return; + } + // Perform basic event selection on both collisions if (!collision1.sel8() || !collision2.sel8()) continue; @@ -803,6 +1152,8 @@ struct correlateStrangeness { continue; if (collision2.centFT0M() > axisRanges[5][1] || collision2.centFT0M() < axisRanges[5][0]) continue; + if ((!collision1.isInelGt0() || !collision2.isInelGt0()) && selectINELgtZERO) + continue; if (!doprocessMixedEventHCascades) { if (collision1.globalIndex() == collision2.globalIndex()) { @@ -821,14 +1172,22 @@ struct correlateStrangeness { fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posZ(), collision1.centFT0M()); } } - void processMixedEventHCascades(soa::Join const& collisions, + void processMixedEventHCascades(soa::Join const& collisions, aod::AssocV0s const&, aod::AssocCascades const& associatedCascades, aod::TriggerTracks const& triggerTracks, V0DatasWithoutTrackX const&, aod::V0sLinked const&, aod::CascDatas const&, TracksComplete const&, aod::BCsWithTimestamps const&) { for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { // ________________________________________________ - auto bc = collision1.bc_as(); - initEfficiencyFromCCDB(bc); + if (applyEfficiencyCorrection) { + auto bc = collision1.bc_as(); + initEfficiencyFromCCDB(bc); + } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && (!bitcheck(triggerPresenceMap[collision1.globalIndex()], triggerBinToSelect) || !bitcheck(triggerPresenceMap[collision2.globalIndex()], triggerBinToSelect))) { + return; + } + // Perform basic event selection on both collisions if (!collision1.sel8() || !collision2.sel8()) continue; @@ -838,6 +1197,8 @@ struct correlateStrangeness { continue; if (collision2.centFT0M() > axisRanges[5][1] || collision2.centFT0M() < axisRanges[5][0]) continue; + if ((!collision1.isInelGt0() || !collision2.isInelGt0()) && selectINELgtZERO) + continue; if (collision1.globalIndex() == collision2.globalIndex()) { histos.fill(HIST("MixingQA/hMixingQA"), 0.0f); // same-collision pair counting @@ -852,14 +1213,21 @@ struct correlateStrangeness { auto slicedAssocCascades = associatedCascades.sliceBy(collisionSliceCascades, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posZ(), collision1.centFT0M()); + fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), collision1.centFT0M()); } } - void processMixedEventHPions(soa::Join const& collisions, + void processMixedEventHPions(soa::Join const& collisions, aod::AssocPions const& assocPions, aod::TriggerTracks const& triggerTracks, TracksComplete const&) { for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && (!bitcheck(triggerPresenceMap[collision1.globalIndex()], triggerBinToSelect) || !bitcheck(triggerPresenceMap[collision2.globalIndex()], triggerBinToSelect))) { + return; + } + // ________________________________________________ // Perform basic event selection on both collisions if (!collision1.sel8() || !collision2.sel8()) @@ -870,6 +1238,8 @@ struct correlateStrangeness { continue; if (collision2.centFT0M() > axisRanges[5][1] || collision2.centFT0M() < axisRanges[5][0]) continue; + if ((!collision1.isInelGt0() || !collision2.isInelGt0()) && selectINELgtZERO) + continue; if (collision1.globalIndex() == collision2.globalIndex()) { histos.fill(HIST("MixingQA/hMixingQA"), 0.0f); // same-collision pair counting @@ -887,8 +1257,30 @@ struct correlateStrangeness { fillCorrelationsPion(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M()); } } - void processMCGenerated(aod::McCollision const&, soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) + + void processMCGenerated(aod::McCollision const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) { + histos.fill(HIST("hClosureTestEventCounter"), 2.5f); + + for (auto const& mcParticle : mcParticles) { + Double_t geta = mcParticle.eta(); + if (std::abs(geta) > 0.8f) { + continue; + } + Double_t gpt = mcParticle.pt(); + if (abs(mcParticle.pdgCode()) == 211 || abs(mcParticle.pdgCode()) == 321 || abs(mcParticle.pdgCode()) == 2212 || abs(mcParticle.pdgCode()) == 11 || abs(mcParticle.pdgCode()) == 13) { + if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("hGeneratedQAPtTrigger"), gpt, 0.0f); // step 1: before all selections + } + } + + if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (abs(mcParticle.pdgCode()) == 310 && doCorrelationK0Short) { + histos.fill(HIST("hGeneratedQAPtAssociatedK0"), gpt, 0.0f); // step 1: before all selections + } + } + } + for (auto const& mcParticle : mcParticles) { if (!mcParticle.isPhysicalPrimary()) continue; @@ -909,7 +1301,6 @@ struct correlateStrangeness { if (mcParticle.pdgCode() == -3334) histos.fill(HIST("Generated/hOmegaPlus"), mcParticle.pt(), mcParticle.eta()); } - if (collisions.size() < 1) return; @@ -918,12 +1309,17 @@ struct correlateStrangeness { int bestCollisionFT0Mpercentile = -1; float bestCollisionVtxZ = 0.0f; bool bestCollisionSel8 = false; + bool bestCollisionINELgtZERO = false; + uint32_t bestCollisionTriggerPresenceMap = 0; + for (auto& collision : collisions) { if (biggestNContribs < collision.numContrib()) { biggestNContribs = collision.numContrib(); bestCollisionFT0Mpercentile = collision.centFT0M(); bestCollisionSel8 = collision.sel8(); bestCollisionVtxZ = collision.posZ(); + bestCollisionINELgtZERO = collision.isInelGt0(); + bestCollisionTriggerPresenceMap = triggerPresenceMap[collision.globalIndex()]; } } @@ -955,52 +1351,272 @@ struct correlateStrangeness { // do selections on best collision // WARNING: if 2 PV case large, this will not necessarily be fine! // caution advised! + + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !bitcheck(bestCollisionTriggerPresenceMap, triggerBinToSelect)) { + return; + } if (!bestCollisionSel8) return; if (std::abs(bestCollisionVtxZ) > 10.0f) return; + if (!bestCollisionINELgtZERO) + return; + + histos.fill(HIST("hClosureTestEventCounter"), 3.5f); for (auto const& mcParticle : mcParticles) { - if (!mcParticle.isPhysicalPrimary()) + Double_t geta = mcParticle.eta(); + if (std::abs(geta) > 0.8f) { + continue; + } + Double_t gpt = mcParticle.pt(); + if (abs(mcParticle.pdgCode()) == 211 || abs(mcParticle.pdgCode()) == 321 || abs(mcParticle.pdgCode()) == 2212 || abs(mcParticle.pdgCode()) == 11 || abs(mcParticle.pdgCode()) == 13) { + if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("hGeneratedQAPtTrigger"), gpt, 1.0f); // step 2: after event selection + } + } + + if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (abs(mcParticle.pdgCode()) == 310 && doCorrelationK0Short) { + histos.fill(HIST("hGeneratedQAPtAssociatedK0"), gpt, 1.0f); // step 2: before all selections + } + } + } + + for (auto const& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) { continue; + } + Double_t geta = mcParticle.eta(); + Double_t gpt = mcParticle.pt(); + if (abs(mcParticle.pdgCode()) == 211 || abs(mcParticle.pdgCode()) == 321 || abs(mcParticle.pdgCode()) == 2212 || abs(mcParticle.pdgCode()) == 11 || abs(mcParticle.pdgCode()) == 13) + histos.fill(HIST("GeneratedWithPV/hTrigger"), gpt, geta); if (abs(mcParticle.pdgCode()) == 211) - histos.fill(HIST("GeneratedWithPV/hPion"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hPion"), gpt, geta); if (abs(mcParticle.pdgCode()) == 310) - histos.fill(HIST("GeneratedWithPV/hK0Short"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hK0Short"), gpt, geta); if (mcParticle.pdgCode() == 3122) - histos.fill(HIST("GeneratedWithPV/hLambda"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hLambda"), gpt, geta); if (mcParticle.pdgCode() == -3122) - histos.fill(HIST("GeneratedWithPV/hAntiLambda"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hAntiLambda"), gpt, geta); if (mcParticle.pdgCode() == 3312) - histos.fill(HIST("GeneratedWithPV/hXiMinus"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hXiMinus"), gpt, geta); if (mcParticle.pdgCode() == -3312) - histos.fill(HIST("GeneratedWithPV/hXiPlus"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hXiPlus"), gpt, geta); if (mcParticle.pdgCode() == 3334) - histos.fill(HIST("GeneratedWithPV/hOmegaMinus"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hOmegaMinus"), gpt, geta); if (mcParticle.pdgCode() == -3334) - histos.fill(HIST("GeneratedWithPV/hOmegaPlus"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("GeneratedWithPV/hOmegaPlus"), gpt, geta); if (abs(mcParticle.y()) < 0.5) { if (abs(mcParticle.pdgCode()) == 211) - histos.fill(HIST("GeneratedWithPV/hPion_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hPion_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (abs(mcParticle.pdgCode()) == 310) - histos.fill(HIST("GeneratedWithPV/hK0Short_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hK0Short_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (mcParticle.pdgCode() == 3122) - histos.fill(HIST("GeneratedWithPV/hLambda_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hLambda_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (mcParticle.pdgCode() == -3122) - histos.fill(HIST("GeneratedWithPV/hAntiLambda_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hAntiLambda_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (mcParticle.pdgCode() == 3312) - histos.fill(HIST("GeneratedWithPV/hXiMinus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hXiMinus_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (mcParticle.pdgCode() == -3312) - histos.fill(HIST("GeneratedWithPV/hXiPlus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hXiPlus_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (mcParticle.pdgCode() == 3334) - histos.fill(HIST("GeneratedWithPV/hOmegaMinus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hOmegaMinus_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); if (mcParticle.pdgCode() == -3334) - histos.fill(HIST("GeneratedWithPV/hOmegaPlus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + histos.fill(HIST("GeneratedWithPV/hOmegaPlus_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); + } + } + } + void processClosureTest(aod::McCollision const& mcCollision, soa::SmallGroups> const& recCollisions, aod::McParticles const& mcParticles) + { + + std::vector triggerIndices; + std::vector> associatedIndices; + std::vector piIndices; + std::vector k0ShortIndices; + std::vector lambdaIndices; + std::vector antiLambdaIndices; + std::vector xiMinusIndices; + std::vector xiPlusIndices; + std::vector omegaMinusIndices; + std::vector omegaPlusIndices; + + for (auto const& mcParticle : mcParticles) { + Double_t geta = mcParticle.eta(); + if (std::abs(geta) > 0.8f) { + continue; + } + Double_t gpt = mcParticle.pt(); + if (abs(mcParticle.pdgCode()) == 211 || abs(mcParticle.pdgCode()) == 321 || abs(mcParticle.pdgCode()) == 2212 || abs(mcParticle.pdgCode()) == 11 || abs(mcParticle.pdgCode()) == 13) { + if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("hClosureQAPtTrigger"), gpt, 0.0f); // step 1: no event selection whatsoever + } + } + + if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (abs(mcParticle.pdgCode()) == 310 && doCorrelationK0Short) { + histos.fill(HIST("hClosureQAPtAssociatedK0"), gpt, 0.0f); // step 1: no event selection whatsoever + } + } + } + + histos.fill(HIST("hClosureTestEventCounter"), 0.5f); + + int bestCollisionFT0Mpercentile = -1; + float bestCollisionVtxZ = 0.0f; + bool bestCollisionSel8 = false; + bool bestCollisionINELgtZERO = false; + int biggestNContribs = -1; + uint32_t bestCollisionTriggerPresenceMap = 0; + + for (auto& recCollision : recCollisions) { + if (biggestNContribs < recCollision.numContrib()) { + biggestNContribs = recCollision.numContrib(); + bestCollisionFT0Mpercentile = recCollision.centFT0M(); + bestCollisionSel8 = recCollision.sel8(); + bestCollisionVtxZ = recCollision.posZ(); + bestCollisionINELgtZERO = recCollision.isInelGt0(); + bestCollisionTriggerPresenceMap = triggerPresenceMap[recCollision.globalIndex()]; } } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !bitcheck(bestCollisionTriggerPresenceMap, triggerBinToSelect)) { + return; + } + + if (doGenEventSelection) { + if (!bestCollisionSel8) + return; + if (std::abs(bestCollisionVtxZ) > zVertexCut) + return; + if (!bestCollisionINELgtZERO) + return; + if (bestCollisionFT0Mpercentile > axisRanges[5][1] || bestCollisionFT0Mpercentile < axisRanges[5][0]) { + return; + } + } + + histos.fill(HIST("hClosureTestEventCounter"), 1.5f); + + for (auto const& mcParticle : mcParticles) { + Double_t geta = mcParticle.eta(); + if (std::abs(geta) > 0.8f) { + continue; + } + Double_t gpt = mcParticle.pt(); + if (abs(mcParticle.pdgCode()) == 211 || abs(mcParticle.pdgCode()) == 321 || abs(mcParticle.pdgCode()) == 2212 || abs(mcParticle.pdgCode()) == 11 || abs(mcParticle.pdgCode()) == 13) { + if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("hClosureQAPtTrigger"), gpt, 1.0f); // step 2: after event selection + } + } + + if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (abs(mcParticle.pdgCode()) == 310 && doCorrelationK0Short) { + histos.fill(HIST("hClosureQAPtAssociatedK0"), gpt, 1.0f); // step 2: after event selection + } + } + } + + int iteratorNum = -1; + for (auto const& mcParticle : mcParticles) { + iteratorNum = iteratorNum + 1; + Double_t geta = mcParticle.eta(); + Double_t gpt = mcParticle.pt(); + Double_t gphi = mcParticle.phi(); + if (std::abs(geta) > 0.8f) { + continue; + } + if (abs(mcParticle.pdgCode()) == 211 || abs(mcParticle.pdgCode()) == 321 || abs(mcParticle.pdgCode()) == 2212 || abs(mcParticle.pdgCode()) == 11 || abs(mcParticle.pdgCode()) == 13) { + if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + triggerIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hTrigger"), gpt, geta, bestCollisionFT0Mpercentile); + } + } + if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (abs(mcParticle.pdgCode()) == 211 && doCorrelationPion) { + piIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hPion"), gpt, geta, gphi); + } + if (abs(mcParticle.pdgCode()) == 310 && doCorrelationK0Short) { + k0ShortIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hK0Short"), gpt, geta, gphi); + } + if (mcParticle.pdgCode() == 3122 && doCorrelationLambda) { + lambdaIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hLambda"), gpt, geta, gphi); + } + if (mcParticle.pdgCode() == -3122 && doCorrelationAntiLambda) { + antiLambdaIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hAntiLambda"), gpt, geta, gphi); + } + if (mcParticle.pdgCode() == 3312 && doCorrelationXiMinus) { + xiMinusIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hXiMinus"), gpt, geta, gphi); + } + if (mcParticle.pdgCode() == -3312 && doCorrelationXiPlus) { + xiPlusIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hXiPlus"), gpt, geta, gphi); + } + if (mcParticle.pdgCode() == 3334 && doCorrelationOmegaMinus) { + omegaMinusIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hOmegaMinus"), gpt, geta, gphi); + } + if (mcParticle.pdgCode() == -3334 && doCorrelationOmegaPlus) { + omegaPlusIndices.emplace_back(iteratorNum); + histos.fill(HIST("ClosureTest/hOmegaPlus"), gpt, geta, gphi); + } + } + } + associatedIndices.emplace_back(piIndices); + associatedIndices.emplace_back(k0ShortIndices); + associatedIndices.emplace_back(lambdaIndices); + associatedIndices.emplace_back(antiLambdaIndices); + associatedIndices.emplace_back(xiMinusIndices); + associatedIndices.emplace_back(xiPlusIndices); + associatedIndices.emplace_back(omegaMinusIndices); + associatedIndices.emplace_back(omegaPlusIndices); + + for (Int_t iTrigger = 0; iTrigger < triggerIndices.size(); iTrigger++) { + auto triggerParticle = mcParticles.iteratorAt(triggerIndices[iTrigger]); + // check range of trigger particle + if (triggerParticle.pt() > axisRanges[3][1] || triggerParticle.pt() < axisRanges[3][0]) { + continue; + } + Double_t getatrigger = triggerParticle.eta(); + Double_t gphitrigger = triggerParticle.phi(); + Double_t pttrigger = triggerParticle.pt(); + auto const& mother = triggerParticle.mothers_first_as(); + Int_t globalIndex = mother.globalIndex(); + static_for<0, 7>([&](auto i) { // associated loop + constexpr int index = i.value; + for (Int_t iassoc = 0; iassoc < associatedIndices[index].size(); iassoc++) { + auto assocParticle = mcParticles.iteratorAt(associatedIndices[index][iassoc]); + if (triggerIndices[iTrigger] != associatedIndices[index][iassoc] && globalIndex != assocParticle.globalIndex()) { // avoid self + Double_t getaassoc = assocParticle.eta(); + Double_t gphiassoc = assocParticle.phi(); + Double_t ptassoc = assocParticle.pt(); + Double_t deltaphi = ComputeDeltaPhi(gphitrigger, gphiassoc); + Double_t deltaeta = getatrigger - getaassoc; + + // skip if basic ranges not met + if (deltaphi < axisRanges[0][0] || deltaphi > axisRanges[0][1]) + continue; + if (deltaeta < axisRanges[1][0] || deltaeta > axisRanges[1][1]) + continue; + if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) + continue; + histos.fill(HIST("ClosureTest/sameEvent/") + HIST(particlenames[index]), ComputeDeltaPhi(gphitrigger, gphiassoc), deltaeta, ptassoc, pttrigger, bestCollisionVtxZ, bestCollisionFT0Mpercentile); + } + } + }); + } } + PROCESS_SWITCH(correlateStrangeness, processSelectEventWithTrigger, "Select events with trigger only", false); PROCESS_SWITCH(correlateStrangeness, processSameEventHV0s, "Process same events, h-V0s", true); PROCESS_SWITCH(correlateStrangeness, processSameEventHCascades, "Process same events, h-Cascades", true); PROCESS_SWITCH(correlateStrangeness, processSameEventHPions, "Process same events, h-Pion", true); @@ -1008,6 +1624,7 @@ struct correlateStrangeness { PROCESS_SWITCH(correlateStrangeness, processMixedEventHCascades, "Process mixed events, h-Cascades", true); PROCESS_SWITCH(correlateStrangeness, processMixedEventHPions, "Process mixed events, h-Pion", true); PROCESS_SWITCH(correlateStrangeness, processMCGenerated, "Process MC generated", true); + PROCESS_SWITCH(correlateStrangeness, processClosureTest, "Process Closure Test", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/lambdapolarization.cxx b/PWGLF/Tasks/Strangeness/lambdapolarization.cxx index e1661729765..ac133f93e83 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolarization.cxx @@ -109,10 +109,11 @@ struct lambdapolarization { Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.5, "minimum daughter pion pt"}; Configurable cfgnMods{"cfgnMods", 1, "The number of modulations of interest starting from 2"}; + Configurable cfgNQvec{"cfgNQvec", 7, "The number of total Qvectors for looping over the task"}; Configurable cfgQvecDetName{"cfgQvecDetName", "FT0C", "The name of detector to be analyzed"}; - Configurable cfgQvecRefAName{"cfgQvecRefAName", "BPos", "The name of detector for reference A"}; - Configurable cfgQvecRefBName{"cfgQvecRefBName", "BNeg", "The name of detector for reference B"}; + Configurable cfgQvecRefAName{"cfgQvecRefAName", "TPCpos", "The name of detector for reference A"}; + Configurable cfgQvecRefBName{"cfgQvecRefBName", "TPCneg", "The name of detector for reference B"}; Configurable cfgShiftCorr{"cfgShiftCorr", false, "additional shift correction"}; Configurable cfgShiftCorrDef{"cfgShiftCorrDef", false, "additional shift correction definition"}; @@ -151,9 +152,9 @@ struct lambdapolarization { return 2; } else if (name.value == "FV0A") { return 3; - } else if (name.value == "BPos") { + } else if (name.value == "TPCpos") { return 4; - } else if (name.value == "BNeg") { + } else if (name.value == "TPCneg") { return 5; } else { return 0; @@ -162,9 +163,6 @@ struct lambdapolarization { void init(o2::framework::InitContext&) { - if (cfgnMods > 1) - LOGF(fatal, "multiple harmonics not implemented yet"); // FIXME: will be updated after Qvector task updates - AxisSpec massAxis = {100, 1.065, 1.165}; AxisSpec ptAxis = {100, 0.0, 10.0}; AxisSpec cosAxis = {110, -1.05, 1.05}; @@ -176,7 +174,7 @@ struct lambdapolarization { AxisSpec pidAxis = {100, -10, 10}; AxisSpec shiftAxis = {10, 0, 10, "shift"}; - AxisSpec basisAxis = {6, 0, 6, "basis"}; + AxisSpec basisAxis = {20, 0, 20, "basis"}; for (auto i = 2; i < cfgnMods + 2; i++) { histos.add(Form("psi%d/h_lambda_cos", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, epAxis}}); @@ -226,7 +224,7 @@ struct lambdapolarization { RefBId = GetDetId(cfgQvecRefBName); if (DetId == RefAId || DetId == RefBId || RefAId == RefBId) { - LOGF(info, "Wrong detector configuration \n The FT0C will be used to get Q-Vector \n The BPos and BNeg will be used as reference systems"); + LOGF(info, "Wrong detector configuration \n The FT0C will be used to get Q-Vector \n The TPCpos and TPCneg will be used as reference systems"); DetId = 0; RefAId = 4; RefBId = 5; @@ -328,9 +326,9 @@ struct lambdapolarization { template void FillShiftCorrection(TCollision const& collision, int nmode) { - QvecDetInd = DetId * 4 + 3 + (nmode - 2) * 24; - QvecRefAInd = RefAId * 4 + 3 + (nmode - 2) * 24; - QvecRefBInd = RefBId * 4 + 3 + (nmode - 2) * 24; + QvecDetInd = DetId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + QvecRefAInd = RefAId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + QvecRefBInd = RefBId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; for (int ishift = 1; ishift <= 10; ishift++) { if (nmode == 2) { histos.fill(HIST("psi2/ShiftFIT"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(collision.qvecIm()[QvecDetInd], collision.qvecRe()[QvecDetInd]) / static_cast(nmode))); @@ -366,9 +364,12 @@ struct lambdapolarization { template void FillEPQA(TCollision const& collision, int nmode) { - QvecDetInd = DetId * 4 + 3 + (nmode - 2) * 24; - QvecRefAInd = RefAId * 4 + 3 + (nmode - 2) * 24; - QvecRefBInd = RefBId * 4 + 3 + (nmode - 2) * 24; + QvecDetInd = DetId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + QvecRefAInd = RefAId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + QvecRefBInd = RefBId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + + if (collision.qvecAmp()[DetId] < 1e-5 || collision.qvecAmp()[RefAId] < 1e-5 || collision.qvecAmp()[RefBId] < 1e-5) + return; if (nmode == 2) { histos.fill(HIST("psi2/QA/EP_Det"), centrality, TMath::ATan2(collision.qvecIm()[QvecDetInd], collision.qvecRe()[QvecDetInd]) / static_cast(nmode)); @@ -401,9 +402,9 @@ struct lambdapolarization { auto deltapsiFT0A = 0.0; auto deltapsiFV0A = 0.0; - auto psidefFT0C = TMath::ATan2(collision.qvecIm()[3 + (nmode - 2) * 24], collision.qvecRe()[3 + (nmode - 2) * 24]) / static_cast(nmode); - auto psidefFT0A = TMath::ATan2(collision.qvecIm()[3 + 4 + (nmode - 2) * 24], collision.qvecRe()[3 + 4 + (nmode - 2) * 24]) / static_cast(nmode); - auto psidefFV0A = TMath::ATan2(collision.qvecIm()[3 + 12 + (nmode - 2) * 24], collision.qvecRe()[3 + 12 + (nmode - 2) * 24]) / static_cast(nmode); + auto psidefFT0C = TMath::ATan2(collision.qvecIm()[QvecDetInd], collision.qvecRe()[QvecDetInd]) / static_cast(nmode); + auto psidefFT0A = TMath::ATan2(collision.qvecIm()[QvecRefAInd], collision.qvecRe()[QvecRefAInd]) / static_cast(nmode); + auto psidefFV0A = TMath::ATan2(collision.qvecIm()[QvecRefBInd], collision.qvecRe()[QvecRefBInd]) / static_cast(nmode); for (int ishift = 1; ishift <= 10; ishift++) { auto coeffshiftxFT0C = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyFT0C = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(centrality, 1.5, ishift - 0.5)); @@ -447,6 +448,10 @@ struct lambdapolarization { template void FillHistograms(TCollision const& collision, V0 const& V0s, int nmode) { + QvecDetInd = DetId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + QvecRefAInd = RefAId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + QvecRefBInd = RefBId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + for (auto& v0 : V0s) { auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); @@ -475,7 +480,7 @@ struct lambdapolarization { aLambdaTag = 1; } - if (!LambdaTag && !aLambdaTag) + if (LambdaTag == aLambdaTag) continue; if (!SelectionV0(collision, v0)) @@ -490,21 +495,22 @@ struct lambdapolarization { PionVec = ROOT::Math::PxPyPzMVector(postrack.px(), postrack.py(), postrack.pz(), massPi); } LambdaVec = ProtonVec + PionVec; + LambdaVec.SetM(massLambda); ROOT::Math::Boost boost{LambdaVec.BoostToCM()}; ProtonBoostedVec = boost(ProtonVec); angle = ProtonBoostedVec.Pz() / ProtonBoostedVec.P(); - relphi = TVector2::Phi_0_2pi(static_cast(nmode) * (LambdaVec.Phi() - TMath::ATan2(collision.qvecIm()[3 + (nmode - 2) * 24], collision.qvecRe()[3 + (nmode - 2) * 24]) / static_cast(nmode))); + relphi = TVector2::Phi_0_2pi(static_cast(nmode) * (LambdaVec.Phi() - TMath::ATan2(collision.qvecIm()[QvecDetInd], collision.qvecRe()[QvecDetInd]) / static_cast(nmode))); if (cfgShiftCorr) { auto deltapsiFT0C = 0.0; auto deltapsiFT0A = 0.0; auto deltapsiFV0A = 0.0; - auto psidefFT0C = TMath::ATan2(collision.qvecIm()[3 + (nmode - 2) * 24], collision.qvecRe()[3 + (nmode - 2) * 24]) / static_cast(nmode); - auto psidefFT0A = TMath::ATan2(collision.qvecIm()[3 + 4 + (nmode - 2) * 24], collision.qvecRe()[3 + 4 + (nmode - 2) * 24]) / static_cast(nmode); - auto psidefFV0A = TMath::ATan2(collision.qvecIm()[3 + 12 + (nmode - 2) * 24], collision.qvecRe()[3 + 12 + (nmode - 2) * 24]) / static_cast(nmode); + auto psidefFT0C = TMath::ATan2(collision.qvecIm()[3 + (nmode - 2) * 28], collision.qvecRe()[3 + (nmode - 2) * 28]) / static_cast(nmode); + auto psidefFT0A = TMath::ATan2(collision.qvecIm()[3 + 4 + (nmode - 2) * 28], collision.qvecRe()[3 + 4 + (nmode - 2) * 28]) / static_cast(nmode); + auto psidefFV0A = TMath::ATan2(collision.qvecIm()[3 + 12 + (nmode - 2) * 28], collision.qvecRe()[3 + 12 + (nmode - 2) * 28]) / static_cast(nmode); for (int ishift = 1; ishift <= 10; ishift++) { auto coeffshiftxFT0C = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyFT0C = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(centrality, 1.5, ishift - 0.5)); @@ -586,10 +592,6 @@ struct lambdapolarization { } } for (int i = 2; i < cfgnMods + 2; i++) { - QvecDetInd = 0; - QvecRefAInd = 4; - QvecRefBInd = 5; - if (cfgShiftCorrDef) { FillShiftCorrection(collision, i); } diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index 00cea1295bc..34e19e9c561 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -38,7 +38,15 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct NPCascCandidate { - int globalIndex; + int64_t trackGlobID; + int64_t trackITSID; + int64_t collisionID; + float matchingChi2; + float itsClusSize; + bool isGoodMatch; + bool isGoodCascade; + int pdgCodeMom; + int pdgCodeGrandma; float pvX; float pvY; float pvZ; @@ -139,7 +147,8 @@ struct NonPromptCascadeTask { using TracksExtData = soa::Join; using TracksExtMC = soa::Join; - using CollisionCandidatesRun3 = soa::Join::iterator; + using CollisionCandidatesRun3 = soa::Join; + using CollisionCandidatesRun3MC = soa::Join; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable propToDCA{"propToDCA", true, "create tracks version propagated to PCA"}; @@ -208,22 +217,22 @@ struct NonPromptCascadeTask { void initCCDB(aod::BCsWithTimestamps::iterator const& bc) { - if (mRunNumber != bc.runNumber()) { - mRunNumber = bc.runNumber(); - auto timestamp = bc.timestamp(); - - if (o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(cfgGRPpath, timestamp)) { - o2::base::Propagator::initFieldFromGRP(grpo); - bz = grpo->getNominalL3Field(); - } else if (o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(cfgGRPmagPath, timestamp)) { - o2::base::Propagator::initFieldFromGRP(grpmag); - bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(debug) << "bz = " << bz; - } else { - LOG(fatal) << "Got nullptr from CCDB for path " << cfgGRPmagPath << " of object GRPMagField and " << cfgGRPpath << " of object GRPObject for timestamp " << timestamp; - } + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + auto timestamp = bc.timestamp(); + + if (o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(cfgGRPpath, timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpo); + bz = grpo->getNominalL3Field(); + } else if (o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(cfgGRPmagPath, timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpmag); + bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(debug) << "bz = " << bz; + } else { + LOG(fatal) << "Got nullptr from CCDB for path " << cfgGRPmagPath << " of object GRPMagField and " << cfgGRPpath << " of object GRPObject for timestamp " << timestamp; } - return; } void init(InitContext const&) @@ -353,35 +362,33 @@ struct NonPromptCascadeTask { dDCA.pionDCAz = impactParameterPiontrack.getZ(); } - void processTrackedCascadesMC(CollisionCandidatesRun3 const& collision, + void processTrackedCascadesMC(CollisionCandidatesRun3MC const& collisions, aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& /*cascades*/, aod::V0s const& /*v0s*/, TracksExtMC const& /*tracks*/, - aod::McParticles const& mcParticles, aod::BCsWithTimestamps const&) + aod::McParticles const& mcParticles, aod::McCollisions const&, aod::BCsWithTimestamps const&) { - candidates.clear(); - bool isOmega{false}; - - auto bc = collision.bc_as(); - initCCDB(bc); - - const auto primaryVertex = getPrimaryVertex(collision); - - o2::vertexing::DCAFitterN<2> df2; - df2.setBz(bz); - df2.setPropagateToPCA(propToDCA); - df2.setMaxR(maxR); - df2.setMaxDZIni(maxDZIni); - df2.setMinParamChange(minParamChange); - df2.setMinRelChi2Change(minRelChi2Change); - df2.setUseAbsDCA(useAbsDCA); + candidates.clear(); std::vector mcParticleId; - for (const auto& trackedCascade : trackedCascades) { + auto collision = trackedCascade.collision_as(); + + auto bc = collision.bc_as(); + initCCDB(bc); + + const auto primaryVertex = getPrimaryVertex(collision); - isOmega = false; + o2::vertexing::DCAFitterN<2> df2; + df2.setBz(bz); + df2.setPropagateToPCA(propToDCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); const auto& track = trackedCascade.track_as(); + const auto& ITStrack = trackedCascade.itsTrack_as(); const auto& casc = trackedCascade.cascade(); const auto& bachelor = casc.bachelor_as(); const auto& v0 = casc.v0(); @@ -442,11 +449,7 @@ struct NonPromptCascadeTask { momenta[1] = {pionTrack.px(), pionTrack.py(), pionTrack.pz()}; const auto v0mass = RecoDecay::m(momenta, masses); - ////Omega hypohesis -> rejecting Xi - if (TMath::Abs(massXi - constants::physics::MassXiMinus) > 0.005) { - isOmega = true; - invMassBCOmega->Fill(massOmega); - } + invMassBCOmega->Fill(massOmega); invMassBCXi->Fill(massXi); invMassBCV0->Fill(v0mass); @@ -458,18 +461,13 @@ struct NonPromptCascadeTask { int bachPionNClusTPC = -1; int bachKaonNClusITS = -1; int bachPionNClusITS = -1; - if (isOmega) { - bachKaonNClusTPC = bachelor.tpcNClsFound(); - bachKaonNClusITS = bachelor.itsNCls(); - } + bachPionNClusTPC = bachelor.tpcNClsFound(); /// by default cascade = Xi bachPionNClusITS = bachelor.itsNCls(); /// by default cascade = Xi bool bachKaonHasTOF = 0; bool bachPionHasTOF = 0; - if (isOmega) { - bachKaonHasTOF = bachelor.hasTOF(); - } + bachPionHasTOF = bachelor.hasTOF(); // if (!bachelor.hasTOF() && !ptrack.hasTOF() && !ntrack.hasTOF()) { @@ -491,22 +489,13 @@ struct NonPromptCascadeTask { // QA PID float nSigmaTPC[nParticles]{bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi()}; - if (isOmega) { - if (bachelor.hasTPC()) { - LOG(debug) << "TPCSignal bachelor " << bachelor.sign() << "/" << bachelor.tpcInnerParam() << "/" << bachelor.tpcSignal(); - if (nSigmaTPC[0] < cfgCutsPID->get(0u, 0u) || nSigmaTPC[0] > cfgCutsPID->get(0u, 1u)) { - continue; - } - } - registry.fill(HIST("h_PIDcutsOmega"), 3, massOmega); - } - - if (bachelor.hasTPC()) { + if (bachelor.hasTPC()) { // same cuts for Omega and Xi LOG(debug) << "TPCSignal bachelor " << bachelor.sign() << "/" << bachelor.tpcInnerParam() << "/" << bachelor.tpcSignal(); - if (nSigmaTPC[1] < cfgCutsPID->get(1u, 0u) || nSigmaTPC[1] > cfgCutsPID->get(1u, 1u)) { + if (nSigmaTPC[0] < cfgCutsPID->get(0u, 0u) || nSigmaTPC[0] > cfgCutsPID->get(0u, 1u)) { continue; } } + registry.fill(HIST("h_PIDcutsOmega"), 3, massOmega); registry.fill(HIST("h_PIDcutsXi"), 3, massXi); LOG(debug) << "TPCSignal protonTrack " << protonTrack.sign() << "/" << protonTrack.tpcInnerParam() << "/" << protonTrack.tpcSignal(); @@ -524,11 +513,9 @@ struct NonPromptCascadeTask { registry.fill(HIST("h_PIDcutsXi"), 5, massXi); - if (isOmega) { - registry.fill(HIST("h_PIDcutsOmega"), 5, massOmega); - invMassACOmega->Fill(massOmega); - registry.fill(HIST("h_massvspt_Omega"), massOmega, track.pt()); - } + registry.fill(HIST("h_PIDcutsOmega"), 5, massOmega); + invMassACOmega->Fill(massOmega); + registry.fill(HIST("h_massvspt_Omega"), massOmega, track.pt()); registry.fill(HIST("h_PIDcutsXi"), 5, massXi); @@ -539,7 +526,7 @@ struct NonPromptCascadeTask { registry.fill(HIST("h_massvspt_V0"), v0mass, track.pt()); motherDCA mDCA; - fillCascadeDCA(track, protonTrack, pionTrack, primaryVertex, isOmega, mDCA); + fillCascadeDCA(track, protonTrack, pionTrack, primaryVertex, true, mDCA); // always filling in MC LOGF(debug, "protonTrack (id: %d, pdg: %d) has mother %d", protonTrack.mcParticleId(), protonTrack.mcParticle().pdgCode(), protonTrack.mcParticle().has_mothers() ? protonTrack.mcParticle().mothersIds()[0] : -1); @@ -553,9 +540,43 @@ struct NonPromptCascadeTask { LOG(debug) << "v0 with PDG code: " << v0part.pdgCode(); } daughtersDCA dDCA; - fillDauDCA(trackedCascade, bachelor, protonTrack, pionTrack, primaryVertex, isOmega, dDCA); + fillDauDCA(trackedCascade, bachelor, protonTrack, pionTrack, primaryVertex, true, dDCA); // always filling in MC + + bool isGoodCascade = false; + + int motherParticleID = -1; + + if (protonTrack.mcParticle().has_mothers() && pionTrack.mcParticle().has_mothers() && bachelor.mcParticle().has_mothers()) { + if (protonTrack.mcParticle().mothersIds()[0] == pionTrack.mcParticle().mothersIds()[0]) { + const auto v0part = protonTrack.mcParticle().mothers_first_as(); + if (abs(v0part.pdgCode()) == 3122 && v0part.has_mothers()) { + const auto motherV0 = v0part.mothers_as()[0]; + // const auto motherBach = bachelor.mcParticle().mothers_as()[0]; + if (v0part.mothersIds()[0] == bachelor.mcParticle().mothersIds()[0]) { + if (abs(motherV0.pdgCode()) == 3312 || abs(motherV0.pdgCode()) == 3334) { + isGoodCascade = true; + motherParticleID = v0part.mothersIds()[0]; + } + } + } + } + } + + bool isGoodMatch = ((motherParticleID == ITStrack.mcParticleId())) ? true : false; - candidates.emplace_back(NPCascCandidate{static_cast(track.globalIndex()), + int pdgCodeMom = 0, pdgCodeGrandma = 0; + if (isGoodCascade && isGoodMatch) { + if (track.mcParticle().has_mothers()) { + const auto mom = track.mcParticle().mothers_as()[0]; + pdgCodeMom = mom.pdgCode(); + if (mom.has_mothers()) { + const auto grandma = mom.mothers_as()[0]; + pdgCodeGrandma = grandma.pdgCode(); + } + } + } + + candidates.emplace_back(NPCascCandidate{track.globalIndex(), ITStrack.globalIndex(), trackedCascade.collisionId(), trackedCascade.matchingChi2(), trackedCascade.itsClsSize(), isGoodMatch, isGoodCascade, pdgCodeMom, pdgCodeGrandma, primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), track.pt(), track.eta(), track.phi(), protonTrack.pt(), protonTrack.eta(), pionTrack.pt(), pionTrack.eta(), bachelor.pt(), bachelor.eta(), @@ -581,8 +602,11 @@ struct NonPromptCascadeTask { } auto particle = mcParticles.iteratorAt(mcParticleId[i]); auto& c = candidates[i]; + auto mcCollision = particle.mcCollision_as(); + auto label = collisions.iteratorAt(c.collisionID); - NPCTableMC(c.pvX, c.pvY, c.pvZ, + NPCTableMC(c.matchingChi2, c.itsClusSize, c.isGoodMatch, c.isGoodCascade, c.pdgCodeMom, c.pdgCodeGrandma, + c.pvX, c.pvY, c.pvZ, c.cascPt, c.cascEta, c.cascPhi, c.protonPt, c.protonEta, c.pionPt, c.pionEta, c.bachPt, c.bachEta, c.cascDCAxy, c.cascDCAz, c.protonDCAxy, c.protonDCAz, c.pionDCAxy, c.pionDCAz, c.bachDCAxy, c.bachDCAz, @@ -593,38 +617,37 @@ struct NonPromptCascadeTask { c.protonTPCNSigma, c.pionTPCNSigma, c.bachKaonTPCNSigma, c.bachPionTPCNSigma, c.protonHasTOF, c.pionHasTOF, c.bachKaonHasTOF, c.bachPionHasTOF, c.protonTOFNSigma, c.pionTOFNSigma, c.bachKaonTOFNSigma, c.bachPionTOFNSigma, - particle.pt(), particle.eta(), particle.phi(), particle.pdgCode()); + particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), mcCollision.posX() - particle.vx(), mcCollision.posY() - particle.vy(), mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == label.mcCollisionId()); } } PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesMC, "process cascades from strangeness tracking: MC analysis", true); - void processTrackedCascadesData(CollisionCandidatesRun3 const& collision, + void processTrackedCascadesData(CollisionCandidatesRun3 const& /*collisions*/, aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& /*cascades*/, aod::V0s const& /*v0s*/, TracksExtData const& /*tracks*/, aod::BCsWithTimestamps const&) { candidates.clear(); - bool isOmega{false}; - - auto bc = collision.bc_as(); - initCCDB(bc); - - const auto primaryVertex = getPrimaryVertex(collision); + for (const auto& trackedCascade : trackedCascades) { + bool isOmega{false}; - o2::vertexing::DCAFitterN<2> df2; - df2.setBz(bz); - df2.setPropagateToPCA(propToDCA); - df2.setMaxR(maxR); - df2.setMaxDZIni(maxDZIni); - df2.setMinParamChange(minParamChange); - df2.setMinRelChi2Change(minRelChi2Change); - df2.setUseAbsDCA(useAbsDCA); + auto collision = trackedCascade.collision_as(); + auto bc = collision.bc_as(); + initCCDB(bc); - for (const auto& trackedCascade : trackedCascades) { + const auto primaryVertex = getPrimaryVertex(collision); - isOmega = false; + o2::vertexing::DCAFitterN<2> df2; + df2.setBz(bz); + df2.setPropagateToPCA(propToDCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); const auto& track = trackedCascade.track_as(); + const auto& ITStrack = trackedCascade.itsTrack_as(); const auto& casc = trackedCascade.cascade(); const auto& bachelor = casc.bachelor_as(); const auto& v0 = casc.v0(); @@ -790,7 +813,7 @@ struct NonPromptCascadeTask { daughtersDCA dDCA; fillDauDCA(trackedCascade, bachelor, protonTrack, pionTrack, primaryVertex, isOmega, dDCA); - candidates.emplace_back(NPCascCandidate{static_cast(track.globalIndex()), + candidates.emplace_back(NPCascCandidate{track.globalIndex(), ITStrack.globalIndex(), trackedCascade.collisionId(), trackedCascade.matchingChi2(), trackedCascade.itsClsSize(), 0, 0, 0, 0, primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), track.pt(), track.eta(), track.phi(), protonTrack.pt(), protonTrack.eta(), pionTrack.pt(), pionTrack.eta(), bachelor.pt(), bachelor.eta(), @@ -802,12 +825,12 @@ struct NonPromptCascadeTask { protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.hasTOF(), pionTrack.hasTOF(), bachKaonHasTOF, bachPionHasTOF, protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi()}); - - } // end loop over tracked cascades + } for (auto& c : candidates) { - NPCTable(c.pvX, c.pvY, c.pvZ, + NPCTable(c.matchingChi2, c.itsClusSize, + c.pvX, c.pvY, c.pvZ, c.cascPt, c.cascEta, c.cascPhi, c.protonPt, c.protonEta, c.pionPt, c.pionEta, c.bachPt, c.bachEta, c.cascDCAxy, c.cascDCAz, c.protonDCAxy, c.protonDCAz, c.pionDCAxy, c.pionDCAz, c.bachDCAxy, c.bachDCAz, diff --git a/PWGLF/Tasks/Strangeness/phik0sanalysis.cxx b/PWGLF/Tasks/Strangeness/phik0sanalysis.cxx index dad756505e5..34ad920e561 100644 --- a/PWGLF/Tasks/Strangeness/phik0sanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/phik0sanalysis.cxx @@ -44,6 +44,9 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/trackUtilities.h" #include "Common/Core/TrackSelection.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "PWGLF/Utils/inelGt.h" +#include "PWGLF/DataModel/mcCentrality.h" using namespace o2; using namespace o2::framework; @@ -52,10 +55,21 @@ using namespace o2::framework::expressions; namespace { static constexpr int nMultBin = 10; +static constexpr int nPtBinK0S = 4; +static constexpr int nPtBinPi = 3; -constexpr float mPhi[nMultBin] = {}; +constexpr float flowmPhiInc[nMultBin] = {1.01074f, 1.01073f, 1.01072f, 1.01074f, 1.01075f, 1.01074f, 1.01075f, 1.01074f, 1.01073f, 1.01074f}; +constexpr float fupmPhiInc[nMultBin] = {1.02778f, 1.02777f, 1.02776f, 1.02778f, 1.02779f, 1.02778f, 1.02779f, 1.02778f, 1.02777f, 1.02778f}; + +constexpr float flowmPhiFCut[nMultBin] = {1.01072f, 1.01073f, 1.01072f, 1.01074f, 1.01075f, 1.01076f, 1.01076f, 1.01076f, 1.01075f, 1.01073f}; +constexpr float fupmPhiFCut[nMultBin] = {1.02776f, 1.02777f, 1.02776f, 1.02778f, 1.02779f, 1.02778f, 1.02778f, 1.02778f, 1.02779f, 1.02777f}; + +constexpr float flowmPhiSCut[nMultBin] = {1.01072f, 1.01074f, 1.01070f, 1.01076f, 1.01075f, 1.01077f, 1.01075f, 1.01075f, 1.01076f, 1.01077f}; +constexpr float fupmPhiSCut[nMultBin] = {1.02776f, 1.02778f, 1.02774f, 1.02780f, 1.02779f, 1.02781f, 1.02779f, 1.02779f, 1.02780f, 1.02774f}; static constexpr float multBin[nMultBin + 1] = {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}; +static constexpr float pTBinK0S[nPtBinK0S + 1] = {0.0, 0.5, 0.8, 1.2, 10.0}; +static constexpr float pTBinPi[nPtBinPi + 1] = {0.0, 0.5, 1.2, 10.0}; static constexpr std::string_view PhiK0SSEInc[nMultBin] = {"h2PhiK0SSEInc_0_1", "h2PhiK0SSEInc_1_5", "h2PhiK0SSEInc_5_10", "h2PhiK0SSEInc_10_15", "h2PhiK0SSEInc_15_20", "h2PhiK0SSEInc_20_30", "h2PhiK0SSEInc_30_40", "h2PhiK0SSEInc_40_50", "h2PhiK0SSEInc_50_70", "h2PhiK0SSEInc_70_100"}; @@ -63,16 +77,45 @@ static constexpr std::string_view PhiK0SSEFCut[nMultBin] = {"h2PhiK0SSEFCut_0_1" "h2PhiK0SSEFCut_20_30", "h2PhiK0SSEFCut_30_40", "h2PhiK0SSEFCut_40_50", "h2PhiK0SSEFCut_50_70", "h2PhiK0SSEFCut_70_100"}; static constexpr std::string_view PhiK0SSESCut[nMultBin] = {"h2PhiK0SSESCut_0_1", "h2PhiK0SSESCut_1_5", "h2PhiK0SSESCut_5_10", "h2PhiK0SSESCut_10_15", "h2PhiK0SSESCut_15_20", "h2PhiK0SSESCut_20_30", "h2PhiK0SSESCut_30_40", "h2PhiK0SSESCut_40_50", "h2PhiK0SSESCut_50_70", "h2PhiK0SSESCut_70_100"}; + +static constexpr std::string_view PhiPiSEInc[nMultBin] = {"h2PhiPiSEInc_0_1", "h2PhiPiSEInc_1_5", "h2PhiPiSEInc_5_10", "h2PhiPiSEInc_10_15", "h2PhiPiSEInc_15_20", + "h2PhiPiSEInc_20_30", "h2PhiPiSEInc_30_40", "h2PhiPiSEInc_40_50", "h2PhiPiSEInc_50_70", "h2PhiPiSEInc_70_100"}; +static constexpr std::string_view PhiPiSEFCut[nMultBin] = {"h2PhiPiSEFCut_0_1", "h2PhiPiSEFCut_1_5", "h2PhiPiSEFCut_5_10", "h2PhiPiSEFCut_10_15", "h2PhiPiSEFCut_15_20", + "h2PhiPiSEFCut_20_30", "h2PhiPiSEFCut_30_40", "h2PhiPiSEFCut_40_50", "h2PhiPiSEFCut_50_70", "h2PhiPiSEFCut_70_100"}; +static constexpr std::string_view PhiPiSESCut[nMultBin] = {"h2PhiPiSESCut_0_1", "h2PhiPiSESCut_1_5", "h2PhiPiSESCut_5_10", "h2PhiPiSESCut_10_15", "h2PhiPiSESCut_15_20", + "h2PhiPiSESCut_20_30", "h2PhiPiSESCut_30_40", "h2PhiPiSESCut_40_50", "h2PhiPiSESCut_50_70", "h2PhiPiSESCut_70_100"}; + +static constexpr std::string_view MCPhiK0SSEInc[nMultBin] = {"h2RecMCPhiK0SSEInc_0_1", "h2RecMCPhiK0SSEInc_1_5", "h2RecMCPhiK0SSEInc_5_10", "h2RecMCPhiK0SSEInc_10_15", "h2RecMCPhiK0SSEInc_15_20", + "h2RecMCPhiK0SSEInc_20_30", "h2RecMCPhiK0SSEInc_30_40", "h2RecMCPhiK0SSEInc_40_50", "h2RecMCPhiK0SSEInc_50_70", "h2RecMCPhiK0SSEInc_70_100"}; +static constexpr std::string_view MCPhiK0SSEFCut[nMultBin] = {"h2RecMCPhiK0SSEFCut_0_1", "h2RecMCPhiK0SSEFCut_1_5", "h2RecMCPhiK0SSEFCut_5_10", "h2RecMCPhiK0SSEFCut_10_15", "h2RecMCPhiK0SSEFCut_15_20", + "h2RecMCPhiK0SSEFCut_20_30", "h2RecMCPhiK0SSEFCut_30_40", "h2RecMCPhiK0SSEFCut_40_50", "h2RecMCPhiK0SSEFCut_50_70", "h2RecMCPhiK0SSEFCut_70_100"}; +static constexpr std::string_view MCPhiK0SSESCut[nMultBin] = {"h2RecMCPhiK0SSESCut_0_1", "h2RecMCPhiK0SSESCut_1_5", "h2RecMCPhiK0SSESCut_5_10", "h2RecMCPhiK0SSESCut_10_15", "h2RecMCPhiK0SSESCut_15_20", + "h2RecMCPhiK0SSESCut_20_30", "h2RecMCPhiK0SSESCut_30_40", "h2RecMCPhiK0SSESCut_40_50", "h2RecMCPhiK0SSESCut_50_70", "h2RecMCPhiK0SSESCut_70_100"}; + +static constexpr std::string_view MCPhiPiSEInc[nMultBin] = {"h2RecMCPhiPiSEInc_0_1", "h2RecMCPhiPiSEInc_1_5", "h2RecMCPhiPiSEInc_5_10", "h2RecMCPhiPiSEInc_10_15", "h2RecMCPhiPiSEInc_15_20", + "h2RecMCPhiPiSEInc_20_30", "h2RecMCPhiPiSEInc_30_40", "h2RecMCPhiPiSEInc_40_50", "h2RecMCPhiPiSEInc_50_70", "h2RecMCPhiPiSEInc_70_100"}; +static constexpr std::string_view MCPhiPiSEFCut[nMultBin] = {"h2RecMCPhiPiSEFCut_0_1", "h2RecMCPhiPiSEFCut_1_5", "h2RecMCPhiPiSEFCut_5_10", "h2RecMCPhiPiSEFCut_10_15", "h2RecMCPhiPiSEFCut_15_20", + "h2RecMCPhiPiSEFCut_20_30", "h2RecMCPhiPiSEFCut_30_40", "h2RecMCPhiPiSEFCut_40_50", "h2RecMCPhiPiSEFCut_50_70", "h2RecMCPhiPiSEFCut_70_100"}; +static constexpr std::string_view MCPhiPiSESCut[nMultBin] = {"h2RecMCPhiPiSESCut_0_1", "h2RecMCPhiPiSESCut_1_5", "h2RecMCPhiPiSESCut_5_10", "h2RecMCPhiPiSESCut_10_15", "h2RecMCPhiPiSESCut_15_20", + "h2RecMCPhiPiSESCut_20_30", "h2RecMCPhiPiSESCut_30_40", "h2RecMCPhiPiSESCut_40_50", "h2RecMCPhiPiSESCut_50_70", "h2RecMCPhiPiSESCut_70_100"}; } // namespace struct phik0shortanalysis { // Histograms are defined with HistogramRegistry HistogramRegistry eventHist{"eventHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry K0SHist{"K0SHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MCeventHist{"MCeventHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry PhicandHist{"PhicandHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry K0SHist{"K0SHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry PhipurHist{"PhipurHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MCPhipurHist{"MCPhipurHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry PhiK0SHist{"PhiK0SHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MCPhiK0SHist{"MCPhiK0SHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry PhiPionHist{"PhiPionHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MCPhiPionHist{"MCPhiPionHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry PhieffHist{"PhieffHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry K0SeffHist{"K0SeffHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry PioneffHist{"PioneffHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry yaccHist{"yaccHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for event selection Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; @@ -94,14 +137,19 @@ struct phik0shortanalysis { Configurable lowmK0S{"lowmK0S", 0.48, "Lower limit on K0Short mass"}; Configurable upmK0S{"upmK0S", 0.52, "Upper limit on K0Short mass"}; + // Configurable on K0S pT + Configurable> binspTK0S{"binspTK0S", std::vector{pTBinK0S, pTBinK0S + nPtBinK0S + 1}, "pT bin limits for K0S"}; + // Configurables on Phi mass - Configurable nBins{"nBins", 50, "N bins in cfgPhimassaxis"}; - Configurable> lowmPhiInc{"lowmPhiInc", std::vector{mPhi, mPhi + nMultBin}, "Lower limits on Phi mass Inclusive"}; - Configurable> upmPhiInc{"upmPhiInc", std::vector{mPhi, mPhi + nMultBin}, "Upper limits on Phi mass Inclusive"}; - Configurable> lowmPhiFCut{"lowmPhiFCut", std::vector{mPhi, mPhi + nMultBin}, "Lower limits on Phi mass First Cut"}; - Configurable> upmPhiFCut{"upmPhiFCut", std::vector{mPhi, mPhi + nMultBin}, "Upper limits on Phi mass First Cut"}; - Configurable> lowmPhiSCut{"lowmPhiSCut", std::vector{mPhi, mPhi + nMultBin}, "Lower limits on Phi mass Second Cut"}; - Configurable> upmPhiSCut{"upmPhiSCut", std::vector{mPhi, mPhi + nMultBin}, "Upper limits on Phi mass Second Cut"}; + Configurable nBins{"nBins", 15, "N bins in cfgPhimassaxis"}; + Configurable> lowmPhiInc{"lowmPhiInc", std::vector{flowmPhiInc, flowmPhiInc + nMultBin}, "Lower limits on Phi mass Inclusive"}; + Configurable> upmPhiInc{"upmPhiInc", std::vector{fupmPhiInc, fupmPhiInc + nMultBin}, "Upper limits on Phi mass Inclusive"}; + Configurable> lowmPhiFCut{"lowmPhiFCut", std::vector{flowmPhiFCut, flowmPhiFCut + nMultBin}, "Lower limits on Phi mass First Cut"}; + Configurable> upmPhiFCut{"upmPhiFCut", std::vector{fupmPhiFCut, fupmPhiFCut + nMultBin}, "Upper limits on Phi mass First Cut"}; + Configurable> lowmPhiSCut{"lowmPhiSCut", std::vector{flowmPhiSCut, flowmPhiSCut + nMultBin}, "Lower limits on Phi mass Second Cut"}; + Configurable> upmPhiSCut{"upmPhiSCut", std::vector{fupmPhiSCut, fupmPhiSCut + nMultBin}, "Upper limits on Phi mass Second Cut"}; + Configurable lowmPhiMB{"lowmPhiMB", 1.01074f, "Upper limits on Phi mass Minimum Bias"}; + Configurable upmPhiMB{"upmPhiMB", 1.02778f, "Upper limits on Phi mass Minimum Bias"}; // Configurables for phi selection Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minimum pt cut"}; @@ -116,45 +164,100 @@ struct phik0shortanalysis { Configurable nsigmaCutTPCKa{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; Configurable nsigmaCutCombinedKa{"nsigmaCutCombined", 3.0, "Value of the TOF Nsigma cut"}; - // Configurables for pions(extra with respect to a few of those defined for V0) + // Configurables for pions selection(extra with respect to a few of those defined for V0) Configurable minITSnCls{"minITSnCls", 4.0f, "min number of ITS clusters"}; Configurable maxChi2ITS{"maxChi2ITS", 36.0f, "max chi2 per cluster ITS"}; Configurable dcaxyMax{"dcaxyMax", 0.1f, "Maximum DCAxy to primary vertex"}; Configurable dcazMax{"dcazMax", 0.1f, "Maximum DCAz to primary vertex"}; + Configurable NSigmaTOFPion{"NSigmaTOFPion", 5.0, "NSigmaTOFPion"}; - // Configurables for invariant mass histograms filling - Configurable cfgFirstCutonDeltay{"cgfFirstCutonDeltay", 0.5, "First upper bound on Deltay selection"}; - Configurable cfgSecondCutonDeltay{"cgfSecondCutonDeltay", 0.2, "Second upper bound on Deltay selection"}; + // Configurable on pion pT + Configurable> binspTPi{"binspTPi", std::vector{pTBinPi, pTBinPi + nPtBinPi + 1}, "pT bin limits for pions"}; + + // Configurables for delta y selection + Configurable nBinsy{"nBinsy", 16, "Number of bins in y and deltay axis"}; + Configurable cfgInclusiveDeltay{"cfgInclusiveDeltay", 0.8, "Inclusive upper bound on Deltay selection"}; + Configurable cfgFirstCutonDeltay{"cgfFirstCutonDeltay", 0.5, "First upper bound on Deltay selection"}; + Configurable cfgSecondCutonDeltay{"cgfSecondCutonDeltay", 0.2, "Second upper bound on Deltay selection"}; // Configurable for event mixing Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + // Configurable for RecMC + Configurable cfgiskNoITSROFrameBorder{"cfgiskNoITSROFrameBorder", false, "kNoITSROFrameBorder request on RecMC collisions"}; + // Configurable axis ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin"}; + // Constants + double massKa = o2::constants::physics::MassKPlus; + double massPi = o2::constants::physics::MassPiPlus; + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Defining filters on V0s (cannot filter on dynamic columns) + Filter preFilterV0 = (nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv && aod::v0data::dcaV0daughters < v0setting_dcav0dau); + + // Defining the type of the collisions for data and MC + using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + using MCCollisions = soa::Join; + + // Defining the type of the V0s + using FullV0s = soa::Filtered; + + // Defining the type of the tracks for data and MC + using FullTracks = soa::Join; + using FullMCTracks = soa::Join; + + using V0DauTracks = soa::Join; + using V0DauMCTracks = soa::Join; + + // Defining the binning policy for mixed event + using BinningTypeVertexContributor = ColumnBinningPolicy; + + SliceCache cache; + + Partition posTracks = aod::track::signed1Pt > cfgCutCharge; + Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + + Partition posMCTracks = aod::track::signed1Pt > cfgCutCharge; + Partition negMCTracks = aod::track::signed1Pt < cfgCutCharge; + + // Necessary to flag INEL>0 events in GenMC + Service pdgDB; + void init(InitContext const&) { // Axes AxisSpec K0SmassAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec PhimassAxis = {200, 0.9f, 1.2f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec vertexZAxis = {100, -15.f, 15.f, "vrtx_{Z} [cm]"}; - AxisSpec deltayAxis = {16, 0.0f, 0.8f, "|#it{#Deltay}|"}; + AxisSpec yAxis = {nBinsy, -0.8f, 0.8f, "#it{y}"}; + AxisSpec deltayAxis = {nBinsy, 0.0f, 1.6f, "|#it{#Deltay}|"}; AxisSpec multAxis = {120, 0.0f, 120.0f, "centFT0M"}; + AxisSpec binnedmultAxis{{0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "centFT0M"}; AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec binnedptK0SAxis{{0.0, 0.5, 0.8, 1.2, 10.0}, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec binnedptPiAxis{{0.0, 0.5, 1.2, 10.0}, "#it{p}_{T} (GeV/#it{c})"}; std::vector cfgPhimassAxisInc; std::vector cfgPhimassAxisFCut; std::vector cfgPhimassAxisSCut; for (int i = 0; i < nMultBin; i++) { cfgPhimassAxisInc.push_back({nBins, lowmPhiInc->at(i), upmPhiInc->at(i), "#it{M}_{inv} [GeV/#it{c}^{2}]"}); cfgPhimassAxisFCut.push_back({nBins, lowmPhiFCut->at(i), upmPhiFCut->at(i), "#it{M}_{inv} [GeV/#it{c}^{2}]"}); - cfgPhimassAxisSCut.push_back({nBins, lowmPhiSCut->at(i), upmPhiFCut->at(i), "#it{M}_{inv} [GeV/#it{c}^{2}]"}); + cfgPhimassAxisSCut.push_back({nBins, lowmPhiSCut->at(i), upmPhiSCut->at(i), "#it{M}_{inv} [GeV/#it{c}^{2}]"}); } + AxisSpec cfgPhimassAxisMB = {nBins, lowmPhiMB, upmPhiMB, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; // Histograms // Number of events per selection - eventHist.add("hEventSelection", "hEVentSelection", kTH1F, {{5, -0.5f, 4.5f}}); + eventHist.add("hEventSelection", "hEventSelection", kTH1F, {{5, -0.5f, 4.5f}}); eventHist.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); eventHist.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); eventHist.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(3, "posZ cut"); @@ -162,14 +265,56 @@ struct phik0shortanalysis { eventHist.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(5, "With at least a #phi cand"); // Event information - eventHist.add("hVertexZRec", "hVertexZRec", kTH1F, {vertexZAxis}); + eventHist.add("hVertexZ", "hVertexZ", kTH1F, {vertexZAxis}); eventHist.add("hMultiplicityPercent", "Multiplicity Percentile", kTH1F, {multAxis}); - // K0S topological/PID cuts - K0SHist.add("hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {{55, 0.0f, 2.2f}}); - K0SHist.add("hV0CosPA", "hV0CosPA", kTH1F, {{100, 0.95f, 1.f}}); - K0SHist.add("hNSigmaPosPionFromK0S", "hNSigmaPosPionFromK0Short", kTH2F, {ptAxis, {100, -5.f, 5.f}}); - K0SHist.add("hNSigmaNegPionFromK0S", "hNSigmaNegPionFromK0Short", kTH2F, {ptAxis, {100, -5.f, 5.f}}); + // Histo to check phi numbers in data + eventHist.add("thereisnoPhiwK0S", "thereisnoPhiwK0S", kTH1F, {{3, -0.5, 2.5}}); + eventHist.get(HIST("thereisnoPhiwK0S"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + eventHist.get(HIST("thereisnoPhiwK0S"))->GetXaxis()->SetBinLabel(2, "|#Delta y|<0.5"); + eventHist.get(HIST("thereisnoPhiwK0S"))->GetXaxis()->SetBinLabel(3, "|#Delta y|<0.2"); + + eventHist.add("thereisnoPhiwPi", "thereisnoPhiwPi", kTH1F, {{3, -0.5, 2.5}}); + eventHist.get(HIST("thereisnoPhiwPi"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + eventHist.get(HIST("thereisnoPhiwPi"))->GetXaxis()->SetBinLabel(2, "|#Delta y|<0.5"); + eventHist.get(HIST("thereisnoPhiwPi"))->GetXaxis()->SetBinLabel(3, "|#Delta y|<0.2"); + + // Number of MC events per selection for Rec and Gen + MCeventHist.add("hRecMCEventSelection", "hRecMCEventSelection", kTH1F, {{8, -0.5f, 7.5f}}); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(2, "kIsTriggerTVX"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(5, "posZ cut"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(6, "INEL>0 cut"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(7, "With at least a gen coll"); + MCeventHist.get(HIST("hRecMCEventSelection"))->GetXaxis()->SetBinLabel(8, "With at least a #phi"); + + // MC Event information for Rec and Gen + MCeventHist.add("hRecMCVertexZ", "hRecMCVertexZ", kTH1F, {vertexZAxis}); + MCeventHist.add("hRecMCMultiplicityPercent", "RecMC Multiplicity Percentile", kTH1F, {multAxis}); + MCeventHist.add("hRecMCGenMultiplicityPercent", "RecMC Gen Multiplicity Percentile", kTH1F, {binnedmultAxis}); + + // Histo to check phi numbers in RecMC + MCeventHist.add("thereisnoPhiwK0SMC", "thereisnoPhiwK0SMC", kTH1F, {{3, -0.5, 2.5}}); + MCeventHist.get(HIST("thereisnoPhiwK0SMC"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + MCeventHist.get(HIST("thereisnoPhiwK0SMC"))->GetXaxis()->SetBinLabel(2, "|#Delta y|<0.5"); + MCeventHist.get(HIST("thereisnoPhiwK0SMC"))->GetXaxis()->SetBinLabel(3, "|#Delta y|<0.2"); + + MCeventHist.add("thereisnoPhiwPiMC", "thereisnoPhiwPiMC", kTH1F, {{3, -0.5, 2.5}}); + MCeventHist.get(HIST("thereisnoPhiwPiMC"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + MCeventHist.get(HIST("thereisnoPhiwPiMC"))->GetXaxis()->SetBinLabel(2, "|#Delta y|<0.5"); + MCeventHist.get(HIST("thereisnoPhiwPiMC"))->GetXaxis()->SetBinLabel(3, "|#Delta y|<0.2"); + + MCeventHist.add("hGenMCEventSelection", "hGenMCEventSelection", kTH1F, {{5, -0.5f, 4.5f}}); + MCeventHist.get(HIST("hGenMCEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + MCeventHist.get(HIST("hGenMCEventSelection"))->GetXaxis()->SetBinLabel(2, "posZ cut"); + MCeventHist.get(HIST("hGenMCEventSelection"))->GetXaxis()->SetBinLabel(3, "INEL>0 cut"); + MCeventHist.get(HIST("hGenMCEventSelection"))->GetXaxis()->SetBinLabel(4, "With at least a #phi"); + MCeventHist.get(HIST("hGenMCEventSelection"))->GetXaxis()->SetBinLabel(5, "With at least a reco coll"); + + MCeventHist.add("hGenMCVertexZ", "hGenMCVertexZ", kTH1F, {vertexZAxis}); + MCeventHist.add("hGenMCMultiplicityPercent", "GenMC Multiplicity Percentile", kTH1F, {binnedmultAxis}); // Phi tpological/PID cuts PhicandHist.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); @@ -178,86 +323,197 @@ struct phik0shortanalysis { PhicandHist.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH2F, {ptAxis, {100, -10.0f, 10.0f}}); PhicandHist.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH2F, {ptAxis, {100, -10.0f, 10.0f}}); + // K0S topological/PID cuts + K0SHist.add("hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {{55, 0.0f, 2.2f}}); + K0SHist.add("hV0CosPA", "hV0CosPA", kTH1F, {{100, 0.95f, 1.f}}); + K0SHist.add("hNSigmaPosPionFromK0S", "hNSigmaPosPionFromK0Short", kTH2F, {ptAxis, {100, -5.f, 5.f}}); + K0SHist.add("hNSigmaNegPionFromK0S", "hNSigmaNegPionFromK0Short", kTH2F, {ptAxis, {100, -5.f, 5.f}}); + // Phi invariant mass for computing purities and normalisation PhipurHist.add("h2PhipurInvMass", "Invariant mass of Phi for Purity (no K0S/Pi)", kTH2F, {multAxis, PhimassAxis}); - PhipurHist.add("h2PhipurK0SInvMassInclusive", "Invariant mass of Phi for Purity (K0S) Inclusive", kTH2F, {multAxis, PhimassAxis}); - PhipurHist.add("h2PhipurK0SInvMassFirstCut", "Invariant mass of Phi for Purity (K0S) Deltay < FirstCut", kTH2F, {multAxis, PhimassAxis}); - PhipurHist.add("h2PhipurK0SInvMassSecondCut", "Invariant mass of Phi for Purity (K0S) Deltay < SecondCut", kTH2F, {multAxis, PhimassAxis}); + + PhipurHist.add("h3PhipurK0SInvMassInclusive", "Invariant mass of Phi for Purity (K0S) Inclusive", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhipurHist.add("h3PhipurK0SInvMassFirstCut", "Invariant mass of Phi for Purity (K0S) Deltay < FirstCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhipurHist.add("h3PhipurK0SInvMassSecondCut", "Invariant mass of Phi for Purity (K0S) Deltay < SecondCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhipurHist.add("h3PhipurPiInvMassInclusive", "Invariant mass of Phi for Purity (Pi) Inclusive", kTH3F, {multAxis, ptAxis, PhimassAxis}); PhipurHist.add("h3PhipurPiInvMassFirstCut", "Invariant mass of Phi for Purity (Pi) Deltay < FirstCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); PhipurHist.add("h3PhipurPiInvMassSecondCut", "Invariant mass of Phi for Purity (Pi) Deltay < SecondCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); - // 2D mass for Phi and K0S + // MCPhi invariant mass for computing purities + MCPhipurHist.add("h2MCPhipurInvMass", "Invariant mass of Phi for Purity (no K0S/Pi)", kTH2F, {multAxis, PhimassAxis}); + + MCPhipurHist.add("h3MCPhipurK0SInvMassInclusive", "Invariant mass of Phi for Purity (K0S) Inclusive", kTH3F, {multAxis, ptAxis, PhimassAxis}); + MCPhipurHist.add("h3MCPhipurK0SInvMassFirstCut", "Invariant mass of Phi for Purity (K0S) Deltay < FirstCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + MCPhipurHist.add("h3MCPhipurK0SInvMassSecondCut", "Invariant mass of Phi for Purity (K0S) Deltay < SecondCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + + MCPhipurHist.add("h3MCPhipurPiInvMassInclusive", "Invariant mass of Phi for Purity (Pi) Inclusive", kTH3F, {multAxis, ptAxis, PhimassAxis}); + MCPhipurHist.add("h3MCPhipurPiInvMassFirstCut", "Invariant mass of Phi for Purity (Pi) Deltay < FirstCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + MCPhipurHist.add("h3MCPhipurPiInvMassSecondCut", "Invariant mass of Phi for Purity (Pi) Deltay < SecondCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + + // 2D mass for Phi and K0S for Same Event and Mixed Event for (int i = 0; i < nMultBin; i++) { - PhiK0SHist.add(PhiK0SSEInc[i].data(), "2D Invariant mass of Phi and K0Short for Same Event Inclusive", kTH2F, {K0SmassAxis, cfgPhimassAxisInc.at(i)}); - PhiK0SHist.add(PhiK0SSEFCut[i].data(), "2D Invariant mass of Phi and K0Short for Same Event Deltay < FirstCut", kTH2F, {K0SmassAxis, cfgPhimassAxisFCut.at(i)}); - PhiK0SHist.add(PhiK0SSESCut[i].data(), "2D Invariant mass of Phi and K0Short for Same Event Deltay < SecondCut", kTH2F, {K0SmassAxis, cfgPhimassAxisSCut.at(i)}); + PhiK0SHist.add(PhiK0SSEInc[i].data(), "2D Invariant mass of Phi and K0Short for Same Event Inclusive", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisInc.at(i)}); + PhiK0SHist.add(PhiK0SSEFCut[i].data(), "2D Invariant mass of Phi and K0Short for Same Event Deltay < FirstCut", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisFCut.at(i)}); + PhiK0SHist.add(PhiK0SSESCut[i].data(), "2D Invariant mass of Phi and K0Short for Same Event Deltay < SecondCut", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisSCut.at(i)}); } + PhiK0SHist.add("h2PhiK0SSEInc_0_100", "2D Invariant mass of Phi and K0Short for Same Event Inclusive MB", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisMB}); + PhiK0SHist.add("h2PhiK0SSEFCut_0_100", "2D Invariant mass of Phi and K0Short for Same Event Deltay < FirstCut MB", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisMB}); + PhiK0SHist.add("h2PhiK0SSESCut_0_100", "2D Invariant mass of Phi and K0Short for Same Event Deltay < SecondCut MB", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisMB}); - PhiK0SHist.add("h3PhiK0SInvMassMixedEventInclusive", "2D Invariant mass of Phi and K0Short for Mixed Event Inclusive", kTH3F, {multAxis, K0SmassAxis, PhimassAxis}); - PhiK0SHist.add("h3PhiK0SInvMassMixedEventFirstCut", "2D Invariant mass of Phi and K0Short for Mixed Event Deltay < FirstCut", kTH3F, {multAxis, K0SmassAxis, PhimassAxis}); - PhiK0SHist.add("h3PhiK0SInvMassMixedEventSecondCut", "2D Invariant mass of Phi and K0Short for Mixed Event Deltay < SecondCut", kTH3F, {multAxis, K0SmassAxis, PhimassAxis}); + PhiK0SHist.add("h4PhiK0SInvMassMixedEventInclusive", "2D Invariant mass of Phi and K0Short for Mixed Event Inclusive", kTHnSparseF, {multAxis, binnedptK0SAxis, K0SmassAxis, PhimassAxis}); + PhiK0SHist.add("h4PhiK0SInvMassMixedEventFirstCut", "2D Invariant mass of Phi and K0Short for Mixed Event Deltay < FirstCut", kTHnSparseF, {multAxis, binnedptK0SAxis, K0SmassAxis, PhimassAxis}); + PhiK0SHist.add("h4PhiK0SInvMassMixedEventSecondCut", "2D Invariant mass of Phi and K0Short for Mixed Event Deltay < SecondCut", kTHnSparseF, {multAxis, binnedptK0SAxis, K0SmassAxis, PhimassAxis}); - // Phi mass vs Pion dE/dx - PhiPionHist.add("h4PhiInvMassPidEdxSameEventInclusive", "Phi Invariant mass vs Pion dE/dx for Same Event Inclusive", kTHnSparseF, {multAxis, ptAxis, {100, -10.0f, 10.0f}, PhimassAxis}); - PhiPionHist.add("h4PhiInvMassPidEdxSameEventFirstCut", "Phi Invariant mass vs Pion dE/dx for Same Event Deltay < FirstCut", kTHnSparseF, {multAxis, ptAxis, {100, -10.0f, 10.0f}, PhimassAxis}); - PhiPionHist.add("h4PhiInvMassPidEdxSameEventSecondCut", "Phi Invariant mass vs Pion dE/dx for Same Event Deltay < SecondCut", kTHnSparseF, {multAxis, ptAxis, {100, -10.0f, 10.0f}, PhimassAxis}); + // MC 2D mass for Phi and K0S + for (int i = 0; i < nMultBin; i++) { + MCPhiK0SHist.add(MCPhiK0SSEInc[i].data(), "2D Invariant mass of Phi and K0Short for RecMC Inclusive", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisInc.at(i)}); + MCPhiK0SHist.add(MCPhiK0SSEFCut[i].data(), "2D Invariant mass of Phi and K0Short for RecMC Deltay < FirstCut", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisFCut.at(i)}); + MCPhiK0SHist.add(MCPhiK0SSESCut[i].data(), "2D Invariant mass of Phi and K0Short for RecMC Deltay < SecondCut", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisSCut.at(i)}); + } + MCPhiK0SHist.add("h2RecMCPhiK0SSEInc_0_100", "2D Invariant mass of Phi and K0Short for RecMC Inclusive MB", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisMB}); + MCPhiK0SHist.add("h2RecMCPhiK0SSEFCut_0_100", "2D Invariant mass of Phi and K0Short for RecMC Deltay < FirstCut MB", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisMB}); + MCPhiK0SHist.add("h2RecMCPhiK0SSESCut_0_100", "2D Invariant mass of Phi and K0Short for RecMC Deltay < SecondCut MB", kTH3F, {binnedptK0SAxis, K0SmassAxis, cfgPhimassAxisMB}); - PhiPionHist.add("h4PhiInvMassPidEdxMixedEventInclusive", "Phi Invariant mass vs Pion dE/dx for Mixed Event Inclusive", kTHnSparseF, {multAxis, ptAxis, {100, -10.0f, 10.0f}, PhimassAxis}); - PhiPionHist.add("h4PhiInvMassPidEdxMixedEventFirstCut", "Phi Invariant mass vs Pion dE/dx for Mixed Event Deltay < FirstCut", kTHnSparseF, {multAxis, ptAxis, {100, -10.0f, 10.0f}, PhimassAxis}); - PhiPionHist.add("h4PhiInvMassPidEdxMixedEventSecondCut", "Phi Invariant mass vs Pion dE/dx for Mixed Event Deltay < SecondCut", kTHnSparseF, {multAxis, ptAxis, {100, -10.0f, 10.0f}, PhimassAxis}); - } + // GenMC K0S coupled to Phi + MCPhiK0SHist.add("h2PhiK0SGenMCInclusive", "K0Short coupled to Phi for GenMC Inclusive", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + MCPhiK0SHist.add("h2PhiK0SGenMCFirstCut", "K0Short coupled to Phi for GenMC Deltay < FirstCut", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + MCPhiK0SHist.add("h2PhiK0SGenMCSecondCut", "K0Short coupled to Phi for GenMC Deltay < SecondCut", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); - // Constants - double massKa = o2::constants::physics::MassKPlus; - double massPi = o2::constants::physics::MassPiPlus; + MCPhiK0SHist.add("h2PhiK0SGenMCInclusiveAssocReco", "K0Short coupled to Phi for GenMC Inclusive Associated Reco Collision", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + MCPhiK0SHist.add("h2PhiK0SGenMCFirstCutAssocReco", "K0Short coupled to Phi for GenMC Deltay < FirstCut Associated Reco Collision", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + MCPhiK0SHist.add("h2PhiK0SGenMCSecondCutAssocReco", "K0Short coupled to Phi for GenMC Deltay < SecondCut Associated Reco Collision", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); - // Defining filters for events (event selection) - // Processed events will be already fulfilling the event selection requirements - Filter eventFilter = (o2::aod::evsel::sel8 == true); - Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + // Phi mass vs Pion NSigma dE/dx for Same Event and Mixed Event + for (int i = 0; i < nMultBin; i++) { + PhiPionHist.add(PhiPiSEInc[i].data(), "Phi Invariant mass vs Pion nSigma TPC/TOF for Same Event Inclusive", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisInc.at(i)}); + PhiPionHist.add(PhiPiSEFCut[i].data(), "Phi Invariant mass vs Pion nSigma TPC/TOF for Same Event Deltay < FirstCut", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisFCut.at(i)}); + PhiPionHist.add(PhiPiSESCut[i].data(), "Phi Invariant mass vs Pion nSigma TPC/TOF for Same Event Deltay < SecondCut", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisSCut.at(i)}); + } + PhiPionHist.add("h2PhiPiSEInc_0_100", "Phi Invariant mass vs Pion nSigma TPC/TOF for Same Event Inclusive MB", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisMB}); + PhiPionHist.add("h2PhiPiSEFCut_0_100", "Phi Invariant mass vs Pion nSigma TPC/TOF for Same Event Deltay < FirstCut MB", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisMB}); + PhiPionHist.add("h2PhiPiSESCut_0_100", "Phi Invariant mass vs Pion nSigma TPC/TOF for Same Event Deltay < SecondCut MB", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisMB}); - // Defining filters on V0s (cannot filter on dynamic columns) - Filter preFilterV0 = (nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv && aod::v0data::dcaV0daughters < v0setting_dcav0dau); + PhiPionHist.add("h5PhiInvMassPiNSigmadEdxMixedEventInclusive", "Phi Invariant mass vs Pion nSigma TPC/TOF for Mixed Event Inclusive", kTHnSparseF, {multAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, PhimassAxis}); + PhiPionHist.add("h5PhiInvMassPiNSigmadEdxMixedEventFirstCut", "Phi Invariant mass vs Pion nSigma TPC/TOF for Mixed Event Deltay < FirstCut", kTHnSparseF, {multAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, PhimassAxis}); + PhiPionHist.add("h5PhiInvMassPiNSigmadEdxMixedEventSecondCut", "Phi Invariant mass vs Pion nSigma TPC/TOF for Mixed Event Deltay < SecondCut", kTHnSparseF, {multAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, PhimassAxis}); + + // MC Phi mass vs Pion NSigma dE/dx + for (int i = 0; i < nMultBin; i++) { + MCPhiPionHist.add(MCPhiPiSEInc[i].data(), "Phi Invariant mass vs Pion nSigma TPC/TOF for RecMC Inclusive", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisInc.at(i)}); + MCPhiPionHist.add(MCPhiPiSEFCut[i].data(), "Phi Invariant mass vs Pion nSigma TPC/TOF for RecMC Deltay < FirstCut", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisFCut.at(i)}); + MCPhiPionHist.add(MCPhiPiSESCut[i].data(), "Phi Invariant mass vs Pion nSigma TPC/TOF for RecMC Deltay < SecondCut", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisSCut.at(i)}); + } + MCPhiPionHist.add("h2RecMCPhiPiSEInc_0_100", "Phi Invariant mass vs Pion nSigma TPC/TOF for RecMC Inclusive MB", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisMB}); + MCPhiPionHist.add("h2RecMCPhiPiSEFCut_0_100", "Phi Invariant mass vs Pion nSigma TPC/TOF for RecMC Deltay < FirstCut MB", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisMB}); + MCPhiPionHist.add("h2RecMCPhiPiSESCut_0_100", "Phi Invariant mass vs Pion nSigma TPC/TOF for RecMC Deltay < SecondCut MB", kTHnSparseF, {binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, cfgPhimassAxisMB}); - // Defining the type of the event - using EventCandidates = soa::Join; + // GenMC Pion coupled to Phi + MCPhiPionHist.add("h2PhiPiGenMCInclusive", "Pion coupled to Phi for GenMC Inclusive", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + MCPhiPionHist.add("h2PhiPiGenMCFirstCut", "Pion coupled to Phi for GenMC Deltay < FirstCut", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + MCPhiPionHist.add("h2PhiPiGenMCSecondCut", "Pion coupled to Phi for GenMC Deltay < SecondCut", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); - // Defining the type of the Phi daughter tracks - using PhiDaughterCandidates = soa::Join; + MCPhiPionHist.add("h2PhiPiGenMCInclusiveAssocReco", "Pion coupled to Phi for GenMC Inclusive Associated Reco Collision", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + MCPhiPionHist.add("h2PhiPiGenMCFirstCutAssocReco", "Pion coupled to Phi for GenMC Deltay < FirstCut Associated Reco Collision", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + MCPhiPionHist.add("h2PhiPiGenMCSecondCutAssocReco", "Pion coupled to Phi for GenMC Deltay < SecondCut Associated Reco Collision", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); - // Defining the type of the V0s - using V0Candidates = soa::Filtered; + // MCPhi invariant mass for computing efficiencies and MCnormalisation + PhieffHist.add("h2PhieffInvMass", "Invariant mass of Phi for Efficiency (no K0S/Pi)", kTH2F, {multAxis, PhimassAxis}); - // Defining the type of the V0 daughter tracks - using V0DaughterCandidates = soa::Join; + PhieffHist.add("h3PhieffK0SInvMassInclusive", "Invariant mass of Phi for Efficiency (K0S) Inclusive", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhieffHist.add("h3PhieffK0SInvMassFirstCut", "Invariant mass of Phi for Efficiency (K0S) Deltay < FirstCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhieffHist.add("h3PhieffK0SInvMassSecondCut", "Invariant mass of Phi for Efficiency (K0S) Deltay < SecondCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); - // Defining the type of the Pions - using PionCandidates = soa::Join; + PhieffHist.add("h3PhieffPiInvMassInclusive", "Invariant mass of Phi for Efficiency (Pi) Inclusive", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhieffHist.add("h3PhieffPiInvMassFirstCut", "Invariant mass of Phi for Efficiency (Pi) Deltay < FirstCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); + PhieffHist.add("h3PhieffPiInvMassSecondCut", "Invariant mass of Phi for Efficiency (Pi) Deltay < SecondCut", kTH3F, {multAxis, ptAxis, PhimassAxis}); - // Defining the binning policy for mixed event - using BinningTypeVertexContributor = ColumnBinningPolicy; + // GenMC Phi and Phi coupled to K0S and Pion + PhieffHist.add("h1PhiGenMC", "Phi for GenMC", kTH1F, {{10, -0.5f, 9.5f}}); - SliceCache cache; - Partition posTracks = aod::track::signed1Pt > cfgCutCharge; - Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + PhieffHist.add("h2PhieffK0SGenMCInclusive", "Phi coupled to K0Short for GenMC Inclusive", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + PhieffHist.add("h2PhieffK0SGenMCFirstCut", "Phi coupled to K0Short for GenMC Deltay < FirstCut", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + PhieffHist.add("h2PhieffK0SGenMCSecondCut", "Phi coupled to K0Short for GenMC Deltay < SecondCut", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + + PhieffHist.add("h2PhieffK0SGenMCInclusiveAssocReco", "Phi coupled to K0Short for GenMC Inclusive", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + PhieffHist.add("h2PhieffK0SGenMCFirstCutAssocReco", "Phi coupled to K0Short for GenMC Deltay < FirstCut", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + PhieffHist.add("h2PhieffK0SGenMCSecondCutAssocReco", "Phi coupled to K0Short for GenMC Deltay < SecondCut", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + + PhieffHist.add("h2PhieffPiGenMCInclusive", "Phi coupled to Pion for GenMC Inclusive", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + PhieffHist.add("h2PhieffPiGenMCFirstCut", "Phi coupled to Pion for GenMC Deltay < FirstCut", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + PhieffHist.add("h2PhieffPiGenMCSecondCut", "Phi coupled to Pion for GenMC Deltay < SecondCut", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + + PhieffHist.add("h2PhieffPiGenMCInclusiveAssocReco", "Phi coupled to Pion for GenMC Inclusive", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + PhieffHist.add("h2PhieffPiGenMCFirstCutAssocReco", "Phi coupled to Pion for GenMC Deltay < FirstCut", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + PhieffHist.add("h2PhieffPiGenMCSecondCutAssocReco", "Phi coupled to Pion for GenMC Deltay < SecondCut", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + + // MCK0S invariant mass and GenMC K0S for computing efficiencies + K0SeffHist.add("h3K0SeffInvMass", "Invariant mass of K0Short for Efficiency", kTH3F, {binnedmultAxis, binnedptK0SAxis, K0SmassAxis}); + K0SeffHist.add("h2K0SGenMC", "K0Short for GenMC", kTH2F, {{10, -0.5f, 9.5f}, {4, -0.5f, 3.5f}}); + + // MCPion invariant mass and GenMC Pion for computing efficiencies + PioneffHist.add("h4PieffInvMass", "Invariant mass of Pion for Efficiency", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + PioneffHist.add("h2PiGenMC", "Pion for GenMC", kTH2F, {{10, -0.5f, 9.5f}, {3, -0.5f, 2.5f}}); + + // y acceptance studies + yaccHist.add("hyaccK0SRecMC", "K0S y acceptance in RecMC", kTH3F, {binnedmultAxis, binnedptK0SAxis, yAxis}); + yaccHist.add("hyaccK0SGenMC", "K0S y acceptance in GenMC", kTH3F, {binnedmultAxis, binnedptK0SAxis, yAxis}); + + yaccHist.add("hyaccPiRecMC", "Pion y acceptance in RecMC", kTH3F, {binnedmultAxis, binnedptPiAxis, yAxis}); + yaccHist.add("hyaccPiGenMC", "Pion y acceptance in GenMC", kTH3F, {binnedmultAxis, binnedptPiAxis, yAxis}); + } // Event selection and QA filling - template - bool acceptEventQA(const T& collision) + template + bool acceptEventQA(const T& collision, bool QA) { - eventHist.fill(HIST("hEventSelection"), 0); // all collisions - if (!collision.sel8()) - return false; - eventHist.fill(HIST("hEventSelection"), 1); // sel8 collisions - if (std::abs(collision.posZ()) > cutzvertex) - return false; - eventHist.fill(HIST("hEventSelection"), 2); // vertex-Z selected - eventHist.fill(HIST("hVertexZRec"), collision.posZ()); - if (!collision.isInelGt0()) - return false; - eventHist.fill(HIST("hEventSelection"), 3); // INEL>0 collisions - return true; + if constexpr (!isMC) { // data event + if (QA) + eventHist.fill(HIST("hEventSelection"), 0); // all collisions + if (!collision.sel8()) + return false; + if (QA) + eventHist.fill(HIST("hEventSelection"), 1); // sel8 collisions + if (std::abs(collision.posZ()) > cutzvertex) + return false; + if (QA) { + eventHist.fill(HIST("hEventSelection"), 2); // vertex-Z selected + eventHist.fill(HIST("hVertexZ"), collision.posZ()); + } + if (!collision.isInelGt0()) + return false; + if (QA) + eventHist.fill(HIST("hEventSelection"), 3); // INEL>0 collisions + return true; + } else { // RecMC event + if (QA) + MCeventHist.fill(HIST("hRecMCEventSelection"), 0); // all collisions + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX)) + return false; + if (QA) + MCeventHist.fill(HIST("hRecMCEventSelection"), 1); // kIsTriggerTVX collisions + if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return false; + if (QA) + MCeventHist.fill(HIST("hRecMCEventSelection"), 2); // kNoTimeFrameBorder collisions + if (cfgiskNoITSROFrameBorder) { + if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return false; + if (QA) + MCeventHist.fill(HIST("hRecMCEventSelection"), 3); // kNoITSROFrameBorder collisions (by default not requested by the selection) + } + if (std::abs(collision.posZ()) > cutzvertex) + return false; + if (QA) { + MCeventHist.fill(HIST("hRecMCEventSelection"), 4); // vertex-Z selected + MCeventHist.fill(HIST("hRecMCVertexZ"), collision.posZ()); + } + if (!collision.isInelGt0()) + return false; + if (QA) + MCeventHist.fill(HIST("hRecMCEventSelection"), 5); // INEL>0 collisions + return true; + } } // Single track selection for strangeness sector @@ -348,16 +604,25 @@ struct phik0shortanalysis { return false; if (track.itsNCls() < minITSnCls) return false; - if (!track.hasTPC()) - return false; - if (track.tpcNClsFound() < minTPCnClsFound) - return false; - if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) - return false; - if (track.tpcChi2NCl() > maxChi2TPC) - return false; if (track.itsChi2NCl() > maxChi2ITS) return false; + + if (track.pt() < 1.2) { + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + if (track.tpcChi2NCl() > maxChi2TPC) + return false; + } + + if (track.pt() > 0.5) { + if (!track.hasTOF()) + return false; + } + if (std::abs(track.dcaXY()) > dcaxyMax) return false; if (std::abs(track.dcaZ()) > dcazMax) @@ -366,10 +631,11 @@ struct phik0shortanalysis { } // Fill 2D invariant mass histogram for V0 and Phi - template + template void fillInvMass2D(TLorentzVector V0, const std::vector listPhi, float multiplicity, double weightInclusive, double weightLtFirstCut, double weightLtSecondCut) { double massV0 = V0.M(); + double ptV0 = V0.Pt(); double rapidityV0 = V0.Rapidity(); for (unsigned int phitag = 0; phitag < listPhi.size(); phitag++) { @@ -378,28 +644,44 @@ struct phik0shortanalysis { double deltay = std::abs(rapidityV0 - rapidityPhi); if constexpr (!isMix) { // same event - PhiK0SHist.fill(HIST(PhiK0SSEInc[iBin]), massV0, massPhi, weightInclusive); + PhiK0SHist.fill(HIST(PhiK0SSEInc[iBin]), ptV0, massV0, massPhi, weightInclusive); + PhiK0SHist.fill(HIST("h2PhiK0SSEInc_0_100"), ptV0, massV0, massPhi, weightInclusive); if (deltay > cfgFirstCutonDeltay) continue; - PhiK0SHist.fill(HIST(PhiK0SSEFCut[iBin]), massV0, massPhi, weightLtFirstCut); + PhiK0SHist.fill(HIST(PhiK0SSEFCut[iBin]), ptV0, massV0, massPhi, weightLtFirstCut); + PhiK0SHist.fill(HIST("h2PhiK0SSEFCut_0_100"), ptV0, massV0, massPhi, weightLtFirstCut); if (deltay > cfgSecondCutonDeltay) continue; - PhiK0SHist.fill(HIST(PhiK0SSESCut[iBin]), massV0, massPhi, weightLtSecondCut); + PhiK0SHist.fill(HIST(PhiK0SSESCut[iBin]), ptV0, massV0, massPhi, weightLtSecondCut); + PhiK0SHist.fill(HIST("h2PhiK0SSESCut_0_100"), ptV0, massV0, massPhi, weightLtSecondCut); } else { // mixed event - PhiK0SHist.fill(HIST("h3PhiK0SInvMassMixedEventInclusive"), multiplicity, massV0, massPhi, weightInclusive); + PhiK0SHist.fill(HIST("h4PhiK0SInvMassMixedEventInclusive"), multiplicity, ptV0, massV0, massPhi, weightInclusive); + if (deltay > cfgFirstCutonDeltay) + continue; + PhiK0SHist.fill(HIST("h4PhiK0SInvMassMixedEventFirstCut"), multiplicity, ptV0, massV0, massPhi, weightLtFirstCut); + if (deltay > cfgSecondCutonDeltay) + continue; + PhiK0SHist.fill(HIST("h4PhiK0SInvMassMixedEventSecondCut"), multiplicity, ptV0, massV0, massPhi, weightLtSecondCut); + } + + if constexpr (isMC) { // MC event + MCPhiK0SHist.fill(HIST(MCPhiK0SSEInc[iBin]), ptV0, massV0, massPhi, weightInclusive); + MCPhiK0SHist.fill(HIST("h2RecMCPhiK0SSEInc_0_100"), ptV0, massV0, massPhi, weightInclusive); if (deltay > cfgFirstCutonDeltay) continue; - PhiK0SHist.fill(HIST("h3PhiK0SInvMassMixedEventFirstCut"), multiplicity, massV0, massPhi, weightLtFirstCut); + MCPhiK0SHist.fill(HIST(MCPhiK0SSEFCut[iBin]), ptV0, massV0, massPhi, weightLtFirstCut); + MCPhiK0SHist.fill(HIST("h2RecMCPhiK0SSEFCut_0_100"), ptV0, massV0, massPhi, weightLtFirstCut); if (deltay > cfgSecondCutonDeltay) continue; - PhiK0SHist.fill(HIST("h3PhiK0SInvMassMixedEventSecondCut"), multiplicity, massV0, massPhi, weightLtSecondCut); + MCPhiK0SHist.fill(HIST(MCPhiK0SSESCut[iBin]), ptV0, massV0, massPhi, weightLtSecondCut); + MCPhiK0SHist.fill(HIST("h2RecMCPhiK0SSESCut_0_100"), ptV0, massV0, massPhi, weightLtSecondCut); } } } - // Fill Phi invariant mass vs Pion dE/dx histogram - template - void fillInvMassdEdx(TLorentzVector Pi, float dEdx, const std::vector listPhi, float multiplicity, double weightInclusive, double weightLtFirstCut, double weightLtSecondCut) + // Fill Phi invariant mass vs Pion nSigmadE/dx histogram + template + void fillInvMassNSigma(TLorentzVector Pi, float nSigmaTPCPi, float nSigmaTOFPi, const std::vector listPhi, float multiplicity, double weightInclusive, double weightLtFirstCut, double weightLtSecondCut) { double rapidityPi = Pi.Rapidity(); double ptPi = Pi.Pt(); @@ -410,29 +692,45 @@ struct phik0shortanalysis { double deltay = std::abs(rapidityPi - rapidityPhi); if constexpr (!isMix) { // same event - PhiK0SHist.fill(HIST("h4PhiInvMassPidEdxSameEventInclusive"), multiplicity, ptPi, dEdx, massPhi, weightInclusive); + PhiPionHist.fill(HIST(PhiPiSEInc[iBin]), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightInclusive); + PhiPionHist.fill(HIST("h2PhiPiSEInc_0_100"), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightInclusive); if (deltay > cfgFirstCutonDeltay) continue; - PhiK0SHist.fill(HIST("h4PhiInvMassPidEdxSameEventFirstCut"), multiplicity, ptPi, dEdx, massPhi, weightLtFirstCut); + PhiPionHist.fill(HIST(PhiPiSEFCut[iBin]), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtFirstCut); + PhiPionHist.fill(HIST("h2PhiPiSEFCut_0_100"), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtFirstCut); if (deltay > cfgSecondCutonDeltay) continue; - PhiK0SHist.fill(HIST("h4PhiInvMassPidEdxsSameEventSecondCut"), multiplicity, ptPi, dEdx, massPhi, weightLtSecondCut); + PhiPionHist.fill(HIST(PhiPiSESCut[iBin]), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtSecondCut); + PhiPionHist.fill(HIST("h2PhiPiSESCut_0_100"), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtSecondCut); } else { // mixed event - PhiK0SHist.fill(HIST("h4PhiInvMassPidEdxMixedEventInclusive"), multiplicity, ptPi, dEdx, massPhi, weightInclusive); + PhiPionHist.fill(HIST("h5PhiInvMassPiNSigmadEdxMixedEventInclusive"), multiplicity, ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightInclusive); + if (deltay > cfgFirstCutonDeltay) + continue; + PhiPionHist.fill(HIST("h5PhiInvMassPiNSigmadEdxMixedEventFirstCut"), multiplicity, ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtFirstCut); + if (deltay > cfgSecondCutonDeltay) + continue; + PhiPionHist.fill(HIST("h5PhiInvMassPiNSigmadEdxMixedEventSecondCut"), multiplicity, ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtSecondCut); + } + + if constexpr (isMC) { // MC event + MCPhiPionHist.fill(HIST(MCPhiPiSEInc[iBin]), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightInclusive); + MCPhiPionHist.fill(HIST("h2RecMCPhiPiSEInc_0_100"), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightInclusive); if (deltay > cfgFirstCutonDeltay) continue; - PhiK0SHist.fill(HIST("h4PhiInvMassPidEdxMixedEventFirstCut"), multiplicity, ptPi, dEdx, massPhi, weightLtFirstCut); + MCPhiPionHist.fill(HIST(MCPhiPiSEFCut[iBin]), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtFirstCut); + MCPhiPionHist.fill(HIST("h2RecMCPhiPiSEFCut_0_100"), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtFirstCut); if (deltay > cfgSecondCutonDeltay) continue; - PhiK0SHist.fill(HIST("h4PhiInvMassPidEdxMixedEventSecondCut"), multiplicity, ptPi, dEdx, massPhi, weightLtSecondCut); + MCPhiPionHist.fill(HIST(MCPhiPiSESCut[iBin]), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtSecondCut); + MCPhiPionHist.fill(HIST("h2RecMCPhiPiSESCut_0_100"), ptPi, nSigmaTPCPi, nSigmaTOFPi, massPhi, weightLtSecondCut); } } } - void processQAPurity(EventCandidates::iterator const& collision, PhiDaughterCandidates const&, PionCandidates const& Pis, V0Candidates const& V0s, V0DaughterCandidates const&) + void processQAPurity(SelCollisions::iterator const& collision, FullTracks const& fullTracks, FullV0s const& V0s, V0DauTracks const&) { // Check if the event selection is passed - if (!acceptEventQA(collision)) + if (!acceptEventQA(collision, true)) return; float multiplicity = collision.centFT0M(); @@ -468,7 +766,7 @@ struct phik0shortanalysis { TLorentzVector recPhi; recPhi = recMother(track1, track2, massKa, massKa); - if (recPhi.Rapidity() > 0.8) + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) continue; if (!isCountedPhi) { @@ -478,14 +776,12 @@ struct phik0shortanalysis { PhipurHist.fill(HIST("h2PhipurInvMass"), multiplicity, recPhi.M()); - bool isCountedK0SInclusive = false; - bool isCountedK0SFirstCut = false; - bool isCountedK0SSecondCut = false; + bool isCountedK0SInclusive[nPtBinK0S] = {false}, isCountedK0SFirstCut[nPtBinK0S] = {false}, isCountedK0SSecondCut[nPtBinK0S] = {false}; // V0 already reconstructed by the builder for (const auto& v0 : V0s) { - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); // Cut on V0 dynamic columns if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) @@ -505,65 +801,82 @@ struct phik0shortanalysis { TLorentzVector recK0S; recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); - if (recK0S.Rapidity() > 0.8) + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) continue; - if (!isCountedK0SInclusive) { - PhipurHist.fill(HIST("h2PhipurK0SInvMassInclusive"), multiplicity, recPhi.M()); - isCountedK0SInclusive = true; + + int ipTBinK0S = 0; + for (int i = 0; i < nPtBinK0S; i++) { + if (pTBinK0S[i] < recK0S.Pt() && recK0S.Pt() <= pTBinK0S[i + 1]) { + ipTBinK0S = i; + break; + } + } + + if (!isCountedK0SInclusive[ipTBinK0S]) { + PhipurHist.fill(HIST("h3PhipurK0SInvMassInclusive"), multiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SInclusive[ipTBinK0S] = true; } if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) continue; - if (!isCountedK0SFirstCut) { - PhipurHist.fill(HIST("h2PhipurK0SInvMassFirstCut"), multiplicity, recPhi.M()); - isCountedK0SFirstCut = true; + if (!isCountedK0SFirstCut[ipTBinK0S]) { + PhipurHist.fill(HIST("h3PhipurK0SInvMassFirstCut"), multiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SFirstCut[ipTBinK0S] = true; } if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) continue; - if (!isCountedK0SSecondCut) { - PhipurHist.fill(HIST("h2PhipurK0SInvMassSecondCut"), multiplicity, recPhi.M()); - isCountedK0SSecondCut = true; + if (!isCountedK0SSecondCut[ipTBinK0S]) { + PhipurHist.fill(HIST("h3PhipurK0SInvMassSecondCut"), multiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SSecondCut[ipTBinK0S] = true; } } + isFilledhV0 = true; - bool isCountedPiInclusive = false; - bool isCountedPiFirstCut = false; - bool isCountedPiSecondCut = false; + bool isCountedPiInclusive[nPtBinPi] = {false}, isCountedPiFirstCut[nPtBinPi] = {false}, isCountedPiSecondCut[nPtBinPi] = {false}; // Loop over all primary pion candidates - for (const auto& pi : Pis) { - if (!selectionPion(pi)) + for (const auto& track : fullTracks) { + if (!selectionPion(track)) continue; TLorentzVector recPi; - recPi.SetXYZM(pi.px(), pi.py(), pi.pz(), massPi); + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); - if (recPi.Rapidity() > 0.8) + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) continue; - if (!isCountedPiInclusive) { + + int ipTBinPi = 0; + for (int i = 0; i < nPtBinPi; i++) { + if (pTBinPi[i] < recPi.Pt() && recPi.Pt() <= pTBinPi[i + 1]) { + ipTBinPi = i; + break; + } + } + + if (!isCountedPiInclusive[ipTBinPi]) { PhipurHist.fill(HIST("h3PhipurPiInvMassInclusive"), multiplicity, recPi.Pt(), recPhi.M()); - isCountedPiInclusive = true; + isCountedPiInclusive[ipTBinPi] = true; } if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) continue; - if (!isCountedPiFirstCut) { + if (!isCountedPiFirstCut[ipTBinPi]) { PhipurHist.fill(HIST("h3PhipurPiInvMassFirstCut"), multiplicity, recPi.Pt(), recPhi.M()); - isCountedPiFirstCut = true; + isCountedPiFirstCut[ipTBinPi] = true; } if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) continue; - if (!isCountedPiSecondCut) { + if (!isCountedPiSecondCut[ipTBinPi]) { PhipurHist.fill(HIST("h3PhipurPiInvMassSecondCut"), multiplicity, recPi.Pt(), recPhi.M()); - isCountedPiSecondCut = true; + isCountedPiSecondCut[ipTBinPi] = true; } } } } } - PROCESS_SWITCH(phik0shortanalysis, processQAPurity, "Process Same Event for QA and Phi Purities", true); + PROCESS_SWITCH(phik0shortanalysis, processQAPurity, "Process for QA and Phi Purities", true); - void processSEPhiK0S(soa::Filtered::iterator const& collision, PhiDaughterCandidates const&, V0Candidates const& V0s, V0DaughterCandidates const&) + void processSEPhiK0S(soa::Filtered::iterator const& collision, FullTracks const&, FullV0s const& V0s, V0DauTracks const&) { if (!collision.isInelGt0()) return; @@ -585,8 +898,8 @@ struct phik0shortanalysis { // V0 already reconstructed by the builder for (const auto& v0 : V0s) { - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); // Cut on V0 dynamic columns if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) @@ -594,7 +907,7 @@ struct phik0shortanalysis { TLorentzVector recK0S; recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); - if (recK0S.Rapidity() > 0.8) + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) continue; std::vector listrecPhi; @@ -619,7 +932,7 @@ struct phik0shortanalysis { TLorentzVector recPhi; recPhi = recMother(track1, track2, massKa, massKa); - if (recPhi.Rapidity() > 0.8) + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) continue; listrecPhi.push_back(recPhi); @@ -637,49 +950,65 @@ struct phik0shortanalysis { } } - float weightInclusive = 1. / static_cast(countInclusive); - float weightLtFirstCut = 1. / static_cast(countLtFirstCut); - float weightLtSecondCut = 1. / static_cast(countLtSecondCut); + float weightInclusive, weightLtFirstCut, weightLtSecondCut; + if (countInclusive > 0) { + weightInclusive = 1. / static_cast(countInclusive); + } else { + weightInclusive = 0; + eventHist.fill(HIST("thereisnoPhiwK0S"), 0); + } + if (countLtFirstCut > 0) { + weightLtFirstCut = 1. / static_cast(countLtFirstCut); + } else { + weightLtFirstCut = 0; + eventHist.fill(HIST("thereisnoPhiwK0S"), 1); + } + if (countLtSecondCut > 0) { + weightLtSecondCut = 1. / static_cast(countLtSecondCut); + } else { + weightLtSecondCut = 0; + eventHist.fill(HIST("thereisnoPhiwK0S"), 2); + } switch (iBin) { case 0: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 1: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 2: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 3: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 4: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 5: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 6: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 7: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 8: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 9: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } default: @@ -688,9 +1017,9 @@ struct phik0shortanalysis { } } - PROCESS_SWITCH(phik0shortanalysis, processSEPhiK0S, "Process Same Event for Analysis Phi-K0S", false); + PROCESS_SWITCH(phik0shortanalysis, processSEPhiK0S, "Process Same Event for Phi-K0S Analysis", false); - void processSEPhiPion(soa::Filtered::iterator const& collision, PhiDaughterCandidates const&, PionCandidates const& Pis) + void processSEPhiPion(soa::Filtered::iterator const& collision, FullTracks const& fullTracks) { if (!collision.isInelGt0()) return; @@ -698,20 +1027,28 @@ struct phik0shortanalysis { float multiplicity = collision.centFT0M(); eventHist.fill(HIST("hMultiplicityPercent"), multiplicity); + int iBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < multiplicity && multiplicity <= multBin[i + 1]) { + iBin = i; + break; + } + } + // Defining positive and negative tracks for phi reconstruction auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); // Loop over all primary pion candidates - for (const auto& pi : Pis) { + for (const auto& track : fullTracks) { // Pion selection - if (!selectionPion(pi)) + if (!selectionPion(track)) continue; TLorentzVector recPi; - recPi.SetXYZM(pi.px(), pi.py(), pi.pz(), massPi); - if (recPi.Rapidity() > 0.8) + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) continue; std::vector listrecPhi; @@ -736,31 +1073,104 @@ struct phik0shortanalysis { TLorentzVector recPhi; recPhi = recMother(track1, track2, massKa, massKa); - if (recPhi.Rapidity() > 0.8) + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) continue; listrecPhi.push_back(recPhi); - countInclusive++; + if (lowmPhiInc->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiInc->at(iBin)) + countInclusive++; if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) continue; - countLtFirstCut++; + if (lowmPhiFCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiFCut->at(iBin)) + countLtFirstCut++; if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) continue; - countLtSecondCut++; + if (lowmPhiSCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiSCut->at(iBin)) + countLtSecondCut++; } } - float weightInclusive = 1. / static_cast(countInclusive); - float weightLtFirstCut = 1. / static_cast(countLtFirstCut); - float weightLtSecondCut = 1. / static_cast(countLtSecondCut); - fillInvMassdEdx(recPi, pi.tpcNSigmaPi(), listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + float nsigmaTPC, nsigmaTOF; + if (track.hasTPC()) + nsigmaTPC = track.tpcNSigmaPi(); + else + nsigmaTPC = -9.99; + if (track.hasTOF()) + nsigmaTOF = track.tofNSigmaPi(); + else + nsigmaTOF = -9.99; + + float weightInclusive, weightLtFirstCut, weightLtSecondCut; + if (countInclusive > 0) { + weightInclusive = 1. / static_cast(countInclusive); + } else { + weightInclusive = 0; + eventHist.fill(HIST("thereisnoPhiwPi"), 0); + } + if (countLtFirstCut > 0) { + weightLtFirstCut = 1. / static_cast(countLtFirstCut); + } else { + weightLtFirstCut = 0; + eventHist.fill(HIST("thereisnoPhiwPi"), 1); + } + if (countLtSecondCut > 0) { + weightLtSecondCut = 1. / static_cast(countLtSecondCut); + } else { + weightLtSecondCut = 0; + eventHist.fill(HIST("thereisnoPhiwPi"), 2); + } + + switch (iBin) { + case 0: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 1: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 2: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 3: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 4: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 5: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 6: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 7: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 8: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 9: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + default: + break; + } } } - PROCESS_SWITCH(phik0shortanalysis, processSEPhiPion, "Process Same Event for Analysis Phi-Pion", false); + PROCESS_SWITCH(phik0shortanalysis, processSEPhiPion, "Process Same Event for Phi-Pion Analysis", false); - void processMEPhiK0S(soa::Filtered const& collisions, PhiDaughterCandidates const&, V0Candidates const& V0s, V0DaughterCandidates const&) + void processMEPhiK0S(soa::Filtered const& collisions, FullTracks const&, FullV0s const& V0s, V0DauTracks const&) { // Mixing the events with similar vertex z and multiplicity BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicity}, true}; @@ -786,8 +1196,8 @@ struct phik0shortanalysis { auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); for (const auto& v0 : V0ThisColl) { - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); // Cut on V0 dynamic columns if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) @@ -795,7 +1205,7 @@ struct phik0shortanalysis { TLorentzVector recK0S; recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); - if (recK0S.Rapidity() > 0.8) + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) continue; std::vector listrecPhi; @@ -808,7 +1218,7 @@ struct phik0shortanalysis { TLorentzVector recPhi; recPhi = recMother(track1, track2, massKa, massKa); - if (recPhi.Rapidity() > 0.8) + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) continue; listrecPhi.push_back(recPhi); @@ -828,43 +1238,43 @@ struct phik0shortanalysis { switch (iBin) { case 0: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 1: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 2: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 3: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 4: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 5: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 6: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 7: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 8: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } case 9: { - fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + fillInvMass2D(recK0S, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); break; } default: @@ -874,9 +1284,9 @@ struct phik0shortanalysis { } } - PROCESS_SWITCH(phik0shortanalysis, processMEPhiK0S, "Process Mixed Event for Analysis Phi-K0S", false); + PROCESS_SWITCH(phik0shortanalysis, processMEPhiK0S, "Process Mixed Event for Phi-K0S Analysis", false); - void processMEPhiPion(soa::Filtered const& collisions, PhiDaughterCandidates const&, PionCandidates const& Pis) + void processMEPhiPion(soa::Filtered const& collisions, FullTracks const& fullTracks) { // Mixing the events with similar vertex z and multiplicity BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicity}, true}; @@ -886,21 +1296,29 @@ struct phik0shortanalysis { float multiplicity = collision1.centFT0M(); + int iBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < multiplicity && multiplicity <= multBin[i + 1]) { + iBin = i; + break; + } + } + // Defining V0s from collision1 - auto PiThisColl = Pis.sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto trackThisColl = fullTracks.sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); // Defining positive and negative tracks for phi reconstruction from collision1 and collision2, respectively auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - for (const auto& pi : PiThisColl) { + for (const auto& track : trackThisColl) { - if (!selectionPion(pi)) + if (!selectionPion(track)) continue; TLorentzVector recPi; - recPi.SetXYZM(pi.px(), pi.py(), pi.pz(), massPi); - if (recPi.Rapidity() > 0.8) + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) continue; std::vector listrecPhi; @@ -913,7 +1331,7 @@ struct phik0shortanalysis { TLorentzVector recPhi; recPhi = recMother(track1, track2, massKa, massKa); - if (recPhi.Rapidity() > 0.8) + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) continue; listrecPhi.push_back(recPhi); @@ -927,15 +1345,1430 @@ struct phik0shortanalysis { countLtSecondCut++; } + float nsigmaTPC, nsigmaTOF; + if (track.hasTPC()) + nsigmaTPC = track.tpcNSigmaPi(); + else + nsigmaTPC = -9.99; + if (track.hasTOF()) + nsigmaTOF = track.tofNSigmaPi(); + else + nsigmaTOF = -9.99; + float weightInclusive = 1. / static_cast(countInclusive); float weightLtFirstCut = 1. / static_cast(countLtFirstCut); float weightLtSecondCut = 1. / static_cast(countLtSecondCut); - fillInvMassdEdx(recPi, pi.tpcNSigmaPi(), listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + + switch (iBin) { + case 0: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 1: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 2: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 3: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 4: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 5: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 6: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 7: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 8: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 9: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, multiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + default: + break; + } + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processMEPhiPion, "Process Mixed Event for Phi-Pion Analysis", false); + + void processRecMCPhiQA(SimCollisions::iterator const& collision, FullMCTracks const& fullMCTracks, FullV0s const& V0s, V0DauMCTracks const&, MCCollisions const&, aod::McParticles const&) + { + if (!acceptEventQA(collision, true)) + return; + + float multiplicity = collision.centFT0M(); + MCeventHist.fill(HIST("hRecMCMultiplicityPercent"), multiplicity); + + if (!collision.has_mcCollision()) + return; + MCeventHist.fill(HIST("hRecMCEventSelection"), 6); // with at least a gen collision + + const auto& mcCollision = collision.mcCollision_as(); + float genmultiplicity = mcCollision.centFT0M(); + MCeventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); + + // Defining positive and negative tracks for phi reconstruction + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + bool isCountedPhi = false; + + for (auto track1 : posThisColl) { // loop over all selected tracks + if (!selectionTrackResonance(track1) || !selectionPIDKaon(track1)) + continue; // topological and PID selection + + auto track1ID = track1.globalIndex(); + + if (!track1.has_mcParticle()) + continue; + + // Loop over all negative candidates + for (auto track2 : negThisColl) { + if (!selectionTrackResonance(track2) || !selectionPIDKaon(track2)) + continue; // topological and PID selection + + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) + continue; // condition to avoid double counting of pair + + if (!track2.has_mcParticle()) + continue; + + auto MCtrack1 = track1.mcParticle_as(); + auto MCtrack2 = track2.mcParticle_as(); + if (MCtrack1.pdgCode() != 321 || MCtrack2.pdgCode() != -321) + continue; + if (!MCtrack1.has_mothers() || !MCtrack2.has_mothers()) + continue; + if (!MCtrack1.isPhysicalPrimary() || !MCtrack2.isPhysicalPrimary()) + continue; + + int pdgParentPhi = 0; + for (const auto& MotherOfMCtrack1 : MCtrack1.mothers_as()) { + for (const auto& MotherOfMCtrack2 : MCtrack2.mothers_as()) { + if (MotherOfMCtrack1 == MotherOfMCtrack2) { + pdgParentPhi = MotherOfMCtrack1.pdgCode(); + } + } + } + + if (pdgParentPhi != 333) + continue; + + TLorentzVector recPhi; + recPhi = recMother(track1, track2, massKa, massKa); + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) + continue; + + if (!isCountedPhi) { + MCeventHist.fill(HIST("hRecMCEventSelection"), 7); // at least a Phi in the event + isCountedPhi = true; + } + + PhieffHist.fill(HIST("h2PhieffInvMass"), genmultiplicity, recPhi.M()); + + bool isCountedK0SInclusive[nPtBinK0S] = {false}, isCountedK0SFirstCut[nPtBinK0S] = {false}, isCountedK0SSecondCut[nPtBinK0S] = {false}; + + // V0 already reconstructed by the builder + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + if (!posDaughterTrack.has_mcParticle() || !negDaughterTrack.has_mcParticle()) + continue; + + auto posMCDaughterTrack = posDaughterTrack.mcParticle_as(); + auto negMCDaughterTrack = negDaughterTrack.mcParticle_as(); + if (posMCDaughterTrack.pdgCode() != 211 || negMCDaughterTrack.pdgCode() != -211) + continue; + if (!posMCDaughterTrack.has_mothers() || !negMCDaughterTrack.has_mothers()) + continue; + + int pdgParentv0 = 0; + bool isPhysPrim = false; + for (const auto& particleMotherOfNeg : negMCDaughterTrack.mothers_as()) { + for (const auto& particleMotherOfPos : posMCDaughterTrack.mothers_as()) { + if (particleMotherOfNeg == particleMotherOfPos) { + pdgParentv0 = particleMotherOfNeg.pdgCode(); + isPhysPrim = particleMotherOfNeg.isPhysicalPrimary(); + } + } + } + if (pdgParentv0 != 310 || !isPhysPrim) + continue; + + // Cut on V0 dynamic columns + if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) + continue; + + TLorentzVector recK0S; + recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); + + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) + continue; + + int ipTBinK0S = 0; + for (int i = 0; i < nPtBinK0S; i++) { + if (pTBinK0S[i] < recK0S.Pt() && recK0S.Pt() <= pTBinK0S[i + 1]) { + ipTBinK0S = i; + break; + } + } + + if (!isCountedK0SInclusive[ipTBinK0S]) { + PhieffHist.fill(HIST("h3PhieffK0SInvMassInclusive"), genmultiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SInclusive[ipTBinK0S] = true; + } + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (!isCountedK0SFirstCut[ipTBinK0S]) { + PhieffHist.fill(HIST("h3PhieffK0SInvMassFirstCut"), genmultiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SFirstCut[ipTBinK0S] = true; + } + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (!isCountedK0SSecondCut[ipTBinK0S]) { + PhieffHist.fill(HIST("h3PhieffK0SInvMassSecondCut"), genmultiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SSecondCut[ipTBinK0S] = true; + } + } + + bool isCountedPiInclusive[nPtBinPi] = {false}, isCountedPiFirstCut[nPtBinPi] = {false}, isCountedPiSecondCut[nPtBinPi] = {false}; + + // Loop over all primary pion candidates + for (const auto& track : fullMCTracks) { + if (!track.has_mcParticle()) + continue; + + auto MCtrack = track.mcParticle_as(); + if (std::abs(MCtrack.pdgCode()) != 211 || !MCtrack.isPhysicalPrimary()) + continue; + + if (!selectionPion(track)) + continue; + + TLorentzVector recPi; + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); + + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) + continue; + + int ipTBinPi = 0; + for (int i = 0; i < nPtBinPi; i++) { + if (pTBinPi[i] < recPi.Pt() && recPi.Pt() <= pTBinPi[i + 1]) { + ipTBinPi = i; + break; + } + } + + if (!isCountedPiInclusive[ipTBinPi]) { + PhieffHist.fill(HIST("h3PhieffPiInvMassInclusive"), genmultiplicity, recPi.Pt(), recPhi.M()); + isCountedPiInclusive[ipTBinPi] = true; + } + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (!isCountedPiFirstCut[ipTBinPi]) { + PhieffHist.fill(HIST("h3PhieffPiInvMassFirstCut"), genmultiplicity, recPi.Pt(), recPhi.M()); + isCountedPiFirstCut[ipTBinPi] = true; + } + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (!isCountedPiSecondCut[ipTBinPi]) { + PhieffHist.fill(HIST("h3PhieffPiInvMassSecondCut"), genmultiplicity, recPi.Pt(), recPhi.M()); + isCountedPiSecondCut[ipTBinPi] = true; + } + } + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processRecMCPhiQA, "Process for ReCMCQA and Phi in RecMC", false); + + void processRecMCPhiK0S(SimCollisions::iterator const& collision, FullMCTracks const&, FullV0s const& V0s, V0DauMCTracks const&, MCCollisions const&, aod::McParticles const&) + { + if (!acceptEventQA(collision, false)) + return; + + if (!collision.has_mcCollision()) + return; + + const auto& mcCollision = collision.mcCollision_as(); + float genmultiplicity = mcCollision.centFT0M(); + + int iBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < genmultiplicity && genmultiplicity <= multBin[i + 1]) { + iBin = i; + break; + } + } + + // Defining positive and negative tracks for phi reconstruction + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + // V0 already reconstructed by the builder + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + if (!posDaughterTrack.has_mcParticle() || !negDaughterTrack.has_mcParticle()) + continue; + + auto posMCDaughterTrack = posDaughterTrack.mcParticle_as(); + auto negMCDaughterTrack = negDaughterTrack.mcParticle_as(); + if (posMCDaughterTrack.pdgCode() != 211 || negMCDaughterTrack.pdgCode() != -211) + continue; + if (!posMCDaughterTrack.has_mothers() || !negMCDaughterTrack.has_mothers()) + continue; + + int pdgParentv0 = 0; + bool isPhysPrim = false; + for (const auto& particleMotherOfNeg : negMCDaughterTrack.mothers_as()) { + for (const auto& particleMotherOfPos : posMCDaughterTrack.mothers_as()) { + if (particleMotherOfNeg == particleMotherOfPos) { + pdgParentv0 = particleMotherOfNeg.pdgCode(); + isPhysPrim = particleMotherOfNeg.isPhysicalPrimary(); + } + } + } + if (pdgParentv0 != 310 || !isPhysPrim) + continue; + + if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) + continue; + + TLorentzVector recK0S; + recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) + continue; + + K0SeffHist.fill(HIST("h3K0SeffInvMass"), genmultiplicity, recK0S.Pt(), recK0S.M()); + + std::vector listrecPhi; + int countInclusive = 0, countLtFirstCut = 0, countLtSecondCut = 0; + + bool isCountedPhi = false; + + // Phi reconstruction + for (auto track1 : posThisColl) { // loop over all selected tracks + if (!selectionTrackResonance(track1) || !selectionPIDKaon(track1)) + continue; // topological and PID selection + + auto track1ID = track1.globalIndex(); + + if (!track1.has_mcParticle()) + continue; + + for (auto track2 : negThisColl) { + if (!selectionTrackResonance(track2) || !selectionPIDKaon(track2)) + continue; // topological and PID selection + + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) + continue; // condition to avoid double counting of pair + + if (!track2.has_mcParticle()) + continue; + + auto MCtrack1 = track1.mcParticle_as(); + auto MCtrack2 = track2.mcParticle_as(); + if (MCtrack1.pdgCode() != 321 || MCtrack2.pdgCode() != -321) + continue; + if (!MCtrack1.has_mothers() || !MCtrack2.has_mothers()) + continue; + if (!MCtrack1.isPhysicalPrimary() || !MCtrack2.isPhysicalPrimary()) + continue; + + int pdgParentPhi = 0; + for (const auto& MotherOfMCtrack1 : MCtrack1.mothers_as()) { + for (const auto& MotherOfMCtrack2 : MCtrack2.mothers_as()) { + if (MotherOfMCtrack1 == MotherOfMCtrack2) { + pdgParentPhi = MotherOfMCtrack1.pdgCode(); + } + } + } + + if (pdgParentPhi != 333) + continue; + + TLorentzVector recPhi; + recPhi = recMother(track1, track2, massKa, massKa); + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) + continue; + + listrecPhi.push_back(recPhi); + + if (!isCountedPhi) { + yaccHist.fill(HIST("hyaccK0SRecMC"), genmultiplicity, recK0S.Pt(), recK0S.Rapidity()); + isCountedPhi = true; + } + + if (lowmPhiInc->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiInc->at(iBin)) + countInclusive++; + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (lowmPhiFCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiFCut->at(iBin)) + countLtFirstCut++; + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (lowmPhiSCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiSCut->at(iBin)) + countLtSecondCut++; + } + } + + float weightInclusive, weightLtFirstCut, weightLtSecondCut; + if (countInclusive > 0) { + weightInclusive = 1. / static_cast(countInclusive); + } else { + weightInclusive = 0; + MCeventHist.fill(HIST("thereisnoPhiwK0SMC"), 0); + } + if (countLtFirstCut > 0) { + weightLtFirstCut = 1. / static_cast(countLtFirstCut); + } else { + weightLtFirstCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwK0SMC"), 1); + } + if (countLtSecondCut > 0) { + weightLtSecondCut = 1. / static_cast(countLtSecondCut); + } else { + weightLtSecondCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwK0SMC"), 2); + } + + switch (iBin) { + case 0: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 1: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 2: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 3: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 4: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 5: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 6: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 7: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 8: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 9: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + default: + break; + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processRecMCPhiK0S, "Process RecMC for Phi-K0S Analysis", false); + + void processRecMCPhiPion(SimCollisions::iterator const& collision, FullMCTracks const& fullMCTracks, MCCollisions const&, aod::McParticles const&) + { + if (!acceptEventQA(collision, false)) + return; + + if (!collision.has_mcCollision()) + return; + + const auto& mcCollision = collision.mcCollision_as(); + float genmultiplicity = mcCollision.centFT0M(); + + int iBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < genmultiplicity && genmultiplicity <= multBin[i + 1]) { + iBin = i; + break; + } + } + + // Defining positive and negative tracks for phi reconstruction + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + // Loop over all primary pion candidates + for (const auto& track : fullMCTracks) { + + if (!track.has_mcParticle()) + continue; + + auto MCtrack = track.mcParticle_as(); + if (std::abs(MCtrack.pdgCode()) != 211 || !MCtrack.isPhysicalPrimary()) + continue; + + // Pion selection + if (!selectionPion(track)) + continue; + + TLorentzVector recPi; + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) + continue; + + float nsigmaTPC, nsigmaTOF; + if (track.hasTPC()) + nsigmaTPC = track.tpcNSigmaPi(); + else + nsigmaTPC = -9.99; + if (track.hasTOF()) + nsigmaTOF = track.tofNSigmaPi(); + else + nsigmaTOF = -9.99; + + PioneffHist.fill(HIST("h4PieffInvMass"), genmultiplicity, recPi.Pt(), nsigmaTPC, nsigmaTOF); + + std::vector listrecPhi; + int countInclusive = 0, countLtFirstCut = 0, countLtSecondCut = 0; + + bool isCountedPhi = false; + + // Phi reconstruction + for (auto track1 : posThisColl) { // loop over all selected tracks + if (!selectionTrackResonance(track1) || !selectionPIDKaon(track1)) + continue; // topological and PID selection + + auto track1ID = track1.globalIndex(); + + if (!track1.has_mcParticle()) + continue; + + for (auto track2 : negThisColl) { + if (!selectionTrackResonance(track2) || !selectionPIDKaon(track2)) + continue; // topological and PID selection + + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) + continue; // condition to avoid double counting of pair + + if (!track2.has_mcParticle()) + continue; + + auto MCtrack1 = track1.mcParticle_as(); + auto MCtrack2 = track2.mcParticle_as(); + if (MCtrack1.pdgCode() != 321 || MCtrack2.pdgCode() != -321) + continue; + if (!MCtrack1.has_mothers() || !MCtrack2.has_mothers()) + continue; + if (!MCtrack1.isPhysicalPrimary() || !MCtrack2.isPhysicalPrimary()) + continue; + + int pdgParentPhi = 0; + for (const auto& MotherOfMCtrack1 : MCtrack1.mothers_as()) { + for (const auto& MotherOfMCtrack2 : MCtrack2.mothers_as()) { + if (MotherOfMCtrack1 == MotherOfMCtrack2) { + pdgParentPhi = MotherOfMCtrack1.pdgCode(); + } + } + } + + if (pdgParentPhi != 333) + continue; + + TLorentzVector recPhi; + recPhi = recMother(track1, track2, massKa, massKa); + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) + continue; + + listrecPhi.push_back(recPhi); + + if (!isCountedPhi) { + yaccHist.fill(HIST("hyaccPiRecMC"), genmultiplicity, recPi.Pt(), recPi.Rapidity()); + isCountedPhi = true; + } + + if (lowmPhiInc->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiInc->at(iBin)) + countInclusive++; + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (lowmPhiFCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiFCut->at(iBin)) + countLtFirstCut++; + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (lowmPhiSCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiSCut->at(iBin)) + countLtSecondCut++; + } + } + + float weightInclusive, weightLtFirstCut, weightLtSecondCut; + if (countInclusive > 0) { + weightInclusive = 1. / static_cast(countInclusive); + } else { + weightInclusive = 0; + MCeventHist.fill(HIST("thereisnoPhiwPiMC"), 0); + } + if (countLtFirstCut > 0) { + weightLtFirstCut = 1. / static_cast(countLtFirstCut); + } else { + weightLtFirstCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwPiMC"), 1); + } + if (countLtSecondCut > 0) { + weightLtSecondCut = 1. / static_cast(countLtSecondCut); + } else { + weightLtSecondCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwPiMC"), 2); + } + + switch (iBin) { + case 0: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 1: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 2: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 3: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 4: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 5: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 6: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 7: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 8: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 9: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + default: + break; + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processRecMCPhiPion, "Process RecMC for Phi-Pion Analysis", false); + + void processRecMCClosurePhiQA(SimCollisions::iterator const& collision, FullMCTracks const& fullMCTracks, FullV0s const& V0s, V0DauMCTracks const&, MCCollisions const&) + { + if (!acceptEventQA(collision, true)) + return; + + if (!collision.has_mcCollision()) + return; + MCeventHist.fill(HIST("hRecMCEventSelection"), 6); // with at least a gen collision + + const auto& mcCollision = collision.mcCollision_as(); + float genmultiplicity = mcCollision.centFT0M(); + MCeventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); + + // Defining positive and negative tracks for phi reconstruction + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + bool isCountedPhi = false; + + for (auto track1 : posThisColl) { // loop over all selected tracks + if (!selectionTrackResonance(track1) || !selectionPIDKaon(track1)) + continue; // topological and PID selection + + auto track1ID = track1.globalIndex(); + + // Loop over all negative candidates + for (auto track2 : negThisColl) { + if (!selectionTrackResonance(track2) || !selectionPIDKaon(track2)) + continue; // topological and PID selection + + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) + continue; // condition to avoid double counting of pair + + TLorentzVector recPhi; + recPhi = recMother(track1, track2, massKa, massKa); + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) + continue; + + if (!isCountedPhi) { + MCeventHist.fill(HIST("hRecMCEventSelection"), 7); // at least a Phi in the event + isCountedPhi = true; + } + + MCPhipurHist.fill(HIST("h2MCPhipurInvMass"), genmultiplicity, recPhi.M()); + + bool isCountedK0SInclusive[nPtBinK0S] = {false}, isCountedK0SFirstCut[nPtBinK0S] = {false}, isCountedK0SSecondCut[nPtBinK0S] = {false}; + + // V0 already reconstructed by the builder + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + + if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) + continue; + + TLorentzVector recK0S; + recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); + + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) + continue; + + int ipTBinK0S = 0; + for (int i = 0; i < nPtBinK0S; i++) { + if (pTBinK0S[i] < recK0S.Pt() && recK0S.Pt() <= pTBinK0S[i + 1]) { + ipTBinK0S = i; + break; + } + } + + if (!isCountedK0SInclusive[ipTBinK0S]) { + MCPhipurHist.fill(HIST("h3MCPhipurK0SInvMassInclusive"), genmultiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SInclusive[ipTBinK0S] = true; + } + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (!isCountedK0SFirstCut[ipTBinK0S]) { + MCPhipurHist.fill(HIST("h3MCPhipurK0SInvMassFirstCut"), genmultiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SFirstCut[ipTBinK0S] = true; + } + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (!isCountedK0SSecondCut[ipTBinK0S]) { + MCPhipurHist.fill(HIST("h3MCPhipurK0SInvMassSecondCut"), genmultiplicity, recK0S.Pt(), recPhi.M()); + isCountedK0SSecondCut[ipTBinK0S] = true; + } + } + + bool isCountedPiInclusive[nPtBinPi] = {false}, isCountedPiFirstCut[nPtBinPi] = {false}, isCountedPiSecondCut[nPtBinPi] = {false}; + + // Loop over all primary pion candidates + for (const auto& track : fullMCTracks) { + + if (!selectionPion(track)) + continue; + + TLorentzVector recPi; + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); + + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) + continue; + + int ipTBinPi = 0; + for (int i = 0; i < nPtBinPi; i++) { + if (pTBinPi[i] < recPi.Pt() && recPi.Pt() <= pTBinPi[i + 1]) { + ipTBinPi = i; + break; + } + } + + if (!isCountedPiInclusive[ipTBinPi]) { + MCPhipurHist.fill(HIST("h3MCPhipurPiInvMassInclusive"), genmultiplicity, recPi.Pt(), recPhi.M()); + isCountedPiInclusive[ipTBinPi] = true; + } + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (!isCountedPiFirstCut[ipTBinPi]) { + MCPhipurHist.fill(HIST("h3MCPhipurPiInvMassFirstCut"), genmultiplicity, recPi.Pt(), recPhi.M()); + isCountedPiFirstCut[ipTBinPi] = true; + } + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (!isCountedPiSecondCut[ipTBinPi]) { + MCPhipurHist.fill(HIST("h3MCPhipurPiInvMassSecondCut"), genmultiplicity, recPi.Pt(), recPhi.M()); + isCountedPiSecondCut[ipTBinPi] = true; + } + } + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processRecMCClosurePhiQA, "Process for ReCMCQA and Phi in RecMCClosure", false); + + void processRecMCClosurePhiK0S(SimCollisions::iterator const& collision, FullMCTracks const&, FullV0s const& V0s, V0DauMCTracks const&, MCCollisions const&) + { + if (!acceptEventQA(collision, false)) + return; + + if (!collision.has_mcCollision()) + return; + + const auto& mcCollision = collision.mcCollision_as(); + float genmultiplicity = mcCollision.centFT0M(); + + int iBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < genmultiplicity && genmultiplicity <= multBin[i + 1]) { + iBin = i; + break; + } + } + + // Defining positive and negative tracks for phi reconstruction + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + // V0 already reconstructed by the builder + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + + if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) + continue; + + TLorentzVector recK0S; + recK0S.SetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); + if (std::abs(recK0S.Rapidity()) > cfgInclusiveDeltay) + continue; + + std::vector listrecPhi; + int countInclusive = 0, countLtFirstCut = 0, countLtSecondCut = 0; + + // Phi reconstruction + for (auto track1 : posThisColl) { // loop over all selected tracks + if (!selectionTrackResonance(track1) || !selectionPIDKaon(track1)) + continue; // topological and PID selection + + auto track1ID = track1.globalIndex(); + + for (auto track2 : negThisColl) { + if (!selectionTrackResonance(track2) || !selectionPIDKaon(track2)) + continue; // topological and PID selection + + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) + continue; // condition to avoid double counting of pair + + TLorentzVector recPhi; + recPhi = recMother(track1, track2, massKa, massKa); + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) + continue; + + listrecPhi.push_back(recPhi); + + if (lowmPhiInc->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiInc->at(iBin)) + countInclusive++; + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (lowmPhiFCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiFCut->at(iBin)) + countLtFirstCut++; + if (std::abs(recK0S.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (lowmPhiSCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiSCut->at(iBin)) + countLtSecondCut++; + } + } + + float weightInclusive, weightLtFirstCut, weightLtSecondCut; + if (countInclusive > 0) { + weightInclusive = 1. / static_cast(countInclusive); + } else { + weightInclusive = 0; + MCeventHist.fill(HIST("thereisnoPhiwK0SMC"), 0); + } + if (countLtFirstCut > 0) { + weightLtFirstCut = 1. / static_cast(countLtFirstCut); + } else { + weightLtFirstCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwK0SMC"), 1); + } + if (countLtSecondCut > 0) { + weightLtSecondCut = 1. / static_cast(countLtSecondCut); + } else { + weightLtSecondCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwK0SMC"), 2); + } + + switch (iBin) { + case 0: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 1: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 2: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 3: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 4: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 5: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 6: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 7: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 8: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 9: { + fillInvMass2D(recK0S, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + default: + break; + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processRecMCClosurePhiK0S, "Process RecMC for MCClosure Phi-K0S Analysis", false); + + void processRecMCClosurePhiPion(SimCollisions::iterator const& collision, FullMCTracks const& fullMCTracks, MCCollisions const&) + { + if (!acceptEventQA(collision, false)) + return; + + if (!collision.has_mcCollision()) + return; + + const auto& mcCollision = collision.mcCollision_as(); + float genmultiplicity = mcCollision.centFT0M(); + + int iBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < genmultiplicity && genmultiplicity <= multBin[i + 1]) { + iBin = i; + break; + } + } + + // Defining positive and negative tracks for phi reconstruction + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + // Loop over all primary pion candidates + for (const auto& track : fullMCTracks) { + + // Pion selection + if (!selectionPion(track)) + continue; + + TLorentzVector recPi; + recPi.SetXYZM(track.px(), track.py(), track.pz(), massPi); + if (std::abs(recPi.Rapidity()) > cfgInclusiveDeltay) + continue; + + float nsigmaTPC, nsigmaTOF; + if (track.hasTPC()) + nsigmaTPC = track.tpcNSigmaPi(); + else + nsigmaTPC = -9.99; + if (track.hasTOF()) + nsigmaTOF = track.tofNSigmaPi(); + else + nsigmaTOF = -9.99; + + std::vector listrecPhi; + int countInclusive = 0, countLtFirstCut = 0, countLtSecondCut = 0; + + // Phi reconstruction + for (auto track1 : posThisColl) { // loop over all selected tracks + if (!selectionTrackResonance(track1) || !selectionPIDKaon(track1)) + continue; // topological and PID selection + + auto track1ID = track1.globalIndex(); + + for (auto track2 : negThisColl) { + if (!selectionTrackResonance(track2) || !selectionPIDKaon(track2)) + continue; // topological and PID selection + + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) + continue; // condition to avoid double counting of pair + + TLorentzVector recPhi; + recPhi = recMother(track1, track2, massKa, massKa); + if (std::abs(recPhi.Rapidity()) > cfgInclusiveDeltay) + continue; + + listrecPhi.push_back(recPhi); + + if (lowmPhiInc->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiInc->at(iBin)) + countInclusive++; + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgFirstCutonDeltay) + continue; + if (lowmPhiFCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiFCut->at(iBin)) + countLtFirstCut++; + if (std::abs(recPi.Rapidity() - recPhi.Rapidity()) > cfgSecondCutonDeltay) + continue; + if (lowmPhiSCut->at(iBin) <= recPhi.M() && recPhi.M() <= upmPhiSCut->at(iBin)) + countLtSecondCut++; + } + } + + float weightInclusive, weightLtFirstCut, weightLtSecondCut; + if (countInclusive > 0) { + weightInclusive = 1. / static_cast(countInclusive); + } else { + weightInclusive = 0; + MCeventHist.fill(HIST("thereisnoPhiwPiMC"), 0); + } + if (countLtFirstCut > 0) { + weightLtFirstCut = 1. / static_cast(countLtFirstCut); + } else { + weightLtFirstCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwPiMC"), 1); + } + if (countLtSecondCut > 0) { + weightLtSecondCut = 1. / static_cast(countLtSecondCut); + } else { + weightLtSecondCut = 0; + MCeventHist.fill(HIST("thereisnoPhiwPiMC"), 2); + } + + switch (iBin) { + case 0: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 1: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 2: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 3: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 4: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 5: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 6: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 7: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 8: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + case 9: { + fillInvMassNSigma(recPi, nsigmaTPC, nsigmaTOF, listrecPhi, genmultiplicity, weightInclusive, weightLtFirstCut, weightLtSecondCut); + break; + } + default: + break; + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processRecMCClosurePhiPion, "Process RecMC for MCClosure Phi-Pion Analysis", false); + + void processGenMCPhiQA(MCCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles) + { + MCeventHist.fill(HIST("hGenMCEventSelection"), 0); // all collisions + if (std::abs(mcCollision.posZ()) > cutzvertex) + return; + MCeventHist.fill(HIST("hGenMCEventSelection"), 1); // vertex-Z selected + MCeventHist.fill(HIST("hGenMCVertexZ"), mcCollision.posZ()); + if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) + return; + MCeventHist.fill(HIST("hGenMCEventSelection"), 2); // INEL>0 collisions + + bool isAssocColl = false; + for (auto collision : collisions) { + if (acceptEventQA(collision, false)) { + isAssocColl = true; + break; + } + } + + float multiplicity = mcCollision.centFT0M(); + MCeventHist.fill(HIST("hGenMCMultiplicityPercent"), multiplicity); + + int imultBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < multiplicity && multiplicity <= multBin[i + 1]) { + imultBin = i; + break; + } + } + + bool isCountedPhi = false; + + for (auto mcParticle1 : mcParticles) { + if (mcParticle1.pdgCode() != 333) + continue; + auto kDaughters = mcParticle1.daughters_as(); + if (kDaughters.size() != 2) + continue; + bool isPosKaon = false, isNegKaon = false; + for (auto kDaughter : kDaughters) { + if (kDaughter.pdgCode() == 321) + isPosKaon = true; + if (kDaughter.pdgCode() == -321) + isNegKaon = true; + } + if (!isPosKaon || !isNegKaon) + continue; + if (std::abs(mcParticle1.y()) > cfgInclusiveDeltay) + continue; + + if (!isCountedPhi) { + MCeventHist.fill(HIST("hGenMCEventSelection"), 3); // at least a Phi in the event + if (isAssocColl) + MCeventHist.fill(HIST("hGenMCEventSelection"), 4); // with at least a reco collision + isCountedPhi = true; + } + + PhieffHist.fill(HIST("h1PhiGenMC"), imultBin); + + bool isCountedK0SInclusive[nPtBinK0S] = {false}, isCountedK0SFirstCut[nPtBinK0S] = {false}, isCountedK0SSecondCut[nPtBinK0S] = {false}; + + for (auto mcParticle2 : mcParticles) { + if (mcParticle2.pdgCode() != 310) + continue; + if (!mcParticle2.isPhysicalPrimary()) + continue; + if (std::abs(mcParticle2.y()) > cfgInclusiveDeltay) + continue; + + int ipTBinK0S = 0; + for (int i = 0; i < nPtBinK0S; i++) { + if (pTBinK0S[i] < mcParticle1.pt() && mcParticle1.pt() <= pTBinK0S[i + 1]) { + ipTBinK0S = i; + break; + } + } + + if (!isCountedK0SInclusive[ipTBinK0S]) { + PhieffHist.fill(HIST("h2PhieffK0SGenMCInclusive"), imultBin, ipTBinK0S); + if (isAssocColl) + PhieffHist.fill(HIST("h2PhieffK0SGenMCFirstCutAssocReco"), imultBin, ipTBinK0S); + isCountedK0SInclusive[ipTBinK0S] = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgFirstCutonDeltay) + continue; + if (!isCountedK0SFirstCut[ipTBinK0S]) { + PhieffHist.fill(HIST("h2PhieffK0SGenMCFirstCut"), imultBin, ipTBinK0S); + if (isAssocColl) + PhieffHist.fill(HIST("h2PhieffK0SGenMCFirstCutAssocReco"), imultBin, ipTBinK0S); + isCountedK0SFirstCut[ipTBinK0S] = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgSecondCutonDeltay) + continue; + if (!isCountedK0SSecondCut[ipTBinK0S]) { + PhieffHist.fill(HIST("h2PhieffK0SGenMCSecondCut"), imultBin, ipTBinK0S); + if (isAssocColl) + PhieffHist.fill(HIST("h2PhieffK0SGenMCSecondCutAssocReco"), imultBin, ipTBinK0S); + isCountedK0SSecondCut[ipTBinK0S] = true; + } + } + + bool isCountedPiInclusive[nPtBinPi] = {false}, isCountedPiFirstCut[nPtBinPi] = {false}, isCountedPiSecondCut[nPtBinPi] = {false}; + + for (auto mcParticle2 : mcParticles) { + if (std::abs(mcParticle2.pdgCode()) != 211) + continue; + if (!mcParticle2.isPhysicalPrimary()) + continue; + if (std::abs(mcParticle2.y()) > cfgInclusiveDeltay) + continue; + + int ipTBinPi = 0; + for (int i = 0; i < nPtBinPi; i++) { + if (pTBinPi[i] < mcParticle1.pt() && mcParticle1.pt() <= pTBinPi[i + 1]) { + ipTBinPi = i; + break; + } + } + + if (!isCountedPiInclusive[ipTBinPi]) { + PhieffHist.fill(HIST("h2PhieffPiGenMCInclusive"), imultBin, ipTBinPi); + if (isAssocColl) + PhieffHist.fill(HIST("h2PhieffPiGenMCInclusiveAssocReco"), imultBin, ipTBinPi); + isCountedPiInclusive[ipTBinPi] = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgFirstCutonDeltay) + continue; + if (!isCountedPiFirstCut[ipTBinPi]) { + PhieffHist.fill(HIST("h2PhieffPiGenMCFirstCut"), imultBin, ipTBinPi); + if (isAssocColl) + PhieffHist.fill(HIST("h2PhieffPiGenMCFirstCutAssocReco"), imultBin, ipTBinPi); + isCountedPiFirstCut[ipTBinPi] = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgSecondCutonDeltay) + continue; + if (!isCountedPiSecondCut[ipTBinPi]) { + PhieffHist.fill(HIST("h2PhieffPiGenMCSecondCut"), imultBin, ipTBinPi); + if (isAssocColl) + PhieffHist.fill(HIST("h2PhieffPiGenMCSecondCutAssocReco"), imultBin, ipTBinPi); + isCountedPiSecondCut[ipTBinPi] = true; + } + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processGenMCPhiQA, "Process for ReCMCQA and Phi in RecMC", false); + + void processGenMCPhiK0S(MCCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles) + { + if (std::abs(mcCollision.posZ()) > cutzvertex) + return; + if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) + return; + + bool isAssocColl = false; + for (auto collision : collisions) { + if (acceptEventQA(collision, false)) { + isAssocColl = true; + break; + } + } + + float multiplicity = mcCollision.centFT0M(); + MCeventHist.fill(HIST("hGenMCMultiplicityPercent"), multiplicity); + + int imultBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < multiplicity && multiplicity <= multBin[i + 1]) { + imultBin = i; + break; + } + } + + for (auto mcParticle1 : mcParticles) { + if (mcParticle1.pdgCode() != 310) + continue; + if (!mcParticle1.isPhysicalPrimary()) + continue; + if (std::abs(mcParticle1.y()) > cfgInclusiveDeltay) + continue; + + int ipTBin = 0; + for (int i = 0; i < nPtBinK0S; i++) { + if (pTBinK0S[i] < mcParticle1.pt() && mcParticle1.pt() <= pTBinK0S[i + 1]) { + ipTBin = i; + break; + } + } + + K0SeffHist.fill(HIST("h2K0SGenMC"), imultBin, ipTBin); + + bool isCountedPhi = false; + + bool isCountedPhiInclusive = false, isCountedPhiFirstCut = false, isCountedPhiSecondCut = false; + + for (auto mcParticle2 : mcParticles) { + if (mcParticle2.pdgCode() != 333) + continue; + auto kDaughters = mcParticle2.daughters_as(); + if (kDaughters.size() != 2) + continue; + bool isPosKaon = false, isNegKaon = false; + for (auto kDaughter : kDaughters) { + if (kDaughter.pdgCode() == 321) + isPosKaon = true; + if (kDaughter.pdgCode() == -321) + isNegKaon = true; + } + if (!isPosKaon || !isNegKaon) + continue; + if (std::abs(mcParticle2.y()) > cfgInclusiveDeltay) + continue; + + if (!isCountedPhi) { + yaccHist.fill(HIST("hyaccK0SGenMC"), multiplicity, mcParticle1.pt(), mcParticle1.y()); + isCountedPhi = true; + } + + if (!isCountedPhiInclusive) { + MCPhiK0SHist.fill(HIST("h2PhiK0SGenMCInclusive"), imultBin, ipTBin); + if (isAssocColl) + MCPhiK0SHist.fill(HIST("h2PhiK0SGenMCInclusiveAssocReco"), imultBin, ipTBin); + isCountedPhiInclusive = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgFirstCutonDeltay) + continue; + if (!isCountedPhiFirstCut) { + MCPhiK0SHist.fill(HIST("h2PhiK0SGenMCFirstCut"), imultBin, ipTBin); + if (isAssocColl) + MCPhiK0SHist.fill(HIST("h2PhiK0SGenMCFirstCutAssocReco"), imultBin, ipTBin); + isCountedPhiFirstCut = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgSecondCutonDeltay) + continue; + if (!isCountedPhiSecondCut) { + MCPhiK0SHist.fill(HIST("h2PhiK0SGenMCSecondCut"), imultBin, ipTBin); + if (isAssocColl) + MCPhiK0SHist.fill(HIST("h2PhiK0SGenMCSecondCutAssocReco"), imultBin, ipTBin); + isCountedPhiSecondCut = true; + } + } + } + } + + PROCESS_SWITCH(phik0shortanalysis, processGenMCPhiK0S, "Process GenMC for Phi-K0S Analysis", false); + + void processGenMCPhiPion(MCCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles) + { + if (std::abs(mcCollision.posZ()) > cutzvertex) + return; + if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) + return; + + bool isAssocColl = false; + for (auto collision : collisions) { + if (acceptEventQA(collision, false)) { + isAssocColl = true; + break; + } + } + + float multiplicity = mcCollision.centFT0M(); + MCeventHist.fill(HIST("hGenMCMultiplicityPercent"), multiplicity); + + int imultBin = 0; + for (int i = 0; i < nMultBin; i++) { + if (multBin[i] < multiplicity && multiplicity <= multBin[i + 1]) { + imultBin = i; + break; + } + } + + for (auto mcParticle1 : mcParticles) { + if (std::abs(mcParticle1.pdgCode()) != 211) + continue; + if (!mcParticle1.isPhysicalPrimary()) + continue; + if (std::abs(mcParticle1.y()) > cfgInclusiveDeltay) + continue; + + int ipTBin = 0; + for (int i = 0; i < nPtBinPi; i++) { + if (pTBinPi[i] < mcParticle1.pt() && mcParticle1.pt() <= pTBinPi[i + 1]) { + ipTBin = i; + break; + } + } + + PioneffHist.fill(HIST("h2PiGenMC"), imultBin, ipTBin); + + bool isCountedPhi = false; + + bool isCountedPhiInclusive = false, isCountedPhiFirstCut = false, isCountedPhiSecondCut = false; + + for (auto mcParticle2 : mcParticles) { + if (mcParticle2.pdgCode() != 333) + continue; + auto kDaughters = mcParticle2.daughters_as(); + if (kDaughters.size() != 2) + continue; + bool isPosKaon = false, isNegKaon = false; + for (auto kDaughter : kDaughters) { + if (kDaughter.pdgCode() == 321) + isPosKaon = true; + if (kDaughter.pdgCode() == -321) + isNegKaon = true; + } + if (!isPosKaon || !isNegKaon) + continue; + if (std::abs(mcParticle2.y()) > cfgInclusiveDeltay) + continue; + + if (!isCountedPhi) { + yaccHist.fill(HIST("hyaccPiGenMC"), multiplicity, mcParticle1.pt(), mcParticle1.y()); + isCountedPhi = true; + } + + if (!isCountedPhiInclusive) { + MCPhiPionHist.fill(HIST("h2PhiPiGenMCInclusive"), imultBin, ipTBin); + if (isAssocColl) + MCPhiPionHist.fill(HIST("h2PhiPiGenMCInclusiveAssocReco"), imultBin, ipTBin); + isCountedPhiInclusive = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgFirstCutonDeltay) + continue; + if (!isCountedPhiFirstCut) { + MCPhiPionHist.fill(HIST("h2PhiPiGenMCFirstCut"), imultBin, ipTBin); + if (isAssocColl) + MCPhiPionHist.fill(HIST("h2PhiPiGenMCFirstCutAssocReco"), imultBin, ipTBin); + isCountedPhiFirstCut = true; + } + if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgSecondCutonDeltay) + continue; + if (!isCountedPhiSecondCut) { + MCPhiPionHist.fill(HIST("h2PhiPiGenMCSecondCut"), imultBin, ipTBin); + if (isAssocColl) + MCPhiPionHist.fill(HIST("h2PhiPiGenMCSecondCutAssocReco"), imultBin, ipTBin); + isCountedPhiSecondCut = true; + } } } } - PROCESS_SWITCH(phik0shortanalysis, processMEPhiPion, "Process Mixed Event for Analysis Phi-Pion", false); + PROCESS_SWITCH(phik0shortanalysis, processGenMCPhiPion, "Process GenMC for Phi-Pion Analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx b/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx index 15fc879797c..c214dc8d75a 100644 --- a/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx +++ b/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx @@ -67,9 +67,19 @@ struct strangeness_in_jets { true, true}; + // QC Histograms + HistogramRegistry registryQC{ + "registryQC", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // Global Parameters Configurable particle_of_interest{"particle_of_interest", 0, "0=v0, 1=cascade, 2=pions"}; Configurable ptLeadingMin{"ptLeadingMin", 5.0f, "pt leading min"}; + Configurable ptJetMin{"ptJetMin", 5.0f, "Minimum pt of the jet"}; + Configurable nPartInJetMin{"nPartInJetMin", 2, "Minimum number of particles inside jet"}; Configurable Rjet{"Rjet", 0.3f, "jet resolution parameter R"}; Configurable Rmax{"Rmax", 0.3f, "radius of the jet and UE cones"}; Configurable zVtx{"zVtx", 10.0f, "z vertex cut"}; @@ -125,6 +135,7 @@ struct strangeness_in_jets { // Event Counters registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "Event Cuts"}}); registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "Event Cuts"}}); + registryQC.add("deltaPt_leading", "deltaPt leading part", HistType::kTH1F, {{1000, -0.1, 0.1, "#Delta p_{T}"}}); // Multiplicity Binning std::vector multBinning = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; @@ -229,25 +240,23 @@ struct strangeness_in_jets { { if (!track.hasITS()) return false; - if (track.itsNCls() < 2) + if (track.itsNCls() < 3) return false; if (!track.hasTPC()) return false; - if (track.tpcNClsFound() < 70) - return false; if (track.tpcNClsCrossedRows() < 70) return false; if (track.tpcChi2NCl() > 4) return false; if (track.itsChi2NCl() > 36) return false; - if (abs(track.eta()) > 0.8) + if (track.eta() < -0.8 || track.eta() > 0.8) return false; - if (track.pt() < 0.15) + if (track.pt() < 0.1) return false; - if (TMath::Abs(track.dcaXY()) > 0.5) + if (TMath::Abs(track.dcaXY()) > (0.0105 * 0.035 / TMath::Power(track.pt(), 1.1))) return false; - if (TMath::Abs(track.dcaZ()) > 0.5) + if (TMath::Abs(track.dcaZ()) > 2.0) return false; return true; } @@ -774,7 +783,7 @@ struct strangeness_in_jets { return; } - void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, aod::V0sLinked const& V0linked, FullTracks const& tracks) + void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, FullTracks const& tracks) { registryData.fill(HIST("number_of_events_data"), 0.5); if (!collision.sel8()) @@ -788,6 +797,7 @@ struct strangeness_in_jets { // Find Leading Particle std::vector particle_ID; + std::vector particle_ID_copy; int leading_ID(0); float ptMax(0); @@ -804,19 +814,25 @@ struct strangeness_in_jets { ptMax = track.pt(); } particle_ID.push_back(i); + particle_ID_copy.push_back(i); } + // Reject events with ptLeading lower than threshold if (ptMax < ptLeadingMin) return; registryData.fill(HIST("number_of_events_data"), 3.5); + // Momentum of the Leading Particle auto const& leading_track = tracks.iteratorAt(leading_ID); - TVector3 p_leading(leading_track.px(), leading_track.py(), leading_track.pz()); - int nParticles = static_cast(particle_ID.size()); + TVector3 p_jet(leading_track.px(), leading_track.py(), leading_track.pz()); // Jet Finder int exit(0); int nPartAssociated(0); + int nParticles = static_cast(particle_ID.size()); + std::vector jet_particle_ID; + jet_particle_ID.push_back(leading_ID); + do { // Initialization float distance_jet_min(1e+08); @@ -835,12 +851,12 @@ struct strangeness_in_jets { TVector3 p_particle(stored_track.px(), stored_track.py(), stored_track.pz()); // Variables - float one_over_pt2_part = 1.0 / (p_particle.Pt() * p_particle.Pt()); - float one_over_pt2_lead = 1.0 / (p_leading.Pt() * p_leading.Pt()); - float deltaEta = p_particle.Eta() - p_leading.Eta(); - float deltaPhi = GetDeltaPhi(p_particle.Phi(), p_leading.Phi()); - float min = Minimum(one_over_pt2_part, one_over_pt2_lead); - float Delta2 = deltaEta * deltaEta + deltaPhi * deltaPhi; + double one_over_pt2_part = 1.0 / (p_particle.Pt() * p_particle.Pt()); + double one_over_pt2_lead = 1.0 / (p_jet.Pt() * p_jet.Pt()); + double deltaEta = p_particle.Eta() - p_jet.Eta(); + double deltaPhi = GetDeltaPhi(p_particle.Phi(), p_jet.Phi()); + double min = Minimum(one_over_pt2_part, one_over_pt2_lead); + double Delta2 = deltaEta * deltaEta + deltaPhi * deltaPhi; // Distances float distance_jet = min * Delta2 / (Rjet * Rjet); @@ -862,12 +878,12 @@ struct strangeness_in_jets { if (distance_jet_min <= distance_bkg_min) { // Add Particle to Jet - // jet_particle_ID.push_back(label_jet_particle); + jet_particle_ID.push_back(label_jet_particle); // Update Momentum of Leading Particle auto jet_track = tracks.iteratorAt(label_jet_particle); TVector3 p_i(jet_track.px(), jet_track.py(), jet_track.pz()); - p_leading = p_leading + p_i; + p_jet = p_jet + p_i; // Remove Element particle_ID[i_jet_particle] = -1; @@ -881,19 +897,16 @@ struct strangeness_in_jets { } while (exit == 0); - // Jet Axis - TVector3 jet_axis(p_leading.X(), p_leading.Y(), p_leading.Z()); - // Cut events with jet not fully inside acceptance - if ((abs(jet_axis.Eta()) + Rmax) > etaMax) + if ((abs(p_jet.Eta()) + Rmax) > etaMax) return; registryData.fill(HIST("number_of_events_data"), 4.5); // Perpendicular Cones for UE TVector3 ue_axis1(0.0, 0.0, 0.0); TVector3 ue_axis2(0.0, 0.0, 0.0); - get_perpendicular_axis(jet_axis, ue_axis1, +1.0); - get_perpendicular_axis(jet_axis, ue_axis2, -1.0); + get_perpendicular_axis(p_jet, ue_axis1, +1.0); + get_perpendicular_axis(p_jet, ue_axis2, -1.0); // Protection against delta<0 if (ue_axis1.X() == 0 && ue_axis1.Y() == 0 && ue_axis1.Z() == 0) @@ -902,6 +915,46 @@ struct strangeness_in_jets { return; registryData.fill(HIST("number_of_events_data"), 5.5); + // Loop over particles + double nChJetPlusUE(0); + double ptJetPlusUE(0); + double ptUE(0); + double ptJet(0); + + for (int i = 0; i < nParticles; i++) { + + auto track = tracks.iteratorAt(particle_ID_copy[i]); + TVector3 particle_dir(track.px(), track.py(), track.pz()); + double deltaEta_jet = particle_dir.Eta() - p_jet.Eta(); + double deltaPhi_jet = GetDeltaPhi(particle_dir.Phi(), p_jet.Phi()); + double deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); + double deltaEta_ue1 = particle_dir.Eta() - ue_axis1.Eta(); + double deltaPhi_ue1 = GetDeltaPhi(particle_dir.Phi(), ue_axis1.Phi()); + double deltaR_ue1 = sqrt(deltaEta_ue1 * deltaEta_ue1 + deltaPhi_ue1 * deltaPhi_ue1); + double deltaEta_ue2 = particle_dir.Eta() - ue_axis2.Eta(); + double deltaPhi_ue2 = GetDeltaPhi(particle_dir.Phi(), ue_axis2.Phi()); + double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); + + if (deltaR_jet < Rmax) { + nChJetPlusUE++; + ptJetPlusUE = ptJetPlusUE + track.pt(); + } + if (deltaR_ue1 < Rmax || deltaR_ue2 < Rmax) { + ptUE = ptUE + track.pt(); + } + } + ptJet = ptJetPlusUE - 0.5 * ptUE; + + // Event Counter: Skip Events with n. particles in jet less than given value + if (nChJetPlusUE < nPartInJetMin) + return; + registryData.fill(HIST("number_of_events_data"), 6.5); + + // Event Counter: Skip Events with Jet Pt lower than threshold + if (ptJet < ptJetMin) + return; + registryData.fill(HIST("number_of_events_data"), 7.5); + // Event multiplicity float multiplicity = collision.centFT0M(); @@ -913,8 +966,8 @@ struct strangeness_in_jets { const auto& neg = v0.negTrack_as(); TVector3 v0dir(v0.px(), v0.py(), v0.pz()); - float deltaEta_jet = v0dir.Eta() - jet_axis.Eta(); - float deltaPhi_jet = GetDeltaPhi(v0dir.Phi(), jet_axis.Phi()); + float deltaEta_jet = v0dir.Eta() - p_jet.Eta(); + float deltaPhi_jet = GetDeltaPhi(v0dir.Phi(), p_jet.Phi()); float deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); float deltaEta_ue1 = v0dir.Eta() - ue_axis1.Eta(); float deltaPhi_ue1 = GetDeltaPhi(v0dir.Phi(), ue_axis1.Phi()); @@ -962,8 +1015,8 @@ struct strangeness_in_jets { auto neg = casc.negTrack_as(); TVector3 cascade_dir(casc.px(), casc.py(), casc.pz()); - float deltaEta_jet = cascade_dir.Eta() - jet_axis.Eta(); - float deltaPhi_jet = GetDeltaPhi(cascade_dir.Phi(), jet_axis.Phi()); + float deltaEta_jet = cascade_dir.Eta() - p_jet.Eta(); + float deltaPhi_jet = GetDeltaPhi(cascade_dir.Phi(), p_jet.Phi()); float deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); float deltaEta_ue1 = cascade_dir.Eta() - ue_axis1.Eta(); float deltaPhi_ue1 = GetDeltaPhi(cascade_dir.Phi(), ue_axis1.Phi()); @@ -1019,8 +1072,8 @@ struct strangeness_in_jets { continue; TVector3 track_dir(track.px(), track.py(), track.pz()); - float deltaEta_jet = track_dir.Eta() - jet_axis.Eta(); - float deltaPhi_jet = GetDeltaPhi(track_dir.Phi(), jet_axis.Phi()); + float deltaEta_jet = track_dir.Eta() - p_jet.Eta(); + float deltaPhi_jet = GetDeltaPhi(track_dir.Phi(), p_jet.Phi()); float deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); float deltaEta_ue1 = track_dir.Eta() - ue_axis1.Eta(); float deltaPhi_ue1 = GetDeltaPhi(track_dir.Phi(), ue_axis1.Phi()); @@ -1094,7 +1147,7 @@ struct strangeness_in_jets { Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; Preslice perCollisionTrk = o2::aod::track::collisionId; - void processMCefficiency(SimCollisions const& collisions, MCTracks const& mcTracks, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, aod::McCollisions const& mcCollisions, const aod::McParticles& mcParticles) + void processMCefficiency(SimCollisions const& collisions, MCTracks const& mcTracks, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, const aod::McParticles& mcParticles) { for (const auto& collision : collisions) { registryMC.fill(HIST("number_of_events_mc"), 0.5); @@ -1346,13 +1399,14 @@ struct strangeness_in_jets { auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); std::vector particle_ID; - int leading_ID = 0; + int leading_ID(0); float pt_max(0); + int i = -1; for (auto& particle : mcParticles_per_coll) { - // Global Index - int i = particle.globalIndex(); + // Particle Index + i++; // Select Primary Particles float deltaX = particle.vx() - collision.posX(); @@ -1394,6 +1448,7 @@ struct strangeness_in_jets { // Momentum of the Leading Particle auto const& leading_track = mcParticles_per_coll.iteratorAt(leading_ID); TVector3 p_leading(leading_track.px(), leading_track.py(), leading_track.pz()); + registryQC.fill(HIST("deltaPt_leading"), pt_max - leading_track.pt()); // Labels int exit(0); @@ -1465,16 +1520,16 @@ struct strangeness_in_jets { } while (exit == 0); // Jet Axis - TVector3 jet_axis(p_leading.X(), p_leading.Y(), p_leading.Z()); + TVector3 p_jet(p_leading.X(), p_leading.Y(), p_leading.Z()); - if ((abs(jet_axis.Eta()) + Rmax) > etaMax) + if ((abs(p_jet.Eta()) + Rmax) > etaMax) return; // Perpendicular Cones for UE TVector3 ue_axis1(0.0, 0.0, 0.0); TVector3 ue_axis2(0.0, 0.0, 0.0); - get_perpendicular_axis(jet_axis, ue_axis1, +1.0); - get_perpendicular_axis(jet_axis, ue_axis2, -1.0); + get_perpendicular_axis(p_jet, ue_axis1, +1.0); + get_perpendicular_axis(p_jet, ue_axis2, -1.0); // Protection against delta<0 if (ue_axis1.X() == 0 && ue_axis1.Y() == 0 && ue_axis1.Z() == 0) @@ -1494,8 +1549,8 @@ struct strangeness_in_jets { continue; TVector3 p_particle(particle.px(), particle.py(), particle.pz()); - float deltaEta_jet = p_particle.Eta() - jet_axis.Eta(); - float deltaPhi_jet = GetDeltaPhi(p_particle.Phi(), jet_axis.Phi()); + float deltaEta_jet = p_particle.Eta() - p_jet.Eta(); + float deltaPhi_jet = GetDeltaPhi(p_particle.Phi(), p_jet.Phi()); float deltaR_jet = sqrt(deltaEta_jet * deltaEta_jet + deltaPhi_jet * deltaPhi_jet); float deltaEta_ue1 = p_particle.Eta() - ue_axis1.Eta(); float deltaPhi_ue1 = GetDeltaPhi(p_particle.Phi(), ue_axis1.Phi()); diff --git a/PWGLF/Tasks/Strangeness/v0postprocessing.cxx b/PWGLF/Tasks/Strangeness/v0postprocessing.cxx index 1806c98a352..1844390a3da 100644 --- a/PWGLF/Tasks/Strangeness/v0postprocessing.cxx +++ b/PWGLF/Tasks/Strangeness/v0postprocessing.cxx @@ -66,7 +66,7 @@ struct v0postprocessing { if (isMC) { registry.add("hMassK0Short_MC", ";M_{#pi^{+}#pi^{-}} [GeV/c^{2}]", {HistType::kTH1F, {{200, 0.4f, 0.6f}}}); - registry.add("hMassVsPtK0Short_MC", ";p_{T} [GeV/c];M_{#pi^{+}#pi^{-}} [GeV/c^{2}]", {HistType::kTH2F, {{250, 0.0f, 25.0f}, {200, 0.4f, 0.6f}}}); + registry.add("hMassVsPtK0Short_MC", ";p_{T} [GeV/c];M_{#pi^{+}#pi^{-}} [GeV/c^{2}]", {HistType::kTH3F, {{250, 0.0f, 25.0f}, {200, 0.4f, 0.6f}, {100, 0.f, 100.f}}}); registry.add("hMassLambda_MC", "hMassLambda", {HistType::kTH1F, {{200, 1.016f, 1.216f}}}); registry.add("hMassVsPtLambda_MC", "hMassVsPtLambda", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {200, 1.016f, 1.216f}}}); registry.add("hMassAntiLambda_MC", "hMassAntiLambda", {HistType::kTH1F, {{200, 1.016f, 1.216f}}}); @@ -217,7 +217,7 @@ struct v0postprocessing { (candidate.pdgcode() == 310)) { registry.fill(HIST("hMassK0Short_MC"), candidate.massk0short()); - registry.fill(HIST("hMassVsPtK0Short_MC"), candidate.v0pt(), candidate.massk0short()); + registry.fill(HIST("hMassVsPtK0Short_MC"), candidate.v0pt(), candidate.multft0m(), candidate.massk0short()); registry.fill(HIST("hK0sV0Radius"), candidate.v0radius()); registry.fill(HIST("hK0sCosPA"), candidate.v0cospa()); diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx new file mode 100644 index 00000000000..82c5eceb7e3 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -0,0 +1,331 @@ +// Copyright 2019-2020 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. +/// +/// \brief V0 task for production of invariant mass plots for Optimised Topological Cuts Analysis +/// \author Nikolaos Karatzenis (nikolaos.karatzenis@cern.ch) +/// \author Roman Lietava (roman.lietava@cern.ch) + +/*Description +This task creates 20 histograms that are filled with the V0 invariant mass under the K0, Lambda and Antilambda mass assumption +for different pt ranges (constituting bins), so 3x20=60 plots.The values are inserted as configurable strings for convinience. +Plots of the invariant masses at different stages of the analysis (ex. before and after the V0 cuts are enforced) and some pt distributions. +This analysis includes two processes, one for Real Data and one for MC Data switchable at the end of the code, only run one at a time*/ + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/DataModel/PIDResponse.h" + +// namespace to be used for pt plots and bins +namespace pthistos +{ +std::shared_ptr KaonPt[20]; +static std::vector kaonptbins; +std::shared_ptr LambdaPt[20]; +static std::vector lambdaptbins; +std::shared_ptr AntilambdaPt[20]; +static std::vector antilambdaptbins; +} // namespace pthistos +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct v0ptinvmassplots { + // Histogram Registries + HistogramRegistry rPtAnalysis{"PtAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rKaonshMassPlots_per_PtBin{"KaonshMassPlots_per_PtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambdaMassPlots_per_PtBin{"LambdaMassPlots_per_PtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntilambdaMassPlots_per_PtBin{"AntilambdaMassPlots_per_PtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable Kaonsh Topological Cuts (best cuts determined by v0topologicalcuts task) + Configurable kaonshsetting_dcav0dau{"kaonshsetting_dcav0dau", 100.0, "DCA V0 Daughters"}; + Configurable kaonshsetting_dcapostopv{"kaonshsetting_dcapostopv", 0.05, "DCA Pos To PV"}; + Configurable kaonshsetting_dcanegtopv{"kaonshsetting_dcanegtopv", 0.05, "DCA Neg To PV"}; + Configurable kaonshsetting_cospa{"kaonshsetting_cospa", 0.50, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 + Configurable kaonshsetting_radius{"kaonshsetting_radius", 0.50, "v0radius"}; + + // Configurable Lambda Topological Cuts (best cuts determined by v0topologicalcuts task) + Configurable lambdasetting_dcav0dau{"lambdasetting_dcav0dau", 100.0, "DCA V0 Daughters"}; + Configurable lambdasetting_dcapostopv{"lambdasetting_dcapostopv", 0.05, "DCA Pos To PV"}; + Configurable lambdasetting_dcanegtopv{"lambdasetting_dcanegtopv", 0.05, "DCA Neg To PV"}; + Configurable lambdasetting_cospa{"lambdasetting_cospa", 0.50, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 + Configurable lambdasetting_radius{"lambdasetting_radius", 0.50, "v0radius"}; + + // Configurable Antilambda Topological Cuts (best cuts determined by v0topologicalcuts task) + Configurable antilambdasetting_dcav0dau{"antilambdasetting_dcav0dau", 100.0, "DCA V0 Daughters"}; + Configurable antilambdasetting_dcapostopv{"antilambdasetting_dcapostopv", 0.05, "DCA Pos To PV"}; + Configurable antilambdasetting_dcanegtopv{"antilambdasetting_dcanegtopv", 0.05, "DCA Neg To PV"}; + Configurable antilambdasetting_cospa{"antilambdasetting_cospa", 0.50, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 + Configurable antilambdasetting_radius{"antilambdasetting_radius", 0.50, "v0radius"}; + + // Configurables for Specific V0s analysis + Configurable kzerosh_analysis{"kzerosh_analysis", true, "Enable Kzerosh Pt Analysis"}; + Configurable lambda_analysis{"lambda_analysis", true, "Enable Lambda Pt Analysis"}; + Configurable antilambda_analysis{"antilambda_analysis", true, "Enable Antilambda Pt Analysis"}; + + // Configurable string for Different Pt Bins + Configurable kzeroshsetting_pt_string{"kzerosetting_ptbins", {"0_0,0_15,0_3,0_45,0_6,0_75,0_9,1_05,1_2,1_35,1_5,1_65,1_8,1_95,2_1,2_25,2_4,2_55,2_7,2_85,3_0"}, "Kzero Pt Bin Values"}; + Configurable lambdasetting_pt_string{"lambdasetting_ptbins", {"0_0,0_15,0_3,0_45,0_6,0_75,0_9,1_05,1_2,1_35,1_5,1_65,1_8,1_95,2_1,2_25,2_4,2_55,2_7,2_85,3_0"}, "Lambda Pt Bin Values"}; + Configurable antilambdasetting_pt_string{"antilambdasetting_ptbins", {"0_0,0_15,0_3,0_45,0_6,0_75,0_9,1_05,1_2,1_35,1_5,1_65,1_8,1_95,2_1,2_25,2_4,2_55,2_7,2_85,3_0"}, "Antilambda Pt Bin Values"}; + + void init(InitContext const&) + { + // Axes + AxisSpec K0ShortMassAxis = {nBins, 0.45f, 0.55f, "#it{M} #pi^{+}#pi^{-} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {nBins, 1.085f, 1.145f, "#it{M} p^{+}#pi^{-} [GeV/#it{c}^{2}]"}; + AxisSpec AntiLambdaMassAxis = {nBins, 1.085f, 1.145f, "#it{M} p^{-}#pi^{+} [GeV/#it{c}^{2}]"}; + AxisSpec ptAxis = {nBins, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + + rPtAnalysis.add("hV0PtAll", "hV0PtAll", {HistType::kTH1F, {{nBins, 0.0f, 10.0f}}}); + + // setting strings from configurable strings in order to manipulate them + size_t commapos = 0; + std::string token1; + // Adding Kzerosh Histograms to registry + if (kzerosh_analysis == true) { + // getting the bin values for the names of the plots for the five topological cuts + std::string kzeroshsetting_ptbins = kzeroshsetting_pt_string; + for (int i = 0; i < 21; i++) { // we have 21 pt values (for the 20 histos) as they are the ranges + commapos = kzeroshsetting_ptbins.find(","); // find comma that separates the values in the string + token1 = kzeroshsetting_ptbins.substr(0, commapos); // store the substring (first individual value) + pthistos::kaonptbins.push_back(token1); // fill the namespace with the value + kzeroshsetting_ptbins.erase(0, commapos + 1); // erase the value from the set string so it moves to the next + } + rPtAnalysis.add("hK0ShortReconstructedPtSpectrum", "hK0ShortReconstructedPtSpectrum", {HistType::kTH1F, {ptAxis}}); + rPtAnalysis.add("hMassK0ShortAll", "hMassK0ShortAll", {HistType::kTH1F, {K0ShortMassAxis}}); + rPtAnalysis.add("hK0ShortPtSpectrumBeforeCuts", "hK0ShortPtSpectrumBeforeCuts", {HistType::kTH1F, {ptAxis}}); + rPtAnalysis.add("hMassK0ShortAllAfterCuts", "hMassK0ShortAllAfterCuts", {HistType::kTH1F, {K0ShortMassAxis}}); + for (int i = 0; i < 20; i++) { + pthistos::KaonPt[i] = rKaonshMassPlots_per_PtBin.add(fmt::format("hPt_from_{0}_to_{1}", pthistos::kaonptbins[i], pthistos::kaonptbins[i + 1]).data(), fmt::format("hPt from {0} to {1}", pthistos::kaonptbins[i], pthistos::kaonptbins[i + 1]).data(), {HistType::kTH1D, {{K0ShortMassAxis}}}); + } + } + // Adding Lambda Histograms + if (lambda_analysis == true) { + // same method as in Kzerosh above + std::string lambdasetting_ptbins = lambdasetting_pt_string; + for (int i = 0; i < 21; i++) { + commapos = lambdasetting_ptbins.find(","); + token1 = lambdasetting_ptbins.substr(0, commapos); + pthistos::lambdaptbins.push_back(token1); + lambdasetting_ptbins.erase(0, commapos + 1); + } + rPtAnalysis.add("hLambdaReconstructedPtSpectrum", "hLambdaReconstructedPtSpectrum", {HistType::kTH1F, {ptAxis}}); + rPtAnalysis.add("hMassLambdaAll", "hMassLambdaAll", {HistType::kTH1F, {LambdaMassAxis}}); + rPtAnalysis.add("hLambdaPtSpectrumBeforeCuts", "hLambdaPtSpectrumBeforeCuts", {HistType::kTH1F, {ptAxis}}); + rPtAnalysis.add("hMassLambdaAllAfterCuts", "hMassLambdaAllAfterCuts", {HistType::kTH1F, {LambdaMassAxis}}); + for (int i = 0; i < 20; i++) { + pthistos::LambdaPt[i] = rLambdaMassPlots_per_PtBin.add(fmt::format("hPt_from_{0}_to_{1}", pthistos::lambdaptbins[i], pthistos::lambdaptbins[i + 1]).data(), fmt::format("hPt from {0} to {1}", pthistos::lambdaptbins[i], pthistos::lambdaptbins[i + 1]).data(), {HistType::kTH1D, {{LambdaMassAxis}}}); + } + } + // Adding Antilambda Histograms + if (antilambda_analysis == true) { + // same method as in Lambda and Kzerosh above + std::string antilambdasetting_ptbins = antilambdasetting_pt_string; + for (int i = 0; i < 21; i++) { + commapos = antilambdasetting_ptbins.find(","); + token1 = antilambdasetting_ptbins.substr(0, commapos); + pthistos::antilambdaptbins.push_back(token1); + antilambdasetting_ptbins.erase(0, commapos + 1); + } + rPtAnalysis.add("hAntilambdaReconstructedPtSpectrum", "hAntilambdaReconstructedPtSpectrum", {HistType::kTH1F, {ptAxis}}); + rPtAnalysis.add("hMassAntilambdaAll", "hMassAntilambdaAll", {HistType::kTH1F, {AntiLambdaMassAxis}}); + rPtAnalysis.add("hAntilambdaPtSpectrumBeforeCuts", "hAntilambdaPtSpectrumBeforeCuts", {HistType::kTH1F, {ptAxis}}); + rPtAnalysis.add("hMassAntilambdaAllAfterCuts", "hMassAntilambdaAllAfterCuts", {HistType::kTH1F, {AntiLambdaMassAxis}}); + for (int i = 0; i < 20; i++) { + pthistos::AntilambdaPt[i] = rAntilambdaMassPlots_per_PtBin.add(fmt::format("hPt_from_{0}_to_{1}", pthistos::antilambdaptbins[i], pthistos::antilambdaptbins[i + 1]).data(), fmt::format("hPt from {0} to {1}", pthistos::antilambdaptbins[i], pthistos::antilambdaptbins[i + 1]).data(), {HistType::kTH1D, {{AntiLambdaMassAxis}}}); + } + } + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + + // Defining the type of the daughter tracks + using DaughterTracks = soa::Join; + + // This is the Process for the MC reconstructed Data + void RecMCprocess(soa::Filtered>::iterator const&, + soa::Join const& V0s, + DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly + aod::McParticles const&) + { + for (const auto& v0 : V0s) { + rPtAnalysis.fill(HIST("hV0PtAll"), v0.pt()); + // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) + if (v0.has_mcParticle()) { + auto v0mcParticle = v0.mcParticle(); + if (kzerosh_analysis == true) { + if (v0mcParticle.pdgCode() == 310) { // kzero matched + rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0ShortPtSpectrumBeforeCuts"), v0.pt()); + // Implementing best kzero cuts + if (v0.v0cosPA() > kaonshsetting_cospa && v0.dcaV0daughters() < kaonshsetting_dcav0dau && v0.v0radius() > kaonshsetting_radius && TMath::Abs(v0.dcapostopv()) > kaonshsetting_dcapostopv && TMath::Abs(v0.dcanegtopv()) > kaonshsetting_dcanegtopv) { + rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0ShortReconstructedPtSpectrum"), v0.pt()); + for (int i = 0; i < 20; i++) { + // getting the pt value in #_# for and converting it to a number #.# for use, we get two values which correspond to the range of each bin + std::string pt1 = pthistos::kaonptbins[i]; // getting the lower string-value of the bin + std::string pt2 = pthistos::kaonptbins[i + 1]; // getting the higher string-value of the bin + size_t pos1 = pt1.find("_"); // finding the "_" character of the lower string-value + size_t pos2 = pt2.find("_"); // finding the "_" character of the higher string-value + pt1[pos1] = '.'; // changing the "_" character of the lower string-value to a "." + pt2[pos2] = '.'; // changing the "_" character of the higher string-value to a "." + const float ptlowervalue = std::stod(pt1); // converting the lower string value to a double + const float pthighervalue = std::stod(pt2); // converting the higher string value to a double + if (ptlowervalue <= v0.pt() && v0.pt() < pthighervalue) { // finding v0s with pt withing the range of our lower and higher value + pthistos::KaonPt[i]->Fill(v0.mK0Short()); // filling the 20 kaon namespace histograms + } + } + } + } + } + // lambda analysis + if (lambda_analysis == true) { + if (v0mcParticle.pdgCode() == 3122) { // lambda matched + rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaPtSpectrumBeforeCuts"), v0.pt()); + // Implementing best lambda cuts + if (v0.v0cosPA() > lambdasetting_cospa && v0.dcaV0daughters() < lambdasetting_dcav0dau && v0.v0radius() > lambdasetting_radius && TMath::Abs(v0.dcapostopv()) > lambdasetting_dcapostopv && TMath::Abs(v0.dcanegtopv()) > lambdasetting_dcanegtopv) { + rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaReconstructedPtSpectrum"), v0.pt()); + for (int i = 0; i < 20; i++) { + // same as above with kzerosh we fill the 20 lambda namespace histograms within their Pt range + std::string pt1 = pthistos::lambdaptbins[i]; + std::string pt2 = pthistos::lambdaptbins[i + 1]; + size_t pos1 = pt1.find("_"); + size_t pos2 = pt2.find("_"); + pt1[pos1] = '.'; + pt2[pos2] = '.'; + const float ptlowervalue = std::stod(pt1); + const float pthighervalue = std::stod(pt2); + if (ptlowervalue <= v0.pt() && v0.pt() < pthighervalue) { + pthistos::LambdaPt[i]->Fill(v0.mLambda()); + } + } + } + } + } + // antilambda analysis + if (antilambda_analysis == true) { + if (v0mcParticle.pdgCode() == -3122) { // antilambda matched + rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hAntilambdaPtSpectrumBeforeCuts"), v0.pt()); + // Implementing best antilambda cuts + if (v0.v0cosPA() > antilambdasetting_cospa && v0.dcaV0daughters() < antilambdasetting_dcav0dau && v0.v0radius() > antilambdasetting_radius && TMath::Abs(v0.dcapostopv()) > antilambdasetting_dcapostopv && TMath::Abs(v0.dcanegtopv()) > antilambdasetting_dcanegtopv) { + rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hAntilambdaReconstructedPtSpectrum"), v0.pt()); + for (int i = 0; i < 20; i++) { + // same as above with kzerosh and lambda we fill the 20 anti-lambda namespace histograms within their Pt range + std::string pt1 = pthistos::antilambdaptbins[i]; + std::string pt2 = pthistos::antilambdaptbins[i + 1]; + size_t pos1 = pt1.find("_"); + size_t pos2 = pt2.find("_"); + pt1[pos1] = '.'; + pt2[pos2] = '.'; + const float ptlowervalue = std::stod(pt1); + const float pthighervalue = std::stod(pt2); + if (ptlowervalue <= v0.pt() && v0.pt() < pthighervalue) { + pthistos::AntilambdaPt[i]->Fill(v0.mAntiLambda()); + } + } + } + } + } + } + } + } + // This is the process for Real Data + void Dataprocess(soa::Filtered>::iterator const&, + aod::V0Datas const& V0s) + { + for (const auto& v0 : V0s) { + // kzero analysis + if (kzerosh_analysis == true) { + // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); + // Implementing best kzero cuts + if (v0.v0cosPA() > kaonshsetting_cospa && v0.dcaV0daughters() < kaonshsetting_dcav0dau && v0.v0radius() > kaonshsetting_radius && TMath::Abs(v0.dcapostopv()) > kaonshsetting_dcapostopv && TMath::Abs(v0.dcanegtopv()) > kaonshsetting_dcanegtopv) { + rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); + for (int i = 0; i < 20; i++) { // same as above MC-process we fill the namespace histos with the kaon invariant mass of the particle within the pt range of the histo + std::string pt1 = pthistos::kaonptbins[i]; + std::string pt2 = pthistos::kaonptbins[i + 1]; + size_t pos1 = pt1.find("_"); + size_t pos2 = pt2.find("_"); + pt1[pos1] = '.'; + pt2[pos2] = '.'; + const float ptlowervalue = std::stod(pt1); + const float pthighervalue = std::stod(pt2); + if (ptlowervalue < v0.pt() && v0.pt() < pthighervalue) { + pthistos::KaonPt[i]->Fill(v0.mK0Short()); + } + } + } + } + // lambda analysis + if (lambda_analysis == true) { + // Filling the five lambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); + // Implementing best lambda cuts + if (v0.v0cosPA() > lambdasetting_cospa && v0.dcaV0daughters() < lambdasetting_dcav0dau && v0.v0radius() > lambdasetting_radius && TMath::Abs(v0.dcapostopv()) > lambdasetting_dcapostopv && TMath::Abs(v0.dcanegtopv()) > lambdasetting_dcanegtopv) { + rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); + for (int i = 0; i < 20; i++) { // same as above MC-process we fill the namespace histos with the lambda invariant mass of the particle within the pt range of the histo + std::string pt1 = pthistos::lambdaptbins[i]; + std::string pt2 = pthistos::lambdaptbins[i + 1]; + size_t pos1 = pt1.find("_"); + size_t pos2 = pt2.find("_"); + pt1[pos1] = '.'; + pt2[pos2] = '.'; + const float ptlowervalue = std::stod(pt1); + const float pthighervalue = std::stod(pt2); + if (ptlowervalue < v0.pt() && v0.pt() < pthighervalue) { + pthistos::LambdaPt[i]->Fill(v0.mLambda()); + } + } + } + } + // anti-lambda analysis + if (antilambda_analysis == true) { + // Filling the five Antilambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); + // implementing best antilambda cuts + if (v0.v0cosPA() > antilambdasetting_cospa && v0.dcaV0daughters() < antilambdasetting_dcav0dau && v0.v0radius() > antilambdasetting_radius && TMath::Abs(v0.dcapostopv()) > antilambdasetting_dcapostopv && TMath::Abs(v0.dcanegtopv()) > antilambdasetting_dcanegtopv) { + rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); + for (int i = 0; i < 20; i++) { // same as above MC-process we fill the namespace histos with the antilambda invariant mass of the particle within the pt range of the histo + std::string pt1 = pthistos::antilambdaptbins[i]; + std::string pt2 = pthistos::antilambdaptbins[i + 1]; + size_t pos1 = pt1.find("_"); + size_t pos2 = pt2.find("_"); + pt1[pos1] = '.'; + pt2[pos2] = '.'; + const float ptlowervalue = std::stod(pt1); + const float pthighervalue = std::stod(pt2); + if (ptlowervalue < v0.pt() && v0.pt() < pthighervalue) { + pthistos::AntilambdaPt[i]->Fill(v0.mAntiLambda()); + } + } + } + } + } + } + PROCESS_SWITCH(v0ptinvmassplots, RecMCprocess, "Process Run 3 MC:Reconstructed", false); + PROCESS_SWITCH(v0ptinvmassplots, Dataprocess, "Process Run 3 Data,", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Strangeness/v0topologicalcuts.cxx b/PWGLF/Tasks/Strangeness/v0topologicalcuts.cxx new file mode 100644 index 00000000000..246df190f57 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/v0topologicalcuts.cxx @@ -0,0 +1,672 @@ +// Copyright 2019-2020 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. +/// +/// \brief V0 task for production of invariant mass plots for Optimised Topological Cuts Analysis +/// \author Nikolaos Karatzenis (nikolaos.karatzenis@cern.ch) +/// \author Roman Lietava (roman.lietava@cern.ch) + +/*Description +This task creates 20 histograms (for each of the 5 different V0 topological cuts, namely cosPointingAngle, +DCA[between]V0daughters, v0radius,DCA-positive[daughter]to-primary-vertex and DCA-negative[daughter]to-primary-vertex) +that are filled with the V0 invariant mass under the K0, Lambda and Antilambda mass assumption +(so 20cutsx5parametersx3particles=300 mass invariant plots).It also produces plots of the topological parameters themselves. +The cuts are passed as configurable strings for convenience. +This analysis includes two processes, one for Real Data and one for MC Data switchable at the end of the code, only run one at a time*/ + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/DataModel/PIDResponse.h" + +// namespaces to be used for the plot names and topological cuts that will be given by a configurable string +namespace cuthistoskzerosh +{ +std::shared_ptr cospaCut[20]; +static std::vector cospacuts; +std::shared_ptr dcaCut[20]; +static std::vector dcacuts; +std::shared_ptr v0radiusCut[20]; +static std::vector v0radiuscuts; +std::shared_ptr dcapostopCut[20]; +static std::vector dcapostopvcuts; +std::shared_ptr dcanegtopCut[20]; +static std::vector dcanegtopvcuts; +} // namespace cuthistoskzerosh +namespace cuthistoslambda +{ +std::shared_ptr cospaCut[20]; +static std::vector cospacuts; +std::shared_ptr dcaCut[20]; +static std::vector dcacuts; +std::shared_ptr v0radiusCut[20]; +static std::vector v0radiuscuts; +std::shared_ptr dcapostopCut[20]; +static std::vector dcapostopvcuts; +std::shared_ptr dcanegtopCut[20]; +static std::vector dcanegtopvcuts; +} // namespace cuthistoslambda +namespace cuthistosantilambda +{ +std::shared_ptr cospaCut[20]; +static std::vector cospacuts; +std::shared_ptr dcaCut[20]; +static std::vector dcacuts; +std::shared_ptr v0radiusCut[20]; +static std::vector v0radiuscuts; +std::shared_ptr dcapostopCut[20]; +static std::vector dcapostopvcuts; +std::shared_ptr dcanegtopCut[20]; +static std::vector dcanegtopvcuts; +} // namespace cuthistosantilambda +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct v0topologicalcuts { + // Histogram Registry includes different V0 Parameteres for all V0s and individual MC-V0s with MC-matching + HistogramRegistry rV0Parameters_MC_V0match{"V0Parameters_MC_V0Match", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rV0Parameters_MC_K0Smatch{"V0Parameters_MC_K0SMatch", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rV0Parameters_MC_Lambdamatch{"V0Parameters_MC_LambdaMatch", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rV0Parameters_MC_AntiLambdamatch{"V0Parameters_MC_AntiLambdaMatch", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rV0Parameters_Data{"rV0Parameters_Data", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // kzero cut Histogram Registry with MC-matching, each will include 20 histograms for 20 different cuts + HistogramRegistry rKzeroShort_cospaCut{"KzeroShort_cospaCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rKzeroShort_dcaCut{"KzeroShort_dcaCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rKzeroShort_v0radiusCut{"KzeroShort_v0radiusCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rKzeroShort_dcapostopCut{"KzeroShort_dcapostopvCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rKzeroShort_dcanegtopCut{"KzeroShort_dcanegtopvCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // lambdas cut histograms with MC-matching (same as in Kzeros above) + HistogramRegistry rLambda_cospaCut{"Lambda_cospaCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda_dcaCut{"Lambda_dcaCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda_v0radiusCut{"Lambda_v0radiusCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda_dcapostopCut{"Lambda_dcapostopvCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda_dcanegtopCut{"Lambda_dcanegtopvCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // antilambdas cut histograms with MC-matching (same as in Lambdas an Kzeros above) + HistogramRegistry rAntiLambda_cospaCut{"AntiLambda_cospaCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntiLambda_dcaCut{"AntiLambda_dcaCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntiLambda_v0radiusCut{"AntiLambda_v0radiusCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntiLambda_dcapostopCut{"AntiLambda_dcapostopvCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntiLambda_dcanegtopCut{"AntiLambda_dcanegtopvCuts", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable strings for Kzero cuts + Configurable kzeroshsetting_cospacuts_string{"kzerosetting_cospacuts", {"0_98,0_981,0_982,0_983,0_984,0_985,0_986,0_987,0_988,0_989,0_99,0_991,0_992,0_993,0_994,0_995,0_996,0_997,0_998,0_999"}, "Kzero cosPA Cut Values"}; + Configurable kzeroshsetting_dcacuts_string{"kzerosetting_dcacuts", {"0_3,0_285,0_27,0_255,0_24,0_225,0_21,0_195,0_18,0_165,0_15,0_135,0_12,0_105,0_09,0_075,0_06,0_045,0_03,0_015"}, "Kzero DCA Cut Values"}; + Configurable kzeroshsetting_v0radius_string{"kzerosetting_v0radiuscuts", {"0_5,0_51,0_52,0_53,0_54,0_55,0_56,0_57,0_58,0_59,0_6,0_61,0_62,0_63,0_64,0_65,0_66,0_67,0_68,0_69"}, "Kzero V0Radius Cut Values"}; + Configurable kzeroshsetting_dcapostopv_string{"kzerosetting_dcapostopvcuts", {"0_0,0_01,0_02,0_03,0_04,0_05,0_06,0_07,0_08,0_09,0_1,0_11,0_12,0_13,0_14,0_15,0_16,0_17,0_18,0_19"}, "Kzero DCA Pos to PV Cut Values"}; + Configurable kzeroshsetting_dcanegtopv_string{"kzerosetting_dcanegtopvcuts", {"0_0,0_01,0_02,0_03,0_04,0_05,0_06,0_07,0_08,0_09,0_1,0_11,0_12,0_13,0_14,0_15,0_16,0_17,0_18,0_19"}, "KzeroDCA Neg to PV Cut Values"}; + + // Configurable strings for Lambdacuts + Configurable lambdasetting_cospacuts_string{"lambdasetting_cospacuts", {"0_98,0_981,0_982,0_983,0_984,0_985,0_986,0_987,0_988,0_989,0_99,0_991,0_992,0_993,0_994,0_995,0_996,0_997,0_998,0_999"}, "Lambda cosPA Cut Values"}; + Configurable lambdasetting_dcacuts_string{"lambdasetting_dcacuts", {"0_3,0_285,0_27,0_255,0_24,0_225,0_21,0_195,0_18,0_165,0_15,0_135,0_12,0_105,0_09,0_075,0_06,0_045,0_03,0_015"}, "Lambda DCA Cut Values"}; + Configurable lambdasetting_v0radius_string{"lambdasetting_v0radiuscuts", {"0_5,0_51,0_52,0_53,0_54,0_55,0_56,0_57,0_58,0_59,0_6,0_61,0_62,0_63,0_64,0_65,0_66,0_67,0_68,0_69"}, "Lambda V0Radius Cut Values"}; + Configurable lambdasetting_dcapostopv_string{"lambdasetting_dcapostopvcuts", {"0_0,0_01,0_02,0_03,0_04,0_05,0_06,0_07,0_08,0_09,0_1,0_11,0_12,0_13,0_14,0_15,0_16,0_17,0_18,0_19"}, "Lambda DCA Pos to PV Cut Values"}; + Configurable lambdasetting_dcanegtopv_string{"lambdasetting_dcanegtopvcuts", {"0_0,0_01,0_02,0_03,0_04,0_05,0_06,0_07,0_08,0_09,0_1,0_11,0_12,0_13,0_14,0_15,0_16,0_17,0_18,0_19"}, "Lambda DCA Neg to PV Cut Values"}; + + // Configurable strings for AntiLambdacuts + Configurable antilambdasetting_cospacuts_string{"antilambdasetting_cospacuts", {"0_98,0_981,0_982,0_983,0_984,0_985,0_986,0_987,0_988,0_989,0_99,0_991,0_992,0_993,0_994,0_995,0_996,0_997,0_998,0_999"}, "Antilambda cosPA Cut Values"}; + Configurable antilambdasetting_dcacuts_string{"antilambdasetting_dcacuts", {"0_3,0_285,0_27,0_255,0_24,0_225,0_21,0_195,0_18,0_165,0_15,0_135,0_12,0_105,0_09,0_075,0_06,0_045,0_03,0_015"}, "Antilambda DCA Cut Values"}; + Configurable antilambdasetting_v0radius_string{"antilambdasetting_v0radiuscuts", {"0_5,0_51,0_52,0_53,0_54,0_55,0_56,0_57,0_58,0_59,0_6,0_61,0_62,0_63,0_64,0_65,0_66,0_67,0_68,0_69"}, "Antilambda V0Radius Cut Values"}; + Configurable antilambdasetting_dcapostopv_string{"antilambdasetting_dcapostopvcuts", {"0_0,0_01,0_02,0_03,0_04,0_05,0_06,0_07,0_08,0_09,0_1,0_11,0_12,0_13,0_14,0_15,0_16,0_17,0_18,0_19"}, "Antilambda DCA Pos to PV Cut Values"}; + Configurable antilambdasetting_dcanegtopv_string{"antilambdasetting_dcanegtopvcuts", {"0_0,0_01,0_02,0_03,0_04,0_05,0_06,0_07,0_08,0_09,0_1,0_11,0_12,0_13,0_14,0_15,0_16,0_17,0_18,0_19"}, "Antilambda DCA Neg to PV Cut Values"}; + + void init(InitContext const&) + { + // kzero filling namespace with configurable strings + + // setting strings from configurable strings in order to manipulate them + size_t commapos = 0; + std::string token1; + std::string kzeroshsetting_cospacuts = kzeroshsetting_cospacuts_string; + std::string kzeroshsetting_dcacuts = kzeroshsetting_dcacuts_string; + std::string kzeroshsetting_v0radiuscuts = kzeroshsetting_v0radius_string; + std::string kzeroshsetting_dcapostopvcuts = kzeroshsetting_dcapostopv_string; + std::string kzeroshsetting_dcanegtopvcuts = kzeroshsetting_dcanegtopv_string; + + // getting the cut values for the names of the plots for the five topological cuts + for (int i = 0; i < 20; i++) { + commapos = kzeroshsetting_cospacuts.find(","); // find comma that separates the values in the string + token1 = kzeroshsetting_cospacuts.substr(0, commapos); // store the substring (first individual value) + cuthistoskzerosh::cospacuts.push_back(token1); // fill the namespace with the value + kzeroshsetting_cospacuts.erase(0, commapos + 1); // erase the value from the set string so it moves to the next + } + for (int i = 0; i < 20; i++) { + commapos = kzeroshsetting_dcacuts.find(","); + token1 = kzeroshsetting_dcacuts.substr(0, commapos); + cuthistoskzerosh::dcacuts.push_back(token1); + kzeroshsetting_dcacuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = kzeroshsetting_v0radiuscuts.find(","); + token1 = kzeroshsetting_v0radiuscuts.substr(0, commapos); + cuthistoskzerosh::v0radiuscuts.push_back(token1); + kzeroshsetting_v0radiuscuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = kzeroshsetting_dcapostopvcuts.find(","); + token1 = kzeroshsetting_dcapostopvcuts.substr(0, commapos); + cuthistoskzerosh::dcapostopvcuts.push_back(token1); + kzeroshsetting_dcapostopvcuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = kzeroshsetting_dcanegtopvcuts.find(","); + token1 = kzeroshsetting_dcanegtopvcuts.substr(0, commapos); + cuthistoskzerosh::dcanegtopvcuts.push_back(token1); + kzeroshsetting_dcanegtopvcuts.erase(0, commapos + 1); + } + + // lambda filling namespace with configurable strings (same as in Kzeros above) + std::string lambdasetting_cospacuts = lambdasetting_cospacuts_string; + std::string lambdasetting_dcacuts = lambdasetting_dcacuts_string; + std::string lambdasetting_v0radiuscuts = lambdasetting_v0radius_string; + std::string lambdasetting_dcapostopvcuts = lambdasetting_dcapostopv_string; + std::string lambdasetting_dcanegtopvcuts = lambdasetting_dcanegtopv_string; + + for (int i = 0; i < 20; i++) { + commapos = lambdasetting_cospacuts.find(","); + token1 = lambdasetting_cospacuts.substr(0, commapos); + cuthistoslambda::cospacuts.push_back(token1); + lambdasetting_cospacuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = lambdasetting_dcacuts.find(","); + token1 = lambdasetting_dcacuts.substr(0, commapos); + cuthistoslambda::dcacuts.push_back(token1); + lambdasetting_dcacuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = lambdasetting_v0radiuscuts.find(","); + token1 = lambdasetting_v0radiuscuts.substr(0, commapos); + cuthistoslambda::v0radiuscuts.push_back(token1); + lambdasetting_v0radiuscuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = lambdasetting_dcapostopvcuts.find(","); + token1 = lambdasetting_dcapostopvcuts.substr(0, commapos); + cuthistoslambda::dcapostopvcuts.push_back(token1); + lambdasetting_dcapostopvcuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = lambdasetting_dcanegtopvcuts.find(","); + token1 = lambdasetting_dcanegtopvcuts.substr(0, commapos); + cuthistoslambda::dcanegtopvcuts.push_back(token1); + lambdasetting_dcanegtopvcuts.erase(0, commapos + 1); + } + // antilambda filling namespace with configurable strings (same as in Lambdas and Kzeros above) + std::string antilambdasetting_cospacuts = antilambdasetting_cospacuts_string; + std::string antilambdasetting_dcacuts = antilambdasetting_dcacuts_string; + std::string antilambdasetting_v0radiuscuts = antilambdasetting_v0radius_string; + std::string antilambdasetting_dcapostopvcuts = antilambdasetting_dcapostopv_string; + std::string antilambdasetting_dcanegtopvcuts = antilambdasetting_dcanegtopv_string; + + for (int i = 0; i < 20; i++) { + commapos = antilambdasetting_cospacuts.find(","); + token1 = antilambdasetting_cospacuts.substr(0, commapos); + cuthistosantilambda::cospacuts.push_back(token1); + antilambdasetting_cospacuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = antilambdasetting_dcacuts.find(","); + token1 = antilambdasetting_dcacuts.substr(0, commapos); + cuthistosantilambda::dcacuts.push_back(token1); + antilambdasetting_dcacuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = antilambdasetting_v0radiuscuts.find(","); + token1 = antilambdasetting_v0radiuscuts.substr(0, commapos); + cuthistosantilambda::v0radiuscuts.push_back(token1); + antilambdasetting_v0radiuscuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = antilambdasetting_dcapostopvcuts.find(","); + token1 = antilambdasetting_dcapostopvcuts.substr(0, commapos); + cuthistosantilambda::dcapostopvcuts.push_back(token1); + antilambdasetting_dcapostopvcuts.erase(0, commapos + 1); + } + for (int i = 0; i < 20; i++) { + commapos = antilambdasetting_dcanegtopvcuts.find(","); + token1 = antilambdasetting_dcanegtopvcuts.substr(0, commapos); + cuthistosantilambda::dcanegtopvcuts.push_back(token1); + antilambdasetting_dcanegtopvcuts.erase(0, commapos + 1); + } + + // Axes for the three invariant mass plots + AxisSpec K0ShortMassAxis = {nBins, 0.45f, 0.55f, "#it{M} #pi^{+}#pi^{-} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {nBins, 1.085f, 1.145f, "#it{M} p^{+}#pi^{-} [GeV/#it{c}^{2}]"}; + AxisSpec AntiLambdaMassAxis = {nBins, 1.085f, 1.145f, "#it{M} p^{-}#pi^{+} [GeV/#it{c}^{2}]"}; + + // adding the invariant mass histograms to their Registries using the namespace for kzeros, lambdas and antilambdas + for (int i = 0; i < 20; i++) { + cuthistoskzerosh::cospaCut[i] = rKzeroShort_cospaCut.add(fmt::format("hKzerocospaCut_{}", cuthistoskzerosh::cospacuts[i]).data(), fmt::format("hKzerocospaCut_{}", cuthistoskzerosh::cospacuts[i]).data(), {HistType::kTH1D, {{K0ShortMassAxis}}}); + cuthistoskzerosh::dcaCut[i] = rKzeroShort_dcaCut.add(fmt::format("hKzerodcaCut_{}", cuthistoskzerosh::dcacuts[i]).data(), fmt::format("hKzerodcaCut_{}", cuthistoskzerosh::dcacuts[i]).data(), {HistType::kTH1D, {{K0ShortMassAxis}}}); + cuthistoskzerosh::v0radiusCut[i] = rKzeroShort_v0radiusCut.add(fmt::format("hKzerov0radiusCut_{}", cuthistoskzerosh::v0radiuscuts[i]).data(), fmt::format("hKzerov0radiusCut_{}", cuthistoskzerosh::v0radiuscuts[i]).data(), {HistType::kTH1D, {{K0ShortMassAxis}}}); + cuthistoskzerosh::dcapostopCut[i] = rKzeroShort_dcapostopCut.add(fmt::format("hKzerodcapostopCut_{}", cuthistoskzerosh::dcapostopvcuts[i]).data(), fmt::format("hKzerodcapostopCut_{}", cuthistoskzerosh::dcapostopvcuts[i]).data(), {HistType::kTH1D, {{K0ShortMassAxis}}}); + cuthistoskzerosh::dcanegtopCut[i] = rKzeroShort_dcanegtopCut.add(fmt::format("hKzerodcanegtopCut_{}", cuthistoskzerosh::dcanegtopvcuts[i]).data(), fmt::format("hKzerodcanegtopCut_{}", cuthistoskzerosh::dcanegtopvcuts[i]).data(), {HistType::kTH1D, {{K0ShortMassAxis}}}); + } + + for (int i = 0; i < 20; i++) { + cuthistoslambda::cospaCut[i] = rLambda_cospaCut.add(fmt::format("hLambdacospaCut_{}", cuthistoslambda::cospacuts[i]).data(), fmt::format("hLambdacospaCut_{}", cuthistoslambda::cospacuts[i]).data(), {HistType::kTH1D, {{LambdaMassAxis}}}); + cuthistoslambda::dcaCut[i] = rLambda_dcaCut.add(fmt::format("hLambdadcaCut_{}", cuthistoslambda::dcacuts[i]).data(), fmt::format("hLambdadcaCut_{}", cuthistoslambda::dcacuts[i]).data(), {HistType::kTH1D, {{LambdaMassAxis}}}); + cuthistoslambda::v0radiusCut[i] = rLambda_v0radiusCut.add(fmt::format("hLambdav0radiusCut_{}", cuthistoslambda::v0radiuscuts[i]).data(), fmt::format("hLambdav0radiusCut_{}", cuthistoslambda::v0radiuscuts[i]).data(), {HistType::kTH1D, {{LambdaMassAxis}}}); + cuthistoslambda::dcapostopCut[i] = rLambda_dcapostopCut.add(fmt::format("hLambdadcapostopCut_{}", cuthistoslambda::dcapostopvcuts[i]).data(), fmt::format("hLambdadcapostopCut_{}", cuthistoslambda::dcapostopvcuts[i]).data(), {HistType::kTH1D, {{LambdaMassAxis}}}); + cuthistoslambda::dcanegtopCut[i] = rLambda_dcanegtopCut.add(fmt::format("hLambdadcanegtopCut_{}", cuthistoslambda::dcanegtopvcuts[i]).data(), fmt::format("hLambdadcanegtopCut_{}", cuthistoslambda::dcanegtopvcuts[i]).data(), {HistType::kTH1D, {{LambdaMassAxis}}}); + } + + for (int i = 0; i < 20; i++) { + cuthistosantilambda::cospaCut[i] = rAntiLambda_cospaCut.add(fmt::format("hAntiLambdacospaCut_{}", cuthistosantilambda::cospacuts[i]).data(), fmt::format("hAntiLambdacospaCut_{}", cuthistosantilambda::cospacuts[i]).data(), {HistType::kTH1D, {{AntiLambdaMassAxis}}}); + cuthistosantilambda::dcaCut[i] = rAntiLambda_dcaCut.add(fmt::format("hAntiLambdadcaCut_{}", cuthistosantilambda::dcacuts[i]).data(), fmt::format("hAntiLambdadcaCut_{}", cuthistosantilambda::dcacuts[i]).data(), {HistType::kTH1D, {{AntiLambdaMassAxis}}}); + cuthistosantilambda::v0radiusCut[i] = rAntiLambda_v0radiusCut.add(fmt::format("hAntiLambdav0radiusCut_{}", cuthistosantilambda::v0radiuscuts[i]).data(), fmt::format("hAntiLambdav0radiusCut_{}", cuthistosantilambda::v0radiuscuts[i]).data(), {HistType::kTH1D, {{AntiLambdaMassAxis}}}); + cuthistosantilambda::dcapostopCut[i] = rAntiLambda_dcapostopCut.add(fmt::format("hAntiLambdadcapostopCut_{}", cuthistosantilambda::dcapostopvcuts[i]).data(), fmt::format("hAntiLambdadcapostopCut_{}", cuthistosantilambda::dcapostopvcuts[i]).data(), {HistType::kTH1D, {{AntiLambdaMassAxis}}}); + cuthistosantilambda::dcanegtopCut[i] = rAntiLambda_dcanegtopCut.add(fmt::format("hAntiLambdadcanegtopCut_{}", cuthistosantilambda::dcanegtopvcuts[i]).data(), fmt::format("hAntiLambdadcanegtopCut_{}", cuthistosantilambda::dcanegtopvcuts[i]).data(), {HistType::kTH1D, {{AntiLambdaMassAxis}}}); + } + + // K0s topological cut histograms added and MC-matched + rV0Parameters_MC_V0match.add("hDCAV0Daughters_V0_Match", "hDCAV0Daughters_No_Match", {HistType::kTH1F, {{nBins, 0.0f, 1.2f}}}); + rV0Parameters_MC_V0match.add("hV0CosPA_V0_Match", "hV0CosPA_No_Match", {HistType::kTH1F, {{nBins, 0.95f, 1.f}}}); + rV0Parameters_MC_V0match.add("hV0Radius_V0_Match", "hV0Radius_No_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_MC_V0match.add("hV0Radius_V0_Match_Full", "hV0Radius_No_Match_Full", {HistType::kTH1F, {{nBins, 0.0f, 40.0f}}}); + rV0Parameters_MC_V0match.add("hDCAPostoPV_V0_Match", "hDCAPostoPV_No_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_MC_V0match.add("hDCANegtoPV_V0_Match", "hDCANegtoPV_No_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + + // kzero match + rV0Parameters_MC_K0Smatch.add("hDCAV0Daughters_KzeroMC_Match", "hDCAV0Daughters_KzeroMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 1.2f}}}); + rV0Parameters_MC_K0Smatch.add("hV0CosPA_KzeroMC_Match", "hV0CosPA_KzeroMC_Match", {HistType::kTH1F, {{nBins, 0.95f, 1.f}}}); + rV0Parameters_MC_K0Smatch.add("hV0Radius_KzeroMC_Match", "hV0Radius_KzeroMC_Match", {HistType::kTH1F, {{nBins, 0.2f, 5.0f}}}); + rV0Parameters_MC_K0Smatch.add("hDCAPostoPV_KzeroMC_Match", "hDCAPostoPV_KzeroMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_MC_K0Smatch.add("hDCANegtoPV_KzeroMC_Match", "hDCANegtoPV_KzeroMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + + // lambda match + rV0Parameters_MC_Lambdamatch.add("hDCAV0Daughters_LambdaMC_Match", "hDCAV0Daughters_LambdaMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 1.2f}}}); + rV0Parameters_MC_Lambdamatch.add("hV0CosPA_LambdaMC_Match", "hV0CosPA_LambdaMC_Match", {HistType::kTH1F, {{nBins, 0.95f, 1.f}}}); + rV0Parameters_MC_Lambdamatch.add("hV0Radius_LambdaMC_Match", "hV0Radius_LambdaMC_Match", {HistType::kTH1F, {{nBins, 0.2f, 5.0f}}}); + rV0Parameters_MC_Lambdamatch.add("hDCAPostoPV_LambdaMC_Match", "hDCAPostoPV_LambdaMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_MC_Lambdamatch.add("hDCANegtoPV_LambdaMC_Match", "hDCANegtoPV_LambdaMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + + // antilambda match + rV0Parameters_MC_AntiLambdamatch.add("hDCAV0Daughters_AntiLambdaMC_Match", "hDCAV0Daughters_AntiLambdaMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 1.2f}}}); + rV0Parameters_MC_AntiLambdamatch.add("hV0CosPA_AntiLambdaMC_Match", "hV0CosPA_AntiLambdaMC_Match", {HistType::kTH1F, {{nBins, 0.95f, 1.f}}}); + rV0Parameters_MC_AntiLambdamatch.add("hV0Radius_AntiLambdaMC_Match", "hV0Radius_AntiLambdaMC_Match", {HistType::kTH1F, {{nBins, 0.2f, 5.0f}}}); + rV0Parameters_MC_AntiLambdamatch.add("hDCAPostoPV_AntiLambdaMC_Match", "hDCAPostoPV_AntiLambdaMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_MC_AntiLambdamatch.add("hDCANegtoPV_AntiLambdaMC_Match", "hDCANegtoPV_AntiLambdaMC_Match", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + + // V0s Data + rV0Parameters_Data.add("hDCAV0Daughters_V0_Data", "hDCAV0Daughters_V0_Data", {HistType::kTH1F, {{nBins, 0.0f, 1.2f}}}); + rV0Parameters_Data.add("hV0CosPA_V0_Data", "hV0CosPA_V0_Data", {HistType::kTH1F, {{nBins, 0.95f, 1.f}}}); + rV0Parameters_Data.add("hV0Radius_V0_Data", "hV0Radius_V0_Data", {HistType::kTH1F, {{nBins, 0.2f, 5.0f}}}); + rV0Parameters_Data.add("hV0Radius_Full_V0_Data", "hV0Radius_Full_V0_Data", {HistType::kTH1F, {{nBins, 0.2f, 5.0f}}}); + rV0Parameters_Data.add("hDCAPostoPV_V0_Data", "hDCAPostoPV_V0_Data", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_Data.add("hDCANegtoPV_V0_Data", "hDCANegtoPV_V0_Data", {HistType::kTH1F, {{nBins, 0.0f, 5.0f}}}); + rV0Parameters_Data.add("hMassK0ShortNoCuts_V0_Data", "hMassK0ShortNoCuts_V0_Data", {HistType::kTH1F, {{K0ShortMassAxis}}}); + rV0Parameters_Data.add("hMassLambdaNoCuts_V0_Data", "hMassLambdaNoCuts_V0_Data", {HistType::kTH1F, {{LambdaMassAxis}}}); + rV0Parameters_Data.add("hMassAntilambdaNoCuts_V0_Data", "hMassAntilambdaNoCuts_V0_Data", {HistType::kTH1F, {{AntiLambdaMassAxis}}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + + // Defining the type of the daughter tracks + using DaughterTracks = soa::Join; + + // This is the Process for the MC reconstructed Data + void RecMCprocess(soa::Filtered>::iterator const&, + soa::Join const& V0s, + DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly + aod::McParticles const&) + { + for (const auto& v0 : V0s) { + + // filling histograms with V0 values + rV0Parameters_MC_V0match.fill(HIST("hDCAV0Daughters_V0_Match"), v0.dcaV0daughters()); + rV0Parameters_MC_V0match.fill(HIST("hV0CosPA_V0_Match"), v0.v0cosPA()); + rV0Parameters_MC_V0match.fill(HIST("hV0Radius_V0_Match"), v0.v0radius()); + rV0Parameters_MC_V0match.fill(HIST("hV0Radius_V0_Match_Full"), v0.v0radius()); + rV0Parameters_MC_V0match.fill(HIST("hDCAPostoPV_V0_Match"), v0.dcapostopv()); + rV0Parameters_MC_V0match.fill(HIST("hDCANegtoPV_V0_Match"), v0.dcanegtopv()); + + // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) + if (v0.has_mcParticle()) { + auto v0mcParticle = v0.mcParticle(); + if (v0mcParticle.pdgCode() == 310) { // kzero matched + + rV0Parameters_MC_K0Smatch.fill(HIST("hDCAV0Daughters_KzeroMC_Match"), v0.dcaV0daughters()); + rV0Parameters_MC_K0Smatch.fill(HIST("hV0CosPA_KzeroMC_Match"), v0.v0cosPA()); + rV0Parameters_MC_K0Smatch.fill(HIST("hV0Radius_KzeroMC_Match"), v0.v0radius()); + rV0Parameters_MC_K0Smatch.fill(HIST("hDCAPostoPV_KzeroMC_Match"), TMath::Abs(v0.dcapostopv())); + rV0Parameters_MC_K0Smatch.fill(HIST("hDCANegtoPV_KzeroMC_Match"), TMath::Abs(v0.dcanegtopv())); + + for (int j = 0; j < 20; j++) { + std::string cospacut = cuthistoskzerosh::cospacuts[j]; // Get the current cut value from the namespace + size_t pos = cospacut.find("_"); // find the "_" which needs to change to a "." for it to be a number + cospacut[pos] = '.'; // change the "_" into an "." + const float cospacutvalue = std::stod(cospacut); // make the string into a float value + if (v0.v0cosPA() > cospacutvalue) { // enforce the cut value + cuthistoskzerosh::cospaCut[j]->Fill(v0.mK0Short()); // fill the corresponding histo from the namespace with the invariant mass (of a Kzero here) + } + } + for (int j = 0; j < 20; j++) { + std::string dcacut = cuthistoskzerosh::dcacuts[j]; + size_t pos = dcacut.find("_"); + dcacut[pos] = '.'; + const float dcacutvalue = std::stod(dcacut); + if (v0.dcaV0daughters() < dcacutvalue) { + cuthistoskzerosh::dcaCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string v0radiuscut = cuthistoskzerosh::v0radiuscuts[j]; + size_t pos = v0radiuscut.find("_"); + v0radiuscut[pos] = '.'; + const float v0radiuscutvalue = std::stod(v0radiuscut); + if (v0.v0radius() > v0radiuscutvalue) { + cuthistoskzerosh::v0radiusCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcapostopcut = cuthistoskzerosh::dcapostopvcuts[j]; + size_t pos = dcapostopcut.find("_"); + dcapostopcut[pos] = '.'; + const float dcapostopcutvalue = std::stod(dcapostopcut); + if (TMath::Abs(v0.dcapostopv()) > dcapostopcutvalue) { + cuthistoskzerosh::dcapostopCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcanegtopcut = cuthistoskzerosh::dcanegtopvcuts[j]; + size_t pos = dcanegtopcut.find("_"); + dcanegtopcut[pos] = '.'; + const float dcanegtopcutvalue = std::stod(dcanegtopcut); + if (TMath::Abs(v0.dcanegtopv()) > dcanegtopcutvalue) { + cuthistoskzerosh::dcanegtopCut[j]->Fill(v0.mK0Short()); + } + } + } + if (v0mcParticle.pdgCode() == 3122) { // lambda matched + rV0Parameters_MC_Lambdamatch.fill(HIST("hDCAV0Daughters_LambdaMC_Match"), v0.dcaV0daughters()); + rV0Parameters_MC_Lambdamatch.fill(HIST("hV0CosPA_LambdaMC_Match"), v0.v0cosPA()); + rV0Parameters_MC_Lambdamatch.fill(HIST("hV0Radius_LambdaMC_Match"), v0.v0radius()); + rV0Parameters_MC_Lambdamatch.fill(HIST("hDCAPostoPV_LambdaMC_Match"), TMath::Abs(v0.dcapostopv())); + rV0Parameters_MC_Lambdamatch.fill(HIST("hDCANegtoPV_LambdaMC_Match"), TMath::Abs(v0.dcanegtopv())); + + // for explanation look at the first Kzero plot above + for (int j = 0; j < 20; j++) { + std::string cospacutlambda = cuthistoslambda::cospacuts[j]; + size_t pos = cospacutlambda.find("_"); + cospacutlambda[pos] = '.'; + const float cospacutlambdavalue = std::stod(cospacutlambda); + if (v0.v0cosPA() > cospacutlambdavalue) { + cuthistoslambda::cospaCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcacutlambda = cuthistoslambda::dcacuts[j]; + size_t pos = dcacutlambda.find("_"); + dcacutlambda[pos] = '.'; + const float dcacutlambdavalue = std::stod(dcacutlambda); + if (v0.dcaV0daughters() < dcacutlambdavalue) { + cuthistoslambda::dcaCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string v0radiuscutlambda = cuthistoslambda::v0radiuscuts[j]; + size_t pos = v0radiuscutlambda.find("_"); + v0radiuscutlambda[pos] = '.'; + const float v0radiuscutlambdavalue = std::stod(v0radiuscutlambda); + if (v0.v0radius() > v0radiuscutlambdavalue) { + cuthistoslambda::v0radiusCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcapostopcutlambda = cuthistoslambda::dcapostopvcuts[j]; + size_t pos = dcapostopcutlambda.find("_"); + dcapostopcutlambda[pos] = '.'; + const float dcapostopcutlambdavalue = std::stod(dcapostopcutlambda); + if (TMath::Abs(v0.dcapostopv()) > dcapostopcutlambdavalue) { + cuthistoslambda::dcapostopCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcanegtopcutlambda = cuthistoslambda::dcanegtopvcuts[j]; + size_t pos = dcanegtopcutlambda.find("_"); + dcanegtopcutlambda[pos] = '.'; + const float dcanegtopcutlambdavalue = std::stod(dcanegtopcutlambda); + if (TMath::Abs(v0.dcanegtopv()) > dcanegtopcutlambdavalue) { + cuthistoslambda::dcanegtopCut[j]->Fill(v0.mLambda()); + } + } + } + if (v0mcParticle.pdgCode() == -3122) { // antilambda matched + rV0Parameters_MC_AntiLambdamatch.fill(HIST("hDCAV0Daughters_AntiLambdaMC_Match"), v0.dcaV0daughters()); + rV0Parameters_MC_AntiLambdamatch.fill(HIST("hV0CosPA_AntiLambdaMC_Match"), v0.v0cosPA()); + rV0Parameters_MC_AntiLambdamatch.fill(HIST("hV0Radius_AntiLambdaMC_Match"), v0.v0radius()); + rV0Parameters_MC_AntiLambdamatch.fill(HIST("hDCAPostoPV_AntiLambdaMC_Match"), TMath::Abs(v0.dcapostopv())); + rV0Parameters_MC_AntiLambdamatch.fill(HIST("hDCANegtoPV_AntiLambdaMC_Match"), TMath::Abs(v0.dcanegtopv())); + // for explanation look at the first Kzero plot above + for (int j = 0; j < 20; j++) { + std::string cospacutantilambda = cuthistosantilambda::cospacuts[j]; + size_t pos = cospacutantilambda.find("_"); + cospacutantilambda[pos] = '.'; + const float cospacutantilambdavalue = std::stod(cospacutantilambda); + if (v0.v0cosPA() > cospacutantilambdavalue) { + cuthistosantilambda::cospaCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcacutantilambda = cuthistosantilambda::dcacuts[j]; + size_t pos = dcacutantilambda.find("_"); + dcacutantilambda[pos] = '.'; + const float dcacutantilambdavalue = std::stod(dcacutantilambda); + if (v0.dcaV0daughters() < dcacutantilambdavalue) { + cuthistosantilambda::dcaCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string v0radiusantilambda = cuthistosantilambda::v0radiuscuts[j]; + size_t pos = v0radiusantilambda.find("_"); + v0radiusantilambda[pos] = '.'; + const float v0radiuscutantilambdavalue = std::stod(v0radiusantilambda); + if (v0.v0radius() > v0radiuscutantilambdavalue) { + cuthistosantilambda::v0radiusCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcapostopantilambda = cuthistosantilambda::dcapostopvcuts[j]; + size_t pos = dcapostopantilambda.find("_"); + dcapostopantilambda[pos] = '.'; + const float dcapostopcutantilambdavalue = std::stod(dcapostopantilambda); + if (TMath::Abs(v0.dcapostopv()) > dcapostopcutantilambdavalue) { + cuthistosantilambda::dcapostopCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcanegtopantilambda = cuthistosantilambda::dcanegtopvcuts[j]; + size_t pos = dcanegtopantilambda.find("_"); + dcanegtopantilambda[pos] = '.'; + const float dcanegtopcutantilambdavalue = std::stod(dcanegtopantilambda); + if (TMath::Abs(v0.dcanegtopv()) > dcanegtopcutantilambdavalue) { + cuthistosantilambda::dcanegtopCut[j]->Fill(v0.mAntiLambda()); + } + } + } + } + } + } + // This is the process for Real Data + void Dataprocess(soa::Filtered>::iterator const&, + aod::V0Datas const& V0s) + { + // filling histograms with the different V0 parameters + for (const auto& v0 : V0s) { + rV0Parameters_Data.fill(HIST("hMassK0ShortNoCuts_V0_Data"), v0.mK0Short()); + rV0Parameters_Data.fill(HIST("hMassLambdaNoCuts_V0_Data"), v0.mLambda()); + rV0Parameters_Data.fill(HIST("hMassAntilambdaNoCuts_V0_Data"), v0.mAntiLambda()); + rV0Parameters_Data.fill(HIST("hDCAV0Daughters_V0_Data"), v0.dcaV0daughters()); + rV0Parameters_Data.fill(HIST("hV0CosPA_V0_Data"), v0.v0cosPA()); + rV0Parameters_Data.fill(HIST("hV0Radius_V0_Data"), v0.v0radius()); + rV0Parameters_Data.fill(HIST("hV0Radius_Full_V0_Data"), v0.v0radius()); + rV0Parameters_Data.fill(HIST("hDCAPostoPV_V0_Data"), TMath::Abs(v0.dcapostopv())); + rV0Parameters_Data.fill(HIST("hDCANegtoPV_V0_Data"), TMath::Abs(v0.dcanegtopv())); + + // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + for (int j = 0; j < 20; j++) { + std::string cospacut = cuthistoskzerosh::cospacuts[j]; + size_t pos = cospacut.find("_"); + cospacut[pos] = '.'; + const float cospacutvalue = std::stod(cospacut); + if (v0.v0cosPA() > cospacutvalue) { + cuthistoskzerosh::cospaCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcacut = cuthistoskzerosh::dcacuts[j]; + size_t pos = dcacut.find("_"); + dcacut[pos] = '.'; + const float dcacutvalue = std::stod(dcacut); + if (v0.dcaV0daughters() < dcacutvalue) { + cuthistoskzerosh::dcaCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string v0radiuscut = cuthistoskzerosh::v0radiuscuts[j]; + size_t pos = v0radiuscut.find("_"); + v0radiuscut[pos] = '.'; + const float v0radiuscutvalue = std::stod(v0radiuscut); + if (v0.v0radius() > v0radiuscutvalue) { + cuthistoskzerosh::v0radiusCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcapostopcut = cuthistoskzerosh::dcapostopvcuts[j]; + size_t pos = dcapostopcut.find("_"); + dcapostopcut[pos] = '.'; + const float dcapostopcutvalue = std::stod(dcapostopcut); + if (TMath::Abs(v0.dcapostopv()) > dcapostopcutvalue) { + cuthistoskzerosh::dcapostopCut[j]->Fill(v0.mK0Short()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcanegtopcut = cuthistoskzerosh::dcanegtopvcuts[j]; + size_t pos = dcanegtopcut.find("_"); + dcanegtopcut[pos] = '.'; + const float dcanegtopcutvalue = std::stod(dcanegtopcut); + if (TMath::Abs(v0.dcanegtopv()) > dcanegtopcutvalue) { + cuthistoskzerosh::dcanegtopCut[j]->Fill(v0.mK0Short()); + } + } + // Filling the five Lambda invariant mass plots for different cuts (which are taken from namespace), same as with Kzeros above,for full explanation see the first kzero cut filling in the MC process + for (int j = 0; j < 20; j++) { + std::string cospacutlambda = cuthistoslambda::cospacuts[j]; + size_t pos = cospacutlambda.find("_"); + cospacutlambda[pos] = '.'; + const float cospacutlambdavalue = std::stod(cospacutlambda); + if (v0.v0cosPA() > cospacutlambdavalue) { + cuthistoslambda::cospaCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcacutlambda = cuthistoslambda::dcacuts[j]; + size_t pos = dcacutlambda.find("_"); + dcacutlambda[pos] = '.'; + const float dcacutlambdavalue = std::stod(dcacutlambda); + if (v0.dcaV0daughters() < dcacutlambdavalue) { + cuthistoslambda::dcaCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string v0radiuscutlambda = cuthistoslambda::v0radiuscuts[j]; + size_t pos = v0radiuscutlambda.find("_"); + v0radiuscutlambda[pos] = '.'; + const float v0radiuscutlambdavalue = std::stod(v0radiuscutlambda); + if (v0.v0radius() > v0radiuscutlambdavalue) { + cuthistoslambda::v0radiusCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcapostopcutlambda = cuthistoslambda::dcapostopvcuts[j]; + size_t pos = dcapostopcutlambda.find("_"); + dcapostopcutlambda[pos] = '.'; + const float dcapostopcutlambdavalue = std::stod(dcapostopcutlambda); + if (TMath::Abs(v0.dcapostopv()) > dcapostopcutlambdavalue) { + cuthistoslambda::dcapostopCut[j]->Fill(v0.mLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcanegtopcutlambda = cuthistoslambda::dcanegtopvcuts[j]; + size_t pos = dcanegtopcutlambda.find("_"); + dcanegtopcutlambda[pos] = '.'; + const float dcanegtopcutlambdavalue = std::stod(dcanegtopcutlambda); + if (TMath::Abs(v0.dcanegtopv()) > dcanegtopcutlambdavalue) { + cuthistoslambda::dcanegtopCut[j]->Fill(v0.mLambda()); + } + } + // Filling the five Anti-Lambda invariant mass plots for different cuts (which are taken from namespace), same as with Kzeros and Lambdas above,for full explanation see the first kzero cut filling in the MC process + for (int j = 0; j < 20; j++) { + std::string cospacutantilambda = cuthistosantilambda::cospacuts[j]; + size_t pos = cospacutantilambda.find("_"); + cospacutantilambda[pos] = '.'; + const float cospacutantilambdavalue = std::stod(cospacutantilambda); + if (v0.v0cosPA() > cospacutantilambdavalue) { + cuthistosantilambda::cospaCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcacutantilambda = cuthistosantilambda::dcacuts[j]; + size_t pos = dcacutantilambda.find("_"); + dcacutantilambda[pos] = '.'; + const float dcacutantilambdavalue = std::stod(dcacutantilambda); + if (v0.dcaV0daughters() < dcacutantilambdavalue) { + cuthistosantilambda::dcaCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string v0radiusantilambda = cuthistosantilambda::v0radiuscuts[j]; + size_t pos = v0radiusantilambda.find("_"); + v0radiusantilambda[pos] = '.'; + const float v0radiuscutantilambdavalue = std::stod(v0radiusantilambda); + if (v0.v0radius() > v0radiuscutantilambdavalue) { + cuthistosantilambda::v0radiusCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcapostopantilambda = cuthistosantilambda::dcapostopvcuts[j]; + size_t pos = dcapostopantilambda.find("_"); + dcapostopantilambda[pos] = '.'; + const float dcapostopcutantilambdavalue = std::stod(dcapostopantilambda); + if (TMath::Abs(v0.dcapostopv()) > dcapostopcutantilambdavalue) { + cuthistosantilambda::dcapostopCut[j]->Fill(v0.mAntiLambda()); + } + } + for (int j = 0; j < 20; j++) { + std::string dcanegtopantilambda = cuthistosantilambda::dcanegtopvcuts[j]; + size_t pos = dcanegtopantilambda.find("_"); + dcanegtopantilambda[pos] = '.'; + const float dcanegtopcutantilambdavalue = std::stod(dcanegtopantilambda); + if (TMath::Abs(v0.dcanegtopv()) > dcanegtopcutantilambdavalue) { + cuthistosantilambda::dcanegtopCut[j]->Fill(v0.mAntiLambda()); + } + } + } + } + PROCESS_SWITCH(v0topologicalcuts, RecMCprocess, "Process Run 3 MC:Reconstructed", true); + PROCESS_SWITCH(v0topologicalcuts, Dataprocess, "Process Run 3 Data,", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index 7767f970749..8d1e563d427 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -34,12 +34,31 @@ class CollisonCuts public: virtual ~CollisonCuts() = default; + enum EvtSel { + kAllEvent = 0, + kFlagZvertex, + kFlagTrigerTVX, + kFlagTimeFrameBorder, + kFlagITSROFrameBorder, + kFlagSel8, + kFlagVertexITSTPC, + kFlagBunchPileup, + kFlagZvtxFT0vsPV, + kFlagOccupancy, + kAllpassed + }; + + inline int binLabel(int index) + { + return index + 1; + } + /// \brief Pass the selection criteria to the class /// \param zvtxMax Maximal value of the z-vertex /// \param checkTrigger whether or not to check for the trigger alias /// \param trig Requested trigger alias /// \param checkOffline whether or not to check for offline selection criteria - void setCuts(float zvtxMax, bool checkTrigger, int trig, bool checkOffline, bool checkRun3, bool triggerTVXsel = false) + void setCuts(float zvtxMax, bool checkTrigger, int trig, bool checkOffline, bool checkRun3, bool triggerTVXsel = false, int trackOccupancyInTimeRangeMax = -1) { mCutsSet = true; mZvtxMax = zvtxMax; @@ -53,6 +72,7 @@ class CollisonCuts mApplyZvertexTimedifference = false; mApplyPileupRejection = false; mApplyNoITSROBorderCut = false; + mtrackOccupancyInTimeRangeMax = trackOccupancyInTimeRangeMax; } /// Initializes histograms for the task @@ -63,7 +83,8 @@ class CollisonCuts LOGF(error, "Event selection not set - quitting!"); } mHistogramRegistry = registry; - mHistogramRegistry->add("Event/posZ", "; vtx_{z} (cm); Entries", kTH1F, {{250, -12.5, 12.5}}); + mHistogramRegistry->add("Event/posZ", "; vtx_{z} (cm); Entries", kTH1F, {{250, -12.5, 12.5}}); // z-vertex histogram after event selections + mHistogramRegistry->add("Event/posZ_noCut", "; vtx_{z} (cm); Entries", kTH1F, {{250, -12.5, 12.5}}); // z-vertex histogram before all selections if (mCheckIsRun3) { mHistogramRegistry->add("Event/CentFV0A", "; vCentV0A; Entries", kTH1F, {{110, 0, 110}}); mHistogramRegistry->add("Event/CentFT0M", "; vCentT0M; Entries", kTH1F, {{110, 0, 110}}); @@ -71,16 +92,29 @@ class CollisonCuts mHistogramRegistry->add("Event/CentFT0A", "; vCentT0A; Entries", kTH1F, {{110, 0, 110}}); mHistogramRegistry->add("Event/posZ_ITSOnly", "; vtx_{z} (cm); Entries", kTH1F, {{250, -12.5, 12.5}}); mHistogramRegistry->add("Event/posZ_ITSTPC", "; vtx_{z} (cm); Entries", kTH1F, {{250, -12.5, 12.5}}); + mHistogramRegistry->add("Event/trackOccupancyInTimeRange_noCut", "; Occupancy; Entries", kTH1F, {{500, 0., 20000.}}); } else { mHistogramRegistry->add("Event/CentRun2V0M", "; vCentV0M; Entries", kTH1F, {{110, 0, 110}}); } + mHistogramRegistry->add("CollCutCounts", "; ; Entries", kTH1F, {{11, 0., 11.}}); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kAllEvent), "all"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagZvertex), "Zvtx"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagTrigerTVX), "IsTriggerTVX"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagTimeFrameBorder), "NoTimeFrameBorder"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagITSROFrameBorder), "NoITSROFrameBorder"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagSel8), "sel8"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagVertexITSTPC), "IsVertexITSTPC"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagBunchPileup), "NoSameBunchPileup"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagZvtxFT0vsPV), "IsGoodZvtxFT0vsPV"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagOccupancy), "LowOccupancy"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kAllpassed), "Allpassed"); } /// Print some debug information void printCuts() { - LOGF(info, "Debug information for Collison Cuts \n Max. z-vertex: %f \n Check trigger: %d \n Trigger: %d \n Check offline: %d \n Check Run3: %d \n Trigger TVX selection: %d \n Apply time frame border cut: %d \n Apply ITS-TPC vertex: %d \n Apply Z-vertex time difference: %d \n Apply Pileup rejection: %d \n Apply NoITSRO frame border cut: %d", - mZvtxMax, mCheckTrigger, mTrigger, mCheckOffline, mCheckIsRun3, mTriggerTVXselection, mApplyTFBorderCut, mApplyITSTPCvertex, mApplyZvertexTimedifference, mApplyPileupRejection, mApplyNoITSROBorderCut); + LOGF(info, "Debug information for Collison Cuts \n Max. z-vertex: %f \n Check trigger: %d \n Trigger: %d \n Check offline: %d \n Check Run3: %d \n Trigger TVX selection: %d \n Apply time frame border cut: %d \n Apply ITS-TPC vertex: %d \n Apply Z-vertex time difference: %d \n Apply Pileup rejection: %d \n Apply NoITSRO frame border cut: %d \n Track occupancy in time range max: %d", + mZvtxMax, mCheckTrigger, mTrigger, mCheckOffline, mCheckIsRun3, mTriggerTVXselection, mApplyTFBorderCut, mApplyITSTPCvertex, mApplyZvertexTimedifference, mApplyPileupRejection, mApplyNoITSROBorderCut, mtrackOccupancyInTimeRangeMax); } /// Set MB selection @@ -111,44 +145,63 @@ class CollisonCuts template bool isSelected(T const& col) { + mHistogramRegistry->fill(HIST("Event/posZ_noCut"), col.posZ()); + if (mCheckIsRun3) { + mHistogramRegistry->fill(HIST("Event/trackOccupancyInTimeRange_noCut"), col.trackOccupancyInTimeRange()); + } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllEvent); if (std::abs(col.posZ()) > mZvtxMax) { LOGF(debug, "Vertex out of range"); return false; } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvertex); if (mCheckIsRun3) { // Run3 case - if (mCheckOffline && !col.sel8()) { - LOGF(debug, "Offline selection failed (Run3)"); - return false; - } - if (mTriggerTVXselection && !col.selection_bit(aod::evsel::kIsTriggerTVX)) { + if (!col.selection_bit(aod::evsel::kIsTriggerTVX) && mTriggerTVXselection) { LOGF(debug, "Offline selection TVX failed (Run3)"); return false; } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTrigerTVX); if (!col.selection_bit(aod::evsel::kNoTimeFrameBorder) && mApplyTFBorderCut) { LOGF(debug, "Time frame border cut failed"); return false; } - if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC) && mApplyITSTPCvertex) { - LOGF(debug, "ITS-TPC matching cut failed"); + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTimeFrameBorder); + if (!col.selection_bit(aod::evsel::kNoITSROFrameBorder) && mApplyNoITSROBorderCut) { + LOGF(debug, "NoITSRO frame border cut failed"); return false; } - if (!col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV) && mApplyZvertexTimedifference) { - LOGF(debug, "Z-vertex time difference cut failed"); + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagITSROFrameBorder); + if (!col.sel8() && mCheckOffline) { + LOGF(debug, "Offline selection failed (Run3)"); + return false; + } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagSel8); + if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC) && mApplyITSTPCvertex) { + LOGF(debug, "ITS-TPC matching cut failed"); return false; } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagVertexITSTPC); if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup) && mApplyPileupRejection) { LOGF(debug, "Pileup rejection failed"); return false; } - if (!col.selection_bit(aod::evsel::kNoITSROFrameBorder) && mApplyNoITSROBorderCut) { - LOGF(debug, "NoITSRO frame border cut failed"); + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagBunchPileup); + if (!col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV) && mApplyZvertexTimedifference) { + LOGF(debug, "Z-vertex time difference cut failed"); + return false; + } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvtxFT0vsPV); + if (mtrackOccupancyInTimeRangeMax > 0 && col.trackOccupancyInTimeRange() > mtrackOccupancyInTimeRangeMax) { + LOGF(debug, "trackOccupancyInTimeRange selection failed"); return false; } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagOccupancy); } else { // Run2 case if (mCheckOffline && !col.sel7()) { LOGF(debug, "Offline selection failed (sel7)"); return false; } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTrigerTVX); } if (mCheckTrigger && !col.alias_bit(mTrigger)) { LOGF(debug, "Trigger selection failed"); @@ -163,6 +216,7 @@ class CollisonCuts } return false; } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllpassed); return true; } @@ -213,6 +267,7 @@ class CollisonCuts bool mApplyNoITSROBorderCut = false; ///< Apply NoITSRO frame border cut int mTrigger = kINT7; ///< Trigger to check for float mZvtxMax = 999.f; ///< Maximal deviation from nominal z-vertex (cm) + int mtrackOccupancyInTimeRangeMax = -1; ///< Maximum trackOccupancyInTimeRange cut (-1 no cut) }; } // namespace o2::analysis diff --git a/PWGLF/Utils/inelGt.h b/PWGLF/Utils/inelGt.h index f0a3514adc1..2a5bfa9d47e 100644 --- a/PWGLF/Utils/inelGt.h +++ b/PWGLF/Utils/inelGt.h @@ -154,6 +154,8 @@ struct ParticleCounter { float countFT0A(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, 3.5f, 4.9f); } float countFT0C(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, -3.3f, -2.1f); } float countFV0A(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, 2.2f, 5.1f); } + float countV0A(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, 2.8f, 5.1f); } + float countV0C(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, -3.7f, -1.7f); } float countFDDA(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, 4.9f, 6.3f); } float countFDDC(const aod::McParticles& mcParticles) { return countMultInAcceptance(mcParticles, -7.f, -4.9f); } diff --git a/PWGLF/Utils/mcParticle.h b/PWGLF/Utils/mcParticle.h index 1c1f5703cb4..e85d98ca5f0 100644 --- a/PWGLF/Utils/mcParticle.h +++ b/PWGLF/Utils/mcParticle.h @@ -34,7 +34,7 @@ namespace pwglf class PIDExtended { public: - typedef o2::track::PID::ID ID; + typedef int16_t ID; static constexpr ID Electron = 0; static constexpr ID Muon = 1; @@ -53,6 +53,8 @@ class PIDExtended static constexpr ID Hyperhydrog4 = 14; static constexpr ID XiMinus = 15; static constexpr ID OmegaMinus = 16; + static constexpr ID HyperHelium4 = 17; + static constexpr ID HyperHelium5 = 18; static_assert(Electron == o2::track::PID::Electron, "PID::Electron mismatch"); static_assert(Muon == o2::track::PID::Muon, "PID::Muon mismatch"); @@ -71,53 +73,60 @@ class PIDExtended static_assert(Hyperhydrog4 == o2::track::PID::Hyperhydrog4, "PID::Hyperhydrog4 mismatch"); static_assert(XiMinus == o2::track::PID::XiMinus, "PID::XiMinus mismatch"); static_assert(OmegaMinus == o2::track::PID::OmegaMinus, "PID::OmegaMinus mismatch"); + // static_assert(HyperHelium4 == o2::track::PID::HyperHelium4, "PID::HyperHelium4 mismatch"); + // static_assert(HyperHelium5 == o2::track::PID::HyperHelium5, "PID::HyperHelium5 mismatch"); - static constexpr ID PIDCounts = 17; // Number of indices defined in PID.h - static_assert(PIDCounts == o2::track::PID::NIDsTot, "PID::NIDsTot mismatch"); + static constexpr ID PIDCountsUntilAl = 9; // Number of indices defined in PID.h equivalent to o2::track::PID::NIDs + // static_assert(PIDCountsUntilAl == o2::track::PID::NIDs, "PID::NIDs mismatch"); - // Define the antiparticles - static constexpr ID Positron = 17; - static constexpr ID MuonPlus = 18; - static constexpr ID PionMinus = 19; - static constexpr ID KaonMinus = 20; - static constexpr ID AntiProton = 21; - static constexpr ID AntiDeuteron = 22; - static constexpr ID AntiTriton = 23; - static constexpr ID AntiHelium3 = 24; - static constexpr ID AntiAlpha = 25; - static constexpr ID AntiLambda = 26; - static constexpr ID AntiHyperTriton = 27; - static constexpr ID AntiHyperhydrog4 = 28; - static constexpr ID XiPlus = 29; - static constexpr ID OmegaPlus = 30; + static constexpr ID PIDCounts = 19; // Number of indices defined in PID.h + // static_assert(PIDCounts == o2::track::PID::NIDsTot, "PID::NIDsTot mismatch"); + // Define an array of IDs + static constexpr std::array mIDsUntilAl = {Electron, Muon, Pion, Kaon, Proton, Deuteron, Triton, Helium3, Alpha}; + static constexpr std::array mIDs = {Electron, Muon, Pion, Kaon, Proton, Deuteron, Triton, Helium3, Alpha, PI0, Photon, K0, Lambda, HyperTriton, Hyperhydrog4, XiMinus, OmegaMinus, HyperHelium4, HyperHelium5}; - static constexpr ID Neutron = 31; - static constexpr ID AntiNeutron = 32; - static constexpr ID HyperHelium4 = 33; - static constexpr ID AntiHyperHelium4 = 34; - static constexpr ID Phi = 35; + // Define the antiparticles + static constexpr ID Positron = PIDCounts; + static constexpr ID MuonPlus = PIDCounts + 1; + static constexpr ID PionMinus = PIDCounts + 2; + static constexpr ID KaonMinus = PIDCounts + 3; + static constexpr ID AntiProton = PIDCounts + 4; + static constexpr ID AntiDeuteron = PIDCounts + 5; + static constexpr ID AntiTriton = PIDCounts + 6; + static constexpr ID AntiHelium3 = PIDCounts + 7; + static constexpr ID AntiAlpha = PIDCounts + 8; + static constexpr ID AntiLambda = PIDCounts + 9; + static constexpr ID AntiHyperTriton = PIDCounts + 10; + static constexpr ID AntiHyperhydrog4 = PIDCounts + 11; + static constexpr ID XiPlus = PIDCounts + 12; + static constexpr ID OmegaPlus = PIDCounts + 13; + static constexpr ID AntiHyperHelium4 = PIDCounts + 14; + static constexpr ID AntiHyperHelium5 = PIDCounts + 15; - static constexpr ID BZero = 36; - static constexpr ID BPlus = 37; - static constexpr ID BS = 38; - static constexpr ID D0 = 39; - static constexpr ID DPlus = 40; - static constexpr ID DS = 41; - static constexpr ID DStar = 42; - static constexpr ID ChiC1 = 43; - static constexpr ID JPsi = 44; - static constexpr ID LambdaB0 = 45; - static constexpr ID LambdaCPlus = 46; - static constexpr ID OmegaC0 = 47; - static constexpr ID SigmaC0 = 48; - static constexpr ID SigmaCPlusPlus = 49; - static constexpr ID X3872 = 50; - static constexpr ID Xi0 = 51; - static constexpr ID XiB0 = 52; - static constexpr ID XiCCPlusPlus = 53; - static constexpr ID XiCPlus = 54; - static constexpr ID XiC0 = 55; - static constexpr ID NIDsTot = 56; + static constexpr ID Neutron = PIDCounts + 16; + static constexpr ID AntiNeutron = PIDCounts + 17; + static constexpr ID Phi = PIDCounts + 18; + static constexpr ID BZero = PIDCounts + 19; + static constexpr ID BPlus = PIDCounts + 20; + static constexpr ID BS = PIDCounts + 21; + static constexpr ID D0 = PIDCounts + 22; + static constexpr ID DPlus = PIDCounts + 23; + static constexpr ID DS = PIDCounts + 24; + static constexpr ID DStar = PIDCounts + 25; + static constexpr ID ChiC1 = PIDCounts + 26; + static constexpr ID JPsi = PIDCounts + 27; + static constexpr ID LambdaB0 = PIDCounts + 28; + static constexpr ID LambdaCPlus = PIDCounts + 29; + static constexpr ID OmegaC0 = PIDCounts + 30; + static constexpr ID SigmaC0 = PIDCounts + 31; + static constexpr ID SigmaCPlusPlus = PIDCounts + 32; + static constexpr ID X3872 = PIDCounts + 33; + static constexpr ID Xi0 = PIDCounts + 34; + static constexpr ID XiB0 = PIDCounts + 35; + static constexpr ID XiCCPlusPlus = PIDCounts + 36; + static constexpr ID XiCPlus = PIDCounts + 37; + static constexpr ID XiC0 = PIDCounts + 38; + static constexpr ID NIDsTot = PIDCounts + 39; static constexpr const char* sNames[NIDsTot + 1] = { o2::track::pid_constants::sNames[Electron], // Electron @@ -137,6 +146,8 @@ class PIDExtended o2::track::pid_constants::sNames[Hyperhydrog4], // Hyperhydrog4 o2::track::pid_constants::sNames[XiMinus], // XiMinus o2::track::pid_constants::sNames[OmegaMinus], // OmegaMinus + "HyperHelium4", // HyperHelium4 + "HyperHelium5", // HyperHelium5 "Positron", // Positron "MuonPlus", // MuonPlus "PionMinus", // PionMinus @@ -151,10 +162,10 @@ class PIDExtended "AntiHyperhydrog4", // AntiHyperhydrog4 "XiPlus", // XiPlus "OmegaPlus", // OmegaPlus + "AntiHyperHelium4", // AntiHyperHelium4 + "AntiHyperHelium5", // AntiHyperHelium5 "Neutron", // Neutron "AntiNeutron", // AntiNeutron - "HyperHelium4", // HyperHelium4 - "AntiHyperHelium4", // AntiHyperHelium4 "Phi", // Phi "BZero", // BZero "BPlus", // BPlus @@ -191,7 +202,7 @@ class PIDExtended /// \brief Convert PDG code to PID index template - static o2::track::pid_constants::ID pdgToId(const TrackType& particle) + static ID pdgToId(const TrackType& particle) { switch (particle.pdgCode()) { case 11: @@ -238,6 +249,10 @@ class PIDExtended return HyperHelium4; case -o2::constants::physics::Pdg::kHyperHelium4: return AntiHyperHelium4; + case o2::constants::physics::Pdg::kHyperHelium5: + return HyperHelium5; + case -o2::constants::physics::Pdg::kHyperHelium5: + return AntiHyperHelium5; case 111: return PI0; case 22: diff --git a/PWGMM/Lumi/Tasks/lumiStability.cxx b/PWGMM/Lumi/Tasks/lumiStability.cxx index ee2f7b8b497..0a6c62f35b9 100644 --- a/PWGMM/Lumi/Tasks/lumiStability.cxx +++ b/PWGMM/Lumi/Tasks/lumiStability.cxx @@ -23,14 +23,17 @@ #include "DataFormatsFT0/Digit.h" #include "DataFormatsFV0/Digit.h" #include "Framework/ASoA.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonDataFormat/BunchFilling.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" using namespace o2; using namespace o2::framework; using BCsWithTimestamps = soa::Join; -int nBCsPerOrbit = 3564; - struct lumiStabilityTask { // Histogram registry: an object to hold your histograms HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -39,19 +42,44 @@ struct lumiStabilityTask { Configurable myMaxDeltaBCFDD{"myMaxDeltaBCFDD", 5, {"My BC cut"}}; Configurable myMaxDeltaBCFT0{"myMaxDeltaBCFT0", 5, {"My BC cut"}}; Configurable myMaxDeltaBCFV0{"myMaxDeltaBCFV0", 5, {"My BC cut"}}; + Configurable nOrbitsConf{"nOrbits", 10000, "number of orbits"}; + Configurable minOrbitConf{"minOrbit", 0, "minimum orbit"}; + + Service ccdb; + int nBCsPerOrbit = 3564; + int lastRunNumber = -1; + int nOrbits = nOrbitsConf; + double minOrbit = minOrbitConf; + int64_t bcSOR = 0; // global bc of the start of the first orbit, setting 0 by default for unanchored MC + int64_t nBCsPerTF = 128 * nBCsPerOrbit; // duration of TF in bcs, should be 128*3564 or 32*3564, setting 128 orbits by default sfor unanchored MC + std::bitset beamPatternA; + std::bitset beamPatternC; + std::bitset bcPatternA; + std::bitset bcPatternC; + std::bitset bcPatternB; + std::bitset bcPatternE; void init(InitContext const&) { - const AxisSpec axisCounts{5, -0.5, 4.5}; + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + const AxisSpec axisCounts{6, -0.5, 5.5}; + const AxisSpec axisV0Counts{5, -0.5, 4.5}; const AxisSpec axisTriggger{nBCsPerOrbit, -0.5f, nBCsPerOrbit - 0.5f}; + histos.add("hBcA", "BC pattern A; BC ; It is present", kTH1F, {axisTriggger}); + histos.add("hBcC", "BC pattern C; BC ; It is present", kTH1F, {axisTriggger}); + histos.add("hBcB", "BC pattern B; BC ; It is present", kTH1F, {axisTriggger}); + histos.add("hBcE", "BC pattern Empty; BC ; It is present", kTH1F, {axisTriggger}); + // histo about triggers - histos.add("FDD/hCounts", "0 CountVertexFDD - 1 CountPFPVertexCoincidencesFDD - 2 CountPFPTriggerCoincidencesFDD - 3 CountPPVertexCoincidencesFDD - 4 CountPPTriggerCoincidencesFDD; Number; counts", kTH1F, {axisCounts}); + histos.add("FDD/hCounts", "0 FDDCount - 1 FDDVertexCount - 2 FDDPPVertexCount - 3 FDDCoincidencesVertexCount - 4 FDDPPCoincidencesVertexCount - 5 FDDPPBotSidesCount; Number; counts", kTH1F, {axisCounts}); histos.add("FDD/bcVertexTrigger", "vertex trigger per BC (FDD);BC in FDD; counts", kTH1F, {axisTriggger}); + histos.add("FDD/bcVertexTriggerPP", "vertex trigger per BC (FDD);BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcVertexTriggerCoincidence", "vertex trigger per BC (FDD) with coincidences;BC in FDD; counts", kTH1F, {axisTriggger}); - histos.add("FDD/bcVertexTriggerCoincidencePFP", "vertex trigger per BC (FDD) with coincidences and Past Future Protection;BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcVertexTriggerCoincidencePP", "vertex trigger per BC (FDD) with coincidences and Past Protection;BC in FDD; counts", kTH1F, {axisTriggger}); - histos.add("FDD/bcVertexTriggerBothSidesCoincidencePFP", "vertex per BC (FDD) with coincidences, at least one side trigger and Past Future Protection;BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcVertexTriggerBothSidesCoincidencePP", "vertex per BC (FDD) with coincidences, at least one side trigger and Past Protection;BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcSCentralTrigger", "scentral trigger per BC (FDD);BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcSCentralTriggerCoincidence", "scentral trigger per BC (FDD) with coincidences;BC in FDD; counts", kTH1F, {axisTriggger}); @@ -61,19 +89,41 @@ struct lumiStabilityTask { histos.add("FDD/bcCentralTriggerCoincidence", "central trigger per BC (FDD) with coincidences;BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcVCTrigger", "vertex and central trigger per BC (FDD);BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FDD/bcVCTriggerCoincidence", "vertex and central trigger per BC (FDD) with coincidences;BC in FDD; counts", kTH1F, {axisTriggger}); - - histos.add("FT0/hCounts", "0 CountVertexFT0 - 1 CountPFPVertexCoincidencesFT0 - 2 CountPFPTriggerCoincidencesFT0 - 3 CountPPVertexCoincidencesFT0 - 4 CountPPTriggerCoincidencesFT0; Number; counts", kTH1F, {axisCounts}); + histos.add("FDD/hBcAVertex", "BC pattern A in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/hBcCVertex", "BC pattern C in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/hBcBVertex", "BC pattern B in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/hBcEVertex", "BC pattern Empty in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/timeACbcBVertex", "time bcB ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/timeACbcAVertex", "time bcA ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/timeACbcCVertex", "time bcC ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/timeACbcEVertex", "time bcE ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/hBcA", "BC pattern A in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/hBcC", "BC pattern C in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/hBcB", "BC pattern B in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/hBcE", "BC pattern Empty in FDD; BC in FDD ; It is present", kTH1F, {axisTriggger}); + histos.add("FDD/timeACbcB", "time bcB ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/timeACbcA", "time bcA ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/timeACbcC", "time bcC ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/timeACbcE", "time bcE ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + + histos.add("FT0/hCounts", "0 FT0Count - 1 FT0VertexCount - 2 FT0PPVertexCount - 3 FT0PPBothSidesCount; Number; counts", kTH1F, {axisCounts}); histos.add("FT0/bcVertexTrigger", "vertex trigger per BC (FT0);BC in FT0; counts", kTH1F, {axisTriggger}); - histos.add("FT0/bcVertexTriggerPFP", "vertex trigger per BC (FT0) with Past Future Protection;BC in FT0; counts", kTH1F, {axisTriggger}); histos.add("FT0/bcVertexTriggerPP", "vertex trigger per BC (FT0) with Past Protection;BC in FT0; counts", kTH1F, {axisTriggger}); - histos.add("FT0/bcVertexTriggerBothSidesPFP", "vertex per BC (FDD) with coincidences, at least one side trigger and Past Future Protection;BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FT0/bcVertexTriggerBothSidesPP", "vertex per BC (FDD) with coincidences, at least one side trigger and Past Protection;BC in FDD; counts", kTH1F, {axisTriggger}); histos.add("FT0/bcSCentralTrigger", "Scentral trigger per BC (FT0);BC in FT0; counts", kTH1F, {axisTriggger}); histos.add("FT0/bcVSCTrigger", "vertex and Scentral trigger per BC (FT0);BC in FT0; counts", kTH1F, {axisTriggger}); histos.add("FT0/bcCentralTrigger", "central trigger per BC (FT0);BC in FT0; counts", kTH1F, {axisTriggger}); histos.add("FT0/bcVCTrigger", "vertex and central trigger per BC (FT0);BC in FT0; counts", kTH1F, {axisTriggger}); - - histos.add("FV0/hCounts", "0 CountCentralFV0 - 1 CountPFPCentralFV0 - 2 CountPFPOutInFV0 - 3 CountPPCentralFV0 - 4 CountPPOutInFV0; Number; counts", kTH1F, {axisCounts}); + histos.add("FT0/hBcA", "BC pattern A in FT0; BC in FT0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FT0/hBcC", "BC pattern C in FT0; BC in FT0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FT0/hBcB", "BC pattern B in FT0; BC in FT0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FT0/hBcE", "BC pattern Empty in FT0; BC in FT0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FT0/timeACbcB", "time bcB ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FT0/timeACbcA", "time bcA ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FT0/timeACbcC", "time bcC ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FT0/timeACbcE", "time bcE ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + + histos.add("FV0/hCounts", "0 CountCentralFV0 - 1 CountPFPCentralFV0 - 2 CountPFPOutInFV0 - 3 CountPPCentralFV0 - 4 CountPPOutInFV0; Number; counts", kTH1F, {axisV0Counts}); histos.add("FV0/bcOutTrigger", "Out trigger per BC (FV0);BC in V0; counts", kTH1F, {axisTriggger}); histos.add("FV0/bcInTrigger", "In trigger per BC (FV0);BC in V0; counts", kTH1F, {axisTriggger}); histos.add("FV0/bcSCenTrigger", "SCen trigger per BC (FV0);BC in V0; counts", kTH1F, {axisTriggger}); @@ -101,8 +151,78 @@ struct lumiStabilityTask { return false; } - void processMain(aod::FDDs const& fdds, aod::FT0s const& ft0s, aod::FV0As const& fv0s, aod::BCsWithTimestamps const&) + void processMain(aod::FDDs const& fdds, aod::FT0s const& ft0s, aod::FV0As const& fv0s, aod::BCsWithTimestamps const& bcs) { + uint32_t nOrbitsPerTF = 128; // 128 in 2022, 32 in 2023 + int runNumber = bcs.iteratorAt(0).runNumber(); + if (runNumber != lastRunNumber) { + lastRunNumber = runNumber; // do it only once + int64_t tsSOR = 0; + int64_t tsEOR = 1; + + if (runNumber >= 500000) { // access CCDB for data or anchored MC only + int64_t ts = bcs.iteratorAt(0).timestamp(); + + // access colliding and beam-gas bc patterns + auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); + beamPatternA = grplhcif->getBunchFilling().getBeamPattern(0); + beamPatternC = grplhcif->getBunchFilling().getBeamPattern(1); + bcPatternA = beamPatternA & ~beamPatternC; + bcPatternC = ~beamPatternA & beamPatternC; + bcPatternB = beamPatternA & beamPatternC; + bcPatternE = ~beamPatternA & ~beamPatternC; + + for (int i = 0; i < nBCsPerOrbit; i++) { + if (bcPatternA[i]) { + histos.fill(HIST("hBcA"), i); + } + if (bcPatternC[i]) { + histos.fill(HIST("hBcC"), i); + } + if (bcPatternB[i]) { + histos.fill(HIST("hBcB"), i); + } + if (bcPatternE[i]) { + histos.fill(HIST("hBcE"), i); + } + } + + EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", ts); + // access orbit-reset timestamp + auto ctpx = ccdb->getForTimeStamp>("CTP/Calib/OrbitReset", ts); + int64_t tsOrbitReset = (*ctpx)[0]; // us + // access TF duration, start-of-run and end-of-run timestamps from ECS GRP + std::map metadata; + metadata["runNumber"] = Form("%d", runNumber); + auto grpecs = ccdb->getSpecific("GLO/Config/GRPECS", ts, metadata); + nOrbitsPerTF = grpecs->getNHBFPerTF(); // assuming 1 orbit = 1 HBF; nOrbitsPerTF=128 in 2022, 32 in 2023 + tsSOR = grpecs->getTimeStart(); // ms + tsEOR = grpecs->getTimeEnd(); // ms + // calculate SOR and EOR orbits + int64_t orbitSOR = (tsSOR * 1000 - tsOrbitReset) / o2::constants::lhc::LHCOrbitMUS; + int64_t orbitEOR = (tsEOR * 1000 - tsOrbitReset) / o2::constants::lhc::LHCOrbitMUS; + // adjust to the nearest TF edge + orbitSOR = orbitSOR / nOrbitsPerTF * nOrbitsPerTF + par->fTimeFrameOrbitShift; + orbitEOR = orbitEOR / nOrbitsPerTF * nOrbitsPerTF + par->fTimeFrameOrbitShift; + // set nOrbits and minOrbit used for orbit-axis binning + nOrbits = orbitEOR - orbitSOR; + minOrbit = orbitSOR; + // first bc of the first orbit (should coincide with TF start) + bcSOR = orbitSOR * o2::constants::lhc::LHCMaxBunches; + // duration of TF in bcs + nBCsPerTF = nOrbitsPerTF * o2::constants::lhc::LHCMaxBunches; + LOGP(info, "tsOrbitReset={} us, SOR = {} ms, EOR = {} ms, orbitSOR = {}, nBCsPerTF = {}", tsOrbitReset, tsSOR, tsEOR, orbitSOR, nBCsPerTF); + } + + // create orbit-axis histograms on the fly with binning based on info from GRP if GRP is available + // otherwise default minOrbit and nOrbits will be used + const AxisSpec axisOrbits{static_cast(nOrbits / nOrbitsPerTF), 0., static_cast(nOrbits), ""}; + histos.add("hOrbitFDD", "FDD Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + histos.add("hOrbitFDDVertex", "FDD Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + histos.add("hOrbitFT0", "FT0 Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + histos.add("hOrbitFV0", "FV0 Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + } + for (auto const& fdd : fdds) { auto bc = fdd.bc_as(); if (bc.timestamp() == 0) { @@ -111,6 +231,7 @@ struct lumiStabilityTask { Long64_t globalBC = bc.globalBC(); int localBC = globalBC % nBCsPerOrbit; + uint64_t orbit = globalBC / nBCsPerOrbit; std::bitset<8> fddTriggers = fdd.triggerMask(); bool vertex = fddTriggers[o2::fdd::Triggers::bitVertex]; @@ -133,10 +254,76 @@ struct lumiStabilityTask { bool isCoinA = checkAnyCoincidence(channelA); bool isCoinC = checkAnyCoincidence(channelC); + histos.fill(HIST("FDD/hCounts"), 0); if (vertex) { histos.fill(HIST("FDD/bcVertexTrigger"), localBC); + histos.fill(HIST("FDD/hCounts"), 1); + histos.fill(HIST("hOrbitFDDVertex"), orbit - minOrbit); + + if (bcPatternA[localBC]) { + histos.fill(HIST("FDD/timeACbcAVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcAVertex"), localBC); + } + if (bcPatternC[localBC]) { + histos.fill(HIST("FDD/timeACbcCVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcCVertex"), localBC); + } + if (bcPatternB[localBC]) { + histos.fill(HIST("FDD/timeACbcBVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcBVertex"), localBC); + } + if (bcPatternE[localBC]) { + histos.fill(HIST("FDD/timeACbcEVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcEVertex"), localBC); + } + + int deltaIndex = 0; // backward move counts + int deltaBC = 0; // current difference wrt globalBC + bool pastActivityFDDVertex = false; + while (deltaBC < myMaxDeltaBCFDD) { + deltaIndex++; + if (fdd.globalIndex() - deltaIndex < 0) { + break; + } + const auto& fdd_past = fdds.iteratorAt(fdd.globalIndex() - deltaIndex); + auto bc_past = fdd_past.bc_as(); + deltaBC = globalBC - bc_past.globalBC(); + + if (deltaBC < myMaxDeltaBCFDD) { + std::bitset<8> fddTriggersPast = fdd_past.triggerMask(); + bool vertexPast = fddTriggersPast[o2::fdd::Triggers::bitVertex]; + pastActivityFDDVertex |= (vertexPast); + } + } + deltaIndex = 0; + deltaBC = 0; + + if (pastActivityFDDVertex == false) { + histos.fill(HIST("FDD/hCounts"), 2); + histos.fill(HIST("FDD/bcVertexTriggerPP"), localBC); + } + if (isCoinA && isCoinC) { histos.fill(HIST("FDD/bcVertexTriggerCoincidence"), localBC); + histos.fill(HIST("FDD/hCounts"), 1); + histos.fill(HIST("hOrbitFDD"), orbit - minOrbit); + + if (bcPatternA[localBC]) { + histos.fill(HIST("FDD/timeACbcA"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcA"), localBC); + } + if (bcPatternC[localBC]) { + histos.fill(HIST("FDD/timeACbcC"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcC"), localBC); + } + if (bcPatternB[localBC]) { + histos.fill(HIST("FDD/timeACbcB"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcB"), localBC); + } + if (bcPatternE[localBC]) { + histos.fill(HIST("FDD/timeACbcE"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcE"), localBC); + } int deltaIndex = 0; // backward move counts int deltaBC = 0; // current difference wrt globalBC @@ -149,7 +336,8 @@ struct lumiStabilityTask { break; } const auto& fdd_past = fdds.iteratorAt(fdd.globalIndex() - deltaIndex); - deltaBC = fdd.bcId() - fdd_past.bcId(); + auto bc_past = fdd_past.bc_as(); + deltaBC = globalBC - bc_past.globalBC(); if (deltaBC < myMaxDeltaBCFDD) { std::bitset<8> fddTriggersPast = fdd_past.triggerMask(); @@ -179,66 +367,16 @@ struct lumiStabilityTask { deltaIndex = 0; deltaBC = 0; - bool futureActivityFDDVertexCoincidences = false; - bool futureActivityFDDTriggerACoincidenceA = false; - bool futureActivityFDDTriggerCCoincidenceC = false; - while (deltaBC < myMaxDeltaBCFDD) { - deltaIndex++; - if (fdd.globalIndex() + deltaIndex >= fdds.size()) { - break; - } - const auto& fdd_future = fdds.iteratorAt(fdd.globalIndex() + deltaIndex); - deltaBC = fdd_future.bcId() - fdd.bcId(); - - if (deltaBC < myMaxDeltaBCFDD) { - std::bitset<8> fddTriggersFuture = fdd_future.triggerMask(); - bool vertexFuture = fddTriggersFuture[o2::fdd::Triggers::bitVertex]; - bool triggerAFuture = fddTriggersFuture[o2::fdd::Triggers::bitA]; - bool triggerCFuture = fddTriggersFuture[o2::fdd::Triggers::bitC]; - auto SideAFuture = fdd_future.chargeA(); - auto SideCFuture = fdd_future.chargeC(); - std::vector channelAFuture; - std::vector channelCFuture; - for (auto i = 0; i < 8; i++) { - if (SideAFuture[i] > 0) { - channelAFuture.push_back(i); - } - if (SideCFuture[i] > 0) { - channelCFuture.push_back(i); - } - } - - bool isCoinAFuture = checkAnyCoincidence(channelAFuture); - bool isCoinCFuture = checkAnyCoincidence(channelCFuture); - futureActivityFDDVertexCoincidences |= (vertexFuture & isCoinAFuture & isCoinCFuture); - futureActivityFDDTriggerACoincidenceA |= (triggerAFuture & isCoinAFuture); - futureActivityFDDTriggerCCoincidenceC |= (triggerCFuture & isCoinCFuture); - } - } - - histos.fill(HIST("FDD/hCounts"), 0); - if ((pastActivityFDDTriggerACoincidenceA || futureActivityFDDTriggerACoincidenceA) == true || (pastActivityFDDTriggerCCoincidenceC || futureActivityFDDTriggerCCoincidenceC) == true) { + if (pastActivityFDDVertexCoincidences == false) { histos.fill(HIST("FDD/hCounts"), 2); - } else { - histos.fill(HIST("FDD/bcVertexTriggerBothSidesCoincidencePFP"), localBC); - } - if (pastActivityFDDTriggerACoincidenceA == true || pastActivityFDDTriggerCCoincidenceC == true) { - histos.fill(HIST("FDD/hCounts"), 4); - } else { - histos.fill(HIST("FDD/bcVertexTriggerBothSidesCoincidencePP"), localBC); - } - if (pastActivityFDDVertexCoincidences == true || futureActivityFDDVertexCoincidences == true) { - histos.fill(HIST("FDD/hCounts"), 1); - } else { - histos.fill(HIST("FDD/bcVertexTriggerCoincidencePFP"), localBC); + histos.fill(HIST("FDD/bcVertexTriggerCoincidencePP"), localBC); } - if (pastActivityFDDVertexCoincidences == true) { + if (pastActivityFDDTriggerACoincidenceA == false || pastActivityFDDTriggerCCoincidenceC == false) { histos.fill(HIST("FDD/hCounts"), 3); - } else { - histos.fill(HIST("FDD/bcVertexTriggerCoincidencePP"), localBC); + histos.fill(HIST("FDD/bcVertexTriggerBothSidesCoincidencePP"), localBC); } - } - } // vertex true + } // coincidences + } // vertex true if (scentral) { histos.fill(HIST("FDD/bcSCentralTrigger"), localBC); @@ -277,14 +415,34 @@ struct lumiStabilityTask { Long64_t globalBC = bc.globalBC(); int localBC = globalBC % nBCsPerOrbit; + uint64_t orbit = globalBC / nBCsPerOrbit; std::bitset<8> fT0Triggers = ft0.triggerMask(); bool vertex = fT0Triggers[o2::ft0::Triggers::bitVertex]; bool sCentral = fT0Triggers[o2::ft0::Triggers::bitSCen]; bool central = fT0Triggers[o2::ft0::Triggers::bitCen]; + histos.fill(HIST("FT0/hCounts"), 0); if (vertex) { histos.fill(HIST("FT0/bcVertexTrigger"), localBC); + histos.fill(HIST("hOrbitFT0"), orbit - minOrbit); + + if (bcPatternA[localBC]) { + histos.fill(HIST("FT0/timeACbcA"), ft0.timeA(), ft0.timeC()); + histos.fill(HIST("FT0/hBcA"), localBC); + } + if (bcPatternC[localBC]) { + histos.fill(HIST("FT0/timeACbcC"), ft0.timeA(), ft0.timeC()); + histos.fill(HIST("FT0/hBcC"), localBC); + } + if (bcPatternB[localBC]) { + histos.fill(HIST("FT0/timeACbcB"), ft0.timeA(), ft0.timeC()); + histos.fill(HIST("FT0/hBcB"), localBC); + } + if (bcPatternE[localBC]) { + histos.fill(HIST("FT0/timeACbcE"), ft0.timeA(), ft0.timeC()); + histos.fill(HIST("FT0/hBcE"), localBC); + } int deltaIndex = 0; // backward move counts int deltaBC = 0; // current difference wrt globalBC @@ -297,7 +455,8 @@ struct lumiStabilityTask { break; } const auto& ft0_past = ft0s.iteratorAt(ft0.globalIndex() - deltaIndex); - deltaBC = ft0.bcId() - ft0_past.bcId(); + auto bc_past = ft0_past.bc_as(); + deltaBC = globalBC - bc_past.globalBC(); if (deltaBC < myMaxDeltaBCFT0) { std::bitset<8> fT0TriggersPast = ft0_past.triggerMask(); @@ -313,49 +472,14 @@ struct lumiStabilityTask { deltaIndex = 0; deltaBC = 0; - bool futureActivityFT0Vertex = false; - bool futureActivityFT0TriggerA = false; - bool futureActivityFT0TriggerC = false; - while (deltaBC < myMaxDeltaBCFT0) { - deltaIndex++; - if (ft0.globalIndex() + deltaIndex >= ft0s.size()) { - break; - } - const auto& ft0_future = ft0s.iteratorAt(ft0.globalIndex() + deltaIndex); - deltaBC = ft0_future.bcId() - ft0.bcId(); - - if (deltaBC < myMaxDeltaBCFT0) { - std::bitset<8> fT0TriggersFuture = ft0_future.triggerMask(); - bool vertexFuture = fT0TriggersFuture[o2::ft0::Triggers::bitVertex]; - bool triggerAFuture = fT0TriggersFuture[o2::ft0::Triggers::bitA]; - bool triggerCFuture = fT0TriggersFuture[o2::ft0::Triggers::bitC]; - - futureActivityFT0Vertex |= vertexFuture; - futureActivityFT0TriggerA |= triggerAFuture; - futureActivityFT0TriggerC |= triggerCFuture; - } - } - - histos.fill(HIST("FT0/hCounts"), 0); - if ((pastActivityFT0TriggerA || futureActivityFT0TriggerA) == true || (pastActivityFT0TriggerC || futureActivityFT0TriggerC) == true) { + histos.fill(HIST("FT0/hCounts"), 1); + if (pastActivityFT0Vertex == false) { histos.fill(HIST("FT0/hCounts"), 2); - } else { - histos.fill(HIST("FT0/bcVertexTriggerBothSidesPFP"), localBC); - } - if (pastActivityFT0TriggerA == true || pastActivityFT0TriggerC == true) { - histos.fill(HIST("FT0/hCounts"), 4); - } else { - histos.fill(HIST("FT0/bcVertexTriggerBothSidesPP"), localBC); - } - if (pastActivityFT0Vertex == true || futureActivityFT0Vertex == true) { - histos.fill(HIST("FT0/hCounts"), 1); - } else { - histos.fill(HIST("FT0/bcVertexTriggerPFP"), localBC); + histos.fill(HIST("FT0/bcVertexTriggerPP"), localBC); } - if (pastActivityFT0Vertex == true) { + if (pastActivityFT0TriggerA == false || pastActivityFT0TriggerC == false) { histos.fill(HIST("FT0/hCounts"), 3); - } else { - histos.fill(HIST("FT0/bcVertexTriggerPP"), localBC); + histos.fill(HIST("FT0/bcVertexTriggerBothSidesPP"), localBC); } } // vertex true @@ -385,6 +509,7 @@ struct lumiStabilityTask { Long64_t globalBC = bc.globalBC(); int localBC = globalBC % nBCsPerOrbit; + uint64_t orbit = globalBC / nBCsPerOrbit; std::bitset<8> fv0Triggers = fv0.triggerMask(); bool aOut = fv0Triggers[o2::fv0::Triggers::bitAOut]; @@ -405,6 +530,7 @@ struct lumiStabilityTask { } if (aCen) { + histos.fill(HIST("hOrbitFV0"), orbit - minOrbit); histos.fill(HIST("FV0/bcCenTrigger"), localBC); int deltaIndex = 0; // backward move counts @@ -418,7 +544,8 @@ struct lumiStabilityTask { break; } const auto& fv0_past = fv0s.iteratorAt(fv0.globalIndex() - deltaIndex); - deltaBC = fv0.bcId() - fv0_past.bcId(); + auto bc_past = fv0_past.bc_as(); + deltaBC = globalBC - bc_past.globalBC(); if (deltaBC < myMaxDeltaBCFV0) { std::bitset<8> fv0Triggers = fv0_past.triggerMask(); diff --git a/PWGMM/Mult/DataModel/CMakeLists.txt b/PWGMM/Mult/DataModel/CMakeLists.txt index 14fe4e618af..42f51846fda 100644 --- a/PWGMM/Mult/DataModel/CMakeLists.txt +++ b/PWGMM/Mult/DataModel/CMakeLists.txt @@ -10,4 +10,4 @@ # or submit itself to any jurisdiction. o2physics_add_header_only_library(MultDataModel - HEADERS ReducedTables.h) + HEADERS ReducedTables.h Gencentralities.h) diff --git a/PWGMM/Mult/DataModel/Gencentralities.h b/PWGMM/Mult/DataModel/Gencentralities.h new file mode 100644 index 00000000000..112072fa2c8 --- /dev/null +++ b/PWGMM/Mult/DataModel/Gencentralities.h @@ -0,0 +1,27 @@ +// Copyright 2019-2020 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. + +#ifndef PWGMM_MULT_DATAMODEL_GENCENTRALITIES_H_ +#define PWGMM_MULT_DATAMODEL_GENCENTRALITIES_H_ + +#include "Framework/AnalysisDataModel.h" +namespace o2::aod +{ +namespace gencents +{ +DECLARE_SOA_COLUMN(GenCentFT0C, gencentFT0C, float); +DECLARE_SOA_COLUMN(GenCentFT0M, gencentFT0M, float); +} // namespace gencents +DECLARE_SOA_TABLE(GenCents, "AOD", "GENCENT", + gencents::GenCentFT0C, + gencents::GenCentFT0M); +} // namespace o2::aod +#endif // PWGMM_MULT_DATAMODEL_GENCENTRALITIES_H_ diff --git a/PWGMM/Mult/TableProducer/CMakeLists.txt b/PWGMM/Mult/TableProducer/CMakeLists.txt index f37c5f106ef..9b1ddb5e997 100644 --- a/PWGMM/Mult/TableProducer/CMakeLists.txt +++ b/PWGMM/Mult/TableProducer/CMakeLists.txt @@ -28,3 +28,8 @@ o2physics_add_dpl_workflow(track-propagation SOURCES trackPropagation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(percentiles + SOURCES percentiles.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGMM/Mult/TableProducer/percentiles.cxx b/PWGMM/Mult/TableProducer/percentiles.cxx new file mode 100644 index 00000000000..c11fca858f8 --- /dev/null +++ b/PWGMM/Mult/TableProducer/percentiles.cxx @@ -0,0 +1,236 @@ +// Copyright 2019-2020 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. +#include "Selections.h" + +#include +#include +#include +#include +#include "Common/DataModel/Centrality.h" +#include +#include +#include +#include + +#include "Gencentralities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using namespace pwgmm::mult; + +constexpr float FT0Alo = -3.3; +constexpr float FT0Ahi = -2.1; +constexpr float FT0Clo = 3.5; +constexpr float FT0Chi = 4.9; + +struct Binner { + Service pdg; + Produces gencents; + HistogramRegistry h{"histograms", {}}; + + using Particles = soa::Filtered; + Preslice perMcCol = aod::mcparticle::mcCollisionId; + Preslice perCol = aod::track::collisionId; + + ConfigurableAxis multBinning{"multBinning", {302, -1.5, 300.5}, ""}; + ConfigurableAxis centBinning{"centBinning", {VARIABLE_WIDTH, 0, 1, 5, 10, 15, 20, 30, 40, 50, 70, 100}, ""}; + + // The objects are uploaded with https://alimonitor.cern.ch/ccdb/upload.jsp + Service ccdb; + Configurable path{"ccdb-path", "Users/a/aalkin/gencentralities", "base path to the ccdb object"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + bool isChargedParticle(int code) const + { + static auto p = pdg->GetParticle(code); + if (p == nullptr) { + return 0; + } + return std::abs(p->Charge()) >= 3.; + } + + template + static inline bool isCollisionSelectedMC(C const& collision) + { + return collision.selection_bit(aod::evsel::kIsTriggerTVX) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kIsVertexITSTPC) && + collision.selection_bit(aod::evsel::kIsVertexTOFmatched); + } + + template + static inline bool isCollisionSelected(C const& collision) + { + return collision.selection_bit(aod::evsel::kIsTriggerTVX) && + collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && + collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kIsVertexITSTPC) && + collision.selection_bit(aod::evsel::kIsVertexTOFmatched); + } + + TH1F* multFT0C = nullptr; + TH1F* multFT0M = nullptr; + + void init(InitContext const&) + { + AxisSpec MultAxis = {multBinning}; + h.add({"hFT0M", "; N_{part} in FT0M acc", {HistType::kTH1F, {MultAxis}}}); + h.add({"hFT0C", "; N_{part} in FT0C acc", {HistType::kTH1F, {MultAxis}}}); + if (dobin) { + ccdb->setURL(url.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + if (docalibrateAdvanced) { + centBinning.value.insert(centBinning.value.begin() + 1, {-2}); + AxisSpec ExtraCentAxis = {centBinning}; + h.add({"hCorrelate", " ; N_{part}^{FT0M}; N_{part}^{FT0C}; N_{trk}^{#eta = 0}", {HistType::kTHnSparseF, {MultAxis, MultAxis, MultAxis, ExtraCentAxis}}}); + } + if (dogetData) { + AxisSpec CentAxis = {centBinning}; + h.add({"hTrkAt0vsFT0M", " ; N_{trk}^{#eta = 0}; FT0M percentile", {HistType::kTH2F, {MultAxis, CentAxis}}}); + } + } + + Filter primaries = ncheckbit(aod::mcparticle::flags, (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); + Partition pFT0M = ((aod::mcparticle::eta > FT0Alo) && (aod::mcparticle::eta < FT0Ahi)) || ((aod::mcparticle::eta > FT0Clo) && (aod::mcparticle::eta < FT0Chi)); + Partition pFT0C = (aod::mcparticle::eta > FT0Clo) && (aod::mcparticle::eta < FT0Chi); + + void calibrate(aod::McCollisions const& mccollisions, Particles const&) + { + for (auto& mcc : mccollisions) { + auto pcFT0M = pFT0M.sliceBy(perMcCol, mcc.globalIndex()); + auto pcFT0C = pFT0C.sliceBy(perMcCol, mcc.globalIndex()); + int nFT0M = 0; + int nFT0C = 0; + for (auto& p : pcFT0M) { + if (isChargedParticle(p.pdgCode())) { + ++nFT0M; + } + } + h.fill(HIST("hFT0M"), nFT0M); + for (auto& p : pcFT0C) { + if (isChargedParticle(p.pdgCode())) { + ++nFT0C; + } + } + h.fill(HIST("hFT0C"), nFT0C); + } + } + + PROCESS_SWITCH(Binner, calibrate, "Create binnings", true); + + using ExColsMCFT0M = soa::Join; + using ExColsCentFT0M = soa::Join; + using Trks = soa::Join; + // require a mix of ITS+TPC and ITS-only tracks (filters on the same table are automatically combined with &&) + Filter fTrackSelectionITS = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, trackSelectionITS); + Filter fTrackSelectionTPC = ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), + ncheckbit(aod::track::trackCutFlag, trackSelectionTPC), true); + Filter fTrackSelectionDCA = nabs(aod::track::dcaZ) <= 0.2f && ncheckbit(aod::track::trackCutFlag, trackSelectionDCAXYonly); + Filter fTracksEta = nabs(aod::track::eta) < 0.5f; + + void calibrateAdvanced(aod::McCollision const& mcc, + soa::SmallGroups const& collisions, + Particles const&, + soa::Filtered const& tracks) + { + auto pcFT0M = pFT0M.sliceBy(perMcCol, mcc.globalIndex()); + auto pcFT0C = pFT0C.sliceBy(perMcCol, mcc.globalIndex()); + int nFT0M = 0; + int nFT0C = 0; + int nTrkAt0 = 0; + for (auto& p : pcFT0M) { + if (isChargedParticle(p.pdgCode())) { + ++nFT0M; + } + } + h.fill(HIST("hFT0M"), nFT0M); + for (auto& p : pcFT0C) { + if (isChargedParticle(p.pdgCode())) { + ++nFT0C; + } + } + h.fill(HIST("hFT0C"), nFT0C); + + bool selected = false; + float cent = 1.e3; + for (auto& c : collisions) { + if (isCollisionSelectedMC(c)) { + selected = true; + auto sample = tracks.sliceBy(perCol, c.globalIndex()); + nTrkAt0 += sample.size(); + if (c.centFT0M() < cent) { + cent = c.centFT0M(); + } + } + } + if (!selected) { + nTrkAt0 = -1; + cent = -1; + } + h.fill(HIST("hCorrelate"), nFT0M, nFT0C, nTrkAt0, cent); + } + + PROCESS_SWITCH(Binner, calibrateAdvanced, "Create binning matched to dN/deta", false); + + void getData(ExColsCentFT0M::iterator const& collision, + soa::Filtered const& tracks) + { + if (isCollisionSelected(collision)) { + h.fill(HIST("hTrkAt0vsFT0M"), tracks.size(), collision.centFT0M()); + } + } + + PROCESS_SWITCH(Binner, getData, "Get data distribution to match to", false); + + void bin(aod::BCsWithTimestamps const& bcs, aod::McCollisions const& mccollisions, Particles const&) + { + auto bc = bcs.begin(); + multFT0M = ccdb->getForTimeStamp(path.value + "/hFT0M", bc.timestamp()); + multFT0C = ccdb->getForTimeStamp(path.value + "/hFT0C", bc.timestamp()); + if (multFT0C == nullptr && multFT0M == nullptr) { + LOGP(fatal, "Unable to get the distributions from CCDB"); + } + for (auto& mcc : mccollisions) { + auto pcFT0M = pFT0M.sliceBy(perMcCol, mcc.globalIndex()); + auto pcFT0C = pFT0C.sliceBy(perMcCol, mcc.globalIndex()); + int nFT0M = 0; + int nFT0C = 0; + for (auto& p : pcFT0M) { + if (isChargedParticle(p.pdgCode())) { + ++nFT0M; + } + } + h.fill(HIST("hFT0M"), nFT0M); + for (auto& p : pcFT0C) { + if (isChargedParticle(p.pdgCode())) { + ++nFT0C; + } + } + h.fill(HIST("hFT0C"), nFT0C); + float percentileFT0M = 100.f * multFT0M->Integral(multFT0M->FindFixBin(nFT0C), multFT0M->FindLastBinAbove()); + float percentileFT0C = 100.f * multFT0C->Integral(multFT0C->FindFixBin(nFT0C), multFT0C->FindLastBinAbove()); + gencents(percentileFT0C, percentileFT0M); + } + } + + PROCESS_SWITCH(Binner, bin, "Bin collisions", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return {adaptAnalysisTask(cfgc)}; +} diff --git a/PWGMM/Mult/TableProducer/reducer.cxx b/PWGMM/Mult/TableProducer/reducer.cxx index 5eda9070ca8..de9d516703b 100644 --- a/PWGMM/Mult/TableProducer/reducer.cxx +++ b/PWGMM/Mult/TableProducer/reducer.cxx @@ -47,10 +47,17 @@ struct Reducer { Configurable> etaBins{"eta", {-1.5, -0.5, 0.5, 1.5}, "eta binning"}; Configurable> phiBins{"phi", {0., PI / 2., PI, 3. * PI / 2., 2. * PI}, "phi binning"}; + Configurable useEvSel{"useEvSel", true, "use event selection"}; + Configurable checkTF{"checkTF", false, "check TF border"}; + Configurable checkITSROF{"checkITSROF", false, "check ITS readout frame border"}; + Configurable checkFT0PVcoincidence{"checkFT0PVcoincidence", true, "Check coincidence between FT0 and PV"}; + Configurable rejectITSonly{"rejectITSonly", true, "Reject ITS-only vertex"}; + Preslice cperBC = aod::collision::bcId; Preslice mccperBC = aod::mccollision::bcId; Preslice perMCc = aod::mcparticle::mcCollisionId; Preslice perC = aod::track::collisionId; + PresliceUnsorted> cperMCc = aod::mccollisionlabel::mcCollisionId; std::random_device rd; std::mt19937 randomgen; @@ -81,6 +88,16 @@ struct Reducer { 1. / (x * TMath::Beta(x, (1. + params->get((int)0, 5) * params->get((int)0, 5)))) * TMath::Power((params->get((int)0, 4) * params->get((int)0, 4)) / ((1. + params->get((int)0, 5) * params->get((int)0, 5)) + (params->get((int)0, 4) * params->get((int)0, 4))), x) * TMath::Power((1. + params->get((int)0, 5) * params->get((int)0, 5)) / ((1. + params->get((int)0, 5) * params->get((int)0, 5)) + (params->get((int)0, 4) * params->get((int)0, 4))), (1. + params->get((int)0, 5) * params->get((int)0, 5)))); } + template + inline bool isCollisionSelected(C const& collision) + { + return collision.selection_bit(aod::evsel::kIsTriggerTVX) && + (!checkTF || collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) && + (!checkITSROF || collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) && + (!checkFT0PVcoincidence || collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && + (!rejectITSonly || collision.selection_bit(aod::evsel::kIsVertexITSTPC)); + } + void init(InitContext const&) { randomgen.seed(rd()); @@ -192,6 +209,19 @@ struct Reducer { ++i; continue; } + if (useEvSel) { + bool pass = false; + for (auto& c : collisions) { + if (isCollisionSelected(c)) { + pass = true; + break; + } + } + if (!pass) { + ++i; + continue; + } + } rmcc(bcId, weights[i], mcc.posX(), mcc.posY(), mcc.posZ(), mcc.impactParameter(), mcc.multMCFT0A(), mcc.multMCFT0C(), mcc.multMCNParticlesEta05(), mcc.multMCNParticlesEta10()); if constexpr (requires {mcc.processId(); mcc.pdf1(); }) { rhepmci(rmcc.lastIndex(), mcc.xsectGen(), mcc.ptHard(), mcc.nMPI(), mcc.processId(), mcc.id1(), mcc.id2(), mcc.pdfId1(), mcc.pdfId2(), mcc.x1(), mcc.x2(), mcc.scalePdf(), mcc.pdf1(), mcc.pdf2()); @@ -201,18 +231,18 @@ struct Reducer { usedLabels.push_back(rmcc.lastIndex()); ++i; } - i = 0; // check Reco events for (auto& c : collisions) { // discard fake events if (!c.has_mcCollision()) { - ++i; continue; } // discard events for which MC event was discarded auto pos = std::find(usedMCCs.begin(), usedMCCs.end(), c.mcCollisionId()); if (pos == usedMCCs.end()) { - ++i; + continue; + } + if (useEvSel && !isCollisionSelected(c)) { continue; } std::fill(binned.begin(), binned.end(), 0); @@ -225,7 +255,6 @@ struct Reducer { } rc(bcId, c.posX(), c.posY(), c.posZ(), c.collisionTimeRes(), c.multFT0A(), c.multFT0C(), c.multFDDA(), c.multFDDC(), c.multZNA(), c.multZNC(), c.multNTracksPV(), c.multNTracksPVeta1(), c.multNTracksPVetaHalf(), binned); rmcl(usedLabels[std::distance(usedMCCs.begin(), pos)]); - ++i; } } }; diff --git a/PWGMM/Mult/Tasks/dndeta-hi.cxx b/PWGMM/Mult/Tasks/dndeta-hi.cxx index 46ff490352e..7ac1bc49bb5 100644 --- a/PWGMM/Mult/Tasks/dndeta-hi.cxx +++ b/PWGMM/Mult/Tasks/dndeta-hi.cxx @@ -154,10 +154,6 @@ AxisSpec PtVarAxis = {kPtVarend - 1, +kPtVarbegin + 0.5, +kPtVarend - 0.5, "", " AxisSpec EvtClassAxis = {kECend - 1, +kECbegin + 0.5, +kECend - 0.5, "", "event class"}; AxisSpec TrigClassAxis = {kTrigend - 1, +kTrigbegin + 0.5, +kTrigend - 0.5, "", "trigger class"}; AxisSpec ParticleTypeAxis = {kParTypeend - 1, +kParTypebegin + 0.5, +kParTypeend - 0.5, "", "Particle type"}; -std::vector centBinningPbPb = {0, 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 70, 80, 100}; -std::vector centBinning = {0., 0.01, 0.1, 1.0, 5.0, 10., 15, 20., 25, 30., 35., 40., 45., 50., 70., 100.0}; -AxisSpec CentAxis = {centBinning, "", "centrality"}; -AxisSpec CentAxisPbPb = {centBinningPbPb, "", "centrality"}; AxisSpec SpeciesAxis = {kSpeciesend - 1, +kSpeciesbegin + 0.5, +kSpeciesend - 0.5, "", "species class"}; AxisSpec MassAxis = {600, 0.3f, 1.3f, "Mass (GeV/c^{2})", "Inv. Mass (GeV/c^{2})"}; AxisSpec SignAxis = {kSignend - 1, +kSignbegin + 0.5, +kSignend - 0.5, "", "sign"}; @@ -199,6 +195,7 @@ struct MultiplicityCounter { Configurable v0radius{"v0radius", 0.5, "Radius"}; Configurable etadau{"etadau", 4, "Eta Daughters"}; Configurable rapidity{"v0rapidity", 0.5, "V0 rapidity"}; + ConfigurableAxis centBinning{"centrality", {VARIABLE_WIDTH, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100}, ""}; // Configurable mftanalysis{"mftanalysis", false, "mft analysis switch"}; Configurable zvtxcut{"zvtxcut", false, "z vtx cut < 10cm"}; @@ -212,6 +209,9 @@ struct MultiplicityCounter { std::vector usedTracksIds; void init(InitContext&) { + + AxisSpec CentAxis = {centBinning, "", "centrality"}; + AxisSpec CentAxisPbPb = {centBinning, "", "centrality"}; registry.add({"hetaresponse", ";etaresponse", {HistType::kTH2D, {{80, -4, 4}, {80, -4, 4}}}}); registry.add({"hft0multiplicity", ";multiplicity", {HistType::kTH1D, {{10000, 0, 100000}}}}); registry.add({"hcentrality", IsPbPb ? " ; centrality_FT0C (%) " : "; centrality_FT0M", {HistType::kTH1F, {{10000, 0, 100}}}}); diff --git a/PWGMM/Mult/Tasks/dndeta.cxx b/PWGMM/Mult/Tasks/dndeta.cxx index 0f777fd0b7b..0d3ff49cd3f 100644 --- a/PWGMM/Mult/Tasks/dndeta.cxx +++ b/PWGMM/Mult/Tasks/dndeta.cxx @@ -21,6 +21,7 @@ #include #include +#include "Gencentralities.h" #include "Index.h" #include "bestCollisionTable.h" @@ -52,33 +53,35 @@ struct MultiplicityCounter { ConfigurableAxis multBinning{"multBinning", {301, -0.5, 300.5}, ""}; ConfigurableAxis centBinning{"centBinning", {VARIABLE_WIDTH, 0, 10, 20, 30, 40, 50, 60, 70, 80, 100}, ""}; - Configurable fillResponse{"fillResponse", true, "Fill respons matrix"}; + Configurable fillResponse{"fillResponse", true, "Fill response matrix"}; Configurable useProcId{"use-process-id", true, "Use process ID from generator"}; Configurable addFT0{"addFT0", false, "add FT0 estimators"}; Configurable addFDD{"addFDD", false, "add FDD estimators"}; - Configurable useEvSel{"useEvSel", true, "use event selection"}; - Configurable checkTF{"checkTF", true, "check TF border"}; - Configurable checkITSROF{"checkITSROF", true, "check ITS readout frame border"}; - Configurable checkFT0PVcoincidence{"checkFT0PVcoincidence", true, "Check coincidence between FT0 and PV"}; - Configurable rejectITSonly{"rejectITSonly", false, "Reject ITS-only vertex"}; + Configurable useEvSel{"useEvSel", true, "Use event selection"}; + Configurable excludeTFborder{"excludeTFborder", true, "Exclude TF border"}; + Configurable excludeITSROFborder{"excludeITSROFborder", true, "Exclude ITS RO frame border"}; + Configurable requireFT0PVcoincidence{"requireFT0PVcoincidence", true, "Require coincidence between FT0 and PV"}; + Configurable rejectITSonly{"rejectITSonly", true, "Reject ITS-only vertex"}; + Configurable requireVtxTOFMatched{"checkTOFMatch", true, "Consider only vertex with TOF match"}; template inline bool isCollisionSelected(C const& collision) { return collision.selection_bit(aod::evsel::kIsTriggerTVX) && - (!checkTF || collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) && - (!checkITSROF || collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) && - (!checkFT0PVcoincidence || collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && - (!rejectITSonly || collision.selection_bit(aod::evsel::kIsVertexITSTPC)); + (!excludeTFborder || collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) && + (!excludeITSROFborder || collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) && + (!requireFT0PVcoincidence || collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && + (!rejectITSonly || collision.selection_bit(aod::evsel::kIsVertexITSTPC)) && + (!requireVtxTOFMatched || collision.selection_bit(aod::evsel::kIsVertexTOFmatched)); } template inline bool isBCSelected(B const& bc) { return bc.selection_bit(aod::evsel::kIsTriggerTVX) && - (!checkTF || bc.selection_bit(aod::evsel::kNoTimeFrameBorder)) && - (!checkITSROF || bc.selection_bit(aod::evsel::kNoITSROFrameBorder)); + (!excludeTFborder || bc.selection_bit(aod::evsel::kNoTimeFrameBorder)) && + (!excludeITSROFborder || bc.selection_bit(aod::evsel::kNoITSROFrameBorder)); } HistogramRegistry commonRegistry{ @@ -239,8 +242,8 @@ struct MultiplicityCounter { x->SetBinLabel(static_cast(EvEffBins::kSelectedPVgt0), EvEffBinLabels[static_cast(EvEffBins::kSelectedPVgt0)].data()); } - if (doprocessGenAmbiguousFT0C || doprocessGenAmbiguousFT0M || doprocessGenAmbiguousFT0Chi || doprocessGenAmbiguousFT0Mhi || - doprocessGenFT0C || doprocessGenFT0M || doprocessGenFT0Chi || doprocessGenFT0Mhi || doprocessGenAmbiguousExFT0C || doprocessGenAmbiguousExFT0M || + if (doprocessGenAmbiguousFT0C || doprocessGenAmbiguousFT0M || doprocessGenAmbiguousFT0Cplus || doprocessGenAmbiguousFT0Mplus || doprocessGenAmbiguousFT0Chi || doprocessGenAmbiguousFT0Mhi || + doprocessGenFT0C || doprocessGenFT0M || doprocessGenFT0Cplus || doprocessGenFT0Mplus || doprocessGenFT0Chi || doprocessGenFT0Mhi || doprocessGenAmbiguousExFT0C || doprocessGenAmbiguousExFT0M || doprocessGenExFT0C || doprocessGenExFT0M) { std::string effLabels{" ; N_{gen}; Z_{vtx} (cm); centrality"}; std::vector effAxes{MultAxis, ZAxis, CentAxis}; @@ -346,28 +349,30 @@ struct MultiplicityCounter { template void processEventStatGeneral(FullBCs const& bcs, C const& collisions) { - std::vector::iterator> cols; + std::vector colids; for (auto& bc : bcs) { if (!useEvSel || isBCSelected(bc)) { commonRegistry.fill(HIST(BCSelection), 1.); - cols.clear(); + colids.clear(); for (auto& collision : collisions) { if (collision.has_foundBC()) { if (collision.foundBCId() == bc.globalIndex()) { - cols.emplace_back(collision); + colids.push_back(collision.globalIndex()); } } else if (collision.bcId() == bc.globalIndex()) { - cols.emplace_back(collision); + colids.push_back(collision.globalIndex()); } } - LOGP(debug, "BC {} has {} collisions", bc.globalBC(), cols.size()); - if (!cols.empty()) { + LOGP(debug, "BC {} has {} collisions", bc.globalBC(), colids.size()); + if (!colids.empty()) { commonRegistry.fill(HIST(BCSelection), 2.); - if (cols.size() > 1) { + if (colids.size() > 1) { commonRegistry.fill(HIST(BCSelection), 3.); } } - for (auto& col : cols) { + auto col = collisions.begin(); + for (auto& colid : colids) { + col.moveByIndex(colid - col.globalIndex()); if constexpr (hasRecoCent()) { float c = -1; if constexpr (C::template contains()) { @@ -1487,6 +1492,16 @@ struct MultiplicityCounter { // add generated centrality estimation if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); + } else if constexpr (hasRecoCent()) { + if constexpr (C::template contains()) { + if constexpr (requires { mcCollision.gencentFT0C(); }) { + c_gen = mcCollision.gencentFT0C(); + } + } else if (C::template contains()) { + if constexpr (requires { mcCollision.gencentFT0M(); }) { + c_gen = mcCollision.gencentFT0M(); + } + } } NrecPerCol.clear(); @@ -1519,6 +1534,11 @@ struct MultiplicityCounter { } } } + if constexpr (hasRecoCent() && !hasSimCent()) { + if (std::abs(c_gen + 1) < 1e-6) { + c_gen = min_c_rec; // if there is no generator centrality info, fall back to reco (from the largest reco collision) + } + } for (auto& collision : collisions) { usedTracksIds.clear(); @@ -1529,11 +1549,7 @@ struct MultiplicityCounter { } else if (C::template contains()) { c_rec = collision.centFT0M(); } - if constexpr (hasSimCent()) { - binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec), c_gen); - } else { - binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec), min_c_rec); - } + binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec)); } @@ -1541,11 +1557,6 @@ struct MultiplicityCounter { c_recPerCol.emplace_back(c_rec); auto z = collision.posZ(); ++moreThanOne; - if constexpr (hasRecoCent() && !hasSimCent()) { - if (!atLeastOne) { - c_gen = min_c_rec; // if there is no generator centrality info, fall back to reco (from the largest reco collision) - } - } atLeastOne = true; auto groupPVcontrib = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -1700,6 +1711,16 @@ struct MultiplicityCounter { // add generated centrality estimation if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); + } else if constexpr (hasRecoCent()) { + if constexpr (C::template contains()) { + if constexpr (requires { mcCollision.gencentFT0C(); }) { + c_gen = mcCollision.gencentFT0C(); + } + } else if (C::template contains()) { + if constexpr (requires { mcCollision.gencentFT0M(); }) { + c_gen = mcCollision.gencentFT0M(); + } + } } bool atLeastOne = false; @@ -1733,6 +1754,12 @@ struct MultiplicityCounter { } } + if constexpr (hasRecoCent() && !hasSimCent()) { + if (std::abs(c_gen + 1) < 1e-6) { + c_gen = min_c_rec; // if there is no generator centrality info, fall back to reco (from the largest reco collision) + } + } + for (auto& collision : collisions) { usedTracksIds.clear(); float c_rec = -1; @@ -1742,11 +1769,7 @@ struct MultiplicityCounter { } else if (C::template contains()) { c_rec = collision.centFT0M(); } - if constexpr (hasSimCent()) { - binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec), c_gen); - } else { - binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec), min_c_rec); - } + binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kRec)); } @@ -1754,11 +1777,6 @@ struct MultiplicityCounter { c_recPerCol.emplace_back(c_rec); auto z = collision.posZ(); ++moreThanOne; - if constexpr (hasRecoCent() && !hasSimCent()) { - if (!atLeastOne) { - c_gen = min_c_rec; // if there is no generator centrality info, fall back to reco (from the largest reco collision) - } - } atLeastOne = true; auto groupPVcontrib = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -1963,6 +1981,26 @@ struct MultiplicityCounter { PROCESS_SWITCH(MultiplicityCounter, processGenFT0C, "Process generator-level info (FT0C centrality) w/o ambiguous", false); + void processGenAmbiguousFT0Cplus( + soa::Join::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneralAmbiguous, ExColsCentFT0C>(mcCollision, collisions, particles, tracks, atracks); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenAmbiguousFT0Cplus, "Process generator-level info (FT0C centrality + gen level)", false); + + void processGenFT0Cplus( + soa::Join::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral, ExColsCentFT0C>(mcCollision, collisions, particles, tracks); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenFT0Cplus, "Process generator-level info (FT0C centrality + gen level) w/o ambiguous", false); + void processGenAmbiguousExFT0C( MCex::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, @@ -2003,6 +2041,26 @@ struct MultiplicityCounter { PROCESS_SWITCH(MultiplicityCounter, processGenFT0M, "Process generator-level info (FT0M centrality) w/o ambiguous", false); + void processGenAmbiguousFT0Mplus( + soa::Join::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneralAmbiguous, ExColsCentFT0M>(mcCollision, collisions, particles, tracks, atracks); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenAmbiguousFT0Mplus, "Process generator-level info (FT0M centrality + gen level)", false); + + void processGenFT0Mplus( + soa::Join::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral, ExColsCentFT0M>(mcCollision, collisions, particles, tracks); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenFT0Mplus, "Process generator-level info (FT0M centrality + gen level) w/o ambiguous", false); + void processGenAmbiguousExFT0M( MCex::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, diff --git a/PWGMM/UE/Tasks/lambdak0sflattenicity.cxx b/PWGMM/UE/Tasks/lambdak0sflattenicity.cxx index 15eb453f58e..f949a2fbed4 100755 --- a/PWGMM/UE/Tasks/lambdak0sflattenicity.cxx +++ b/PWGMM/UE/Tasks/lambdak0sflattenicity.cxx @@ -110,10 +110,14 @@ struct lambdak0sflattenicity { // Histograms // Event selection - rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + rEventSelection.add("hVertexZ", "hVertexZ", {HistType::kTH1F, {vertexZAxis}}); rEventSelection.add("hEventsRejected", "hEventsRejected", {HistType::kTH1F, {{11, -0.5, 10.5}}}); rEventSelection.add("hEventsSelected", "hEventsSelected", {HistType::kTH1F, {{11, -0.5, 10.5}}}); + if (doprocessGenMC) { + rEventSelection.add("hVertexZGen", "hVertexZGen", {HistType::kTH1F, {vertexZAxis}}); + rEventSelection.add("hEventSelectionMCGen", "hEventSelectionMCGen", {HistType::kTH1F, {{11, -0.5, 10.5}}}); + } // K0s reconstruction // Mass rKzeroShort.add("hMassK0s", "hMassK0s", {HistType::kTH1F, {K0sMassAxis}}); @@ -129,6 +133,10 @@ struct lambdak0sflattenicity { rKzeroShort.add("hNSigmaNegPionFromK0s", "hNSigmaNegPionFromK0s", {HistType::kTH2F, {{100, -5.f, 5.f}, {ptAxis}}}); rKzeroShort.add("hMassK0spT", "hMassK0spT", {HistType::kTH2F, {{K0sMassAxis}, {ptAxis}}}); + if (doprocessGenMC) { + rKzeroShort.add("hPtK0ShortGen", "hPtK0ShortGen", {HistType::kTH1F, {ptAxis}}); + rKzeroShort.add("K0sCounterMCGen", "K0sCounterMCGen", {HistType::kTH1F, {{10, 0, 10}}}); + } // Lambda reconstruction // Mass rLambda.add("hMassLambda", "hMassLambda", {HistType::kTH1F, {LambdaMassAxis}}); @@ -144,6 +152,10 @@ struct lambdak0sflattenicity { rLambda.add("h2DdecayRadiusLambda", "h2DdecayRadiusLambda", {HistType::kTH1F, {{100, 0.0f, 1.0f, "c#tau (cm)"}}}); rLambda.add("hMassLambdapT", "hMassLambdapT", {HistType::kTH2F, {{LambdaMassAxis}, {ptAxis}}}); + if (doprocessGenMC) { + rLambda.add("hPtLambdaGen", "hPtLambdaGen", {HistType::kTH1F, {ptAxis}}); + rLambda.add("LambdaCounterMCGen", "LambdaCounterMCGen", {HistType::kTH1F, {{10, 0, 10}}}); + } // AntiLambda reconstruction // Mass rAntiLambda.add("hMassAntiLambda", "hMassAntiLambda", {HistType::kTH1F, {AntiLambdaMassAxis}}); @@ -159,6 +171,11 @@ struct lambdak0sflattenicity { rAntiLambda.add("h2DdecayRadiusAntiLambda", "h2DdecayRadiusAntiLambda", {HistType::kTH1F, {{100, 0.0f, 1.0f, "c#tau (cm)"}}}); rAntiLambda.add("hMassAntiLambdapT", "hMassAntiLambdapT", {HistType::kTH2F, {{AntiLambdaMassAxis}, {ptAxis}}}); + if (doprocessGenMC) { + rAntiLambda.add("hPtAntiLambdaGen", "hPtAntiLambdaGen", {HistType::kTH1F, {ptAxis}}); + rAntiLambda.add("AntiLambdaCounterMCGen", "AntiLambdaCounterMCGen", {HistType::kTH1F, {{10, 0, 10}}}); + } + rFlattenicity.add("hEv", "Ev", HistType::kTH1F, {{6, -0.5, 5.5, "index activated detector"}}); rFlattenicity.add("hFV0amplRing1to4", "FV01to4", HistType::kTH1F, {{4000, -0.5, +49999.5, "FV0 amplitude"}}); rFlattenicity.add("hFT0Aampl", "FTAampl", HistType::kTH1F, {{50000, -0.5, +199999.5, "FT0A amplitude"}}); @@ -197,6 +214,16 @@ struct lambdak0sflattenicity { rFlattenicity.add("hAmpV0vsVtx", "", HistType::kTH2F, {{30, -15.0, +15.0, "Trk mult"}, {1000, -0.5, +39999.5, "FV0 amplitude"}}); rFlattenicity.add("hAmpT0AvsVtx", "", HistType::kTH2F, {{30, -15.0, +15.0, "Vtx_z"}, {600, -0.5, +5999.5, "FT0A amplitude"}}); rFlattenicity.add("hAmpT0CvsVtx", "", HistType::kTH2F, {{30, -15.0, +15.0, "Vtx_z"}, {600, -0.5, +5999.5, "FT0C amplitude"}}); + + if (doprocessDataRun3 && (doprocessRecMC || doprocessGenMC)) { + LOGF(fatal, "Both Data and MC are both set to true; try again with only one of them set to true"); + } + if (!doprocessDataRun3 && !(doprocessRecMC || doprocessGenMC)) { + LOGF(fatal, "Both Data and MC set to false; try again with only one of them set to false"); + } + if ((doprocessRecMC && !doprocessGenMC) || (!doprocessRecMC && doprocessGenMC)) { + LOGF(fatal, "MCRec and MCGen are set to opposite switches, try again with both set to either true or false"); + } } int getT0ASector(int i_ch) @@ -400,72 +427,54 @@ struct lambdak0sflattenicity { std::array estimator; - // Defining filters for events (event selection) - // Processed events will be already fulfilling the event selection requirements - Filter eventFilter = (o2::aod::evsel::sel8 == true); - Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); - - // Filters on V0s - // Cannot filter on dynamic columns, so we cut on DCA to PV and DCA between daughters only - Filter preFilterV0 = (nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && - nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv && - aod::v0data::dcaV0daughters < v0setting_dcav0dau); - - Filter trackFilter = (nabs(aod::track::eta) < cfgTrkEtaCut); - using TrackCandidates = soa::Filtered>; - - void process(soa::Filtered>::iterator const& collision, - soa::Filtered const& V0s, TrackCandidates const& tracks, soa::Join const& /*bcs*/, - aod::MFTTracks const& /*mfttracks*/, aod::FT0s const& /*ft0s*/, - aod::FV0As const& /*fv0s*/) + template + bool isEventSelected(TCollision const& collision) { - // Fill the event counter - auto vtxZ = collision.posZ(); - auto vtxY = collision.posY(); - auto vtxX = collision.posX(); - rEventSelection.fill(HIST("hEventsSelected"), 0); - if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - rEventSelection.fill(HIST("hEventsRejected"), 0); - return; + if (collision.isInelGt0() == false) { + rEventSelection.fill(HIST("hEventsRejected"), 1); + return false; } rEventSelection.fill(HIST("hEventsSelected"), 1); - if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - rEventSelection.fill(HIST("hEventsRejected"), 1); - return; + if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + rEventSelection.fill(HIST("hEventsRejected"), 2); + return false; } rEventSelection.fill(HIST("hEventsSelected"), 2); - if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - rEventSelection.fill(HIST("hEventsRejected"), 2); - return; + if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + rEventSelection.fill(HIST("hEventsRejected"), 3); + return false; } rEventSelection.fill(HIST("hEventsSelected"), 3); - if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - rEventSelection.fill(HIST("hEventsRejected"), 3); - return; + if (!collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + rEventSelection.fill(HIST("hEventsRejected"), 4); + return false; } rEventSelection.fill(HIST("hEventsSelected"), 4); - if (!collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - rEventSelection.fill(HIST("hEventsRejected"), 4); - return; + if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + rEventSelection.fill(HIST("hEventsRejected"), 5); + return false; } rEventSelection.fill(HIST("hEventsSelected"), 5); - if (collision.isInelGt0() == false) { - rEventSelection.fill(HIST("hEventsRejected"), 5); - return; + if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + rEventSelection.fill(HIST("hEventsRejected"), 6); + return false; } rEventSelection.fill(HIST("hEventsSelected"), 6); - rEventSelection.fill(HIST("hVertexZRec"), vtxZ); - - // ============== Flattenicity estimation begins ===================== + return true; + } + // ============== Flattenicity estimation begins ===================== // + template + void EstimateFlattenicity(TCollision const& collision, Tracks const& tracks) + { const int nDetVtx = 3; TGraph* gVtx[nDetVtx]; const char* nameDet[nDetVtx] = {"AmpV0", "AmpT0A", "AmpT0C"}; @@ -490,6 +499,7 @@ struct lambdak0sflattenicity { for (int i_d = 0; i_d < nDetVtx; ++i_d) { gVtx[i_d]->SetName(Form("g%s", nameDet[i_d])); } + auto vtxZ = collision.posZ(); float sumAmpFV0 = 0; float sumAmpFV01to4Ch = 0; @@ -531,6 +541,7 @@ struct lambdak0sflattenicity { RhoLattice[channelv0phi] = ampl_ch / 2.0; // two channels per bin } } + rFlattenicity.fill(HIST("hAmpV0vsVtxBeforeCalibration"), vtxZ, sumAmpFV0); if (applyCalibVtx) { sumAmpFV0 *= gVtx[0]->Eval(vtxZ); @@ -595,6 +606,7 @@ struct lambdak0sflattenicity { } rFlattenicity.fill(HIST("hFT0C"), amplitude); } + rFlattenicity.fill(HIST("hAmpT0AvsVtxBeforeCalibration"), vtxZ, sumAmpFT0A); rFlattenicity.fill(HIST("hAmpT0CvsVtxBeforeCalibration"), vtxZ, sumAmpFT0C); if (applyCalibVtx) { @@ -676,18 +688,30 @@ struct lambdak0sflattenicity { float flatenicity_ft0v0 = 0.5 * flattenicityfv0 + 0.5 * flatenicity_t0c; estimator[6] = 1.0 - flatenicity_ft0v0; estimator[7] = ptT; - static_for<0, 7>([&](auto i) { - constexpr int index = i.value; - rFlattenicity.fill(HIST(nhEst[index]), estimator[index], estimator[0]); }); + + rFlattenicity.fill(HIST(nhEst[0]), estimator[0], estimator[0]); + rFlattenicity.fill(HIST(nhEst[1]), estimator[1], estimator[0]); + rFlattenicity.fill(HIST(nhEst[2]), estimator[2], estimator[0]); + rFlattenicity.fill(HIST(nhEst[3]), estimator[3], estimator[0]); + rFlattenicity.fill(HIST(nhEst[4]), estimator[4], estimator[0]); + rFlattenicity.fill(HIST(nhEst[5]), estimator[5], estimator[0]); + rFlattenicity.fill(HIST(nhEst[6]), estimator[6], estimator[0]); + rFlattenicity.fill(HIST(nhEst[7]), estimator[7], estimator[0]); + // plot pt vs estimators for (auto& track : tracks) { if (!track.isGlobalTrack()) { continue; } float pt = track.pt(); - static_for<0, 7>([&](auto i) { - constexpr int index = i.value; - rFlattenicity.fill(HIST(nhPtEst[index]), estimator[index], pt); }); + rFlattenicity.fill(HIST(nhPtEst[0]), estimator[0], pt); + rFlattenicity.fill(HIST(nhPtEst[1]), estimator[1], pt); + rFlattenicity.fill(HIST(nhPtEst[2]), estimator[2], pt); + rFlattenicity.fill(HIST(nhPtEst[3]), estimator[3], pt); + rFlattenicity.fill(HIST(nhPtEst[4]), estimator[4], pt); + rFlattenicity.fill(HIST(nhPtEst[5]), estimator[5], pt); + rFlattenicity.fill(HIST(nhPtEst[6]), estimator[6], pt); + rFlattenicity.fill(HIST(nhPtEst[7]), estimator[7], pt); } for (int iCh = 0; iCh < 48; ++iCh) { @@ -698,8 +722,39 @@ struct lambdak0sflattenicity { rFlattenicity.fill(HIST("fMultFv0"), sumAmpFV0); rFlattenicity.fill(HIST("hFlatFT0CvsFlatFT0A"), flatenicity_t0c, flatenicity_t0a); } + } + // ====================== Flattenicity estimation ends ===================== + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on V0s + // Cannot filter on dynamic columns, so we cut on DCA to PV and DCA between daughters only + Filter preFilterV0 = (nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && + nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv && + aod::v0data::dcaV0daughters < v0setting_dcav0dau); + + Filter trackFilter = (nabs(aod::track::eta) < cfgTrkEtaCut); + using TrackCandidates = soa::Filtered>; - // ====================== Flattenicity estimation ends ===================== + void processDataRun3(soa::Filtered>::iterator const& collision, + soa::Filtered const& V0s, TrackCandidates const& tracks, soa::Join const& /*bcs*/, + aod::MFTTracks const& /*mfttracks*/, aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0s*/) + { + if (!(isEventSelected(collision))) { // Checking if the event passes the selection criteria + return; + } + + auto vtxZ = collision.posZ(); + auto vtxY = collision.posY(); + auto vtxX = collision.posX(); + + EstimateFlattenicity(collision, tracks); + + rEventSelection.fill(HIST("hVertexZ"), vtxZ); for (const auto& v0 : V0s) { const auto& posDaughterTrack = v0.posTrack_as(); @@ -783,6 +838,210 @@ struct lambdak0sflattenicity { } } } + + using TrackCandidatesMC = soa::Filtered>; + void processRecMC(soa::Filtered>::iterator const& collision, + soa::Filtered> const& V0s, + TrackCandidatesMC const& tracks, + soa::Join const& /*bcs*/, + aod::MFTTracks const& /*mfttracks*/, aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0s*/, aod::McParticles const&) + { + if (!(isEventSelected(collision))) { // Checking if the event passes the selection criteria + return; + } + + auto vtxZ = collision.posZ(); + auto vtxY = collision.posY(); + auto vtxX = collision.posX(); + + EstimateFlattenicity(collision, tracks); + + rEventSelection.fill(HIST("hVertexZ"), vtxZ); + + for (const auto& v0 : V0s) { + + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + + if (!posDaughterTrack.has_mcParticle() || !negDaughterTrack.has_mcParticle()) { + continue; + } + if (TMath::Abs(posDaughterTrack.eta()) > 0.8 || TMath::Abs(negDaughterTrack.eta()) > 0.8) { + continue; + } + + auto mcnegtrack = negDaughterTrack.mcParticle_as(); + auto mcpostrack = posDaughterTrack.mcParticle_as(); + + float massK0s = v0.mK0Short(); + float massLambda = v0.mLambda(); + float massAntiLambda = v0.mAntiLambda(); + + rKzeroShort.fill(HIST("hMassK0s"), massK0s); + rLambda.fill(HIST("hMassLambda"), massLambda); + rAntiLambda.fill(HIST("hMassAntiLambda"), massAntiLambda); + + float decayvtxX = v0.x(); + float decayvtxY = v0.y(); + float decayvtxZ = v0.z(); + + float decaylength = TMath::Sqrt(TMath::Power(decayvtxX - vtxX, 2) + TMath::Power(decayvtxY - vtxY, 2) + TMath::Power(decayvtxZ - vtxZ, 2)); + float v0p = TMath::Sqrt(v0.pt() * v0.pt() + v0.pz() * v0.pz()); + + float ctauK0s = decaylength * massK0s / v0p; + float ctauLambda = decaylength * massLambda / v0p; + float ctauAntiLambda = decaylength * massAntiLambda / v0p; + + // Cut on dynamic columns for K0s + + for (auto& particleMotherOfNeg : mcnegtrack.mothers_as()) { + for (auto& particleMotherOfPos : mcpostrack.mothers_as()) { + if (particleMotherOfNeg == particleMotherOfPos && (particleMotherOfNeg.pdgCode() == 3122 || particleMotherOfNeg.pdgCode() == -3122 || particleMotherOfNeg.pdgCode() == 310) && particleMotherOfNeg.isPhysicalPrimary()) { + + if (particleMotherOfNeg.pdgCode() == 310 && v0.v0cosPA() >= v0setting_cospaK0s && v0.v0radius() >= v0setting_radiusK0s && TMath::Abs(posDaughterTrack.tpcNSigmaPi()) <= NSigmaTPCPion && TMath::Abs(negDaughterTrack.tpcNSigmaPi()) <= NSigmaTPCPion && ctauK0s < v0setting_ctauK0s && TMath::Abs(v0.rapidity(0)) <= 0.5 && TMath::Abs(massLambda - pdgmassLambda) > 0.005 && TMath::Abs(massAntiLambda - pdgmassLambda) > 0.005) { + + rKzeroShort.fill(HIST("hMassK0sSelected"), massK0s); + rKzeroShort.fill(HIST("hDCAV0DaughtersK0s"), v0.dcaV0daughters()); + rKzeroShort.fill(HIST("hV0CosPAK0s"), v0.v0cosPA()); + rKzeroShort.fill(HIST("hrapidityK0s"), v0.rapidity(0)); + rKzeroShort.fill(HIST("hctauK0s"), ctauK0s); + rKzeroShort.fill(HIST("h2DdecayRadiusK0s"), v0.v0radius()); + rKzeroShort.fill(HIST("hMassK0spT"), massK0s, v0.pt()); + + // Filling the PID of the V0 daughters in the region of the K0s peak + if (0.45 < massK0s && massK0s < 0.55) { + rKzeroShort.fill(HIST("hNSigmaPosPionFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + rKzeroShort.fill(HIST("hNSigmaNegPionFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + } + } + + // Cut on dynamic columns for Lambda + if (particleMotherOfNeg.pdgCode() == 3122 && v0.v0cosPA() >= v0setting_cospaLambda && v0.v0radius() >= v0setting_radiusLambda && TMath::Abs(posDaughterTrack.tpcNSigmaPr()) <= NSigmaTPCProton && TMath::Abs(negDaughterTrack.tpcNSigmaPi()) <= NSigmaTPCPion && ctauLambda < v0setting_ctauLambda && TMath::Abs(v0.rapidity(1)) <= 0.5 && TMath::Abs(massK0s - pdgmassK0s) > 0.01) { + + rLambda.fill(HIST("hMassLambdaSelected"), massLambda); + rLambda.fill(HIST("hDCAV0DaughtersLambda"), v0.dcaV0daughters()); + rLambda.fill(HIST("hV0CosPALambda"), v0.v0cosPA()); + rLambda.fill(HIST("hrapidityLambda"), v0.rapidity(1)); + rLambda.fill(HIST("hctauLambda"), ctauLambda); + rLambda.fill(HIST("h2DdecayRadiusLambda"), v0.v0radius()); + rLambda.fill(HIST("hMassLambdapT"), massLambda, v0.pt()); + + // Filling the PID of the V0 daughters in the region of the Lambda peak + if (1.015 < massLambda && massLambda < 1.215) { + rLambda.fill(HIST("hNSigmaPosPionFromLambda"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); + rLambda.fill(HIST("hNSigmaNegPionFromLambda"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + } + } + + // Cut on dynamic columns for AntiLambda + if (particleMotherOfNeg.pdgCode() == -3122 && v0.v0cosPA() >= v0setting_cospaLambda && v0.v0radius() >= v0setting_radiusLambda && TMath::Abs(posDaughterTrack.tpcNSigmaPi()) <= NSigmaTPCPion && TMath::Abs(negDaughterTrack.tpcNSigmaPr()) <= NSigmaTPCProton && ctauAntiLambda < v0setting_ctauLambda && TMath::Abs(v0.rapidity(2)) <= 0.5 && TMath::Abs(massK0s - pdgmassK0s) > 0.01) { + + rAntiLambda.fill(HIST("hMassAntiLambdaSelected"), massAntiLambda); + rAntiLambda.fill(HIST("hDCAV0DaughtersAntiLambda"), v0.dcaV0daughters()); + rAntiLambda.fill(HIST("hV0CosPAAntiLambda"), v0.v0cosPA()); + rAntiLambda.fill(HIST("hrapidityAntiLambda"), v0.rapidity(2)); + rAntiLambda.fill(HIST("hctauAntiLambda"), ctauAntiLambda); + rAntiLambda.fill(HIST("h2DdecayRadiusAntiLambda"), v0.v0radius()); + rAntiLambda.fill(HIST("hMassAntiLambdapT"), massAntiLambda, v0.pt()); + + // Filling the PID of the V0 daughters in the region of the AntiLambda peak + if (1.015 < massAntiLambda && massAntiLambda < 1.215) { + rAntiLambda.fill(HIST("hNSigmaPosPionFromAntiLambda"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + rAntiLambda.fill(HIST("hNSigmaNegPionFromAntiLambda"), negDaughterTrack.tpcNSigmaPr(), negDaughterTrack.tpcInnerParam()); + } + } + } + } + } + } + } + + // Filter posZFilterMC = (nabs(o2::aod::mccollision::posZ) < cutzvertex); + void processGenMC(o2::aod::McCollision const& mcCollision, + const soa::SmallGroups>& collisions, + o2::aod::McParticles const& mcParticles) + { + // if (collisions.size() < 1) // to process generated collisions that've been reconstructed at least once + // { + // return; + // } + + std::vector SelectedEvents(collisions.size()); + int nevts = 0; + for (const auto& collision : collisions) { + if (!collision.sel8()) { + continue; + } + SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + } + SelectedEvents.resize(nevts); + + const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); + + rEventSelection.fill(HIST("hEventSelectionMCGen"), 0); + + if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + return; + } + rEventSelection.fill(HIST("hEventSelectionMCGen"), 1); // hSelAndRecoMcCollCounter + + if (abs(mcCollision.posZ()) > cutzvertex) { // 10cm + return; + } + rEventSelection.fill(HIST("hEventSelectionMCGen"), 2); + + rEventSelection.fill(HIST("hVertexZGen"), mcCollision.posZ()); + + for (const auto& mcParticle : mcParticles) { + + if (mcParticle.isPhysicalPrimary() && mcParticle.y() < 0.5) { + if (!mcParticle.has_daughters()) { + continue; + } + + if (mcParticle.pdgCode() == 310) { + rKzeroShort.fill(HIST("K0sCounterMCGen"), 0); + rKzeroShort.fill(HIST("hPtK0ShortGen"), mcParticle.pt()); + for (auto& mcparticleDaughter0 : mcParticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcParticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -211) { + rKzeroShort.fill(HIST("K0sCounterMCGen"), 1); + } + } + } + } + + if (mcParticle.pdgCode() == 3122) { + rLambda.fill(HIST("LambdaCounterMCGen"), 0); + rLambda.fill(HIST("hPtLambdaGen"), mcParticle.pt()); + for (auto& mcparticleDaughter0 : mcParticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcParticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == -211 && mcparticleDaughter1.pdgCode() == 2212) { + rLambda.fill(HIST("LambdaCounterMCGen"), 1); + } + } + } + } + + if (mcParticle.pdgCode() == -3122) { + rAntiLambda.fill(HIST("AntiLambdaCounterMCGen"), 0.5); + rAntiLambda.fill(HIST("hPtAntiLambdaGen"), mcParticle.pt()); + for (auto& mcparticleDaughter0 : mcParticle.daughters_as()) { + for (auto& mcparticleDaughter1 : mcParticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -2212) { + rAntiLambda.fill(HIST("AntiLambdaCounterMCGen"), 1); + } + } + } + } + } + } + } + + PROCESS_SWITCH(lambdak0sflattenicity, processDataRun3, "Process Run 3 Data", false); + PROCESS_SWITCH(lambdak0sflattenicity, processRecMC, "Process Run 3 mc, reconstructed", true); + PROCESS_SWITCH(lambdak0sflattenicity, processGenMC, "Process Run 3 mc, generated", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGMM/UE/Tasks/uecharged.cxx b/PWGMM/UE/Tasks/uecharged.cxx index 44e27ff502b..3db96c9dbac 100644 --- a/PWGMM/UE/Tasks/uecharged.cxx +++ b/PWGMM/UE/Tasks/uecharged.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \author Antonio Ortiz (antonio.ortiz@nucleares.unam.mx) /// \since November 2021 -/// \last update: May 2024 +/// \last update: July 2024 #include #include @@ -196,7 +196,7 @@ void ueCharged::init(InitContext const&) ConfigurableAxis ptBinningt{"ptBinningt", {0, 0.15, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 25.0, 30.0, 40.0, 50.0}, "pTtrig bin limits"}; AxisSpec ptAxist = {ptBinningt, "#it{p}_{T}^{trig} (GeV/#it{c})"}; - ConfigurableAxis ptBinning{"ptBinning", {0, 0.0, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 25.0, 30.0, 40.0, 50.0}, "pTassoc bin limits"}; + ConfigurableAxis ptBinning{"ptBinning", {0, 0.0, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 25.0, 30.0, 40.0, 50.0}, "pTassoc bin limits"}; AxisSpec ptAxis = {ptBinning, "#it{p}_{T}^{assoc} (GeV/#it{c})"}; f_Eff.setObject(new TF1("fpara", "(x<0.3)*((0.221456)+x*(3.4271)+x*x*(-6.7668))+(x>=0.3&&x<2.1)*((0.610649)+(0.148627)*x+(-0.0772185)*x*x+(0.0157586)*x*x*x)+(x>=2.1)*(0.726557)", 0., 1e5)); @@ -730,11 +730,9 @@ void ueCharged::processMeasMC(const C& collision, const T& tracks, const P& part return; } ue.fill(HIST("hCounter"), 1); - if (timeEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { - return; - } - + // TODO:Implement time frame selection (only if MC includes this effect) ue.fill(HIST("hCounter"), 2); + if (piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return; } diff --git a/PWGUD/Core/UDHelpers.h b/PWGUD/Core/UDHelpers.h index 933120b7c2a..703fbfd590b 100644 --- a/PWGUD/Core/UDHelpers.h +++ b/PWGUD/Core/UDHelpers.h @@ -218,7 +218,7 @@ T MCcompatibleBCs(F const& collision, int ndt, T const& bcs, int nMinBCs = 7) // return if collisions has no associated BC if (!collision.has_foundBC()) { - LOGF(info, "Collision %i - no BC found!", collision.globalIndex()); + LOGF(debug, "Collision %i - no BC found!", collision.globalIndex()); return T{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; } @@ -743,7 +743,7 @@ bool cleanCalo(T const& bc, aod::Calos& calos, std::vector& /*lims*/, Sli // ----------------------------------------------------------------------------- // check if all tracks come from same MCCollision template -int64_t sameMCCollision(T tracks, aod::McCollisions mccols, aod::McParticles mcparts) +int64_t sameMCCollision(T tracks, aod::McCollisions, aod::McParticles) { int64_t colID = -1; for (auto const& track : tracks) { diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index d205d69aeb9..4b757fdc963 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -43,8 +43,14 @@ void printMediumMessage(std::string info) LOGF(info, "+++++++++++++ %s +++++++++++++", info); } +void printDebugMessage(std::string info) +// Helper to printf info message to terminal +{ + LOGF(debug, "X!X!X!X!X!X!X!X!X %s X!X!X!X!X!X!X!X!X", info); +} + template -int testPIDhypothesis(T trackPIDinfo, float nSigmaShift = 0., bool isMC = false) +int testPIDhypothesis(T trackPIDinfo, float maxNsigmaTPC = 5.0, float maxNsigmaTOF = 5.0, bool useTOF = true, bool useTOFsigmaAfterTPC = true, float nSigmaShift = 0., bool isMC = false) // Choose, which particle it is according to PID { float nSigmaTPC[5]; @@ -70,14 +76,31 @@ int testPIDhypothesis(T trackPIDinfo, float nSigmaShift = 0., bool isMC = false) int enumChoiceTOF = std::distance(std::begin(nSigmaTOF), std::min_element(std::begin(nSigmaTOF), std::end(nSigmaTOF))); - if (trackPIDinfo.hasTPC() || trackPIDinfo.hasTOF()) { - if (trackPIDinfo.hasTOF()) { - return enumChoiceTOF; + if (trackPIDinfo.hasTPC()) { + if (trackPIDinfo.hasTOF() && useTOF) { + if (nSigmaTOF[enumChoiceTOF] < maxNsigmaTOF) { + return enumChoiceTOF; + } else { + printDebugMessage(Form("testPIDhypothesis cut - the lowest nSigmaTOF is higher than %f", maxNsigmaTPC)); + return -1; + } + } else if (trackPIDinfo.hasTOF() && useTOFsigmaAfterTPC) { + if (nSigmaTPC[enumChoiceTPC] < maxNsigmaTPC && nSigmaTOF[enumChoiceTPC] < maxNsigmaTOF) { + return enumChoiceTPC; + } else { + printDebugMessage(Form("testPIDhypothesis cut - the lowest nSigmaTPC is higher than %f or the lowest nSigmaTOF is higher than %f", maxNsigmaTPC, maxNsigmaTOF)); + return -1; + } } else { - return enumChoiceTPC; + if (nSigmaTPC[enumChoiceTPC] < maxNsigmaTPC) { + return enumChoiceTPC; + } else { + printDebugMessage(Form("testPIDhypothesis cut - the lowest nSigmaTPC is higher than %f", maxNsigmaTPC)); + return -1; + } } } else { - LOGF(debug, "testPIDhypothesis failed - track did not leave information in TPC or TOF"); + printDebugMessage("testPIDhypothesis failed - track did not leave information in TPC"); return -1; } } @@ -97,7 +120,7 @@ int trackPDG(T trackPIDinfo) } else if (testPIDhypothesis(trackPIDinfo) == P_PROTON) { return 2212; } else { - printMediumMessage("Something is wrong with track PDG selector"); + printDebugMessage("Something is wrong with track PDG selector"); return -1.; } } @@ -116,7 +139,7 @@ int enumMyParticle(int valuePDG) } else if (std::abs(valuePDG) == 2212) { return P_PROTON; } else { - printMediumMessage("PDG value not found in enumMyParticle. Returning -1."); + printDebugMessage("PDG value not found in enumMyParticle. Returning -1."); return -1.; } } diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index f230f078b6f..46f379c24d5 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -355,19 +355,51 @@ DECLARE_SOA_TABLE(UDFwdTracks, "AOD", "UDFWDTRACK", udfwdtrack::TrackTime, udfwdtrack::TrackTimeRes); +namespace udfwdmatchindex +{ +DECLARE_SOA_INDEX_COLUMN(UDCollision, udCollision); //! +DECLARE_SOA_COLUMN(GlobalIndex, globalIndex, int64_t); //! Index of the track in the global track table +DECLARE_SOA_COLUMN(MCHTrackId, mchTrackId, int64_t); //! Id of original MCH track used for matching +DECLARE_SOA_COLUMN(MFTTrackId, mftTrackId, int64_t); //! Id of original MFT track used for matching +} // namespace udfwdmatchindex + +// Details about FWD indices +DECLARE_SOA_TABLE(UDFwdIndices, "AOD", "UDFWDINDEX", + o2::soa::Index<>, + udfwdmatchindex::UDCollisionId, + udfwdmatchindex::GlobalIndex, + udfwdmatchindex::MCHTrackId, + udfwdmatchindex::MFTTrackId); + // Muon track quality details -DECLARE_SOA_TABLE(UDFwdTracksExtra, "AOD", "UDFWDTRACKEXTRA", +// Version with only MCH-MID tracks +DECLARE_SOA_TABLE(UDFwdTracksExtra_000, "AOD", "UDFWDTRACKEXTRA", fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, - fwdtrack::Chi2MatchMCHMFT, fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards); +// Version with global tracks +DECLARE_SOA_TABLE_VERSIONED(UDFwdTracksExtra_001, "AOD", "UDFWDTRACKEXTRA", 1, + fwdtrack::TrackType, + fwdtrack::NClusters, + fwdtrack::PDca, + fwdtrack::RAtAbsorberEnd, + fwdtrack::Chi2, + fwdtrack::Chi2MatchMCHMID, + fwdtrack::Chi2MatchMCHMFT, + fwdtrack::MCHBitMap, + fwdtrack::MIDBitMap, + fwdtrack::MIDBoards); + +using UDFwdTracksExtra = UDFwdTracksExtra_001; + using UDFwdTrack = UDFwdTracks::iterator; +using UDFwdIndex = UDFwdIndices::iterator; using UDFwdTrackExtra = UDFwdTracksExtra::iterator; DECLARE_SOA_TABLE(UDFwdTracksProp, "AOD", "UDFWDTRACKPROP", diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index 2406868718c..8234d926ef2 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -9,6 +9,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +add_subdirectory(Converters) + o2physics_add_dpl_workflow(dgcand-producer SOURCES DGCandProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder diff --git a/PWGUD/TableProducer/Converters/CMakeLists.txt b/PWGUD/TableProducer/Converters/CMakeLists.txt new file mode 100644 index 00000000000..b8d13cc587e --- /dev/null +++ b/PWGUD/TableProducer/Converters/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright 2019-2020 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. + +o2physics_add_dpl_workflow(fwd-tracks-extra-converter + SOURCES UDFwdTracksExtraConverter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx b/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx new file mode 100644 index 00000000000..f9b1f2d0d22 --- /dev/null +++ b/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx @@ -0,0 +1,68 @@ +// Copyright 2019-2020 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. + +/// \file UDFwdTracksExtraConverter.cxx +/// \brief Converts UDFwdTracksExtra table from version 000 to 001 + +/// This task allows for the conversion of the UDFwdTracksExtra table from the version 000, +/// that is before the introduction of global tracks (and so contains only MCH-MID and +/// MCH only tracks), to the version 001, that includes global tracks +/// Global tracks introduced here: https://github.com/AliceO2Group/O2Physics/commit/72f673611ddcd7c39978787dbed9f77e6e7c3d6a) + +/// executable name o2-analysis-ud-fwd-tracks-extra-converter + +/// \author Andrea Giovanni Riffero + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" + +using namespace o2; +using namespace o2::framework; + +// Converts UDFwdTracksExtra for version 000 to 001 +// v_000 only MID-MCH and MCH only tracks +// v_001 global tracks +struct UDFwdTracksExtraConverter { + Produces udFwdTracksExtra_001; + + void process(o2::aod::UDFwdTracksExtra_000 const& tracks) + { + int trkType = 3; // trackType of MCH-MID tracks is 3 + + for (const auto& track : tracks) { + + if (track.chi2MatchMCHMID() > 0) + trkType = 3; // trackType of MCH-MID tracks is 3 + if (track.chi2MatchMCHMID() < 0) + trkType = 4; // trackType of MCH only tracks is 4 + + udFwdTracksExtra_001(trkType, + track.nClusters(), + track.pDca(), + track.rAtAbsorberEnd(), + track.chi2(), + track.chi2MatchMCHMID(), + 0.0f, // dummy mchmftChi2, not available in version 000 + track.mchBitMap(), + track.midBitMap(), + track.midBoards()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/DGCandProducer.cxx index 03ba6f4b749..e0a6f5df303 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/DGCandProducer.cxx @@ -71,7 +71,8 @@ struct DGCandProducer { outputFwdTracks(outputCollisions.lastIndex(), fwdtrack.px(), fwdtrack.py(), fwdtrack.pz(), fwdtrack.sign(), bcnum, fwdtrack.trackTime(), fwdtrack.trackTimeRes()); - outputFwdTracksExtra(fwdtrack.nClusters(), + outputFwdTracksExtra(fwdtrack.trackType(), + fwdtrack.nClusters(), fwdtrack.pDca(), fwdtrack.rAtAbsorberEnd(), fwdtrack.chi2(), diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index bb46e2be8c0..a38dc6a334c 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -81,7 +81,8 @@ struct SGCandProducer { outputFwdTracks(outputCollisions.lastIndex(), fwdtrack.px(), fwdtrack.py(), fwdtrack.pz(), fwdtrack.sign(), bcnum, fwdtrack.trackTime(), fwdtrack.trackTimeRes()); - outputFwdTracksExtra(fwdtrack.nClusters(), + outputFwdTracksExtra(fwdtrack.trackType(), + fwdtrack.nClusters(), fwdtrack.pDca(), fwdtrack.rAtAbsorberEnd(), fwdtrack.chi2(), diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 486cb4b726a..47da6d3ffbd 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -37,6 +37,7 @@ struct UpcCandProducer { Produces udFwdTracks; Produces udFwdTracksExtra; + Produces udFwdIndices; Produces udFwdTrkClusters; Produces udFwdTrackLabels; @@ -367,9 +368,13 @@ struct UpcCandProducer { mchmidChi2 = -999.; // no MID match } double mchmftChi2 = track.chi2MatchMCHMFT(); + int64_t globalIndex = track.globalIndex(); + int64_t mchIndex = track.matchMCHTrackId(); + int64_t mftIndex = track.matchMFTTrackId(); udFwdTracks(candID, track.px(), track.py(), track.pz(), track.sign(), globalBC, trTime, track.trackTimeRes()); - udFwdTracksExtra(track.nClusters(), track.pDca(), track.rAtAbsorberEnd(), track.chi2(), mchmidChi2, mchmftChi2, + udFwdTracksExtra(track.trackType(), track.nClusters(), track.pDca(), track.rAtAbsorberEnd(), track.chi2(), mchmidChi2, mchmftChi2, track.mchBitMap(), track.midBitMap(), track.midBoards()); + udFwdIndices(candID, globalIndex, mchIndex, mftIndex); // fill MC labels and masks if needed if (fDoMC) { const auto& label = mcTrackLabels->iteratorAt(trackID); diff --git a/PWGUD/TableProducer/fwdTrackPropagation.cxx b/PWGUD/TableProducer/fwdTrackPropagation.cxx index 20db4b41959..cc6ba621690 100644 --- a/PWGUD/TableProducer/fwdTrackPropagation.cxx +++ b/PWGUD/TableProducer/fwdTrackPropagation.cxx @@ -142,16 +142,16 @@ struct FwdTrackPropagation { float sigPhi = TMath::Sqrt(cov(2, 2)); float sigTgl = TMath::Sqrt(cov(3, 3)); float sig1Pt = TMath::Sqrt(cov(4, 4)); - auto rhoXY = static_cast(128. * cov(0, 1) / (sigX * sigY)); - auto rhoPhiX = static_cast(128. * cov(0, 2) / (sigPhi * sigX)); - auto rhoPhiY = static_cast(128. * cov(1, 2) / (sigPhi * sigY)); - auto rhoTglX = static_cast(128. * cov(0, 3) / (sigTgl * sigX)); - auto rhoTglY = static_cast(128. * cov(1, 3) / (sigTgl * sigY)); - auto rhoTglPhi = static_cast(128. * cov(2, 3) / (sigTgl * sigPhi)); - auto rho1PtX = static_cast(128. * cov(0, 4) / (sig1Pt * sigX)); - auto rho1PtY = static_cast(128. * cov(1, 4) / (sig1Pt * sigY)); - auto rho1PtPhi = static_cast(128. * cov(2, 4) / (sig1Pt * sigPhi)); - auto rho1PtTgl = static_cast(128. * cov(3, 4) / (sig1Pt * sigTgl)); + auto rhoXY = static_cast(128. * cov(0, 1) / (sigX * sigY)); + auto rhoPhiX = static_cast(128. * cov(0, 2) / (sigPhi * sigX)); + auto rhoPhiY = static_cast(128. * cov(1, 2) / (sigPhi * sigY)); + auto rhoTglX = static_cast(128. * cov(0, 3) / (sigTgl * sigX)); + auto rhoTglY = static_cast(128. * cov(1, 3) / (sigTgl * sigY)); + auto rhoTglPhi = static_cast(128. * cov(2, 3) / (sigTgl * sigPhi)); + auto rho1PtX = static_cast(128. * cov(0, 4) / (sig1Pt * sigX)); + auto rho1PtY = static_cast(128. * cov(1, 4) / (sig1Pt * sigY)); + auto rho1PtPhi = static_cast(128. * cov(2, 4) / (sig1Pt * sigPhi)); + auto rho1PtTgl = static_cast(128. * cov(3, 4) / (sig1Pt * sigTgl)); propFwdTracksCov(sigX, sigY, sigTgl, sigPhi, sig1Pt, rhoXY, rhoPhiX, rhoPhiY, rhoTglX, rhoTglY, rhoTglPhi, rho1PtX, rho1PtY, diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 521a4bcc53b..a93b9c01311 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -168,7 +168,32 @@ o2physics_add_dpl_workflow(sg-exclusive-phi PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(sg-exclusive-phi-its + SOURCES sgExclusivePhiITSselections.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upc-pion-analysis SOURCES upcPionAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(fwd-muons-upc + SOURCES fwdMuonsUPC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upc-event-itsrof-counter + SOURCES upcEventITSROFcounter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upc-rho-analysis + SOURCES upcRhoAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-by-event + SOURCES eventByevent.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/dgCandAnalyzer.cxx b/PWGUD/Tasks/dgCandAnalyzer.cxx index d0966dc794d..90d4bd8e011 100644 --- a/PWGUD/Tasks/dgCandAnalyzer.cxx +++ b/PWGUD/Tasks/dgCandAnalyzer.cxx @@ -217,7 +217,11 @@ struct DGCandAnalyzer { } } - void processReco(UDCollisionFull const& dgcand, UDTracksFull const& dgtracks) + // PV contributors + Filter PVContributorFilter = aod::udtrack::isPVContributor == true; + using PVTracks = soa::Filtered; + + void processReco(UDCollisionFull const& dgcand, UDTracksFull const& dgtracks, PVTracks const& PVContributors) { // count collisions registry.fill(HIST("stat/candCaseAll"), 0., 1.); @@ -273,8 +277,8 @@ struct DGCandAnalyzer { registry.fill(HIST("FIT/FDDCAmplitude"), dgcand.totalFDDAmplitudeC(), 1.); // skip events with too few/many tracks - Partition PVContributors = aod::udtrack::isPVContributor == true; - PVContributors.bindTable(dgtracks); + // Partition PVContributors = aod::udtrack::isPVContributor == true; + // PVContributors.bindTable(dgtracks); if (dgcand.numContrib() != PVContributors.size()) { LOGF(info, "Missmatch of PVContributors %d != %d", dgcand.numContrib(), PVContributors.size()); } diff --git a/PWGUD/Tasks/diffMCDataScanner.cxx b/PWGUD/Tasks/diffMCDataScanner.cxx index 05a3e497e17..8ad8d7ae853 100644 --- a/PWGUD/Tasks/diffMCDataScanner.cxx +++ b/PWGUD/Tasks/diffMCDataScanner.cxx @@ -102,9 +102,21 @@ struct collisionsInfo { using MFs = aod::MFTTracks; using FWs = aod::FwdTracks; - void process(CC const& collision, BCs const& bct0s, - TCs& tracks, /* MFs& mfttracks,*/ FWs& fwdtracks, aod::FT0s& /*ft0s*/, aod::FV0As& /*fv0as*/, aod::FDDs& /*fdds*/, - aod::McCollisions& /*McCols*/, aod::McParticles& /*McParts*/) + // filter for global tracks + Filter globalTrackFilter = requireGlobalTrackInFilter(); + using globalTracks = soa::Filtered; + + void process(CC const& collision, + BCs const& bct0s, + TCs& tracks, + /* MFs& mfttracks,*/ + FWs& fwdtracks, + globalTracks& goodTracks, + aod::FT0s& /*ft0s*/, + aod::FV0As& /*fv0as*/, + aod::FDDs& /*fdds*/, + aod::McCollisions& /*McCols*/, + aod::McParticles& /*McParts*/) { // obtain slice of compatible BCs @@ -123,8 +135,6 @@ struct collisionsInfo { } // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); - goodTracks.bindTable(tracks); int cntGlobal = goodTracks.size(); // count tracks diff --git a/PWGUD/Tasks/diffMCQA.cxx b/PWGUD/Tasks/diffMCQA.cxx index 4d199892762..19bf3016a97 100644 --- a/PWGUD/Tasks/diffMCQA.cxx +++ b/PWGUD/Tasks/diffMCQA.cxx @@ -239,12 +239,26 @@ struct DiffMCQA { PROCESS_SWITCH(DiffMCQA, processMCTruth, "Process MC truth", true); // ............................................................................................................... - void processMain(CC const& collision, BCs const& bct0s, - TCs const& tracks, FWs const& fwdtracks, ATs const& /*ambtracks*/, AFTs const& /*ambfwdtracks*/, - aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, aod::FDDs const& /*fdds*/, - aod::Zdcs& zdcs, aod::Calos& calos, - aod::V0s const& v0s, aod::Cascades const& cascades, - aod::McCollisions const& /*McCols*/, aod::McParticles const& McParts) + // filter for global tracks + Filter globalTrackFilter = requireGlobalTrackInFilter(); + using globalTracks = soa::Filtered; + + void processMain(CC const& collision, + BCs const& bct0s, + TCs const& tracks, + FWs const& fwdtracks, + globalTracks const& goodTracks, + ATs const& /*ambtracks*/, + AFTs const& /*ambfwdtracks*/, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs& zdcs, + aod::Calos& calos, + aod::V0s const& v0s, + aod::Cascades const& cascades, + aod::McCollisions const& /*McCols*/, + aod::McParticles const& McParts) { bool isDGcandidate = true; @@ -263,10 +277,6 @@ struct DiffMCQA { registry.get(HIST("all/mcCols"))->Fill(0., 1.); } - // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); - goodTracks.bindTable(tracks); - // update collision histograms if (isPythiaDiff) { registry.get(HIST("MBRDiff/Stat"))->Fill(0., 1.); diff --git a/PWGUD/Tasks/diffQA.cxx b/PWGUD/Tasks/diffQA.cxx index f219bc4eccb..a1e9ec34185 100644 --- a/PWGUD/Tasks/diffQA.cxx +++ b/PWGUD/Tasks/diffQA.cxx @@ -218,11 +218,24 @@ struct DiffQA { } // ............................................................................................................... - void processMain(CC const& collision, BCs const& bct0s, - TCs const& tracks, FWs const& fwdtracks, ATs const& /*ambtracks*/, AFTs const& /*ambfwdtracks*/, - aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, aod::FDDs const& /*fdds*/, - aod::Zdcs& zdcs, aod::Calos& calos, - aod::V0s const& v0s, aod::Cascades const& cascades) + // filter for global tracks + Filter globalTrackFilter = requireGlobalTrackInFilter(); + using globalTracks = soa::Filtered; + + void processMain(CC const& collision, + BCs const& bct0s, + TCs const& tracks, + FWs const& fwdtracks, + globalTracks const& goodTracks, + ATs const& /*ambtracks*/, + AFTs const& /*ambfwdtracks*/, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs& zdcs, + aod::Calos& calos, + aod::V0s const& v0s, + aod::Cascades const& cascades) { LOGF(debug, " Collision %d", collision.globalIndex()); LOGF(debug, " Start %i", abcrs.size()); @@ -239,8 +252,6 @@ struct DiffQA { // vertex tracks registry.get(HIST("collisions/PVTracks"))->Fill(collision.numContrib()); // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); - goodTracks.bindTable(tracks); registry.get(HIST("collisions/globalTracks"))->Fill(goodTracks.size()); // loop over all tracks diff --git a/PWGUD/Tasks/eventByevent.cxx b/PWGUD/Tasks/eventByevent.cxx new file mode 100644 index 00000000000..3df594af546 --- /dev/null +++ b/PWGUD/Tasks/eventByevent.cxx @@ -0,0 +1,302 @@ +// Copyright 2019-2020 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. +// + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "iostream" +#include "PWGUD/DataModel/UDTables.h" +#include +#include +#include "TLorentzVector.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/SGTrackSelector.h" + +using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// \brief Event by event study of pions +/// \author Amrit Gautam +/// \author Anisa Khatun +/// \date 20.07.2024 + +namespace o2::aod +{ +namespace tree +{ +// DECLARE_SOA_COLUMN(GAPSIDE, gapside, int); +// DECLARE_SOA_COLUMN(FT0AAMP, ft0Aamp, float); // namespace udzdc +// DECLARE_SOA_COLUMN(FT0CAMP, ft0Camp, float); +// DECLARE_SOA_COLUMN(FDDAAMP, fddAamp, float); +// DECLARE_SOA_COLUMN(FDDCAMP, fddCamp, float); +// DECLARE_SOA_COLUMN(FV0AAMP, fv0Aamp, float); +// ZDC tables +DECLARE_SOA_COLUMN(ZAENERGY, zaenergy, float); // namespace udzdc +DECLARE_SOA_COLUMN(ZCENERGY, zcenergy, float); +// track tables +// DECLARE_SOA_COLUMN(TRACKID, TrackId,std::vector); +DECLARE_SOA_COLUMN(SIGMAPI, sigmapi, std::vector); +DECLARE_SOA_COLUMN(SIGMAK, sigmak, std::vector); +DECLARE_SOA_COLUMN(SIGMAEL, sigmael, std::vector); +DECLARE_SOA_COLUMN(SIGMAPR, sigmapr, std::vector); +// DECLARE_SOA_COLUMN(SIGMAPI2, sigmapi2,float); +// DECLARE_SOA_COLUMN(SIGMAK2, sigmak2,float); +// DECLARE_SOA_COLUMN(SIGMAEL2, sigmael2,float); +// DECLARE_SOA_COLUMN(SIGMAPI3, sigmapi3,float); +// DECLARE_SOA_COLUMN(SIGMAK3, sigmak3,float); +// DECLARE_SOA_COLUMN(SIGMAEL3, sigmael3,float); +// DECLARE_SOA_COLUMN(SIGMAPI4, sigmapi4,float); +// DECLARE_SOA_COLUMN(SIGMAK4, sigmak4,float); +// DECLARE_SOA_COLUMN(SIGMAEL4, sigmael4,float); +DECLARE_SOA_COLUMN(PT, Pt, float); +DECLARE_SOA_COLUMN(RAP, rap, float); +DECLARE_SOA_COLUMN(PHI, Phi, float); +DECLARE_SOA_COLUMN(TOTSIGN, totsign, int); +DECLARE_SOA_COLUMN(MASS, mass, float); +DECLARE_SOA_COLUMN(NPVTRACK, npvtrack, int); +DECLARE_SOA_COLUMN(PTS, Pts, std::vector); +DECLARE_SOA_COLUMN(ETAS, etas, std::vector); +DECLARE_SOA_COLUMN(PHIS, Phis, std::vector); +DECLARE_SOA_COLUMN(SIGNS, Signs, std::vector); +// DECLARE_SOA_COLUMN(RAWTRACKS, rawtracks, int); +// DECLARE_SOA_COLUMN(PTRACKS, ptracks, int); + +// DECLARE_SOA_COLUMN(NTPCCLS, ntpccls,int); +} // namespace tree + +DECLARE_SOA_TABLE(TREE, "AOD", "Tree", //! ZDC information + // tree::GAPSIDE, + // tree::FT0AAMP, + // tree::FT0CAMP, + // tree::FDDAAMP, + // tree::FDDCAMP, + // tree::FV0AAMP, + tree::ZAENERGY, + tree::ZCENERGY, + tree::PT, + tree::RAP, + tree::PHI, + tree::MASS, + tree::TOTSIGN, + tree::NPVTRACK, + tree::SIGMAPI, + // tree::SIGMAPI2, + // tree::SIGMAPI3, + // tree::SIGMAPI4, + tree::SIGMAK, + // tree::SIGMAK2, + // tree::SIGMAK3, + // tree::SIGMAK4, + tree::SIGMAEL, + // tree::SIGMAEL2, + // tree::SIGMAEL3, + // tree::SIGMAEL4, + tree::SIGMAPR, + tree::PTS, + tree::ETAS, + tree::PHIS, + tree::SIGNS + // tree::RAWTRACKS, + // tree::PTRACKS +); + +} // namespace o2::aod + +struct EventByEvent { + SGSelector sgSelector; + Produces tree; + + Configurable FV0_cut{"FV0", 100., "FV0A threshold"}; + Configurable FT0A_cut{"FT0A", 200., "FT0A threshold"}; + Configurable FT0C_cut{"FT0C", 100., "FT0C threshold"}; + Configurable FDDA_cut{"FDDA", 10000., "FDDA threshold"}; + Configurable FDDC_cut{"FDDC", 10000., "FDDC threshold"}; + Configurable ZDC_cut{"ZDC", 10., "ZDC threshold"}; + Configurable gap_Side{"gap", 2, "gap selection"}; + + // Collision selection + Configurable collcontrib_cut{"collcontrib_cut", 10, "no. of PV contributor per collsion"}; + Configurable Zvtx_cut{"Zvtx_cut", 15, "z-vertex selection"}; + + // Track Selections + Configurable PV_cut{"PV_cut", 1.0, "Use Only PV tracks"}; + Configurable dcaZ_cut{"dcaZ_cut", 2.0, "dcaZ cut"}; + Configurable dcaXY_cut{"dcaXY_cut", 0.0, "dcaXY cut (0 for Pt-function)"}; + Configurable tpcChi2_cut{"tpcChi2_cut", 4, "Max tpcChi2NCl"}; + Configurable tpcNClsFindable_cut{"tpcNClsFindable_cut", 70, "Min tpcNClsFindable"}; + Configurable itsChi2_cut{"itsChi2_cut", 36, "Max itsChi2NCl"}; + Configurable eta_cut{"eta_cut", 0.9, "Track Pseudorapidity"}; + Configurable pt_cut{"pt_cut", 0.1, "Track Pt"}; + Configurable TPC_cluster{"TPC_cluster", 50, "No.of TPC cluster"}; + + // Kinmatic cuts + Configurable PID_cut{"PID_cut", 5, "TPC PID"}; + Configurable Rap_cut{"Rap_cut", 0.9, "Track rapidity"}; + Configurable Mass_Max{"Mass_Max", 10, "Invariant Mass range high"}; + Configurable Mass_Min{"Mass_Min", 0, "Invariant Mass range low"}; + Configurable Pt_coherent{"Pt_coherent", 0.15, "Coherent selection"}; + + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //----------------------------------------------------------------------------------------------------------------------- + void init(o2::framework::InitContext&) + { + + registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{20, 0., 20.}}); + + TString SelectionCuts[18] = {"NoSelection", "gapside", "goodtracks", "truegap", "ncollcontrib ", "zvtx", "2collcontrib", "2goodtrk", "TPCPID", "Rap_cut", "unlikesign", "mass_cut", "coherent", "incoherent", "likesign", "mass_cut", "coherent", "incoherent"}; + // now we can set BinLabel in histogram Registry + + for (int i = 0; i < 18; i++) { + hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); + } + + // tracks + registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("h4TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}}); + registry.add("hdEdxPion", "p_{#pi} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}}); + + // using Angular Correlation method + } + + using udtracks = soa::Join; + using udtracksfull = soa::Join; + using UDCollisionsFull = soa::Join; + //__________________________________________________________________________ + // Main process + void process(UDCollisionsFull::iterator const& collision, udtracksfull const& tracks) + { + registry.fill(HIST("hSelectionCounter"), 0); + // LOGF(info, " BC ID %d",collision.gapSide()); + int gapSide = collision.gapSide(); + if (gapSide < 0 || gapSide > 2) + return; + + registry.fill(HIST("hSelectionCounter"), 1); + + float FIT_cut[5] = {FV0_cut, FT0A_cut, FT0C_cut, FDDA_cut, FDDC_cut}; + int truegapSide = sgSelector.trueGap(collision, FIT_cut[0], FIT_cut[1], FIT_cut[2], ZDC_cut); + std::vector parameters = {PV_cut, dcaZ_cut, dcaXY_cut, tpcChi2_cut, tpcNClsFindable_cut, itsChi2_cut, eta_cut, pt_cut}; + registry.fill(HIST("hSelectionCounter"), 2); + + registry.fill(HIST("GapSide"), gapSide); + registry.fill(HIST("TrueGapSide"), truegapSide); + gapSide = truegapSide; + + registry.fill(HIST("hSelectionCounter"), 3); + //_____________________________________ + // Create pions and apply TPC Pion PID + std::vector allTracks; + std::vector onlyPionTracks; + std::vector onlyPionSigma; + std::vector rawPionTracks; + std::vector trackpt; + std::vector tracketa; + std::vector trackphi; + std::vector tracksign; + std::vector pitpcpid; + std::vector ktpcpid; + std::vector eltpcpid; + std::vector prtpcpid; + + TLorentzVector p; + + if (gapSide == gap_Side) { + + // registry.fill(HIST("hTracks"), tracks.size()); + + if (collision.numContrib() > collcontrib_cut) + return; + + registry.fill(HIST("hSelectionCounter"), 4); + if ((collision.posZ() < -(Zvtx_cut)) || (collision.posZ() > Zvtx_cut)) + return; + registry.fill(HIST("hSelectionCounter"), 5); + + for (auto t : tracks) { + + if (!trackselector(t, parameters)) + continue; + + double dEdx = t.tpcSignal(); + + registry.fill(HIST("hdEdx"), t.tpcInnerParam() / t.sign(), dEdx); + TLorentzVector a; + a.SetXYZM(t.px(), t.py(), t.pz(), o2::constants::physics::MassPionCharged); + allTracks.push_back(a); + auto nSigmaPi = t.tpcNSigmaPi(); + + if (fabs(nSigmaPi) < PID_cut) { + onlyPionTracks.push_back(a); + onlyPionSigma.push_back(nSigmaPi); + rawPionTracks.push_back(t); + registry.fill(HIST("hdEdxPion"), t.tpcInnerParam() / t.sign(), dEdx); + } + } + registry.fill(HIST("hTracksPions"), onlyPionTracks.size()); + + //_____________________________________ + if (collision.numContrib() >= 2) { + // Four pions analysis + registry.fill(HIST("hSelectionCounter"), 6); + if ((rawPionTracks.size() >= 2) && (allTracks.size() >= 2)) { + + for (auto pion : onlyPionTracks) { + p += pion; + } + + registry.fill(HIST("h4TracksPions"), onlyPionTracks.size()); + registry.fill(HIST("hSelectionCounter"), 7); + + for (auto rtrk : rawPionTracks) { + + TLorentzVector itrk; + itrk.SetXYZM(rtrk.px(), rtrk.py(), rtrk.pz(), o2::constants::physics::MassPionCharged); + trackpt.push_back(itrk.Pt()); + tracketa.push_back(itrk.Eta()); + trackphi.push_back(itrk.Phi()); + tracksign.push_back(rtrk.sign()); + pitpcpid.push_back(rtrk.tpcNSigmaPi()); + ktpcpid.push_back(rtrk.tpcNSigmaKa()); + eltpcpid.push_back(rtrk.tpcNSigmaEl()); + prtpcpid.push_back(rtrk.tpcNSigmaPr()); + } + + int sign = 0; + TLorentzVector piplus, piminus; + for (auto rawPion : rawPionTracks) { + sign += rawPion.sign(); + } + + registry.fill(HIST("hTracks"), collision.numContrib()); + + tree(collision.energyCommonZNA(), collision.energyCommonZNC(), p.Pt(), p.Y(), p.Phi(), p.M(), sign, collision.numContrib(), pitpcpid, ktpcpid, eltpcpid, prtpcpid, trackpt, tracketa, trackphi, tracksign); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/fwdMuonsUPC.cxx b/PWGUD/Tasks/fwdMuonsUPC.cxx new file mode 100644 index 00000000000..34075b7a862 --- /dev/null +++ b/PWGUD/Tasks/fwdMuonsUPC.cxx @@ -0,0 +1,445 @@ +// Copyright 2019-2020 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. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "TLorentzVector.h" +#include "TSystem.h" +#include "TMath.h" + +namespace dimu +{ +// dimuon +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +// tracks positive (p) and negative (n) +DECLARE_SOA_COLUMN(Ptp, ptp, float); +DECLARE_SOA_COLUMN(Etap, etap, float); +DECLARE_SOA_COLUMN(Phip, phip, float); +DECLARE_SOA_COLUMN(Ptn, ptn, float); +DECLARE_SOA_COLUMN(Etan, etan, float); +DECLARE_SOA_COLUMN(Phin, phin, float); +// zn +DECLARE_SOA_COLUMN(Tzna, tzna, float); +DECLARE_SOA_COLUMN(Ezna, ezna, float); +DECLARE_SOA_COLUMN(Tznc, tznc, float); +DECLARE_SOA_COLUMN(Eznc, eznc, float); +DECLARE_SOA_COLUMN(Nclass, nclass, int); +} // namespace dimu + +namespace o2::aod +{ +DECLARE_SOA_TABLE(DiMu, "AOD", "DIMU", + dimu::M, dimu::Pt, dimu::Rap, dimu::Phi, + dimu::Ptp, dimu::Etap, dimu::Phip, + dimu::Ptn, dimu::Etan, dimu::Phin, + dimu::Tzna, dimu::Ezna, dimu::Tznc, dimu::Eznc, dimu::Nclass); +} + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// defining constants +double mMu = 0.10566; // mass of muon + +// constants used in the track selection +const float kRAbsMin = 17.6; +const float kRAbsMid = 26.5; +const float kRAbsMax = 89.5; +const float kPDca1 = 200.; +const float kPDca2 = 200.; +const float kEtaMin = -4.0; +const float kEtaMax = -2.5; +const float kPtMin = 0.; + +struct fwdMuonsUPC { + + using CandidatesFwd = soa::Join; + using ForwardTracks = soa::Join; + + Produces dimuSel; + + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry reg0n0n{"reg0n0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry regXn0n{"regXn0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry regXnXn{"regXnXn", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // CONFIGURABLES + // pT of muon pairs + Configurable nBinsPt{"nBinsPt", 250, "N bins in pT histo"}; + Configurable lowPt{"lowPt", 0., "lower limit in pT histo"}; + Configurable highPt{"highPt", 0.5, "upper limit in pT histo"}; + // mass of muon pairs + Configurable nBinsMass{"nBinsMass", 500, "N bins in mass histo"}; + Configurable lowMass{"lowMass", 0., "lower limit in mass histo"}; + Configurable highMass{"highMass", 10., "upper limit in mass histo"}; + // eta of muon pairs + Configurable nBinsEta{"nBinsEta", 600, "N bins in eta histo"}; + Configurable lowEta{"lowEta", -10., "lower limit in eta histo"}; + Configurable highEta{"highEta", -2., "upper limit in eta histo"}; + // rapidity of muon pairs + Configurable nBinsRapidity{"nBinsRapidity", 250, "N bins in rapidity histo"}; + Configurable lowRapidity{"lowRapidity", -4.5, "lower limit in rapidity histo"}; + Configurable highRapidity{"highRapidity", -2., "upper limit in rapidity histo"}; + // phi of muon pairs + Configurable nBinsPhi{"nBinsPhi", 600, "N bins in phi histo"}; + Configurable lowPhi{"lowPhi", -TMath::Pi(), "lower limit in phi histo"}; + Configurable highPhi{"highPhi", TMath::Pi(), "upper limit in phi histo"}; + // pT of single muons + Configurable nBinsPtSingle{"nBinsPtSingle", 500, "N bins in pT histo single muon"}; + Configurable lowPtSingle{"lowPtSingle", 0., "lower limit in pT histo single muon"}; + Configurable highPtSingle{"highPtSingle", 2., "upper limit in pT histo single muon"}; + // eta of single muons + Configurable nBinsEtaSingle{"nBinsEtaSingle", 250, "N bins in eta histo single muon"}; + Configurable lowEtaSingle{"lowEtaSingle", -4.5, "lower limit in eta histo single muon"}; + Configurable highEtaSingle{"highEtaSingle", -2., "upper limit in eta histo single muon"}; + // phi of single muons + Configurable nBinsPhiSingle{"nBinsPhiSingle", 600, "N bins in phi histo single muon"}; + Configurable lowPhiSingle{"lowPhiSingle", -TMath::Pi(), "lower limit in phi histo single muon"}; + Configurable highPhiSingle{"highPhiSingle", TMath::Pi(), "upper limit in phi histo single muon"}; + // ZDC + Configurable nBinsZDCen{"nBinsZDCen", 200, "N bins in ZN energy"}; + Configurable lowEnZN{"lowEnZN", -50., "lower limit in ZN energy histo"}; + Configurable highEnZN{"highEnZN", 250., "upper limit in ZN energy histo"}; + + // configuarble rapidity cuts + Configurable yCutLow{"yCutLow", -4, "Lower cut in pair rapidity"}; + Configurable yCutUp{"yCutUp", -2.5, "Upper cut in pair rapidity"}; + + void init(InitContext&) + { + // binning of pT axis fr fit + std::vector ptFitBinning = { + 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, + 0.11, 0.12, 0.13, 0.14, 0.15, 0.175, 0.20, 0.25, 0.30, 0.40, 0.50, + 0.60, 0.70, 0.80, 0.90, 1.00, 1.20, 1.40, 1.60, 1.80, 2.00, 2.50, + 3.00, 3.50}; + + // axis + const AxisSpec axisPt{nBinsPt, lowPt, highPt, "#it{p}_{T} GeV/#it{c}"}; + const AxisSpec axisPtFit = {ptFitBinning, "#it{p}_{T} (GeV/c)"}; + const AxisSpec axisMass{nBinsMass, lowMass, highMass, "m_{#mu#mu} GeV/#it{c}^{2}"}; + const AxisSpec axisEta{nBinsEta, lowEta, highEta, "#eta"}; + const AxisSpec axisRapidity{nBinsRapidity, lowRapidity, highRapidity, "Rapidity"}; + const AxisSpec axisPhi{nBinsPhi, lowPhi, highPhi, "#varphi"}; + const AxisSpec axisPtSingle{nBinsPtSingle, lowPtSingle, highPtSingle, "#it{p}_{T}_{ trk} GeV/#it{c}"}; + const AxisSpec axisTimeZN{200, -10, 10, "ZDC time (ns)"}; + const AxisSpec axisEnergyZNA{nBinsZDCen, lowEnZN, highEnZN, "ZNA energy (TeV)"}; + const AxisSpec axisEnergyZNC{nBinsZDCen, lowEnZN, highEnZN, "ZNC energy (TeV)"}; + const AxisSpec axisEtaSingle{nBinsEtaSingle, lowEtaSingle, highEtaSingle, "#eta_{trk}"}; + const AxisSpec axisPhiSingle{nBinsPhiSingle, lowPhiSingle, highPhiSingle, "#varphi_{trk}"}; + + // histos + registry.add("hMass", "Ivariant mass of muon pairs;;#counts", kTH1D, {axisMass}); + registry.add("hPt", "Transverse momentum mass of muon pairs;;#counts", kTH1D, {axisPt}); + registry.add("hPtFit", "Transverse momentum mass of muon pairs;;#counts", kTH1D, {axisPtFit}); + registry.add("hEta", "Pseudorapidty of muon pairs;;#counts", kTH1D, {axisEta}); + registry.add("hRapidity", "Rapidty of muon pairs;;#counts", kTH1D, {axisRapidity}); + registry.add("hPhi", "#varphi of muon pairs;;#counts", kTH1D, {axisPhi}); + registry.add("hCharge", "Charge;#it{charge};;#counts", kTH1D, {{5, -2.5, 2.5}}); + registry.add("hContrib", "hContrib;;#counts", kTH1D, {{6, -0.5, 5.5}}); + registry.add("hEvSign", "Sum of the charges of all the tracks in each event;;#counts", kTH1D, {{5, -2.5, 2.5}}); + registry.add("hPtTrkPos", "Pt of positive muons;;#counts", kTH1D, {axisPtSingle}); + registry.add("hPtTrkNeg", "Pt of negative muons;;#counts", kTH1D, {axisPtSingle}); + registry.add("hEtaTrkPos", "#eta of positive muons;;#counts", kTH1D, {axisEtaSingle}); + registry.add("hEtaTrkNeg", "#eta of negative muons;;#counts", kTH1D, {axisEtaSingle}); + registry.add("hPhiTrkPos", "#varphi of positive muons;;#counts", kTH1D, {axisPhiSingle}); + registry.add("hPhiTrkNeg", "#varphi of negative muons;;#counts", kTH1D, {axisPhiSingle}); + registry.add("hTimeZNA", "ZNA Times;;#counts", kTH1D, {axisTimeZN}); + registry.add("hTimeZNC", "ZNC Times;;#counts", kTH1D, {axisTimeZN}); + registry.add("hEnergyZN", "ZNA vs ZNC energy", kTH2D, {axisEnergyZNA, axisEnergyZNC}); + registry.add("hSameSign", "hSameSign;;#counts", kTH1D, {{6, -0.5, 5.5}}); + + reg0n0n.add("hMass", "Ivariant mass of muon pairs - 0n0n;;#counts", kTH1D, {axisMass}); + reg0n0n.add("hPt", "Transverse momentum mass of muon pairs - 0n0n;;#counts", kTH1D, {axisPt}); + reg0n0n.add("hEta", "Pseudorapidty of muon pairs - 0n0n;;#counts", kTH1D, {axisEta}); + reg0n0n.add("hRapidity", "Rapidty of muon pairs - 0n0n;;#counts", kTH1D, {axisRapidity}); + reg0n0n.add("hPtFit", "Transverse momentum mass of muon pairs - 0n0n;;#counts", kTH1D, {axisPtFit}); + + regXn0n.add("hMass", "Ivariant mass of muon pairs - Xn0n;;#counts", kTH1D, {axisMass}); + regXn0n.add("hPt", "Transverse momentum mass of muon pairs - Xn0n;;#counts", kTH1D, {axisPt}); + regXn0n.add("hEta", "Pseudorapidty of muon pairs - Xn0n;;#counts", kTH1D, {axisEta}); + regXn0n.add("hRapidity", "Rapidty of muon pairs - Xn0n;;#counts", kTH1D, {axisRapidity}); + regXn0n.add("hPtFit", "Transverse momentum mass of muon pairs - Xn0n;;#counts", kTH1D, {axisPtFit}); + + regXnXn.add("hMass", "Ivariant mass of muon pairs - XnXn;;#counts", kTH1D, {axisMass}); + regXnXn.add("hPt", "Transverse momentum mass of muon pairs - XnXn;;#counts", kTH1D, {axisPt}); + regXnXn.add("hEta", "Pseudorapidty of muon pairs - XnXn;;#counts", kTH1D, {axisEta}); + regXnXn.add("hRapidity", "Rapidty of muon pairs - XnXn;;#counts", kTH1D, {axisRapidity}); + regXnXn.add("hPtFit", "Transverse momentum mass of muon pairs - XnXn;;#counts", kTH1D, {axisPtFit}); + } + + // FUNCTIONS + + // template function that fills a map with the collision id of each udcollision as key + // and a vector with the tracks + // map == (key, element) == (udCollisionId, vector of trks) + template + void collectCandIDs(std::unordered_map>& tracksPerCand, TTracks& tracks) + { + for (const auto& tr : tracks) { + int32_t candId = tr.udCollisionId(); + if (candId < 0) { + continue; + } + tracksPerCand[candId].push_back(tr.globalIndex()); + } + } + + // struct used to store the ZDC info in a map + struct ZDCinfo { + float timeA; + float timeC; + float enA; + float enC; + int32_t id; + }; + + // function that fills a map with the collision id of each udcollision as key + // and a ZDCinfo struct with the ZDC information + void collectCandZDCInfo(std::unordered_map& zdcPerCand, o2::aod::UDZdcsReduced& ZDCs) + { + + for (auto& zdc : ZDCs) { + int32_t candId = zdc.udCollisionId(); + if (candId < 0) { + continue; + } + + zdcPerCand[candId].timeA = zdc.timeZNA(); + zdcPerCand[candId].timeC = zdc.timeZNC(); + zdcPerCand[candId].enA = zdc.energyCommonZNA(); + zdcPerCand[candId].enC = zdc.energyCommonZNC(); + + // take care of the infinity + if (std::isinf(zdcPerCand[candId].timeA)) + zdcPerCand[candId].timeA = -999; + if (std::isinf(zdcPerCand[candId].timeC)) + zdcPerCand[candId].timeC = -999; + if (std::isinf(zdcPerCand[candId].enA)) + zdcPerCand[candId].enA = -999; + if (std::isinf(zdcPerCand[candId].enC)) + zdcPerCand[candId].enC = -999; + } + } + + // function to select muon tracks + bool isMuonSelected(const ForwardTracks::iterator& fwdTrack) + { + float rAbs = fwdTrack.rAtAbsorberEnd(); + float pDca = fwdTrack.pDca(); + TLorentzVector p; + p.SetXYZM(fwdTrack.px(), fwdTrack.py(), fwdTrack.pz(), mMu); + float eta = p.Eta(); + float pt = p.Pt(); + float pDcaMax = rAbs < kRAbsMid ? kPDca1 : kPDca2; + + if (eta < kEtaMin || eta > kEtaMax) + return false; + if (pt < kPtMin) + return false; + if (rAbs < kRAbsMin || rAbs > kRAbsMax) + return false; + if (pDca > pDcaMax) + return false; + return true; + } + + // function that processes the candidates: + // it applies V0 selection, trk selection, and fills the histograms + void processCand(CandidatesFwd::iterator const& cand, + const ForwardTracks::iterator& tr1, const ForwardTracks::iterator& tr2, + ZDCinfo& zdc) + { + // V0 selection + const auto& ampsV0A = cand.amplitudesV0A(); + const auto& ampsRelBCsV0A = cand.ampRelBCsV0A(); + for (unsigned int i = 0; i < ampsV0A.size(); ++i) { + if (std::abs(ampsRelBCsV0A[i]) <= 1) { + if (ampsV0A[i] > 100.) + return; + } + } + + // track selection + TLorentzVector p1, p2; + p1.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), mMu); + p2.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), mMu); + TLorentzVector p = p1 + p2; + if (!isMuonSelected(tr1)) + return; + if (!isMuonSelected(tr2)) + return; + + // MCH-MID match selection + int nMIDs = 0; + if (tr1.chi2MatchMCHMID() > 0) + nMIDs++; + if (tr2.chi2MatchMCHMID() > 0) + nMIDs++; + if (nMIDs != 2) + return; + + // cuts on pair kinematics + if (!(p.M() > 2 && p.M() < 6 && p.Pt() < 5)) + return; + + // select opposite charge events only + if (cand.netCharge() != 0) { + registry.fill(HIST("hSameSign"), cand.numContrib()); + return; + } + + // select rapidity ranges + if (p.Rapidity() < yCutLow) + return; + if (p.Rapidity() > yCutUp) + return; + + // zdc info + if (TMath::Abs(zdc.timeA) < 10) + registry.fill(HIST("hTimeZNA"), zdc.timeA); + if (TMath::Abs(zdc.timeC) < 10) + registry.fill(HIST("hTimeZNC"), zdc.timeC); + registry.fill(HIST("hEnergyZN"), zdc.enA, zdc.enC); + + // divide the events in neutron classes + bool neutron_A = false; + bool neutron_C = false; + int znClass = -1; + + if (TMath::Abs(zdc.timeA) < 2) + neutron_A = true; + if (TMath::Abs(zdc.timeC) < 2) + neutron_C = true; + + if (std::isinf(zdc.timeC)) + neutron_C = false; + if (std::isinf(zdc.timeA)) + neutron_A = false; + + // fill the histos in neutron classes and assign neutron class label + // 0n0n + if (neutron_C == false && neutron_A == false) { + znClass = 0; + reg0n0n.fill(HIST("hMass"), p.M()); + reg0n0n.fill(HIST("hPt"), p.Pt()); + reg0n0n.fill(HIST("hPtFit"), p.Pt()); + reg0n0n.fill(HIST("hEta"), p.Eta()); + reg0n0n.fill(HIST("hRapidity"), p.Rapidity()); + } else if (neutron_A ^ neutron_C) { // Xn0n + 0nXn + if (neutron_A) + znClass = 1; + else if (neutron_C) + znClass = 2; + regXn0n.fill(HIST("hMass"), p.M()); + regXn0n.fill(HIST("hPt"), p.Pt()); + regXn0n.fill(HIST("hPtFit"), p.Pt()); + regXn0n.fill(HIST("hEta"), p.Eta()); + regXn0n.fill(HIST("hRapidity"), p.Rapidity()); + } else if (neutron_A && neutron_C) { // XnXn + znClass = 3; + regXnXn.fill(HIST("hMass"), p.M()); + regXnXn.fill(HIST("hPt"), p.Pt()); + regXnXn.fill(HIST("hPtFit"), p.Pt()); + regXnXn.fill(HIST("hEta"), p.Eta()); + regXnXn.fill(HIST("hRapidity"), p.Rapidity()); + } + + // fill the histos without looking at neutron emission + registry.fill(HIST("hContrib"), cand.numContrib()); + registry.fill(HIST("hPtTrkPos"), p1.Pt()); + registry.fill(HIST("hPtTrkNeg"), p2.Pt()); + registry.fill(HIST("hEtaTrkPos"), p1.Eta()); + registry.fill(HIST("hEtaTrkNeg"), p2.Eta()); + registry.fill(HIST("hPhiTrkPos"), p1.Phi()); + registry.fill(HIST("hPhiTrkNeg"), p2.Phi()); + registry.fill(HIST("hEvSign"), cand.netCharge()); + registry.fill(HIST("hMass"), p.M()); + registry.fill(HIST("hPt"), p.Pt()); + registry.fill(HIST("hPtFit"), p.Pt()); + registry.fill(HIST("hEta"), p.Eta()); + registry.fill(HIST("hRapidity"), p.Rapidity()); + registry.fill(HIST("hPhi"), p.Phi()); + registry.fill(HIST("hCharge"), tr1.sign()); + registry.fill(HIST("hCharge"), tr2.sign()); + + // store the event to save it into a tree + if (tr1.sign() > 0) { + dimuSel(p.M(), p.Pt(), p.Rapidity(), p.Phi(), + p1.Pt(), p1.PseudoRapidity(), p1.Phi(), + p2.Pt(), p2.PseudoRapidity(), p2.Phi(), + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + } else { + dimuSel(p.M(), p.Pt(), p.Rapidity(), p.Phi(), + p2.Pt(), p2.PseudoRapidity(), p2.Phi(), + p1.Pt(), p1.PseudoRapidity(), p1.Phi(), + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + } + } + + // PROCESS FUNCTION + void process(CandidatesFwd const& eventCandidates, + o2::aod::UDZdcsReduced& ZDCs, + ForwardTracks const& fwdTracks) + { + + // map with the tracks + std::unordered_map> tracksPerCand; + collectCandIDs(tracksPerCand, fwdTracks); + + // map with the ZDC info + std::unordered_map zdcPerCand; + collectCandZDCInfo(zdcPerCand, ZDCs); + + // loop over the candidates + for (const auto& item : tracksPerCand) { + int32_t trId1 = item.second[0]; + int32_t trId2 = item.second[1]; + int32_t candID = item.first; + auto cand = eventCandidates.iteratorAt(candID); + auto tr1 = fwdTracks.iteratorAt(trId1); + auto tr2 = fwdTracks.iteratorAt(trId2); + + ZDCinfo zdc; + + if (zdcPerCand.count(candID) != 0) { + zdc = zdcPerCand.at(candID); + } else { + zdc.timeA = -999; + zdc.timeC = -999; + zdc.enA = -999; + zdc.enC = -999; + } + + processCand(cand, tr1, tr2, zdc); + } + } + + PROCESS_SWITCH(fwdMuonsUPC, process, "", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGUD/Tasks/sgExclusivePhiITSselections.cxx b/PWGUD/Tasks/sgExclusivePhiITSselections.cxx new file mode 100644 index 00000000000..cf615d18257 --- /dev/null +++ b/PWGUD/Tasks/sgExclusivePhiITSselections.cxx @@ -0,0 +1,398 @@ +// Copyright 2019-2020 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. +// +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "iostream" +#include "PWGUD/DataModel/UDTables.h" +#include +#include "TLorentzVector.h" +#include "Common/DataModel/PIDResponse.h" +#include "PWGUD/Core/SGSelector.h" + +using std::array; +using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// \brief Exclusive phi without PID +/// \author Simone Ragoni, Creighton +/// \date 8/8/2024 + +struct sgExclusivePhiITSselections { + SGSelector sgSelector; + Configurable FV0_cut{"FV0", 100., "FV0A threshold"}; + Configurable FT0A_cut{"FT0A", 200., "FT0A threshold"}; + Configurable FT0C_cut{"FT0C", 100., "FT0C threshold"}; + Configurable ZDC_cut{"ZDC", 10., "ZDC threshold"}; + Configurable gap_Side{"gap", 2, "gap selection"}; + Configurable DGactive{"DGactive", false, "DG active"}; + Configurable SGactive{"SGactive", true, "SG active"}; + // Configurable DGorSG{"DGorSG", 1, "SG = 1, DG = 2"}; + Configurable NofITShits{"NofITShits", 7, "ITS layers hit"}; + Configurable pt_threshold{"pt_threshold", 0.180, "pT threshold"}; + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + //----------------------------------------------------------------------------------------------------------------------- + void init(o2::framework::InitContext&) + { + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{12, 0., 12.}}); + TString SelectionCuts[12] = {"NoSelection", "Trackloop", "PVtracks", "|nsigmaka|<3", "|nsigmapi|>3", "|nsigmael|>3", "|nsigmamu|>3", "two tracks", "Phi-peak", "pt<0.2 GeV/c", "pt>0.2 GeV/c"}; + + for (int i = 0; i < 12; i++) { + hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); + } + + registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + + registry.add("posx", "Vertex position in x", kTH1F, {{100, -0.5, 0.5}}); + registry.add("posy", "Vertex position in y", kTH1F, {{100, -0.5, 0.5}}); + registry.add("posz", "Vertex position in z", kTH1F, {{1000, -100., 100.}}); + + registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTracksITSonly", "N_{tracks ITS only}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hITSCluster", "N_{cluster}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hChi2ITSTrkSegment", "N_{cluster}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTPCCluster", "N_{cluster}", kTH1F, {{200, -0.5, 199.5}}); + registry.add("hTracksKaons", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon1", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon2", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon3", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon4", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon5", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon6", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon7", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon8", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon9", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + + registry.add("hNsigEvsKa2", "NSigmaKa(t1) vs NSigmaKa (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, 0., 1000.}, {100, 0., 1000}}); + registry.add("hMomentum", "p_{#ka};#it{p_{trk}}, GeV/c;", kTH1F, {{100, 0., 3.}}); + registry.add("hClusterSizeAllTracks", "ClusterSizeAllTracks;Average cls size in the ITS layers;", kTH1F, {{1000, 0., 100.}}); + registry.add("hClusterSizeMomentumCut", "ClusterSizeMomentumCut;Average cls size in the ITS layers;", kTH1F, {{1000, 0., 100.}}); + registry.add("hClusterSizeOnlyIdentifiedKaons", "ClusterSizeOnlyIdentifiedKaons;Average cls size in the ITS layers;", kTH1F, {{1000, 0., 100.}}); + registry.add("hClusterSizeOnlyITS", "ClusterSizeOnlyITS;Average cls size in the ITS layers;", kTH1F, {{1000, 0., 100.}}); + registry.add("hClusterSizeOnlyITS2", "ClusterSizeOnlyITS;Average cls size in the ITS layers;", kTH1F, {{1000, 0., 100.}}); + registry.add("hClusterSizeAllTracksVsP", "ClusterSizeAllTracks vs p; p; Average cls size in the ITS layers", kTH2F, {{100, 0.0, 10.0}, {1000, 0., 100.}}); + registry.add("hClusterSizeMomentumCutVsP", "hClusterSizeMomentumCut vs p; p; Average cls size in the ITS layers", kTH2F, {{100, 0.0, 10.0}, {1000, 0., 100.}}); + registry.add("hClusterSizeOnlyITSVsP", "hClusterSizeOnlyITS vs p; p; Average cls size in the ITS layers", kTH2F, {{100, 0.0, 10.0}, {1000, 0., 100.}}); + registry.add("hEta1", "#eta_{#ka};#it{#eta_{trk}}, GeV/c;", kTH1F, {{100, -2., 2.}}); + + auto hSelectionCounter2 = registry.add("hSelectionCounter2", "hSelectionCounter;;NEvents", HistType::kTH1I, {{12, 0., 12.}}); + TString SelectionCuts2[12] = {"NoSelection", "Trackloop", "PVtracks", "|nTPCCluster|<50", " track pt<0.180 GeV/c", "Kaon Band", "ITSCluster<6", "two tracks", "Phi-peak", "pt<0.2 GeV/c", "pt>0.2 GeV/c"}; + + for (int i = 0; i < 12; i++) { + hSelectionCounter2->GetXaxis()->SetBinLabel(i + 1, SelectionCuts2[i].Data()); + } + + registry.add("hMassPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("hMassPtPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + + // Phi peak region + registry.add("PHI/hPtPhiWithoutPID", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHI/hMassVsPt", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("PHI/hRapidityPhiWithoutPID", "Rapidity;#it{y_{KK}};", kTH1F, {{100, -2., 2.}}); + registry.add("PHI/hPtKaonVsKaon", "Pt1 vs Pt2;p_{T};p_{T};", kTH2F, {{100, 0., 3.}, {100, 0., 3.}}); + + // DIfferent phi topologies, 2 identified kaons, 1 identified kaon + 1 ITS track with correct selections and N ITS clusters + registry.add("KaonBandPHI/hMassPtPhiIdentifiedKaons", "Raw Inv.M;#it{m_{KK}} (GeV/c^{2});Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("KaonBandPHI/hMassPhiIdentifiedKaons", "Raw Inv.M;#it{M_{KK}} (GeV/c^{2});", kTH1F, {{400, 0., 4.}}); + registry.add("KaonBandPHI/hPtPhiIdentifiedKaons", "Pt;#it{p_{t}} (GeV/c);", kTH1F, {{400, 0., 4.}}); + registry.add("KaonBandPHI/hMassPtPhiIdentifiedKaonAndITSkaon", "Raw Inv.M;#it{m_{KK}} (GeV/c^{2});Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("KaonBandPHI/hMassPhiIdentifiedKaonAndITSkaon", "Raw Inv.M;#it{m_{KK}} (GeV/c^{2});", kTH1F, {{400, 0., 4.}}); + registry.add("KaonBandPHI/hPtPhiIdentifiedKaonAndITSkaon", "Pt;#it{p_{t}} (GeV/c);", kTH1F, {{400, 0., 4.}}); + + registry.add("PHI/hMassLike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hMassUnlike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hlikePt", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHI/hUnlikePt", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHI/hCoherentPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hInCoherentPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hCoherentMassLike", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hInCoherentMassLike", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + } + + using udtracks = soa::Join; + using udtracksfull = soa::Join; + using UDCollisionsFull = soa::Join; + //__________________________________________________________________________ + // Main process + void eventprocessing(int gapSide, udtracksfull const& tracks) + { + registry.fill(HIST("hSelectionCounter"), 0); + + if (gapSide == gap_Side) { + TLorentzVector phi, phiWithoutPID, phiWithKaonPID; // lorentz vectors of tracks and the mother + + // =================================== + // Task for phi WITHOUT PID + // =================================== + + // ==================================== + // Selections for events to be stored + // ------------------------------------ + // - PV: only PV contributors + // - only two PV contributors + // - both PV have t.hasITS() ON + // - only ITS tracks + //_____________________________________ + // Create kaons WITHOUT PID + std::vector onlyTwoTracks; + std::vector onlyKaonBandPID; + std::vector onlyITS; + std::vector allTracksAreKaons; + std::vector allTracksAreKaonsBandPID; + std::vector allTracksAreITSonlyAndFourITSclusters; + for (auto t : tracks) { + registry.fill(HIST("hSelectionCounter2"), 0); + if (!t.isPVContributor()) { + continue; + } + registry.fill(HIST("hSelectionCounter2"), 1); + registry.fill(HIST("hTracks"), t.size()); + + double momentum = TMath::Sqrt(t.px() * t.px() + t.py() * t.py() + t.pz() * t.pz()); + double dEdx = t.tpcSignal(); + + int clusterSize[7]; + double averageClusterSize = 0.; + double activeClusters = 0.; + for (int i = 0; i < 7; i++) { // info stored in 4 bits + clusterSize[i] = (((1 << 4) - 1) & (t.itsClusterSizes() >> 4 * i)); + auto clusterSizeValue = static_cast(clusterSize[i]); + if (clusterSizeValue != 0) { + averageClusterSize += clusterSizeValue; + activeClusters += 1; + } + averageClusterSize += static_cast(clusterSize[i]); + } + if (activeClusters != 0) { + averageClusterSize /= activeClusters; + } else { + averageClusterSize = -999.; + } + registry.fill(HIST("hClusterSizeAllTracks"), averageClusterSize); + registry.fill(HIST("hClusterSizeAllTracksVsP"), momentum, averageClusterSize); + + int NFindable = t.tpcNClsFindable(); + int NMinusFound = t.tpcNClsFindableMinusFound(); + int NCluster = NFindable - NMinusFound; + + if (NCluster > 50) { + continue; + } + registry.fill(HIST("hSelectionCounter2"), 3); + registry.fill(HIST("hdEdxKaon5"), t.tpcInnerParam() / t.sign(), dEdx); + + if (t.pt() > pt_threshold) { + continue; + } + if (!(std::abs(t.dcaZ()) < 2.)) { + continue; + } + double dcaLimit = 0.0105 + 0.035 / pow(t.pt(), 1.1); + if (!(std::abs(t.dcaXY()) < dcaLimit)) { + continue; + } + + registry.fill(HIST("hSelectionCounter2"), 4); + registry.fill(HIST("hMomentum"), momentum); + registry.fill(HIST("hdEdxKaon6"), t.tpcInnerParam() / t.sign(), dEdx); + registry.fill(HIST("hdEdxKaon2"), momentum, dEdx); + registry.fill(HIST("hClusterSizeMomentumCut"), averageClusterSize); + registry.fill(HIST("hClusterSizeMomentumCutVsP"), momentum, averageClusterSize); + + onlyTwoTracks.push_back(t); + + TLorentzVector a; + a.SetXYZM(t.px(), t.py(), t.pz(), o2::constants::physics::MassKaonCharged); + allTracksAreKaons.push_back(a); + + bool kaonBand = false; + if ((momentum < 0.150) && (dEdx > 300)) { + kaonBand = true; + } else if ((momentum > 0.150) && (momentum < 0.220) && (dEdx > 250)) { + kaonBand = true; + } else if ((momentum > 0.220) && (momentum < 0.300) && (dEdx > 180)) { + kaonBand = true; + } else if ((momentum > 0.300) && (momentum < 0.500) && (dEdx > 110)) { + kaonBand = true; + } + + if (kaonBand == true) { + registry.fill(HIST("hSelectionCounter2"), 5); + allTracksAreKaonsBandPID.push_back(a); + onlyKaonBandPID.push_back(t); + registry.fill(HIST("hdEdxKaon7"), t.tpcInnerParam() / t.sign(), dEdx); + registry.fill(HIST("hClusterSizeOnlyIdentifiedKaons"), averageClusterSize); + } + + if (NFindable < 1 && t.itsNCls() < NofITShits) { + allTracksAreITSonlyAndFourITSclusters.push_back(a); + onlyITS.push_back(t); + registry.fill(HIST("hdEdxKaon8"), t.tpcInnerParam() / t.sign(), dEdx); + registry.fill(HIST("hSelectionCounter2"), 6); + registry.fill(HIST("hClusterSizeOnlyITS2"), averageClusterSize); + } + + } // track loop + + //_____________________________________ + // Creating phis and saving all the information + // in the case that there are ONLY 2 PV + if (allTracksAreKaons.size() == 2) { + registry.fill(HIST("hSelectionCounter2"), 7); + for (auto kaon : allTracksAreKaons) { + phiWithoutPID += kaon; + } + registry.fill(HIST("hTracksKaons"), allTracksAreKaons.size()); + registry.fill(HIST("hNsigEvsKa2"), onlyTwoTracks[0].tpcSignal(), onlyTwoTracks[1].tpcSignal()); + registry.fill(HIST("hEta1"), allTracksAreKaons[0].Eta()); + registry.fill(HIST("hEta1"), allTracksAreKaons[1].Eta()); + + // All invariant mass region + registry.fill(HIST("hMassPhiWithoutPID"), phiWithoutPID.M()); + registry.fill(HIST("hMassPtPhiWithoutPID"), phiWithoutPID.M(), phiWithoutPID.Pt()); + + // Phi peak region + registry.fill(HIST("PHI/hMassVsPt"), phiWithoutPID.M(), phiWithoutPID.Pt()); + if ((phiWithoutPID.M() > 0.98) && (phiWithoutPID.M() < 1.05)) { + registry.fill(HIST("PHI/hPtPhiWithoutPID"), phiWithoutPID.Pt()); + registry.fill(HIST("PHI/hRapidityPhiWithoutPID"), phiWithoutPID.Rapidity()); + registry.fill(HIST("PHI/hPtKaonVsKaon"), allTracksAreKaons[0].Pt(), allTracksAreKaons[1].Pt()); + + // unlike-sign + if (onlyTwoTracks[0].sign() != onlyTwoTracks[1].sign()) { + registry.fill(HIST("hSelectionCounter2"), 8); + registry.fill(HIST("PHI/hUnlikePt"), phiWithoutPID.Pt()); + registry.fill(HIST("PHI/hMassUnlike"), phiWithoutPID.M()); + if (phiWithoutPID.Pt() < 0.1) { + registry.fill(HIST("hSelectionCounter2"), 9); + registry.fill(HIST("PHI/hCoherentPhiWithoutPID"), phiWithoutPID.M()); + } else { + registry.fill(HIST("hSelectionCounter2"), 10); + registry.fill(HIST("PHI/hInCoherentPhiWithoutPID"), phiWithoutPID.M()); + } + } else { + // Likesign quantities + registry.fill(HIST("PHI/hMassLike"), phiWithoutPID.M()); + registry.fill(HIST("PHI/hlikePt"), phiWithoutPID.Pt()); + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHI/hCoherentMassLike"), phiWithoutPID.M()); + } else { + registry.fill(HIST("PHI/hInCoherentMassLike"), phiWithoutPID.M()); + } + } + } // Mass cut + } // end of two tracks only loop + + if (allTracksAreKaonsBandPID.size() == 2) { + registry.fill(HIST("hTracksKaons"), allTracksAreKaonsBandPID.size() + 10); + TLorentzVector reallyPhi; + for (auto kaon : allTracksAreKaonsBandPID) { + reallyPhi += kaon; + } + registry.fill(HIST("KaonBandPHI/hPtPhiIdentifiedKaons"), reallyPhi.Pt()); + registry.fill(HIST("KaonBandPHI/hMassPtPhiIdentifiedKaons"), reallyPhi.M(), reallyPhi.Pt()); + if (reallyPhi.Pt() < 0.2) { + registry.fill(HIST("KanonBandPHI/hMassPhiIdentifiedKaons"), reallyPhi.M()); + } + } + + if (allTracksAreKaonsBandPID.size() == 1 && allTracksAreITSonlyAndFourITSclusters.size() > 0) { + + registry.fill(HIST("hTracksKaons"), allTracksAreKaonsBandPID.size() + 20); + registry.fill(HIST("hTracksKaons"), allTracksAreITSonlyAndFourITSclusters.size() + 40); + + double momentum = TMath::Sqrt(onlyKaonBandPID[0].px() * onlyKaonBandPID[0].px() + onlyKaonBandPID[0].py() * onlyKaonBandPID[0].py() + onlyKaonBandPID[0].pz() * onlyKaonBandPID[0].pz()); + double dEdx = onlyKaonBandPID[0].tpcSignal(); + registry.fill(HIST("hdEdxKaon9"), momentum, dEdx); + registry.fill(HIST("hTracksITSonly"), allTracksAreITSonlyAndFourITSclusters.size()); + + for (int kaon = 0; kaon < allTracksAreITSonlyAndFourITSclusters.size(); kaon++) { + + int clusterSize[7]; + double averageClusterSize = 0.; + double activeClusters = 0.; + for (int i = 0; i < 7; i++) { // info stored in 4 bits + clusterSize[i] = (((1 << 4) - 1) & (onlyITS[kaon].itsClusterSizes() >> 4 * i)); + auto clusterSizeValue = static_cast(clusterSize[i]); + if (clusterSizeValue != 0) { + averageClusterSize += clusterSizeValue; + activeClusters += 1; + } + averageClusterSize += static_cast(clusterSize[i]); + } + if (activeClusters != 0) { + averageClusterSize /= activeClusters; + } else { + averageClusterSize = -999.; + } + registry.fill(HIST("hClusterSizeOnlyITS"), averageClusterSize); + registry.fill(HIST("hClusterSizeOnlyITSVsP"), momentum, averageClusterSize); + + TLorentzVector reallyPhi; + reallyPhi += allTracksAreKaonsBandPID[0]; + reallyPhi += allTracksAreITSonlyAndFourITSclusters[kaon]; + registry.fill(HIST("KaonBandPHI/hMassPtPhiIdentifiedKaonAndITSkaon"), reallyPhi.M(), reallyPhi.Pt()); + registry.fill(HIST("KaonBandPHI/hPtPhiIdentifiedKaonAndITSkaon"), reallyPhi.Pt()); + if (reallyPhi.Pt() < 0.2) { + registry.fill(HIST("KaonBandPHI/hMassPhiIdentifiedKaonAndITSkaon"), reallyPhi.M()); + } + } + } // Kaon Band + + } // double gap + } // end of process + + void processSG(UDCollisionsFull::iterator const& collision, udtracksfull const& tracks) + // process function subscribing to SG data + { + int gapSide = collision.gapSide(); + if (gapSide < 0 || gapSide > 2) + return; + + registry.fill(HIST("posx"), collision.posX()); + registry.fill(HIST("posy"), collision.posY()); + registry.fill(HIST("posz"), collision.posZ()); + int truegapSide = sgSelector.trueGap(collision, FV0_cut, FT0A_cut, FT0C_cut, ZDC_cut); + registry.fill(HIST("GapSide"), gapSide); + registry.fill(HIST("TrueGapSide"), truegapSide); + gapSide = truegapSide; + + eventprocessing(gapSide, tracks); + } + PROCESS_SWITCH(sgExclusivePhiITSselections, processSG, "Process SG data", SGactive); + + void processDG(aod::UDCollisions::iterator const& collision, udtracksfull const& tracks) + // process function subscribing to DG data + { + int gapSide = 2; + registry.fill(HIST("posx"), collision.posX()); + registry.fill(HIST("posy"), collision.posY()); + registry.fill(HIST("posz"), collision.posZ()); + registry.fill(HIST("GapSide"), gapSide); + eventprocessing(gapSide, tracks); + } + PROCESS_SWITCH(sgExclusivePhiITSselections, processDG, "Process DG data", DGactive); + +}; // end of struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/sgFITAnalyzer.cxx b/PWGUD/Tasks/sgFITAnalyzer.cxx index 7194937cf6e..73d42421b87 100644 --- a/PWGUD/Tasks/sgFITAnalyzer.cxx +++ b/PWGUD/Tasks/sgFITAnalyzer.cxx @@ -81,6 +81,7 @@ struct SGFITAnalyzer { void init(InitContext&) { const AxisSpec axispt{ptAxis, "p_{T}"}; + const AxisSpec axismeanpt{ptAxis, ""}; const AxisSpec axisBC{BCAxis, "BC"}; const AxisSpec axiseta{etaAxis, "#eta"}; const AxisSpec axismult{multAxis, "N_{tracks}"}; @@ -108,6 +109,12 @@ struct SGFITAnalyzer { registry.add("collisions/multiplicityZ1PVCAC", "Multiplicity of PV contributors AC-side; PV contributors; Tracks", {HistType::kTH1F, {{axismult}}}); registry.add("collisions/GapSide", "Gap Side: A, C, A+C", {HistType::kTH1F, {{3, -0.5, 2.5}}}); registry.add("collisions/TrueGapSide", "Gap Side: A, C, A+C", {HistType::kTH1F, {{4, -1.5, 2.5}}}); + registry.add("collisions/2D/multiplicityVsMeanPtPVCA", "Multiplicity of PV contributors A-side; PV contributors; mean #{p}_{T}", {HistType::kTH2F, {{axismult}, {axismeanpt}}}); + registry.add("collisions/2D/multiplicityVsEtaPVCA", "Multiplicity of PV contributors A-side; PV contributors; #eta", {HistType::kTH2F, {{axismult}, {axiseta}}}); + registry.add("collisions/2D/multiplicityVsMeanPtPVCC", "Multiplicity of PV contributors C-side; PV contributors; mean #{p}_{T}", {HistType::kTH2F, {{axismult}, {axismeanpt}}}); + registry.add("collisions/2D/multiplicityVsEtaPVCC", "Multiplicity of PV contributors C-side; PV contributors; #eta", {HistType::kTH2F, {{axismult}, {axiseta}}}); + registry.add("collisions/2D/multiplicityVsMeanPtPVCAC", "Multiplicity of PV contributors AC-side; PV contributors; mean #{p}_{T}", {HistType::kTH2F, {{axismult}, {axismeanpt}}}); + registry.add("collisions/2D/multiplicityVsEtaPVCAC", "Multiplicity of PV contributors AC-side; PV contributors; #eta", {HistType::kTH2F, {{axismult}, {axiseta}}}); // track histograms registry.add("tracks/QCAll", "Track QC of all tracks; Hit in detector; Tracks", {HistType::kTH1F, {{5, -0.5, 4.5}}}); @@ -418,8 +425,14 @@ struct SGFITAnalyzer { } } int pva = 0; + double avPtPVa = 0; + std::vector vecEtaPVa; int pvc = 0; + double avPtPVc = 0; + std::vector vecEtaPVc; int pvac = 0; + double avPtPVac = 0; + std::vector vecEtaPVac; int z0pva = 0; int z0pvc = 0; int z0pvac = 0; @@ -747,6 +760,9 @@ struct SGFITAnalyzer { registry.get(HIST("tracks/ptPVC"))->Fill(track.pt(), 1.); // registry.get(HIST("tracks/etavsptPVC"))->Fill(vtrk.Eta(), track.pt(), 1.); if (truegapSide == 0) { + pva++; + avPtPVa += track.pt(); + vecEtaPVa.push_back(vtrk.Eta()); registry.get(HIST("tracks/etaApv"))->Fill(vtrk.Eta(), 1.); if (!an) registry.get(HIST("tracks/eta2Apv"))->Fill(vtrk.Eta(), 1.); @@ -754,9 +770,11 @@ struct SGFITAnalyzer { z0pva++; else if (an == 4) z1pva++; - pva++; } if (truegapSide == 1) { + pvc++; + avPtPVc += track.pt(); + vecEtaPVc.push_back(vtrk.Eta()); registry.get(HIST("tracks/etaCpv"))->Fill(vtrk.Eta(), 1.); if (!cn) registry.get(HIST("tracks/eta2Cpv"))->Fill(vtrk.Eta(), 1.); @@ -764,9 +782,11 @@ struct SGFITAnalyzer { z0pvc++; else if (cn == 4) z1pvc++; - pvc++; } if (truegapSide == 2) { + pvac++; + avPtPVac += track.pt(); + vecEtaPVac.push_back(vtrk.Eta()); registry.get(HIST("tracks/etaACpv"))->Fill(vtrk.Eta(), 1.); if (!an && !cn) registry.get(HIST("tracks/eta2ACpv"))->Fill(vtrk.Eta(), 1.); @@ -774,18 +794,29 @@ struct SGFITAnalyzer { z0pvac++; else if (an >= 3 && cn >= 3) z1pvac++; - pvac++; } registry.get(HIST("tracks/TPCSignalvspPVC"))->Fill(vtrk.Mag(), signalTPC, 1.); registry.get(HIST("tracks/TOFSignalvspPVC"))->Fill(vtrk.Mag(), signalTOF, 1.); } } - if (pva) + if (pva) { registry.get(HIST("collisions/multiplicityPVCA"))->Fill(pva, 1.); - if (pvc) + registry.get(HIST("collisions/2D/multiplicityVsMeanPtPVCA"))->Fill(pva, avPtPVa / pva, 1.); + for (auto& element : vecEtaPVa) + registry.get(HIST("collisions/2D/multiplicityVsEtaPVCA"))->Fill(pva, element, 1.); + } + if (pvc) { registry.get(HIST("collisions/multiplicityPVCC"))->Fill(pvc, 1.); - if (pvac) + registry.get(HIST("collisions/2D/multiplicityVsMeanPtPVCC"))->Fill(pvc, avPtPVc / pvc, 1.); + for (auto& element : vecEtaPVc) + registry.get(HIST("collisions/2D/multiplicityVsEtaPVCC"))->Fill(pvc, element, 1.); + } + if (pvac) { registry.get(HIST("collisions/multiplicityPVCAC"))->Fill(pvac, 1.); + registry.get(HIST("collisions/2D/multiplicityVsMeanPtPVCAC"))->Fill(pvac, avPtPVac / pvac, 1.); + for (auto& element : vecEtaPVac) + registry.get(HIST("collisions/2D/multiplicityVsEtaPVCAC"))->Fill(pvac, element, 1.); + } if (pva) registry.get(HIST("collisions/multiplicityZ0PVCA"))->Fill(z0pva, 1.); if (pvc) diff --git a/PWGUD/Tasks/upcEventITSROFcounter.cxx b/PWGUD/Tasks/upcEventITSROFcounter.cxx new file mode 100644 index 00000000000..a49ee0c8f07 --- /dev/null +++ b/PWGUD/Tasks/upcEventITSROFcounter.cxx @@ -0,0 +1,129 @@ +// Copyright 2019-2020 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. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "ITSMFTBase/DPLAlpideParam.h" +#include "CCDB/BasicCCDBManager.h" + +#include "Common/DataModel/EventSelection.h" + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using BCsWithRun3Matchings = soa::Join; +using CCs = soa::Join; + +struct UpcEventITSROFcounter { + Service ccdb; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable nTracksForUPCevent{"nTracksForUPCevent", 16, {"Maximum of tracks defining a UPC collision"}}; + + void init(InitContext&) + { + + histos.add("Events/hCountCollisionsExactMatching", ";;Number of collision (-)", HistType::kTH1D, {{11, -0.5, 10.5}}); + histos.add("Events/hCountUPCcollisionsExactMatching", ";;Number of UPC (mult < 17) collision (-)", HistType::kTH1D, {{11, -0.5, 10.5}}); + histos.add("Events/hCountCollisionsInROFborderMatching", ";;Number of collision (-)", HistType::kTH1D, {{11, -0.5, 10.5}}); + histos.add("Events/hCountUPCcollisionsInROFborderMatching", ";;Number of UPC (mult < 17) collision (-)", HistType::kTH1D, {{11, -0.5, 10.5}}); + + } // end init + + void process(BCsWithRun3Matchings const& bcs, CCs const& collisions) + { + int nAllColls = 0; + int nUPCcolls = 0; + uint16_t previousBCinITSROF = 0; + std::vector> vecITSROFborders; + bool isFirst = true; + uint16_t firstBCglobalIndex = 0; + uint16_t previousBCglobalIndex = 0; + + // extract ITS time frame parameters + int64_t ts = bcs.iteratorAt(0).timestamp(); + auto alppar = ccdb->getForTimeStamp>("ITS/Config/AlpideParam", ts); + + for (auto bc : bcs) { + uint64_t globalBC = bc.globalBC(); + uint64_t globalIndex = bc.globalIndex(); + if (isFirst) { + firstBCglobalIndex = globalIndex; + isFirst = false; + } + uint16_t bcInITSROF = (globalBC + o2::constants::lhc::LHCMaxBunches - alppar->roFrameBiasInBC) % alppar->roFrameLengthInBC; + + if (bcInITSROF - previousBCinITSROF < 0) { + histos.get(HIST("Events/hCountCollisionsExactMatching"))->Fill(nAllColls); + histos.get(HIST("Events/hCountUPCcollisionsExactMatching"))->Fill(nUPCcolls); + nAllColls = 0; + nUPCcolls = 0; + vecITSROFborders.push_back(std::make_pair(firstBCglobalIndex, previousBCglobalIndex)); + firstBCglobalIndex = globalIndex; + } + previousBCinITSROF = bcInITSROF; + previousBCglobalIndex = globalIndex; + // next is based on exact matching of bc and collision + for (auto& collision : collisions) { + if (collision.has_foundBC()) { + if (collision.foundBCId() == bc.globalIndex()) { + nAllColls++; + if (collision.numContrib() < nTracksForUPCevent + 1) { + nUPCcolls++; + } + } + } else if (collision.bcId() == bc.globalIndex()) { + nAllColls++; + if (collision.numContrib() < nTracksForUPCevent + 1) { + nUPCcolls++; + } + } + } // end loop over collisions + } // end loop over bcs + + int arrAllColls[1000] = {0}; + int arrUPCcolls[1000] = {0}; + + // next is based on matching of collision bc within ITSROF range in bcs + for (auto& itsrofBorder : vecITSROFborders) { + int nAllCollsInROF = 0; + int nUpcCollsInROF = 0; + for (auto& collision : collisions) { + if ((itsrofBorder.first < collision.bcId()) && (collision.bcId() < itsrofBorder.second)) { + nAllCollsInROF++; + if (collision.numContrib() < nTracksForUPCevent + 1) { + nUpcCollsInROF++; + } + } + } // end loop over collisions + arrAllColls[nAllCollsInROF]++; + arrUPCcolls[nUpcCollsInROF]++; + } // end loop over ITSROFs + + for (int ncol = 0; ncol < 12; ncol++) { + histos.get(HIST("Events/hCountCollisionsInROFborderMatching"))->Fill(ncol, arrAllColls[ncol]); + histos.get(HIST("Events/hCountUPCcollisionsInROFborderMatching"))->Fill(ncol, arrUPCcolls[ncol]); + } + } + + PROCESS_SWITCH(UpcEventITSROFcounter, process, "Counts number of collisions within ITSROF", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"upc-event-itsrof-counter"})}; +} diff --git a/PWGUD/Tasks/upcJpsiCentralBarrelCorr.cxx b/PWGUD/Tasks/upcJpsiCentralBarrelCorr.cxx index 951e0945e29..064dcbb91dc 100644 --- a/PWGUD/Tasks/upcJpsiCentralBarrelCorr.cxx +++ b/PWGUD/Tasks/upcJpsiCentralBarrelCorr.cxx @@ -60,15 +60,20 @@ struct UpcJpsiCentralBarrel { Configurable TOFOneProton{"TOFOneProton", false, "one candidate proton has TOF hits"}; Configurable TPCNsigmaCut{"TPCNsigmaCut", false, "cut on nSigma"}; Configurable TPCPIDOnly{"TPCPIDOnly", false, "Only TPC PID"}; + Configurable smallestPID{"smallestPID", false, "Use smallest PID hypo."}; + Configurable DCAcut{"DCAcut", false, "DCA cut from run2."}; + Configurable newCutTPC{"newCutTPC", false, "New cuts for TPC tracks."}; Configurable TPCNSigmaMu{"TPCNSigmaMu", 3, "PID for TPC Mu track"}; Configurable EtaCut{"EtaCut", 0.9f, "acceptance cut per track"}; Configurable RapCut{"RapCut", 0.8f, "choose event in midrapidity"}; Configurable dcaZCut{"dcaZCut", 2, "cut on the impact parameter in z of the track to the PV"}; Configurable dcaXYCut{"dcaXYCut", 1e10, "cut on the impact parameter in xy of the track to the PV"}; - Configurable ITSNClsCut{"ITSNClsCut", 1, "minimal number of ITS clusters"}; + Configurable ITSNClsCut{"ITSNClsCut", 4, "minimal number of ITS clusters"}; Configurable ITSChi2NClsCut{"ITSChi2NClsCut", 36, "minimal Chi2/cluster for the ITS track"}; Configurable TPCNClsCrossedRowsCut{"TPCNClsCrossedRowsCut", 70, "minimal number of crossed TPC rows"}; Configurable TPCChi2NCls{"TPCChi2NCls", 4, "minimal Chi2/cluster for the TPC track"}; + Configurable TPCMinNCls{"TPCMinNCls", 3, "minimum number of TPC clusters"}; + Configurable TPCCrossedOverFindable{"TPCCrossedOverFindable", 3, "number of TPC crosseed rows over findable clusters"}; Configurable maxJpsiMass{"maxJpsiMass", 3.18, "Maximum of the jpsi peak for peak cut"}; Configurable minJpsiMass{"minJpsiMass", 3.0, "Minimum of the jpsi peak for peak cut"}; @@ -186,6 +191,8 @@ struct UpcJpsiCentralBarrel { PVContributors.add("PVContributors/hTrackPt", "hTrackPt", {HistType::kTH1F, {axispt}}); PVContributors.add("PVContributors/hTrackEta", "hTrackEta", {HistType::kTH1F, {axiseta}}); PVContributors.add("PVContributors/hTrackPhi", "hTrackPhi", {HistType::kTH1F, {axisPhi}}); + PVContributors.add("PVContributors/hTPCNClsFindable", "hTPCNClsFindable", {HistType::kTH1F, {axisTPC}}); + PVContributors.add("PVContributors/hTPCNClsFindableMinusFound", "hTPCNClsFindableMinusFound", {HistType::kTH1F, {axisTPC}}); PVContributors.add("PVContributors/PID/hTPCVsP", "hTPCVsP", {HistType::kTH2F, {axisp, axisTPC}}); PVContributors.add("PVContributors/PID/hTPCVsPt", "hTPCVsPt", {HistType::kTH2F, {axispt, axisTPC}}); PVContributors.add("PVContributors/PID/hTPCVsPhi", "hTPCVsPhi", {HistType::kTH2F, {axisPhi, axisTPC}}); @@ -203,6 +210,8 @@ struct UpcJpsiCentralBarrel { TG.add("TG/hTrackPt2", "hTrackPt2", {HistType::kTH1F, {axispt}}); TG.add("TG/hTrackEta2", "hTrackEta2", {HistType::kTH1F, {axiseta}}); TG.add("TG/hTrackPhi2", "hTrackPhi2", {HistType::kTH1F, {axisPhi}}); + TG.add("TG/hTPCNClsFindable", "hTPCNClsFindable", {HistType::kTH1F, {axisTPC}}); + TG.add("TG/hTPCNClsFindableMinusFound", "hTPCNClsFindableMinusFound", {HistType::kTH1F, {axisTPC}}); TG.add("TG/PID/hTPCVsP", "hTPCVsP", {HistType::kTH2F, {axisp, axisTPC}}); TG.add("TG/PID/hTPCVsPt", "hTPCVsPt", {HistType::kTH2F, {axispt, axisTPC}}); TG.add("TG/PID/hTPCVsPhi", "hTPCVsPhi", {HistType::kTH2F, {axisPhi, axisTPC}}); @@ -215,6 +224,8 @@ struct UpcJpsiCentralBarrel { TG.add("TG/TPC/hNsigmaMu", "hNsigmaMu", HistType::kTH1F, {axisSigma}); TG.add("TG/TPC/hNsigmaEl", "hNsigmaEl", HistType::kTH1F, {axisSigma}); TG.add("TG/TPC/hNsigmaPr", "hNsigmaPr", HistType::kTH1F, {axisSigma}); + TG.add("TG/TPC/TPCPosSignal", "TPCPosSignal", HistType::kTH1F, {axisTPC}); + TG.add("TG/TPC/TPCNegSignal", "TPCNegSignal", HistType::kTH1F, {axisTPC}); TG.add("TG/TOF/hNsigmaMu", "hNsigmaMu", HistType::kTH1F, {axisSigma}); TG.add("TG/TOF/hNsigmaEl", "hNsigmaEl", HistType::kTH1F, {axisSigma}); TG.add("TG/TOF/hNsigmaPr", "hNsigmaPr", HistType::kTH1F, {axisSigma}); @@ -228,6 +239,8 @@ struct UpcJpsiCentralBarrel { TGmu.add("TGmu/hTrackPhi2", "hTrackPhi2", {HistType::kTH1F, {axisPhi}}); TGmu.add("TGmu/hNsigmaMu", "hNsigmaMu", HistType::kTH1F, {axisSigma}); TGmu.add("TGmu/hNsigmaMuTOF", "hNsigmaMuTOF", HistType::kTH1F, {axisSigma}); + TGmu.add("TGmu/TPCPosSignal", "TPCPosSignal", HistType::kTH1F, {axisTPC}); + TGmu.add("TGmu/TPCNegSignal", "TPCNegSignal", HistType::kTH1F, {axisTPC}); TGmu.add("TGmu/PID/hTPCVsP", "hTPCVsP", {HistType::kTH2F, {axisp, axisTPC}}); TGmu.add("TGmu/PID/hTPCVsPt", "hTPCVsPt", {HistType::kTH2F, {axispt, axisTPC}}); TGmu.add("TGmu/PID/hTPCVsPhi", "hTPCVsPhi", {HistType::kTH2F, {axisPhi, axisTPC}}); @@ -251,6 +264,8 @@ struct UpcJpsiCentralBarrel { TGmuCand.add("TGmuCand/hPairIVM", "hPairIVM", {HistType::kTH1F, {axisIVMWide}}); TGmuCand.add("TGmuCand/hJpsiPt", "hJpsiPt", {HistType::kTH1F, {axispt}}); TGmuCand.add("TGmuCand/hJpsiRap", "hJpsiRap", {HistType::kTH1F, {axiseta}}); + TGmuCand.add("TGmuCand/TPCPosSignal", "TPCPosSignal", HistType::kTH1F, {axisTPC}); + TGmuCand.add("TGmuCand/TPCNegSignal", "TPCNegSignal", HistType::kTH1F, {axisTPC}); TGmuCand.add("TGmuCand/PID/hTPCVsP", "hTPCVsP", {HistType::kTH2F, {axisp, axisTPC}}); TGmuCand.add("TGmuCand/PID/hTPCVsPt", "hTPCVsPt", {HistType::kTH2F, {axispt, axisTPC}}); TGmuCand.add("TGmuCand/PID/hTPCVsPhi", "hTPCVsPhi", {HistType::kTH2F, {axisPhi, axisTPC}}); @@ -270,6 +285,8 @@ struct UpcJpsiCentralBarrel { TGel.add("TGel/hTrackPhi2", "hTrackPhi2", {HistType::kTH1F, {axisPhi}}); TGel.add("TGel/hNsigmaEl", "hNsigmaEl", HistType::kTH1F, {axisSigma}); TGel.add("TGel/hNsigmaElTOF", "hNsigmaElTOF", HistType::kTH1F, {axisSigma}); + TGel.add("TGel/TPCPosSignal", "TPCPosSignal", HistType::kTH1F, {axisTPC}); + TGel.add("TGel/TPCNegSignal", "TPCNegSignal", HistType::kTH1F, {axisTPC}); TGel.add("TGel/PID/hTPCVsP", "hTPCVsP", {HistType::kTH2F, {axisp, axisTPC}}); TGel.add("TGel/PID/hTPCVsPt", "hTPCVsPt", {HistType::kTH2F, {axispt, axisTPC}}); TGel.add("TGel/PID/hTPCVsPhi", "hTPCVsPhi", {HistType::kTH2F, {axisPhi, axisTPC}}); @@ -287,6 +304,8 @@ struct UpcJpsiCentralBarrel { TGelCand.add("TGelCand/hTrackPt2", "hTrackPt2", {HistType::kTH1F, {axispt}}); TGelCand.add("TGelCand/hTrackEta2", "hTrackEta2", {HistType::kTH1F, {axiseta}}); TGelCand.add("TGelCand/hTrackPhi2", "hTrackPhi2", {HistType::kTH1F, {axisPhi}}); + TGelCand.add("TGelCand/TPCPosSignal", "TPCPosSignal", HistType::kTH1F, {axisTPC}); + TGelCand.add("TGelCand/TPCNegSignal", "TPCNegSignal", HistType::kTH1F, {axisTPC}); TGelCand.add("TGelCand/hTrackITSNcls1", "hTrackITSNcls1", {HistType::kTH1F, {axisCounter}}); TGelCand.add("TGelCand/hTrackITSNcls2", "hTrackITSNcls2", {HistType::kTH1F, {axisCounter}}); TGelCand.add("TGelCand/hPairPt", "hPairPt", {HistType::kTH1F, {axispt}}); @@ -521,8 +540,15 @@ struct UpcJpsiCentralBarrel { if (track.dcaZ() > dcaZCut) { return false; } - if (track.dcaXY() > dcaXYCut) { - return false; + if (DCAcut) { + float dcaXYCut = 0.0105f + 0.0350f / pow(track.pt(), 1.1f); + if (abs(track.dcaXY()) > dcaXYCut) { + return false; + } + } else { + if (track.dcaXY() > dcaXYCut) { + return false; + } } // ITS if (!track.hasITS()) { @@ -544,6 +570,14 @@ struct UpcJpsiCentralBarrel { if (track.tpcChi2NCl() > TPCChi2NCls) { return false; // TPC chi2 } + if (newCutTPC) { + if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) < TPCMinNCls) { + return false; + } + if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < TPCCrossedOverFindable) { + return false; + } + } return true; } @@ -584,6 +618,8 @@ struct UpcJpsiCentralBarrel { PVContributors.get(HIST("PVContributors/PID/hTPCVsPt"))->Fill(track.pt(), track.tpcSignal()); PVContributors.get(HIST("PVContributors/PID/hTPCVsEta"))->Fill(RecoDecay::eta(std::array{trkPx, trkPy, trkPz}), track.tpcSignal()); PVContributors.get(HIST("PVContributors/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(trkPx, trkPy), track.tpcSignal()); + PVContributors.get(HIST("PVContributors/hTPCNClsFindable"))->Fill(track.tpcNClsFindable()); + PVContributors.get(HIST("PVContributors/hTPCNClsFindableMinusFound"))->Fill(track.tpcNClsFindableMinusFound()); } if (track.hasTOF()) { @@ -636,24 +672,36 @@ struct UpcJpsiCentralBarrel { continue; } countGT++; - int hypoID; - if (TPCPIDOnly) { - hypoID = testPIDhypoTPC(track); - } else { - hypoID = testPIDhypo(track); - } - if (hypoID == P_ELECTRON || hypoID == P_MUON || hypoID == P_PROTON) { - countGTselected++; - trkIdx.push_back(track.index()); - if (hypoID == P_ELECTRON) { - countGTel++; - } - if (hypoID == P_MUON) { - countGTmu++; + trkIdx.push_back(track.index()); + if (smallestPID) { + int hypoID; + if (TPCPIDOnly) { + hypoID = testPIDhypoTPC(track); + } else { + hypoID = testPIDhypo(track); } - if (hypoID == P_PROTON) { - countGTp++; + if (hypoID == P_ELECTRON || hypoID == P_MUON || hypoID == P_PROTON) { + countGTselected++; + trkIdx.push_back(track.index()); + if (hypoID == P_ELECTRON) { + countGTel++; + } + if (hypoID == P_MUON) { + countGTmu++; + } + if (hypoID == P_PROTON) { + countGTp++; + } } + + Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(3., countGTselected); + Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(4., countGTel); + Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(5., countGTmu); + + Statistics.get(HIST("Statistics/hNumberGTselected"))->Fill(countGTselected); + Statistics.get(HIST("Statistics/hNumberGTel"))->Fill(countGTel); + Statistics.get(HIST("Statistics/hNumberGTmu"))->Fill(countGTmu); + Statistics.get(HIST("Statistics/hNumberGTp"))->Fill(countGTp); } if (std::abs(track.tpcNSigmaMu()) < 3) { countGTMuSigma++; @@ -670,14 +718,7 @@ struct UpcJpsiCentralBarrel { } Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(2., countGT); - Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(3., countGTselected); - Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(4., countGTel); - Statistics.get(HIST("Statistics/hNumberOfTracks"))->Fill(5., countGTmu); Statistics.get(HIST("Statistics/hNumberGT"))->Fill(countGT); - Statistics.get(HIST("Statistics/hNumberGTselected"))->Fill(countGTselected); - Statistics.get(HIST("Statistics/hNumberGTel"))->Fill(countGTel); - Statistics.get(HIST("Statistics/hNumberGTmu"))->Fill(countGTmu); - Statistics.get(HIST("Statistics/hNumberGTp"))->Fill(countGTp); Statistics.get(HIST("Statistics/hNumberGTelSigma"))->Fill(countGTElSigma); Statistics.get(HIST("Statistics/hNumberGTmuSigma"))->Fill(countGTMuSigma); Statistics.get(HIST("Statistics/hNumberGTpSigma"))->Fill(countGTPSigma); @@ -689,22 +730,24 @@ struct UpcJpsiCentralBarrel { if (countGT == 2) { TLorentzVector mom, daughter[2]; + auto trkDaughter1 = tracks.iteratorAt(trkIdx[0]); auto trkDaughter2 = tracks.iteratorAt(trkIdx[1]); + if ((trkDaughter1.sign() * trkDaughter2.sign()) > 0) { return; } - auto ene1 = RecoDecay::e(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), massEl); + /*auto ene1 = RecoDecay::e(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), massEl); auto ene2 = RecoDecay::e(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), massEl); daughter[0].SetPxPyPzE(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), ene1); daughter[1].SetPxPyPzE(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), ene2); - mom = daughter[0] + daughter[1]; + mom = daughter[0] + daughter[1];*/ std::array daughter1 = {trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz()}; std::array daughter2 = {trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz()}; - std::array mother = {trkDaughter1.px() + trkDaughter2.px(), trkDaughter1.py() + trkDaughter2.py(), trkDaughter1.pz() + trkDaughter2.pz()}; + // std::array mother = {trkDaughter1.px() + trkDaughter2.px(), trkDaughter1.py() + trkDaughter2.py(), trkDaughter1.pz() + trkDaughter2.pz()}; TG.get(HIST("TG/hTrackPt1"))->Fill(trkDaughter1.pt()); TG.get(HIST("TG/hTrackPt2"))->Fill(trkDaughter2.pt()); @@ -721,6 +764,13 @@ struct UpcJpsiCentralBarrel { TG.get(HIST("TG/TPC/hNsigmaMu"))->Fill(trkDaughter1.tpcNSigmaMu()); TG.get(HIST("TG/TPC/hNsigmaEl"))->Fill(trkDaughter1.tpcNSigmaEl()); TG.get(HIST("TG/TPC/hNsigmaPr"))->Fill(trkDaughter1.tpcNSigmaPr()); + TG.get(HIST("TG/hTPCNClsFindable"))->Fill(trkDaughter1.tpcNClsFindable()); + TG.get(HIST("TG/hTPCNClsFindableMinusFound"))->Fill(trkDaughter1.tpcNClsFindableMinusFound()); + if (trkDaughter1.sign() > 0) { + TG.get(HIST("TG/TPC/TPCPosSignal"))->Fill(trkDaughter1.tpcSignal()); + } else { + TG.get(HIST("TG/TPC/TPCNegSignal"))->Fill(trkDaughter1.tpcSignal()); + } } if (trkDaughter2.hasTPC()) { TG.get(HIST("TG/PID/hTPCVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz()), trkDaughter2.tpcSignal()); @@ -730,6 +780,13 @@ struct UpcJpsiCentralBarrel { TG.get(HIST("TG/TPC/hNsigmaMu"))->Fill(trkDaughter2.tpcNSigmaMu()); TG.get(HIST("TG/TPC/hNsigmaEl"))->Fill(trkDaughter2.tpcNSigmaEl()); TG.get(HIST("TG/TPC/hNsigmaPr"))->Fill(trkDaughter2.tpcNSigmaPr()); + TG.get(HIST("TG/hTPCNClsFindable"))->Fill(trkDaughter2.tpcNClsFindable()); + TG.get(HIST("TG/hTPCNClsFindableMinusFound"))->Fill(trkDaughter2.tpcNClsFindableMinusFound()); + if (trkDaughter2.sign() > 0) { + TG.get(HIST("TG/TPC/TPCPosSignal"))->Fill(trkDaughter2.tpcSignal()); + } else { + TG.get(HIST("TG/TPC/TPCNegSignal"))->Fill(trkDaughter2.tpcSignal()); + } } if (trkDaughter1.hasTOF()) { TG.get(HIST("TG/PID/hTOFVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz()), trkDaughter1.tofSignal()); @@ -751,10 +808,16 @@ struct UpcJpsiCentralBarrel { TG.get(HIST("TG/TOF/hNsigmaPr"))->Fill(trkDaughter2.tofNSigmaPr()); } - if (countGTel == 2) { - if (!(RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaMu(), trkDaughter2.tpcNSigmaMu()) > RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaEl(), trkDaughter2.tpcNSigmaEl()))) { - return; - } + if (RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaMu(), trkDaughter2.tpcNSigmaMu()) > RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaEl(), trkDaughter2.tpcNSigmaEl())) { + + auto ene1 = RecoDecay::e(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), massEl); + auto ene2 = RecoDecay::e(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), massEl); + daughter[0].SetPxPyPzE(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), ene1); + daughter[1].SetPxPyPzE(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), ene2); + mom = daughter[0] + daughter[1]; + + std::array mother = {trkDaughter1.px() + trkDaughter2.px(), trkDaughter1.py() + trkDaughter2.py(), trkDaughter1.pz() + trkDaughter2.pz()}; + if (TOFBothTracks) { if (!trkDaughter1.hasTOF() || !trkDaughter2.hasTOF()) return; @@ -785,6 +848,11 @@ struct UpcJpsiCentralBarrel { TGel.get(HIST("TGel/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter1), trkDaughter1.tpcSignal()); TGel.get(HIST("TGel/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter1), trkDaughter1.tpcSignal()); TGel.get(HIST("TGel/hNsigmaEl"))->Fill(trkDaughter1.tpcNSigmaEl()); + if (trkDaughter1.sign() > 0) { + TGel.get(HIST("TGel/TPCPosSignal"))->Fill(trkDaughter1.tpcSignal()); + } else { + TGel.get(HIST("TGel/TPCNegSignal"))->Fill(trkDaughter1.tpcSignal()); + } } if (trkDaughter2.hasTPC()) { TGel.get(HIST("TGel/PID/hTPCVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz()), trkDaughter2.tpcSignal()); @@ -792,6 +860,11 @@ struct UpcJpsiCentralBarrel { TGel.get(HIST("TGel/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter2), trkDaughter2.tpcSignal()); TGel.get(HIST("TGel/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter2), trkDaughter2.tpcSignal()); TGel.get(HIST("TGel/hNsigmaEl"))->Fill(trkDaughter2.tpcNSigmaEl()); + if (trkDaughter2.sign() > 0) { + TGel.get(HIST("TGel/TPCPosSignal"))->Fill(trkDaughter2.tpcSignal()); + } else { + TGel.get(HIST("TGel/TPCNegSignal"))->Fill(trkDaughter2.tpcSignal()); + } } if (trkDaughter1.hasTOF()) { TGel.get(HIST("TGel/PID/hTOFVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz()), trkDaughter1.tofSignal()); @@ -829,6 +902,11 @@ struct UpcJpsiCentralBarrel { TGelCand.get(HIST("TGelCand/PID/hTPCVsPt"))->Fill(trkDaughter1.pt(), trkDaughter1.tpcSignal()); TGelCand.get(HIST("TGelCand/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter1), trkDaughter1.tpcSignal()); TGelCand.get(HIST("TGelCand/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter1), trkDaughter1.tpcSignal()); + if (trkDaughter1.sign() > 0) { + TGelCand.get(HIST("TGelCand/TPCPosSignal"))->Fill(trkDaughter1.tpcSignal()); + } else { + TGelCand.get(HIST("TGelCand/TPCNegSignal"))->Fill(trkDaughter1.tpcSignal()); + } } if (trkDaughter2.hasTPC()) { TGelCand.get(HIST("TGelCand/PID/hTPCVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz()), trkDaughter2.tpcSignal()); @@ -912,7 +990,7 @@ struct UpcJpsiCentralBarrel { Asymmetry.get(HIST("Asymmetry/Electron/Coherent/DeltaPhi"))->Fill(dp); delete[] q; - } + } // end coherent electrons if (RecoDecay::pt(mother) > 0.2f) { // fill track histos JPsiToEl.get(HIST("JPsiToEl/Incoherent/hPt1"))->Fill(trkDaughter1.pt()); @@ -966,15 +1044,18 @@ struct UpcJpsiCentralBarrel { Asymmetry.get(HIST("Asymmetry/Electron/Incoherent/DeltaPhi"))->Fill(dp); delete[] q; - } - } - } // end electrons - if (countGTmu == 2) { - - if (!(RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaEl(), trkDaughter2.tpcNSigmaEl()) > RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaMu(), trkDaughter2.tpcNSigmaMu()))) { - return; - } - + } // end incoherent electrons + } // end mass cut + } // end electrons + if (RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaEl(), trkDaughter2.tpcNSigmaEl()) > RecoDecay::sumOfSquares(trkDaughter1.tpcNSigmaMu(), trkDaughter2.tpcNSigmaMu())) { + + auto ene1 = RecoDecay::e(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), massMu); + auto ene2 = RecoDecay::e(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), massMu); + daughter[0].SetPxPyPzE(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), ene1); + daughter[1].SetPxPyPzE(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), ene2); + mom = daughter[0] + daughter[1]; + + std::array mother = {trkDaughter1.px() + trkDaughter2.px(), trkDaughter1.py() + trkDaughter2.py(), trkDaughter1.pz() + trkDaughter2.pz()}; if (TOFBothTracks) { if (!trkDaughter1.hasTOF() || !trkDaughter2.hasTOF()) return; @@ -1005,6 +1086,11 @@ struct UpcJpsiCentralBarrel { TGmu.get(HIST("TGmu/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter1), trkDaughter1.tpcSignal()); TGmu.get(HIST("TGmu/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter1), trkDaughter1.tpcSignal()); TGmu.get(HIST("TGmu/hNsigmaMu"))->Fill(trkDaughter1.tpcNSigmaMu()); + if (trkDaughter1.sign() > 0) { + TGmu.get(HIST("TGmu/TPCPosSignal"))->Fill(trkDaughter1.tpcSignal()); + } else { + TGmu.get(HIST("TGmu/TPCNegSignal"))->Fill(trkDaughter1.tpcSignal()); + } } if (trkDaughter2.hasTPC()) { TGmu.get(HIST("TGmu/PID/hTPCVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz()), trkDaughter2.tpcSignal()); @@ -1012,6 +1098,11 @@ struct UpcJpsiCentralBarrel { TGmu.get(HIST("TGmu/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter2), trkDaughter2.tpcSignal()); TGmu.get(HIST("TGmu/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter2), trkDaughter2.tpcSignal()); TGmu.get(HIST("TGmu/hNsigmaMu"))->Fill(trkDaughter2.tpcNSigmaMu()); + if (trkDaughter2.sign() > 0) { + TGmu.get(HIST("TGmu/TPCPosSignal"))->Fill(trkDaughter2.tpcSignal()); + } else { + TGmu.get(HIST("TGmu/TPCNegSignal"))->Fill(trkDaughter2.tpcSignal()); + } } if (trkDaughter1.hasTOF()) { TGmu.get(HIST("TGmu/PID/hTOFVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz()), trkDaughter1.tofSignal()); @@ -1049,12 +1140,22 @@ struct UpcJpsiCentralBarrel { TGmuCand.get(HIST("TGmuCand/PID/hTPCVsPt"))->Fill(trkDaughter1.pt(), trkDaughter1.tpcSignal()); TGmuCand.get(HIST("TGmuCand/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter1), trkDaughter1.tpcSignal()); TGmuCand.get(HIST("TGmuCand/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter1), trkDaughter1.tpcSignal()); + if (trkDaughter1.sign() > 0) { + TGmuCand.get(HIST("TGmuCand/TPCPosSignal"))->Fill(trkDaughter1.tpcSignal()); + } else { + TGmuCand.get(HIST("TGmuCand/TPCNegSignal"))->Fill(trkDaughter1.tpcSignal()); + } } if (trkDaughter2.hasTPC()) { TGmuCand.get(HIST("TGmuCand/PID/hTPCVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz()), trkDaughter2.tpcSignal()); TGmuCand.get(HIST("TGmuCand/PID/hTPCVsPt"))->Fill(trkDaughter2.pt(), trkDaughter2.tpcSignal()); TGmuCand.get(HIST("TGmuCand/PID/hTPCVsEta"))->Fill(RecoDecay::eta(daughter2), trkDaughter2.tpcSignal()); TGmuCand.get(HIST("TGmuCand/PID/hTPCVsPhi"))->Fill(RecoDecay::phi(daughter2), trkDaughter2.tpcSignal()); + if (trkDaughter2.sign() > 0) { + TGmuCand.get(HIST("TGmuCand/TPCPosSignal"))->Fill(trkDaughter2.tpcSignal()); + } else { + TGmuCand.get(HIST("TGmuCand/TPCNegSignal"))->Fill(trkDaughter2.tpcSignal()); + } } if (trkDaughter1.hasTOF()) { TGmuCand.get(HIST("TGmuCand/PID/hTOFVsP"))->Fill(RecoDecay::sqrtSumOfSquares(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz()), trkDaughter1.tofSignal()); @@ -1189,7 +1290,15 @@ struct UpcJpsiCentralBarrel { } } } // end muons - if (countGTp == 2) { + if (RecoDecay::sumOfSquares((trkDaughter1.hasTOF() ? trkDaughter1.tofNSigmaPr() : trkDaughter1.tpcNSigmaPr()), (trkDaughter2.hasTOF() ? trkDaughter2.tofNSigmaPr() : trkDaughter2.tpcNSigmaPr()) < 4)) { + + auto ene1 = RecoDecay::e(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), massPr); + auto ene2 = RecoDecay::e(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), massPr); + daughter[0].SetPxPyPzE(trkDaughter1.px(), trkDaughter1.py(), trkDaughter1.pz(), ene1); + daughter[1].SetPxPyPzE(trkDaughter2.px(), trkDaughter2.py(), trkDaughter2.pz(), ene2); + mom = daughter[0] + daughter[1]; + + std::array mother = {trkDaughter1.px() + trkDaughter2.px(), trkDaughter1.py() + trkDaughter2.py(), trkDaughter1.pz() + trkDaughter2.pz()}; if (TOFBothProtons) { if (!trkDaughter1.hasTOF() || !trkDaughter2.hasTOF()) @@ -1334,7 +1443,7 @@ struct UpcJpsiCentralBarrel { JPsiToP.get(HIST("JPsiToP/Coherent/hEta"))->Fill(RecoDecay::eta(mother)); JPsiToP.get(HIST("JPsiToP/Coherent/hPhi"))->Fill(RecoDecay::phi(mother)); JPsiToP.get(HIST("JPsiToP/Coherent/hRap"))->Fill(rapJpsi); - } + } // end coherent if (RecoDecay::pt(mother) > 0.2f) { // fill track histos JPsiToP.get(HIST("JPsiToP/Incoherent/hPt1"))->Fill(trkDaughter1.pt()); @@ -1374,12 +1483,12 @@ struct UpcJpsiCentralBarrel { JPsiToP.get(HIST("JPsiToP/Incoherent/hEta"))->Fill(RecoDecay::eta(mother)); JPsiToP.get(HIST("JPsiToP/Incoherent/hPhi"))->Fill(RecoDecay::phi(mother)); JPsiToP.get(HIST("JPsiToP/Incoherent/hRap"))->Fill(rapJpsi); - } - } - } // end protons - } // end two tracks - } // end process -}; // end struct + } // end incoherent + } // end mass cut + } // end protons + } // end two tracks + } // end process +}; // end struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGUD/Tasks/upcPionAnalysis.cxx b/PWGUD/Tasks/upcPionAnalysis.cxx index 1c4bf34e47b..8cab0acb000 100644 --- a/PWGUD/Tasks/upcPionAnalysis.cxx +++ b/PWGUD/Tasks/upcPionAnalysis.cxx @@ -16,8 +16,11 @@ #include "iostream" #include "PWGUD/DataModel/UDTables.h" #include +#include #include "TLorentzVector.h" #include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/SGTrackSelector.h" +#include "Common/Core/RecoDecay.h" using namespace std; using namespace o2; using namespace o2::aod; @@ -30,15 +33,41 @@ using namespace o2::framework::expressions; struct UPCPionAnalysis { SGSelector sgSelector; + Configurable FV0_cut{"FV0", 100., "FV0A threshold"}; Configurable FT0A_cut{"FT0A", 200., "FT0A threshold"}; Configurable FT0C_cut{"FT0C", 100., "FT0C threshold"}; + Configurable FDDA_cut{"FDDA", 10000., "FDDA threshold"}; + Configurable FDDC_cut{"FDDC", 10000., "FDDC threshold"}; Configurable ZDC_cut{"ZDC", 10., "ZDC threshold"}; Configurable gap_Side{"gap", 2, "gap selection"}; + + // Collision selection + Configurable collcontrib_cut{"collcontrib_cut", 10, "no. of PV contributor per collsion"}; + Configurable Zvtx_cut{"Zvtx_cut", 15, "z-vertex selection"}; + + // Track Selections + Configurable PV_cut{"PV_cut", 1.0, "Use Only PV tracks"}; + Configurable dcaZ_cut{"dcaZ_cut", 2.0, "dcaZ cut"}; + Configurable dcaXY_cut{"dcaXY_cut", 0.0, "dcaXY cut (0 for Pt-function)"}; + Configurable tpcChi2_cut{"tpcChi2_cut", 4, "Max tpcChi2NCl"}; + Configurable tpcNClsFindable_cut{"tpcNClsFindable_cut", 70, "Min tpcNClsFindable"}; + Configurable itsChi2_cut{"itsChi2_cut", 36, "Max itsChi2NCl"}; + Configurable eta_cut{"eta_cut", 0.9, "Track Pseudorapidity"}; + Configurable pt_cut{"pt_cut", 0.1, "Track Pt"}; + Configurable TPC_cluster{"TPC_cluster", 50, "No.of TPC cluster"}; + + // Kinmatic cuts + Configurable PID_cut{"PID_cut", 5, "TPC PID"}; + Configurable Rap_cut{"Rap_cut", 0.9, "Track rapidity"}; + Configurable Mass_Max{"Mass_Max", 10, "Invariant Mass range high"}; + Configurable Mass_Min{"Mass_Min", 0, "Invariant Mass range low"}; + Configurable Pt_coherent{"Pt_coherent", 0.15, "Coherent selection"}; + // defining histograms using histogram registry HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; - //_____________________________________________________________________________ + //_____________________________________________________________________________________________ Double_t CosThetaHelicityFrame(TLorentzVector pionPositive, TLorentzVector pionNegative, TLorentzVector possibleRhoZero) @@ -100,6 +129,150 @@ struct UPCPionAnalysis { Double_t phi = TMath::ATan2((pPi1Dipi.Vect()).Dot(yaxis), (pPi1Dipi.Vect()).Dot(xaxis)); return phi; } + //----------------------------------------------------------------------------------------------- + float* AngCorrelation(TLorentzVector* lv1, TLorentzVector* lv2, TLorentzVector* lv) + { + TLorentzVector pa(1., 0., 0, 1); // projectile + TLorentzVector pb(1., 0., 0, -1); // target + + float* q = new float[3]; // to save values + + // Accoplanarity angle + Float_t deltaPhi; + deltaPhi = lv1->Phi() - lv2->Phi(); + float accoplCut = 1. - std::abs(deltaPhi) / o2::constants::math::PI; + // z + TLorentzVector z; + Float_t part1, part2; + + // Dot product: v1*v2 = t1*t2-x1*x2-y1*y2-z1*z2 + + part1 = lv->Dot(pb); + part2 = lv->Dot(pa); + + Float_t part3x = pa.X() * part1; + Float_t part3y = pa.Y() * part1; + Float_t part3z = pa.Z() * part1; + Float_t part3e = pa.T() * part1; + + Float_t part4x = pb.X() * part2; + Float_t part4y = pb.Y() * part2; + Float_t part4z = pb.Z() * part2; + Float_t part4e = pb.T() * part2; + + TLorentzVector part3(TVector3(part3x, part3y, part3z), part3e); + TLorentzVector part4(TVector3(part4x, part4y, part4z), part4e); + + // Un-normalized Z + z = part3 - part4; + + // Normalized z + Float_t normz = std::sqrt(-z * z); + Float_t znx = z.X() / normz; + Float_t zny = z.Y() / normz; + Float_t znz = z.Z() / normz; + Float_t zne = z.E() / normz; + + // Normalized z + TLorentzVector zhat(TVector3(znx, zny, znz), zne); + + // calculate x + TLorentzVector x; + + Float_t constant1 = (lv->Dot(*lv)) / (2 * (lv->Dot(pa))); + Float_t constant2 = (lv->Dot(*lv)) / (2 * (lv->Dot(pb))); + + Float_t comp1x = pa.X() * constant1; + Float_t comp1y = pa.Y() * constant1; + Float_t comp1z = pa.Z() * constant1; + Float_t comp1e = pa.T() * constant1; + + TLorentzVector comp1(TVector3(comp1x, comp1y, comp1z), comp1e); + + Float_t comp2x = pb.X() * constant2; + Float_t comp2y = pb.Y() * constant2; + Float_t comp2z = pb.Z() * constant2; + Float_t comp2e = pb.T() * constant2; + + TLorentzVector comp2(TVector3(comp2x, comp2y, comp2z), comp2e); + + // Un-normalized x + x = *lv - comp1 - comp2; + // normalize x + Float_t normx = std::sqrt(-x * x); + Float_t xnx = x.X() / normx; + Float_t xny = x.Y() / normx; + Float_t xnz = x.Z() / normx; + Float_t xne = x.E() / normx; + + // Normalized x + TLorentzVector xhat(TVector3(xnx, xny, xnz), xne); + + // calculate y + // TLorentzVector y; + Float_t yone = pa.Y() * pb.Z() * lv->E() - pa.Z() * pb.Y() * lv->E() + pa.Z() * pb.E() * lv->Y() + pa.E() * pb.Y() * lv->Z() - pa.Y() * pb.E() * lv->Z() - pa.E() * pb.Z() * lv->Y(); + Float_t ytwo = -pa.Z() * pb.E() * lv->X() + pa.Z() * pb.X() * lv->E() - pa.X() * pb.Z() * lv->E() + pa.X() * pb.E() * lv->Z() - pa.E() * pb.X() * lv->Z() + pa.E() * pb.Z() * lv->X(); + Float_t ythree = pa.X() * pb.Y() * lv->E() - pa.Y() * pb.X() * lv->E() + pa.Y() * pb.E() * lv->X() - pa.X() * pb.E() * lv->Y() + pa.E() * pb.X() * lv->Y() - pa.E() * pb.Y() * lv->X(); + Float_t yfour = -pa.X() * pb.Y() * lv->Z() + pa.X() * pb.Z() * lv->Y() - pa.Z() * pb.X() * lv->Y() + pa.Z() * pb.Y() * lv->X() - pa.Y() * pb.Z() * lv->X() + pa.Y() * pb.X() * lv->Z(); + + // Un-normalized y + TLorentzVector y(TVector3(yone, ytwo, ythree), yfour); + + // normalize y + Float_t normy = std::sqrt(-y * y); + Float_t ynx = y.X() / normy; + Float_t yny = y.Y() / normy; + Float_t ynz = y.Z() / normy; + Float_t yne = y.E() / normy; + + // normalized y + TLorentzVector yhat(TVector3(ynx, yny, ynz), yne); + + // Lepton momentum difference + TLorentzVector diff; + diff = (*lv1 - *lv2); + Float_t diff2x = diff.X() / 2.; + Float_t diff2y = diff.Y() / 2.; + Float_t diff2z = diff.Z() / 2.; + Float_t diff2e = diff.E() / 2.; + TLorentzVector diff2(TVector3(diff2x, diff2y, diff2z), diff2e); + + // Normalize diff2 + Float_t norm2 = std::sqrt(-diff2 * diff2); + Float_t diff3x = diff2.X() / norm2; + Float_t diff3y = diff2.Y() / norm2; + Float_t diff3z = diff2.Z() / norm2; + Float_t diff3e = diff2.E() / norm2; + + TLorentzVector diff3(TVector3(diff3x, diff3y, diff3z), diff3e); + + // computing the angles + float cosThetaCS = zhat * diff3; + Double_t SinThetaCosPhiCS = xhat * diff3; + Double_t SinThetaSinPhiCS = yhat * diff3; + //************************************** + + float phi = atan2(SinThetaSinPhiCS, SinThetaCosPhiCS); + // if (phi>=0) phi = phi; + if (phi < 0) + phi = phi + o2::constants::math::TwoPI; + + q[0] = accoplCut; + q[1] = phi; + q[2] = cosThetaCS; + + return q; + } + + double DeltaPhi(TLorentzVector lv1, TLorentzVector lv2) + { + TLorentzVector lv_sum = lv1 + lv2; + TLorentzVector lv_diff = lv1 - lv2; + + double dp = lv_sum.DeltaPhi(lv_diff); + + return dp; + } //____________________________________________________________________________________________ float momentum(float px, float py, float pz) // Just a simple function to return momentum @@ -127,48 +300,58 @@ struct UPCPionAnalysis { registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); - auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{10, 0., 10.}}); + registry.add("posx", "Vertex position in x", kTH1F, {{100, -0.5, 0.5}}); + registry.add("posy", "Vertex position in y", kTH1F, {{100, -0.5, 0.5}}); + registry.add("posz", "Vertex position in z", kTH1F, {{1000, -100., 100.}}); + + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{20, 0., 20.}}); - TString SelectionCuts[7] = {"NoSelection", "2pioncandidates", "tpcNClsCrossedRows", "opposite_charge", "|nsigmapi|<3", "nsigmael", "track_momenta>0.3GeV/c"}; + TString SelectionCuts[18] = {"NoSelection", "gapside", "goodtracks", "truegap", "ncollcontrib ", "zvtx", "2collcontrib", "2goodtrk", "TPCPID", "Rap_cut", "unlikesign", "mass_cut", "coherent", "incoherent", "likesign", "mass_cut", "coherent", "incoherent"}; // now we can set BinLabel in histogram Registry - for (int i = 0; i < 7; i++) { + for (int i = 0; i < 18; i++) { hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); } - + // tracks registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); registry.add("hTracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); - registry.add("h2TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("TwoPion/h2TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); registry.add("h4TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); registry.add("h6TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); registry.add("h8TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); - registry.add("hMassLike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{1000, 0., 20.}}); - registry.add("hMassUnlike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{1000, 0., 20.}}); - registry.add("hMassUnlikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{1000, 0., 20.}}); registry.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}}); registry.add("hdEdxPion", "p_{#pi} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}}); - registry.add("hNsigPi1vsPi2", "NSigmaPi(t1) vs NSigmapi (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); - registry.add("hNsigEl1vsEl2", "NSigmaEl(t1) vs NSigmaEl (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); - registry.add("hNsigPivsPt1", "Pt vs NSigmaPi (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); - registry.add("hNsigPivsPt2", "Pt vs NSigmaPi (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); - registry.add("hNsigElvsPt1", "Pt vs NSigmaEl (t1);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); - registry.add("hNsigElvsPt2", "Pt vs NSigmaEl (t2);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); - registry.add("hNsigMuvsPt1", "Pt vs NSigmaMu (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); - registry.add("hNsigMuvsPt2", "Pt vs NSigmaMu (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); - - registry.add("hEta_t1", "Eta of t1;#it{#eta};", kTH1F, {{100, -5., 5.}}); - registry.add("hEta_t2", "Eta of t2;#it{#eta};", kTH1F, {{100, -5., 5.}}); + registry.add("TwoPion/hNsigPi1vsPi2", "NSigmaPi(t1) vs NSigmapi (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); + registry.add("TwoPion/hNsigEl1vsEl2", "NSigmaEl(t1) vs NSigmaEl (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); + registry.add("TwoPion/hNsigPivsPt1", "Pt vs NSigmaPi (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigPivsPt2", "Pt vs NSigmaPi (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigElvsPt1", "Pt vs NSigmaEl (t1);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigElvsPt2", "Pt vs NSigmaEl (t2);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigMuvsPt1", "Pt vs NSigmaMu (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigMuvsPt2", "Pt vs NSigmaMu (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("trackpt", "Track pT per track; Track pT; Track bit; Tracks", {HistType::kTH2F, {{4, 0.5, 4.5}, {100, 0.0, 10.}}}); + registry.add("tracketa", "Track eta per track; Track eta; Track bit; Tracks", {HistType::kTH2F, {{4, 0.5, 4.5}, {100, -5, 5.}}}); + registry.add("trackphi", "Track phi per track; Track phi; Track bit; Tracks", {HistType::kTH2F, {{4, 0.5, 4.5}, {100, 0. * TMath::Pi(), 2. * TMath::Pi()}}}); + registry.add("tracksign", "Track sign per track; Track sign; Track bit; Tracks", {HistType::kTH2F, {{4, 0.5, 4.5}, {200, -10., 10.}}}); registry.add("hCharge", "Charge;#it{charge};", kTH1F, {{500, -10., 10.}}); - registry.add("hPtsingle_track1", "Pt t1;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}}); - registry.add("hPtsingle_track2", "Pt t2;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}}); - registry.add("hP1", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}}); - registry.add("hTPCsig", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}}); - registry.add("hP2", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}}); - registry.add("hTPCsig1", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}}); - + registry.add("TwoPion/hPtsingle_track1", "Pt t1;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}}); + registry.add("TwoPion/hPtsingle_track2", "Pt t2;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}}); + registry.add("TwoPion/hEta_t1", "Eta of t1;#it{#eta};", kTH1F, {{100, -5., 5.}}); + registry.add("TwoPion/hEta_t2", "Eta of t2;#it{#eta};", kTH1F, {{100, -5., 5.}}); + registry.add("TwoPion/hP1", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}}); + registry.add("TwoPion/hTPCsig", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}}); + registry.add("TwoPion/hP2", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}}); + registry.add("TwoPion/hTPCsig1", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}}); + + registry.add("TwoPion/hMassLike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/hMassUnlike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Coherent/hMassUnlikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Coherent/hMassLikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Incoherent/hMassUnlikeInCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Incoherent/hMassLikeInCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); registry.add("hMassFourPionsCoherent", "Raw Inv.M;#it{M_{#pi#pi}} (GeV/c^{2});", kTH1D, {{1000, 0., 10.}}); registry.add("hMassSixPionsCoherent", "Raw Inv.M;#it{M_{6#pi}} (GeV/c^{2});", kTH1D, {{1000, 0., 10.}}); registry.add("hMassEightPionsCoherent", "Raw Inv.M;#it{M_{6#pi}} (GeV/c^{2});", kTH1D, {{1000, 0., 10.}}); @@ -183,7 +366,8 @@ struct UPCPionAnalysis { registry.add("hPhiEtaSixPionsRightSign", "Phi vs Eta;#it{#phi};#it{#eta};", kTH2F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}, {120, -2, 2}}); registry.add("hPhiEta8PionsRightSign", "Phi vs Eta;#it{#phi};#it{#eta};", kTH2F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}, {120, -2, 2}}); - registry.add("hPt", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); + registry.add("TwoPion/hPt", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); + registry.add("TwoPion/hPtLike", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); registry.add("hPt4Pion", "Pt1;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); registry.add("hPt6Pion", "Pt2;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); registry.add("hPt8Pion", "Pt2;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); @@ -191,77 +375,124 @@ struct UPCPionAnalysis { registry.add("hPt6PionRightSign", "Pt2;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); registry.add("hPt8PionRightSign", "Pt2;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); - registry.add("hEta", "Eta;#it{#eta};", kTH1F, {{500, -10., 10.}}); + registry.add("TwoPion/hEta", "Eta;#it{#eta};", kTH1F, {{500, -10., 10.}}); registry.add("hEta4Pion", "Eta of four pion;#it{#eta};", kTH1F, {{100, -5., 5.}}); registry.add("hEta6Pion", "Eta of six pion;#it{#eta};", kTH1F, {{100, -5., 5.}}); registry.add("hEta8Pion", "Eta of six pion;#it{#eta};", kTH1F, {{100, -5., 5.}}); - registry.add("hRap", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}}); + registry.add("TwoPion/hRap", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}}); registry.add("hRap4Pion", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}}); registry.add("hRap6Pion", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}}); registry.add("hRap8pion", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}}); - registry.add("hPhi", "Phi;#it{#Phi};", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); - registry.add("hPhi4Pion", "Phi;#it{#Phi};", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); - registry.add("hPhi6Pion", "Phi;#it{#Phi};", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); - registry.add("hPhi8Pion", "Phi;#it{#Phi};", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/hPhiSystem", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); - registry.add("hCostheta", "Costheta;#it{Cos#Theta};", kTH1F, {{100, -1., 1.}}); - registry.add("hCostheta4Pion", "Costheta;#it{Cos#Theta};", kTH1F, {{100, -1., 1.}}); - registry.add("hCostheta6Pion", "Costheta;#it{Cos#Theta};", kTH1F, {{100, -1., 1.}}); - registry.add("hCostheta8Pion", "Costheta;#it{Cos#Theta};", kTH1F, {{100, -1., 1.}}); - - registry.add("hMPt", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 10.}, {100, 0., 10.}}); + registry.add("TwoPion/hMPt", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 10.}, {100, 0., 10.}}); registry.add("hMPt1", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 10.}, {100, 0., 10.}}); registry.add("hMPt2", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 10.}, {100, 0., 10.}}); registry.add("hMPt3", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 20.}, {100, 0., 10.}}); + + // Uisng Polarisaion method + registry.add("TwoPion/Coherent/hPhi", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Incoherent/hPhiInCoherent", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("hPhi4Pion", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("hPhi6Pion", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("hPhi8Pion", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + + registry.add("TwoPion/Coherent/hCostheta", "Costheta;#it{Cos#Theta};", kTH1F, {{300, -1.5, 1.5}}); + registry.add("TwoPion/Incoherent/hCosthetaInCoherent", "Costheta;#it{Cos#Theta};", kTH1F, {{300, -1.5, 1.5}}); + registry.add("hCostheta4Pion", "Costheta;#it{Cos#Theta};", kTH1F, {{300, -1.5, 1.5}}); + registry.add("hCostheta6Pion", "Costheta;#it{Cos#Theta};", kTH1F, {{300, -1.5, 1.5}}); + registry.add("hCostheta8Pion", "Costheta;#it{Cos#Theta};", kTH1F, {{300, -1.5, 1.5}}); + + // Using Angular Correlation method + + registry.add("TwoPion/Coherent/AccoplAngle", "AccoplAngle", kTH1F, {{250, -0.2, 0.2}}); + registry.add("TwoPion/Coherent/CosTheta", "CosTheta", kTH1F, {{300, -1.5, 1.5}}); + registry.add("TwoPion/Coherent/Phi", "Phi", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Coherent/Phi1", "Phi1", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Coherent/Phi2", "Phi2", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Coherent/CosThetaPhi", "CosThetaPhi", kTH2F, {{300, -1.5, 1.5}, {250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + + registry.add("TwoPion/Incoherent/AccoplAngle", "AccoplAngle", kTH1F, {{250, -0.2, 0.2}}); + registry.add("TwoPion/Incoherent/CosTheta", "CosTheta", kTH1F, {{300, -1.5, 1.5}}); + registry.add("TwoPion/Incoherent/Phi", "Phi", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Incoherent/Phi1", "Phi1", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Incoherent/Phi2", "Phi2", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/Incoherent/CosThetaPhi", "CosThetaPhi", kTH2F, {{300, -1.5, 1.5}, {250, 0., 2. * TMath::Pi()}}); + + // Asymmetry histograms + registry.add("TwoPion/Coherent/DeltaPhi", "DeltaPhi", kTH1F, {{360, -TMath::Pi(), TMath::Pi()}}); + registry.add("TwoPion/Incoherent/DeltaPhi", "DeltaPhi", kTH1F, {{360, -TMath::Pi(), TMath::Pi()}}); } using udtracks = soa::Join; - using udtracksfull = soa::Join; + using udtracksfull = soa::Join; using UDCollisionsFull = soa::Join; //__________________________________________________________________________ // Main process void process(UDCollisionsFull::iterator const& collision, udtracksfull const& tracks) { registry.fill(HIST("hSelectionCounter"), 0); - + // LOGF(info, " BC ID %d",collision.gapSide()); int gapSide = collision.gapSide(); if (gapSide < 0 || gapSide > 2) return; + registry.fill(HIST("hSelectionCounter"), 1); + + float FIT_cut[5] = {FV0_cut, FT0A_cut, FT0C_cut, FDDA_cut, FDDC_cut}; // int truegapSide = sgSelector.trueGap(collision, FV0_cut, ZDC_cut); - int truegapSide = sgSelector.trueGap(collision, FV0_cut, FT0A_cut, FT0C_cut, ZDC_cut); + int truegapSide = sgSelector.trueGap(collision, FIT_cut[0], FIT_cut[1], FIT_cut[2], ZDC_cut); + std::vector parameters = {PV_cut, dcaZ_cut, dcaXY_cut, tpcChi2_cut, tpcNClsFindable_cut, itsChi2_cut, eta_cut, pt_cut}; + registry.fill(HIST("hSelectionCounter"), 2); + registry.fill(HIST("GapSide"), gapSide); registry.fill(HIST("TrueGapSide"), truegapSide); gapSide = truegapSide; if (gapSide == gap_Side) { + + registry.fill(HIST("hSelectionCounter"), 3); //_____________________________________ // Create pions and apply TPC Pion PID std::vector allTracks; std::vector onlyPionTracks; std::vector onlyPionSigma; std::vector rawPionTracks; + std::vector trackpt; + std::vector tracketa; + std::vector trackphi; + std::vector tracksign; TLorentzVector p; registry.fill(HIST("hTracks"), tracks.size()); - // if(collision.numContrib() > 10) return; + if (collision.numContrib() > collcontrib_cut) + return; - for (auto t : tracks) { - if (!t.isPVContributor()) { - continue; - } + registry.fill(HIST("hSelectionCounter"), 4); + if ((collision.posZ() < -(Zvtx_cut)) || (collision.posZ() > Zvtx_cut)) + return; + registry.fill(HIST("hSelectionCounter"), 5); - double dEdx = t.tpcSignal(); + for (auto t : tracks) { - if (TMath::Abs(eta(t.px(), t.py(), t.pz()) > 0.9)) { + /*if (!t.isPVContributor()) { continue; - } + }*/ - if (t.pt() < 0.15) { + if (!trackselector(t, parameters)) continue; - } + + int NFindable = t.tpcNClsFindable(); + int NMinusFound = t.tpcNClsFindableMinusFound(); + int NCluster = NFindable - NMinusFound; + + /*if (NCluster < TPC_cluster) { + continue; + }*/ + + double dEdx = t.tpcSignal(); registry.fill(HIST("hdEdx"), t.tpcInnerParam() / t.sign(), dEdx); TLorentzVector a; @@ -269,7 +500,7 @@ struct UPCPionAnalysis { allTracks.push_back(a); auto nSigmaPi = t.tpcNSigmaPi(); - if (fabs(nSigmaPi) < 3.) { + if (fabs(nSigmaPi) < PID_cut) { onlyPionTracks.push_back(a); onlyPionSigma.push_back(nSigmaPi); rawPionTracks.push_back(t); @@ -285,35 +516,28 @@ struct UPCPionAnalysis { //_____________________________________ if (collision.numContrib() == 4) { // Four pions analysis + if ((rawPionTracks.size() == 4) && (onlyPionTracks.size() == 4)) { - registry.fill(HIST("hEta_t1"), onlyPionTracks[0].Eta()); - registry.fill(HIST("hEta_t2"), onlyPionTracks[1].Eta()); - - /*if ((onlyPionSigma[0] * onlyPionSigma[0] + onlyPionSigma[1] * onlyPionSigma[1]) > 9) { - return; - } - if ((onlyPionSigma[2] * onlyPionSigma[2] + onlyPionSigma[3] * onlyPionSigma[3]) > 9) { - return; - }*/ - - // Quality Control - registry.fill(HIST("hNsigPi1vsPi2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi()); - registry.fill(HIST("hNsigEl1vsEl2"), rawPionTracks[2].tpcNSigmaPi(), rawPionTracks[3].tpcNSigmaPi()); - registry.fill(HIST("hNsigPivsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi()); - registry.fill(HIST("hNsigPivsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi()); - registry.fill(HIST("hNsigElvsPt1"), onlyPionTracks[2].Pt(), rawPionTracks[2].tpcNSigmaPi()); - registry.fill(HIST("hNsigElvsPt2"), onlyPionTracks[3].Pt(), rawPionTracks[3].tpcNSigmaPi()); - - registry.fill(HIST("hNsigMuvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaMu()); - registry.fill(HIST("hNsigMuvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaMu()); - - registry.fill(HIST("hPtsingle_track1"), onlyPionTracks[0].Pt()); - registry.fill(HIST("hPtsingle_track2"), onlyPionTracks[1].Pt()); - registry.fill(HIST("hP1"), onlyPionTracks[0].P(), rawPionTracks[0].tpcSignal()); - registry.fill(HIST("hTPCsig"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal()); - registry.fill(HIST("hP2"), onlyPionTracks[2].P(), rawPionTracks[2].tpcSignal()); - registry.fill(HIST("hTPCsig1"), rawPionTracks[2].tpcSignal(), rawPionTracks[3].tpcSignal()); + registry.get(HIST("trackpt"))->Fill(1., onlyPionTracks[0].Pt()); + registry.get(HIST("trackpt"))->Fill(2., onlyPionTracks[1].Pt()); + registry.get(HIST("trackpt"))->Fill(3., onlyPionTracks[2].Pt()); + registry.get(HIST("trackpt"))->Fill(4., onlyPionTracks[3].Pt()); + + registry.get(HIST("tracketa"))->Fill(1., onlyPionTracks[0].Eta()); + registry.get(HIST("tracketa"))->Fill(2., onlyPionTracks[1].Eta()); + registry.get(HIST("tracketa"))->Fill(3., onlyPionTracks[2].Eta()); + registry.get(HIST("tracketa"))->Fill(4., onlyPionTracks[3].Eta()); + + registry.get(HIST("trackphi"))->Fill(1., onlyPionTracks[0].Phi()); + registry.get(HIST("trackphi"))->Fill(2., onlyPionTracks[1].Phi()); + registry.get(HIST("trackphi"))->Fill(3., onlyPionTracks[2].Phi()); + registry.get(HIST("trackphi"))->Fill(4., onlyPionTracks[3].Phi()); + + registry.get(HIST("tracksign"))->Fill(1., rawPionTracks[0].sign()); + registry.get(HIST("tracksign"))->Fill(2., rawPionTracks[1].sign()); + registry.get(HIST("tracksign"))->Fill(3., rawPionTracks[2].sign()); + registry.get(HIST("tracksign"))->Fill(4., rawPionTracks[3].sign()); int sign = 0; TLorentzVector piplus, piminus; @@ -337,27 +561,28 @@ struct UPCPionAnalysis { auto phihel = 1. * TMath::Pi() + PhiHelicityFrame(piplus, piminus, p); registry.fill(HIST("hPhi4Pion"), phihel); - if (p.Rapidity() > -0.9 && p.Rapidity() < 0.9) { + if ((p.Rapidity() > -Rap_cut) && (p.Rapidity() < Rap_cut)) { + if ((p.M() > 0.8) && (p.M() < 2.5)) { + if (sign != 0) { + registry.fill(HIST("hMassFourPions"), p.M()); + registry.fill(HIST("hPt4Pion"), p.Pt()); + } - if (sign != 0) { - registry.fill(HIST("hMassFourPions"), p.M()); - registry.fill(HIST("hPt4Pion"), p.Pt()); - } + if (sign == 0) { + registry.fill(HIST("hCharge"), sign); + registry.fill(HIST("h4TracksPions"), onlyPionTracks.size()); - if (sign == 0) { - registry.fill(HIST("hCharge"), sign); - registry.fill(HIST("h4TracksPions"), onlyPionTracks.size()); - if (p.Pt() < 0.15) { - registry.fill(HIST("hMassFourPionsCoherent"), p.M()); - } - // if ((p.M() > 0.8) && (p.M() < 2.5)) { - registry.fill(HIST("hPt4PionRightSign"), p.Pt()); - // } - registry.fill(HIST("hMassFourPionsRightSign"), p.M()); - registry.fill(HIST("hMPt1"), p.M(), p.Pt()); - registry.fill(HIST("hRap4Pion"), p.Rapidity()); - registry.fill(HIST("hEta4Pion"), p.Eta()); + if (p.Pt() < Pt_coherent) { + registry.fill(HIST("hMassFourPionsCoherent"), p.M()); + } + + registry.fill(HIST("hPt4PionRightSign"), p.Pt()); + registry.fill(HIST("hMassFourPionsRightSign"), p.M()); + registry.fill(HIST("hMPt1"), p.M(), p.Pt()); + registry.fill(HIST("hRap4Pion"), p.Rapidity()); + registry.fill(HIST("hEta4Pion"), p.Eta()); + } for (auto pion : onlyPionTracks) { registry.fill(HIST("hPhiEtaFourPionsRightSign"), pion.Phi(), pion.Eta()); } @@ -365,7 +590,7 @@ struct UPCPionAnalysis { } } } - //_____________________________________ + //_____________________________________________________________________________________________________ // Six pions analysis if (collision.numContrib() == 6) { if ((rawPionTracks.size() == 6) && (onlyPionTracks.size() == 6)) { @@ -397,7 +622,7 @@ struct UPCPionAnalysis { auto phihel = 1. * TMath::Pi() + PhiHelicityFrame(piplus, piminus, p); registry.fill(HIST("hPhi6Pion"), phihel); - if (p.Rapidity() > -0.9 && p.Rapidity() < 0.9) { + if ((p.Rapidity() > -Rap_cut) && (p.Rapidity() < Rap_cut)) { if (sign != 0) { registry.fill(HIST("hMassSixPions"), p.M()); registry.fill(HIST("hPt6Pion"), p.Pt()); @@ -405,7 +630,7 @@ struct UPCPionAnalysis { if (sign == 0) { registry.fill(HIST("h6TracksPions"), onlyPionTracks.size()); - if (p.Pt() < 0.15) { + if (p.Pt() < Pt_coherent) { registry.fill(HIST("hMassSixPionsCoherent"), p.M()); } registry.fill(HIST("hMassSixPionsRightSign"), p.M()); @@ -456,14 +681,14 @@ struct UPCPionAnalysis { auto phihel = 1. * TMath::Pi() + PhiHelicityFrame(piplus, piminus, p); registry.fill(HIST("hPhi8Pion"), phihel); - if (p.Rapidity() > -0.9 && p.Rapidity() < 0.9) { + if ((p.Rapidity() > -Rap_cut) && (p.Rapidity() < Rap_cut)) { if (sign != 0) { registry.fill(HIST("hMassEightPions"), p.M()); registry.fill(HIST("hPt8Pion"), p.Pt()); } if (sign == 0) { registry.fill(HIST("h8TracksPions"), onlyPionTracks.size()); - if (p.Pt() < 0.15) { + if (p.Pt() < Pt_coherent) { registry.fill(HIST("hMassEightPionsCoherent"), p.M()); } registry.fill(HIST("hMass8PionsRightSign"), p.M()); @@ -481,57 +706,144 @@ struct UPCPionAnalysis { //_____________________________________ // CUTS if (collision.numContrib() == 2) { - if (onlyPionTracks.size() != 2) { - return; - } - registry.fill(HIST("h2TracksPions"), onlyPionTracks.size()); - if ((onlyPionSigma[0] * onlyPionSigma[0] + onlyPionSigma[1] * onlyPionSigma[1]) > 9) { - return; - } + registry.fill(HIST("hSelectionCounter"), 6); - if (onlyPionTracks[0].P() < 0.3 || onlyPionTracks[1].P() < 0.3) { - return; - } - if (p.Rapidity() < -0.9 || p.Rapidity() > 0.9) { - return; - } - if (rawPionTracks[0].sign() == rawPionTracks[1].sign()) { - registry.fill(HIST("hMassLike"), p.M()); - return; - } - registry.fill(HIST("hMassUnlike"), p.M()); + if ((rawPionTracks.size() == 2) && (onlyPionTracks.size() == 2)) { + registry.fill(HIST("hSelectionCounter"), 7); - TLorentzVector tplus, tminus; - if (rawPionTracks[0].sign() > 0) { - tplus = onlyPionTracks[0]; - } else { - tminus = onlyPionTracks[0]; - } - if (rawPionTracks[1].sign() < 0) { - tminus = onlyPionTracks[1]; - } else { - tplus = onlyPionTracks[1]; - } + registry.fill(HIST("TwoPion/h2TracksPions"), onlyPionTracks.size()); + registry.fill(HIST("TwoPion/hNsigPivsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hNsigPivsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hTPCsig"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal()); + registry.fill(HIST("TwoPion/hNsigPi1vsPi2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi()); + + if ((onlyPionSigma[0] * onlyPionSigma[0] + onlyPionSigma[1] * onlyPionSigma[1]) > (PID_cut * PID_cut)) { + return; + } + registry.fill(HIST("hSelectionCounter"), 8); + if ((p.Rapidity() < -Rap_cut) || (p.Rapidity() > Rap_cut)) { + return; + } + registry.fill(HIST("hSelectionCounter"), 9); + + TLorentzVector tplus, tminus; + if (rawPionTracks[0].sign() > 0) { + tplus = onlyPionTracks[0]; + } else { + tminus = onlyPionTracks[0]; + } + if (rawPionTracks[1].sign() < 0) { + tminus = onlyPionTracks[1]; + } else { + tplus = onlyPionTracks[1]; + } + + auto costheta = CosThetaHelicityFrame(tplus, tminus, p); + auto phihel = 1. * TMath::Pi() + PhiHelicityFrame(tplus, tminus, p); + + // Unlike sign + if (rawPionTracks[0].sign() != rawPionTracks[1].sign()) { + + registry.fill(HIST("hSelectionCounter"), 10); + registry.fill(HIST("TwoPion/hMassUnlike"), p.M()); + + if ((p.M() > Mass_Min) && (p.M() < Mass_Max)) { + + registry.fill(HIST("hSelectionCounter"), 11); + + registry.fill(HIST("TwoPion/hPt"), p.Pt()); + registry.fill(HIST("TwoPion/hEta"), p.Eta()); + registry.fill(HIST("TwoPion/hRap"), p.Rapidity()); + registry.fill(HIST("TwoPion/hPhiSystem"), p.Phi()); + registry.fill(HIST("TwoPion/hMPt"), p.M(), p.Pt()); + + if (p.Pt() < Pt_coherent) { + + registry.fill(HIST("hSelectionCounter"), 12); - auto costheta = CosThetaHelicityFrame(tplus, tminus, p); - registry.fill(HIST("hCostheta"), costheta); - auto phihel = 1. * TMath::Pi() + PhiHelicityFrame(tplus, tminus, p); - registry.fill(HIST("hPhi"), phihel); + // Quality Control + registry.fill(HIST("TwoPion/hEta_t1"), onlyPionTracks[0].Eta()); + registry.fill(HIST("TwoPion/hEta_t2"), onlyPionTracks[1].Eta()); + registry.fill(HIST("TwoPion/hPtsingle_track1"), onlyPionTracks[0].Pt()); + registry.fill(HIST("TwoPion/hPtsingle_track2"), onlyPionTracks[1].Pt()); - registry.fill(HIST("hPt"), p.Pt()); - registry.fill(HIST("hEta"), p.Eta()); - registry.fill(HIST("hRap"), p.Rapidity()); - // registry.fill(HIST("hPhi"), p.Phi()); - registry.fill(HIST("hMPt"), p.M(), p.Pt()); + registry.fill(HIST("TwoPion/hNsigMuvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hNsigMuvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hNsigElvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaEl()); + registry.fill(HIST("TwoPion/hNsigElvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaEl()); + registry.fill(HIST("TwoPion/hNsigEl1vsEl2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi()); - if (p.Pt() < 0.2) { - registry.fill(HIST("hMassUnlikeCoherent"), p.M()); + registry.fill(HIST("TwoPion/hP1"), onlyPionTracks[0].P(), rawPionTracks[0].tpcSignal()); + registry.fill(HIST("TwoPion/hP2"), onlyPionTracks[1].P(), rawPionTracks[1].tpcSignal()); + registry.fill(HIST("TwoPion/hTPCsig1"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal()); + + registry.fill(HIST("posx"), collision.posX()); + registry.fill(HIST("posy"), collision.posY()); + registry.fill(HIST("posz"), collision.posZ()); + + registry.fill(HIST("TwoPion/Coherent/hCostheta"), costheta); + registry.fill(HIST("TwoPion/Coherent/hPhi"), phihel); + registry.fill(HIST("TwoPion/Coherent/hMassUnlikeCoherent"), p.M()); + + // angular correlations + float* q = AngCorrelation(&onlyPionTracks[0], &onlyPionTracks[1], &p); + registry.fill(HIST("TwoPion/Coherent/Phi"), q[1], 1.); + registry.fill(HIST("TwoPion/Coherent/Phi1"), RecoDecay::phi(onlyPionTracks[0]), 1.); + registry.fill(HIST("TwoPion/Coherent/Phi2"), RecoDecay::phi(onlyPionTracks[1]), 1.); + registry.fill(HIST("TwoPion/Coherent/CosTheta"), q[2], 1.); + registry.fill(HIST("TwoPion/Coherent/CosThetaPhi"), q[2], q[1]); + registry.fill(HIST("TwoPion/Coherent/AccoplAngle"), q[0], 1.); + + double delphi = DeltaPhi(onlyPionTracks[0], onlyPionTracks[1]); + registry.fill(HIST("TwoPion/Coherent/DeltaPhi"), delphi); + } + + if (p.Pt() > Pt_coherent) { + + registry.fill(HIST("hSelectionCounter"), 13); + + registry.fill(HIST("TwoPion/Incoherent/hCosthetaInCoherent"), costheta); + registry.fill(HIST("TwoPion/Incoherent/hPhiInCoherent"), phihel); + registry.fill(HIST("TwoPion/Incoherent/hMassUnlikeInCoherent"), p.M()); + + // angular correlations + float* q = AngCorrelation(&onlyPionTracks[0], &onlyPionTracks[1], &p); + registry.fill(HIST("TwoPion/Incoherent/Phi"), q[1], 1.); + registry.fill(HIST("TwoPion/Incoherent/Phi1"), RecoDecay::phi(onlyPionTracks[0]), 1.); + registry.fill(HIST("TwoPion/Incoherent/Phi2"), RecoDecay::phi(onlyPionTracks[1]), 1.); + registry.fill(HIST("TwoPion/Incoherent/CosTheta"), q[2], 1.); + registry.fill(HIST("TwoPion/Incoherent/CosThetaPhi"), q[2], q[1]); + registry.fill(HIST("TwoPion/Incoherent/AccoplAngle"), q[0], 1.); + + double delphi = DeltaPhi(onlyPionTracks[0], onlyPionTracks[1]); + registry.fill(HIST("TwoPion/Incoherent/DeltaPhi"), delphi); + } + } + } + + // Like sign + if (rawPionTracks[0].sign() == rawPionTracks[1].sign()) { + + registry.fill(HIST("hSelectionCounter"), 14); + registry.fill(HIST("TwoPion/hMassLike"), p.M()); + if ((p.M() > Mass_Min) && (p.M() < Mass_Max)) { + registry.fill(HIST("hSelectionCounter"), 15); + registry.fill(HIST("TwoPion/hPtLike"), p.Pt()); + if (p.Pt() < Pt_coherent) { + registry.fill(HIST("hSelectionCounter"), 16); + registry.fill(HIST("TwoPion/Coherent/hMassLikeCoherent"), p.M()); + } + if (p.Pt() > Pt_coherent) { + registry.fill(HIST("hSelectionCounter"), 17); + registry.fill(HIST("TwoPion/Incoherent/hMassLikeInCoherent"), p.M()); + } + } + } } } - } // double gap - } // end of process - -}; // end of struct + } + } +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx new file mode 100644 index 00000000000..c80b7457da6 --- /dev/null +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -0,0 +1,620 @@ +// Copyright 2019-2020 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. +/// +/// \brief task for analysis of rho in UPCs using UD tables (from SG producer) +/// includes event tagging based on ZN information, track selection, reconstruction, +/// and also some basic stuff for decay phi anisotropy studies +/// \author Jakub Juracka, jakub.juracka@cern.ch + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" // used instead of TLorentzVector +#include "Math/Vector2D.h" +#include "random" + +#include "Common/DataModel/PIDResponse.h" + +#include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using FullUDSgCollision = soa::Join::iterator; +using FullUDTracks = soa::Join; + +struct upcRhoAnalysis { + double PcEtaCut = 0.9; // physics coordination recommendation + Configurable specifyGapSide{"specifyGapSide", true, "specify gap side for SG/DG produced data"}; + Configurable tracksTpcNSigmaPiCut{"tracksTpcNSigmaPiCut", 3.0, "TPC nSigma pion cut"}; + Configurable tracksDcaMaxCut{"tracksDcaMaxCut", 1.0, "max DCA cut on tracks"}; + Configurable collisionsPosZMaxCut{"collisionsPosZMaxCut", 10.0, "max Z position cut on collisions"}; + Configurable ZNcommonEnergyCut{"ZNcommonEnergyCut", 0.0, "ZN common energy cut"}; + Configurable ZNtimeCut{"ZNtimeCut", 2.0, "ZN time cut"}; + Configurable systemMassMinCut{"systemMassMinCut", 0.5, "min M cut for reco system"}; + Configurable systemMassMaxCut{"systemMassMaxCut", 1.2, "max M cut for reco system"}; + Configurable systemPtCut{"systemPtMaxCut", 0.3, "max pT cut for reco system"}; + Configurable systemYCut{"systemYCut", 0.9, "rapiditiy cut for reco system"}; + + ConfigurableAxis mAxis{"mAxis", {1000, 0.0, 10.0}, "m (GeV/#it{c}^{2})"}; + ConfigurableAxis mCutAxis{"mCutAxis", {70, 0.5, 1.2}, "m (GeV/#it{c}^{2})"}; + ConfigurableAxis ptAxis{"ptAxis", {1000, 0.0, 10.0}, "p_{T} (GeV/#it{c})"}; + ConfigurableAxis ptCutAxis{"ptCutAxis", {30, 0.0, 0.3}, "p_{T} (GeV/#it{c})"}; + ConfigurableAxis pt2Axis{"pt2Axis", {90, 0.0, 0.09}, "p_{T}^{2} (GeV^{2}/#it{c}^{2})"}; + ConfigurableAxis etaAxis{"etaAxis", {180, -0.9, 0.9}, "#eta"}; + ConfigurableAxis yAxis{"yAxis", {180, -0.9, 0.9}, "y"}; + ConfigurableAxis phiAxis{"phiAxis", {180, 0.0, 2.0 * o2::constants::math::PI}, "#phi"}; + ConfigurableAxis phiAsymmAxis{"phiAsymmAxis", {364, 0, o2::constants::math::PI}, "#phi"}; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + // QA // + // collisions + registry.add("QC/collisions/hPosXY", ";x (cm);y (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); + registry.add("QC/collisions/hPosZ", ";z (cm);counts", kTH1D, {{400, -20.0, 20.0}}); + registry.add("QC/collisions/hNumContrib", ";number of contributors;counts", kTH1D, {{36, -0.5, 35.5}}); + registry.add("QC/collisions/hZdcCommonEnergy", ";ZNA common energy;ZNC common energy;counts", kTH2D, {{250, -5.0, 20.0}, {250, -5.0, 20.0}}); + registry.add("QC/collisions/hZdcTime", ";ZNA time (ns);ZNC time (ns);counts", kTH2D, {{200, -10.0, 10.0}, {200, -10.0, 10.0}}); + registry.add("QC/collisions/hZnaTimeVsCommonEnergy", ";ZNA common energy;ZNA time (ns);counts", kTH2D, {{250, -5.0, 20.0}, {200, -10.0, 10.0}}); + registry.add("QC/collisions/hZncTimeVsCommonEnergy", ";ZNC common energy;ZNC time (ns);counts", kTH2D, {{250, -5.0, 20.0}, {200, -10.0, 10.0}}); + // all tracks + registry.add("QC/allTracks/hTpcNSigmaPi", ";TPC n#sigma_{#pi};counts", kTH1D, {{400, -10.0, 30.0}}); + registry.add("QC/allTracks/hTofNSigmaPi", ";TOF n#sigma_{#pi};counts", kTH1D, {{400, -20.0, 20.0}}); + registry.add("QC/allTracks/hDcaXYZ", ";DCA_{z} (cm);DCA_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {1000, -5.0, 5.0}}); + // tracks passing selections + registry.add("QC/cutTracks/hTpcNsigmaPi2D", ";TPC n#sigma(#pi_{1});TPC n#sigma(#pi_{2});counts", kTH2D, {{400, -10.0, 30.0}, {400, -10.0, 30.0}}); + registry.add("QC/cutTracks/hTpcSignalVsPt", ";p_{T} (GeV/#it{c});TPC signal;counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); + registry.add("QC/cutTracks/hRemainingTracks", ";remaining tracks;counts", kTH1D, {{21, -0.5, 20.5}}); + + // RECO HISTOS // + // PIONS + // no selection + registry.add("reco/pions/unlike-sign/hPt", ";p_{T}(#pi_{1}) (GeV/#it{c});p_{T}(#pi_{2}) (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + registry.add("reco/pions/unlike-sign/hEta", ";#eta(#pi_{1});#eta(#pi_{2});counts", kTH2D, {etaAxis, etaAxis}); + registry.add("reco/pions/unlike-sign/hPhi", ";#phi(#pi_{1});#phi(#pi_{2});counts", kTH2D, {phiAxis, phiAxis}); + registry.add("reco/pions/like-sign/hPt", ";p_{T}(#pi_{1}) (GeV/#it{c});p_{T}(#pi_{2}) (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + registry.add("reco/pions/like-sign/hEta", ";#eta(#pi_{1});#eta(#pi_{2});counts", kTH2D, {etaAxis, etaAxis}); + registry.add("reco/pions/like-sign/hPhi", ";#phi(#pi_{1});#phi(#pi_{2});counts", kTH2D, {phiAxis, phiAxis}); + + // RAW RHOS + registry.add("reco/system/2pi/raw/unlike-sign/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + registry.add("reco/system/2pi/raw/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + registry.add("reco/system/2pi/raw/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + registry.add("reco/system/2pi/raw/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/raw/like-sign/positive/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + registry.add("reco/system/2pi/raw/like-sign/positive/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + registry.add("reco/system/2pi/raw/like-sign/positive/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + registry.add("reco/system/2pi/raw/like-sign/positive/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/raw/like-sign/negative/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + registry.add("reco/system/2pi/raw/like-sign/negative/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + registry.add("reco/system/2pi/raw/like-sign/negative/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + registry.add("reco/system/2pi/raw/like-sign/negative/hY", ";y;counts", kTH1D, {yAxis}); + + // SELECTED RHOS + // no selection + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/unlike-sign/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + // 0n0n + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/unlike-sign/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + // Xn0n + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + // 0nXn + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/unlike-sign/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + // XnXn + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/unlike-sign/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mCutAxis, ptCutAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiRandomVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + registry.add("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiChargeVsM", ";m (GeV/#it{c}^{2});#phi;counts", kTH2D, {mCutAxis, phiAsymmAxis}); + + // 4PI AND 6PI SYSTEM + registry.add("reco/system/4pi/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + registry.add("reco/system/4pi/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + registry.add("reco/system/4pi/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + registry.add("reco/system/4pi/hY", ";y;counts", kTH1D, {yAxis}); + registry.add("reco/system/6pi/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + registry.add("reco/system/6pi/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + registry.add("reco/system/6pi/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + registry.add("reco/system/6pi/hY", ";y;counts", kTH1D, {yAxis}); + } + + template + bool collisionPassesCuts(T const& collision) // collision cuts + { + if (std::abs(collision.posZ()) > collisionsPosZMaxCut) + return false; + if (specifyGapSide && collision.gapSide() != 2) + return false; + return true; + } + + template + bool trackPassesCuts(T const& track) // track cuts (PID done separately) + { + if (!track.isPVContributor()) + return false; + if (!track.hasITS()) + return false; + if (std::abs(track.dcaZ()) > tracksDcaMaxCut || std::abs(track.dcaXY()) > tracksDcaMaxCut) + return false; + if (std::abs(eta(track.px(), track.py(), track.pz())) > PcEtaCut) + return false; + return true; + } + + template + bool tracksPassPiPID(const T& cutTracks) // n-dimensional PID cut + { + double radius = 0.0; + for (const auto& track : cutTracks) + radius += std::pow(track.tpcNSigmaPi(), 2); + return radius < std::pow(tracksTpcNSigmaPiCut, 2); + } + + template + double tracksTotalCharge(const T& cutTracks) // total charge of selected tracks + { + double charge = 0.0; + for (const auto& track : cutTracks) + charge += track.sign(); + return charge; + } + + template + bool systemPassCuts(const T& system) // system cuts + { + if (system.M() < systemMassMinCut || system.M() > systemMassMaxCut) + return false; + if (system.Pt() > systemPtCut) + return false; + if (std::abs(system.Rapidity()) > systemYCut) + return false; + return true; + } + + ROOT::Math::PxPyPzMVector reconstructSystem(const std::vector& cutTracks4Vecs) // reconstruct system from 4-vectors + { + ROOT::Math::PxPyPzMVector system; + for (const auto& track4Vec : cutTracks4Vecs) + system += track4Vec; + return system; + } + + template + double getPhiRandom(const T& cutTracks) // decay phi anisotropy + { // two possible definitions of phi: randomize the tracks + std::vector indices = {0, 1}; + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // get time-based seed + std::shuffle(indices.begin(), indices.end(), std::default_random_engine(seed)); // shuffle indices + // calculate phi + ROOT::Math::XYVector pOne(cutTracks[indices[0]].px(), cutTracks[indices[0]].py()); + ROOT::Math::XYVector pTwo(cutTracks[indices[1]].px(), cutTracks[indices[1]].py()); + auto pPlus = pOne + pTwo; + auto pMinus = pOne - pTwo; + // no method for direct calculation of angle -> use dot product formula + double cosPhi = (pPlus.Dot(pMinus)) / (std::sqrt(pPlus.Mag2()) * std::sqrt(pMinus.Mag2())); + return std::acos(cosPhi); + } + + template + double getPhiCharge(const T& cutTracks) + { // two possible definitions of phi: charge-based assignment + ROOT::Math::XYVector pOne, pTwo; + if (cutTracks[0].sign() > 0) { + pOne.SetXY(cutTracks[0].px(), cutTracks[0].py()); + pTwo.SetXY(cutTracks[1].px(), cutTracks[1].py()); + } else { + pOne.SetXY(cutTracks[1].px(), cutTracks[1].py()); + pTwo.SetXY(cutTracks[0].px(), cutTracks[0].py()); + } + auto pPlus = pOne + pTwo; + auto pMinus = pOne - pTwo; + double cosPhi = (pPlus.Dot(pMinus)) / (std::sqrt(pPlus.Mag2()) * std::sqrt(pMinus.Mag2())); + return std::acos(cosPhi); + } + + void processReco(FullUDSgCollision const& collision, FullUDTracks const& tracks) + { + // QC histograms + registry.fill(HIST("QC/collisions/hPosXY"), collision.posX(), collision.posY()); + registry.fill(HIST("QC/collisions/hPosZ"), collision.posZ()); + registry.fill(HIST("QC/collisions/hZdcCommonEnergy"), collision.energyCommonZNA(), collision.energyCommonZNC()); + registry.fill(HIST("QC/collisions/hZdcTime"), collision.timeZNA(), collision.timeZNC()); + registry.fill(HIST("QC/collisions/hZnaTimeVsCommonEnergy"), collision.energyCommonZNA(), collision.timeZNA()); + registry.fill(HIST("QC/collisions/hZncTimeVsCommonEnergy"), collision.energyCommonZNC(), collision.timeZNC()); + registry.fill(HIST("QC/collisions/hNumContrib"), collision.numContrib()); + + if (!collisionPassesCuts(collision)) + return; + + // event tagging + bool XnXn = false, OnOn = false, XnOn = false, OnXn = false; // note: On == 0n... + if (collision.energyCommonZNA() < ZNcommonEnergyCut && collision.energyCommonZNC() < ZNcommonEnergyCut) + OnOn = true; + if (collision.energyCommonZNA() > ZNcommonEnergyCut && std::abs(collision.timeZNA()) < ZNtimeCut && + collision.energyCommonZNC() > ZNcommonEnergyCut && std::abs(collision.timeZNC()) < ZNtimeCut) + XnXn = true; + if (collision.energyCommonZNA() > ZNcommonEnergyCut && std::abs(collision.timeZNA()) < ZNtimeCut && collision.energyCommonZNC() < ZNcommonEnergyCut) + XnOn = true; + if (collision.energyCommonZNA() < ZNcommonEnergyCut && collision.energyCommonZNC() > ZNcommonEnergyCut && std::abs(collision.timeZNC()) < ZNtimeCut) + OnXn = true; + // vectors for storing selected tracks and their 4-vectors + std::vector cutTracks; + std::vector cutTracks4Vecs; + + int trackCounter = 0; + for (const auto& track : tracks) { + registry.fill(HIST("QC/allTracks/hTpcNSigmaPi"), track.tpcNSigmaPi()); + registry.fill(HIST("QC/allTracks/hTofNSigmaPi"), track.tofNSigmaPi()); + registry.fill(HIST("QC/allTracks/hDcaXYZ"), track.dcaZ(), track.dcaXY()); + + if (!trackPassesCuts(track)) + continue; + trackCounter++; + cutTracks.push_back(track); + cutTracks4Vecs.push_back(ROOT::Math::PxPyPzMVector(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged)); // apriori assume pion mass + registry.fill(HIST("QC/cutTracks/hTpcSignalVsPt"), track.pt(), track.tpcSignal()); + } + registry.fill(HIST("QC/cutTracks/hRemainingTracks"), trackCounter); + + if (cutTracks.size() == 2) + registry.fill(HIST("QC/cutTracks/hTpcNsigmaPi2D"), cutTracks[0].tpcNSigmaPi(), cutTracks[1].tpcNSigmaPi()); + + if (!tracksPassPiPID(cutTracks)) + return; + // reonstruct system and calculate total charge + auto system = reconstructSystem(cutTracks4Vecs); + int totalCharge = tracksTotalCharge(cutTracks); + int nTracks = cutTracks.size(); + + if (nTracks == 2) { + // fill raw histograms according to the total charge + if (totalCharge == 0) { + registry.fill(HIST("reco/pions/unlike-sign/hPt"), cutTracks4Vecs[0].Pt(), cutTracks4Vecs[1].Pt()); + registry.fill(HIST("reco/pions/unlike-sign/hEta"), cutTracks4Vecs[0].Eta(), cutTracks4Vecs[1].Eta()); + registry.fill(HIST("reco/pions/unlike-sign/hPhi"), cutTracks4Vecs[0].Phi() + o2::constants::math::PI, cutTracks4Vecs[1].Phi() + o2::constants::math::PI); + registry.fill(HIST("reco/system/2pi/raw/unlike-sign/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/raw/unlike-sign/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/raw/unlike-sign/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/raw/unlike-sign/hY"), system.Rapidity()); + } else { + registry.fill(HIST("reco/pions/like-sign/hPt"), cutTracks4Vecs[0].Pt(), cutTracks4Vecs[1].Pt()); + registry.fill(HIST("reco/pions/like-sign/hEta"), cutTracks4Vecs[0].Eta(), cutTracks4Vecs[1].Eta()); + registry.fill(HIST("reco/pions/like-sign/hPhi"), cutTracks4Vecs[0].Phi() + o2::constants::math::PI, cutTracks4Vecs[1].Phi() + o2::constants::math::PI); + if (totalCharge == 2) { + registry.fill(HIST("reco/system/2pi/raw/like-sign/positive/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/raw/like-sign/positive/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/raw/like-sign/positive/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/raw/like-sign/positive/hY"), system.Rapidity()); + } else if (totalCharge == -2) { + registry.fill(HIST("reco/system/2pi/raw/like-sign/negative/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/raw/like-sign/negative/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/raw/like-sign/negative/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/raw/like-sign/negative/hY"), system.Rapidity()); + } + } + // apply cuts to system + if (!systemPassCuts(system)) + return; + // fill histograms for system passing cuts + switch (totalCharge) { + case 0: + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/unlike-sign/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + if (OnOn) { + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/unlike-sign/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (XnOn) { + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/unlike-sign/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (OnXn) { + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/unlike-sign/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (XnXn) { + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/unlike-sign/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } + break; + + case 2: + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/positive/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + if (OnOn) { + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/positive/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (XnOn) { + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/positive/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (OnXn) { + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/positive/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (XnXn) { + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/positive/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } + break; + + case -2: + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/no-selection/like-sign/negative/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + if (OnOn) { + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0n0n/like-sign/negative/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (XnOn) { + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/Xn0n/like-sign/negative/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (OnXn) { + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/0nXn/like-sign/negative/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } else if (XnXn) { + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hM"), system.M()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPt"), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPt2"), system.Pt() * system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hY"), system.Rapidity()); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiRandom"), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiCharge"), getPhiCharge(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiRandomVsM"), system.M(), getPhiRandom(cutTracks)); + registry.fill(HIST("reco/system/2pi/cut/XnXn/like-sign/negative/hPhiChargeVsM"), system.M(), getPhiCharge(cutTracks)); + } + break; + + default: + break; + } + } else if (nTracks == 4 && tracksTotalCharge(cutTracks) == 0) { // 4pi system + registry.fill(HIST("reco/system/4pi/hM"), system.M()); + registry.fill(HIST("reco/system/4pi/hPt"), system.Pt()); + registry.fill(HIST("reco/system/4pi/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/4pi/hY"), system.Rapidity()); + } else if (nTracks == 6 && tracksTotalCharge(cutTracks) == 0) { // 6pi system + registry.fill(HIST("reco/system/6pi/hM"), system.M()); + registry.fill(HIST("reco/system/6pi/hPt"), system.Pt()); + registry.fill(HIST("reco/system/6pi/hPtVsM"), system.M(), system.Pt()); + registry.fill(HIST("reco/system/6pi/hY"), system.Rapidity()); + } + } + PROCESS_SWITCH(upcRhoAnalysis, processReco, "analyse reco tracks", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + o2::framework::adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/upcTauCentralBarrelRL.cxx b/PWGUD/Tasks/upcTauCentralBarrelRL.cxx index 881a58c84ce..965bfb6f327 100644 --- a/PWGUD/Tasks/upcTauCentralBarrelRL.cxx +++ b/PWGUD/Tasks/upcTauCentralBarrelRL.cxx @@ -32,6 +32,7 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/Core/SGSelector.h" // ROOT headers #include "TLorentzVector.h" @@ -48,91 +49,25 @@ struct UpcTauCentralBarrelRL { bool isFirstReconstructedCollisions; int countCollisions; Service pdg; + SGSelector sgSelector; - HistogramRegistry histos{ - "histos", - {{"Events/hCountCollisions", ";Number of analysed collision (-)", {HistType::kTH1D, {{10, 0.5, 10.5}}}}, - {"Events/hNreconstructedTracks", ";Number of tracks in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hNreconstructedPVGTelectrons", ";Number of good track electrons from primary vertex in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hNreconstructedPVGTmuons", ";Number of good track muons from primary vertex in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hNreconstructedPVGTpions", ";Number of good track pions from primary vertex in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hNreconstructedPVGTothers", ";Number of good track NOT electron/muon/pion particles from primary vertex in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hNreconstructedPVGT", ";Number of good track particles from primary vertex in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hNreconstructedNotPVGT", ";Number of good track particles from NOT primary vertex in a collision (-);Number of events (-)", {HistType::kTH1D, {{30, -0.5, 29.5}}}}, - {"Events/hChannelsRatio", ";Channels (-);Branching Ratio (-)", {HistType::kTH1D, {{10, -0.5, 9.5}}}}}}; - HistogramRegistry histosPID{ - "histosPID", - {{"Tracks/raw/PID/hTPCsignalVsZ", "All tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/hTPCsignalVsP", "All tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/hTPCsignalVsPt", "All tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/hTPCsignalVsEta", "All tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/hTPCsignalVsPhi", "All tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/raw/PID/PosCharge/hTPCsignalVsZ", "Positively charged track;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/PosCharge/hTPCsignalVsP", "Positively charged track;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/PosCharge/hTPCsignalVsPt", "Positively charged track;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/PosCharge/hTPCsignalVsEta", "Positively charged track;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/PosCharge/hTPCsignalVsPhi", "Positively charged track;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/raw/PID/NegCharge/hTPCsignalVsZ", "Negatively charged track;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/NegCharge/hTPCsignalVsP", "Negatively charged track;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/NegCharge/hTPCsignalVsPt", "Negatively charged track;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/NegCharge/hTPCsignalVsEta", "Negatively charged track;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/raw/PID/NegCharge/hTPCsignalVsPhi", "Negatively charged track;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/hTPCsignalVsZ", "All good tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/hTPCsignalVsP", "All good tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/hTPCsignalVsPt", "All good tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/hTPCsignalVsEta", "All good tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/hTPCsignalVsPhi", "All good tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsZ", "Positively charged track;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsP", "Positively charged track;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPt", "Positively charged track;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsEta", "Positively charged track;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPhi", "Positively charged track;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsZ", "Negatively charged track;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsP", "Negatively charged track;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPt", "Negatively charged track;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsEta", "Negatively charged track;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPhi", "Negatively charged track;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Electron/hTPCsignalVsZ", "Identified electron;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Electron/hTPCsignalVsP", "Identified electron;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Electron/hTPCsignalVsPt", "Identified electron;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Electron/hTPCsignalVsEta", "Identified electron;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Electron/hTPCsignalVsPhi", "Identified electron;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Muon/hTPCsignalVsZ", "Identified Muon;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Muon/hTPCsignalVsP", "Identified Muon;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Muon/hTPCsignalVsPt", "Identified Muon;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Muon/hTPCsignalVsEta", "Identified Muon;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Muon/hTPCsignalVsPhi", "Identified Muon;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Pion/hTPCsignalVsZ", "Identified Pion;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Pion/hTPCsignalVsP", "Identified Pion;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Pion/hTPCsignalVsPt", "Identified Pion;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Pion/hTPCsignalVsEta", "Identified Pion;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Pion/hTPCsignalVsPhi", "Identified Pion;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Others/hTPCsignalVsZ", "Identified NOT electron/Muon/Pion;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, -20., 20.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Others/hTPCsignalVsP", "Identified NOT electron/Muon/Pion;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Others/hTPCsignalVsPt", "Identified NOT electron/Muon/Pion;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Others/hTPCsignalVsEta", "Identified NOT electron/Muon/Pion;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{500, -2., 2.}, {200, 0., 200}}}}, - {"Tracks/GoodTrack/PID/Others/hTPCsignalVsPhi", "Identified NOT electron/Muon/Pion;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{64, 0, 2 * o2::constants::math::PI}, {200, 0., 200}}}}, - {"EventTwoTracks/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventTwoTracks/TwoElectrons/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventTwoTracks/TwoMuons/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventTwoTracks/TwoPions/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventTwoTracks/ElectronMuon/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventTwoTracks/ElectronPion/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventTwoTracks/MuonPion/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventFourTracks/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventFourTracks/WithElectron/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventFourTracks/WithMuon/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventFourTracks/WithPion/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventSixTracks/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}, - {"EventSixTracks/SixPions/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", {HistType::kTH2D, {{200, 0., 2.}, {200, 0., 200}}}}}}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // declare configurables Configurable verboseInfo{"verboseInfo", true, {"Print general info to terminal; default it true."}}; - Configurable verboseDebug{"verboseDebug", false, {"Print debug info to terminal; default it false."}}; Configurable whichGapSide{"whichGapSide", 2, {"0 for side A, 1 for side C, 2 for both sides"}}; + Configurable useTrueGap{"useTrueGap", true, {"Calculate gapSide for a given FV0/FT0/ZDC thresholds"}}; + Configurable cutMyGapSideFV0{"FV0", 100, "FV0A threshold for SG selector"}; + Configurable cutMyGapSideFT0A{"FT0A", 200., "FT0A threshold for SG selector"}; + Configurable cutMyGapSideFT0C{"FT0C", 100., "FT0C threshold for SG selector"}; + Configurable cutMyGapSideZDC{"ZDC", 10., "ZDC threshold for SG selector"}; + Configurable usePIDwithTOF{"usePIDwithTOF", false, {"Determine whether also TOF should be used in testPIDhypothesis"}}; + Configurable usePIDwithTOFsigmaAfterTPC{"usePIDwithTOFsigmaAfterTPC", true, {"Determine whether cut on TOF n sigma should be used after TPC-based decision in testPIDhypothesis"}}; Configurable cutMyTPCnSigmaEl{"cutMyTPCnSigmaEl", 3.f, {"n sigma cut on el in absolut values"}}; Configurable cutMyTPCnSigmaMu{"cutMyTPCnSigmaMu", 3.f, {"n sigma cut on mu in absolut values"}}; Configurable cutMyTPCnSigmaPi{"cutMyTPCnSigmaPi", 3.f, {"n sigma cut on pi in absolut values"}}; + Configurable cutMyNsigmaTPCPIDselector{"cutMyNsigmaTPCPIDselector", 35.f, {"n sigma TPC cut on all particles in absolut values for testPIDhypothesis"}}; + Configurable cutMyNsigmaTOFPIDselector{"cutMyNsigmaTOFPIDselector", 35.f, {"n sigma TOF cut on all particles in absolut values for testPIDhypothesis"}}; Configurable cutAvgITSclusterSize{"cutAvgITSclusterSize", 2.05f, {"specific study"}}; Configurable cutPtAvgITSclusterSize{"cutPtAvgITSclusterSize", 0.7f, {"specific study"}}; Configurable cutMyGlobalTracksOnly{"cutMyGlobalTracksOnly", false, {"Applies cut on here defined global tracks"}}; @@ -152,16 +87,19 @@ struct UpcTauCentralBarrelRL { Configurable cutMyGTtpcNClsCrossedRowsMin{"cutMyGTtpcNClsCrossedRowsMin", 70, {"MyGlobalTrack cut"}}; Configurable cutMyGTtpcNClsCrossedRowsOverNClsMin{"cutMyGTtpcNClsCrossedRowsOverNClsMin", 0.8f, {"MyGlobalTrack cut"}}; Configurable cutMyGTtpcChi2NclMax{"cutMyGTtpcChi2NclMax", 4.f, {"MyGlobalTrack cut"}}; - Configurable doTwoTracks{"doTwoTracks", false, {"Define histos for two tracks and allow to fill them"}}; + Configurable doMainHistos{"doMainHistos", true, {"Fill main histos"}}; + Configurable doPIDhistos{"doPIDhistos", true, {"Fill PID histos"}}; + Configurable doTwoTracks{"doTwoTracks", true, {"Define histos for two tracks and allow to fill them"}}; Configurable doPionStudy{"doPionStudy", false, {"Define histos for two pions and allow to fill them"}}; Configurable doMuonStudy{"doMuonStudy", false, {"Define histos for two muons and allow to fill them"}}; Configurable doJpsiMuMuTests{"doJpsiMuMuTests", false, {"Define specific-tests histos for two muons and allow to fill them"}}; Configurable doFourTracks{"doFourTracks", false, {"Define histos for four tracks and allow to fill them"}}; + Configurable doFourTrackPsi2S{"doFourTrackPsi2S", true, {"Define histos for Psi2S into four charged tracks (pi/mu) and allow to fill them"}}; Configurable doSixTracks{"doSixTracks", false, {"Define histos for six tracks and allow to fill them"}}; using FullUDTracks = soa::Join; using FullUDCollision = soa::Join::iterator; - using FullSGUDCollision = soa::Join::iterator; + using FullSGUDCollision = soa::Join::iterator; TF1* funcPhiCutL = nullptr; TF1* funcPhiCutH = nullptr; @@ -176,6 +114,7 @@ struct UpcTauCentralBarrelRL { countCollisions = 0; isFirstReconstructedCollisions = true; + const AxisSpec axisNtracks{30, -0.5, 29.5}; const AxisSpec axisZvtx{40, -20., 20.}; const AxisSpec axisInvMass{400, 1., 5.}; const AxisSpec axisInvMassWide{1000, 0., 10.}; @@ -188,14 +127,29 @@ struct UpcTauCentralBarrelRL { const AxisSpec axisEta{50, -1.2, 1.2}; const AxisSpec axisRap{50, -1.2, 1.2}; const AxisSpec axisAcoplanarity{32, 0.0, o2::constants::math::PI}; - const AxisSpec axisAvgITSclsSizes{500, 0., 10.}; const AxisSpec axisDCA{100, -0.5, 0.5}; + const AxisSpec axisAvgITSclsSizes{500, 0., 10.}; + const AxisSpec axisTPCdEdx{2000, 0., 200.}; + const AxisSpec axisTOFsignal{2500, -10000., 40000.}; + const AxisSpec axisNsigma{200, -10., 10.}; const AxisSpec axisITSnCls{8, -0.5, 7.5}; const AxisSpec axisITSchi2{100, 0, 50}; const AxisSpec axisTPCnCls{165, -0.5, 164.5}; const AxisSpec axisTPCxRwsFrac{200, 0.0, 2.0}; const AxisSpec axisTPCchi2{100, 0, 10}; + histos.add("Events/hCountCollisions", ";;Number of analysed collision (-)", HistType::kTH1D, {{1, 0.5, 1.5}}); + histos.add("Events/UDtableGapSide", ";GapSide value from UD table (-);Number of events (-)", HistType::kTH1D, {{4, -1.5, 2.5}}); + histos.add("Events/TrueGapSideDiffToTableValue", ";Difference trueGapSide from SGselector and gapSide from UD table (-);Number of events (-)", HistType::kTH1D, {{7, -3.5, 3.5}}); + histos.add("Events/hNreconstructedTracks", ";Number of tracks in a collision (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hNreconstructedPVGT", ";Number of good track particles from primary vertex in a collision (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hNreconstructedNotPVGT", ";Number of good track particles from NOT primary vertex in a collision (-);Number of events (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hNreconstructedPVGTelectrons", ";Number of good track identified electrons from primary vertex in a collision (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hNreconstructedPVGTmuons", ";Number of good track identified muons from primary vertex in a collision (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hNreconstructedPVGTpions", ";Number of good track identified pions from primary vertex in a collision (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hNreconstructedPVGTothers", ";Number of good track NOT identified electron/muon/pion particles from primary vertex in a collision (-);Number of events (-)", HistType::kTH1D, {axisNtracks}); + histos.add("Events/hChannelsRatio", ";Channels (-);Number of events (-)", HistType::kTH1D, {{10, -0.5, 9.5}}); + histos.add("Tracks/raw/hTrackZ", ";Track z-vertex (cm);Number of events (-)", HistType::kTH1D, {axisZvtx}); histos.add("Tracks/raw/hTrackP", ";Track #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMom}); histos.add("Tracks/raw/hTrackPt", ";Track #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); @@ -213,6 +167,24 @@ struct UpcTauCentralBarrelRL { histos.add("Tracks/raw/TPC/tpcCrossedRows", "number of crossed TPC rows;# crossed rows TPC", kTH1D, {axisTPCnCls}); histos.add("Tracks/raw/TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {axisTPCxRwsFrac}); histos.add("Tracks/raw/TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {axisTPCchi2}); + histos.add("Tracks/raw/PID/hTPCsignalVsZ", "All tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/raw/PID/hTPCsignalVsP", "All tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/raw/PID/hTPCsignalVsPt", "All tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/raw/PID/hTPCsignalVsEta", "All tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/raw/PID/hTPCsignalVsPhi", "All tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/raw/PID/hTOFsignalVsP", "All tracks;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/raw/PID/PosCharge/hTPCsignalVsZ", "Positively charged tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/raw/PID/PosCharge/hTPCsignalVsP", "Positively charged tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/raw/PID/PosCharge/hTPCsignalVsPt", "Positively charged tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/raw/PID/PosCharge/hTPCsignalVsEta", "Positively charged tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/raw/PID/PosCharge/hTPCsignalVsPhi", "Positively charged tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/raw/PID/PosCharge/hTOFsignalVsP", "Positively charged tracks;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/raw/PID/NegCharge/hTPCsignalVsZ", "Negatively charged tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/raw/PID/NegCharge/hTPCsignalVsP", "Negatively charged tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/raw/PID/NegCharge/hTPCsignalVsPt", "Negatively charged tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/raw/PID/NegCharge/hTPCsignalVsEta", "Negatively charged tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/raw/PID/NegCharge/hTPCsignalVsPhi", "Negatively charged tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/raw/PID/NegCharge/hTOFsignalVsP", "Negatively charged tracks;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); histos.add("Tracks/GoodTrack/hTrackZ", ";Track z-vertex (cm);Number of events (-)", HistType::kTH1D, {axisZvtx}); histos.add("Tracks/GoodTrack/hTrackP", ";Track #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMom}); @@ -231,6 +203,78 @@ struct UpcTauCentralBarrelRL { histos.add("Tracks/GoodTrack/TPC/tpcCrossedRows", "number of crossed TPC rows;# crossed rows TPC", kTH1D, {axisTPCnCls}); histos.add("Tracks/GoodTrack/TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {axisTPCxRwsFrac}); histos.add("Tracks/GoodTrack/TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {axisTPCchi2}); + histos.add("Tracks/GoodTrack/PID/hTPCsignalVsZ", "All good tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/hTPCsignalVsP", "All good tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/hTPCsignalVsPt", "All good tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/hTPCsignalVsEta", "All good tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/hTPCsignalVsPhi", "All good tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/hTOFsignalVsP", "All good tracks;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsZ", "Positively charged good tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsP", "Positively charged good tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPt", "Positively charged good tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsEta", "Positively charged good tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPhi", "Positively charged good tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/PosCharge/hTOFsignalVsP", "Positively charged good tracks;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsZ", "Negatively charged good tracks;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsP", "Negatively charged good tracks;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPt", "Negatively charged good tracks;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsEta", "Negatively charged good tracks;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPhi", "Negatively charged good tracks;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/NegCharge/hTOFsignalVsP", "Negatively charged good tracks;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCsignalVsZ", "Identified electrons;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCsignalVsP", "Identified electrons;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCsignalVsPt", "Identified electrons;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCsignalVsEta", "Identified electrons;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCsignalVsPhi", "Identified electrons;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Electron/hTOFsignalVsP", "Identified electrons;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCnSigmaVsP", "Identified electrons;Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTOFnSigmaVsP", "Identified electrons;Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsMu", "Identified electrons;n#sigma^{#it{e}}_{TPC} (arb. units);n#sigma^{#mu}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsMu", "Identified electrons;n#sigma^{#it{e}}_{TOF} (arb. units);n#sigma^{#mu}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsPi", "Identified electrons;n#sigma^{#it{e}}_{TPC} (arb. units);n#sigma^{#pi}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsPi", "Identified electrons;n#sigma^{#it{e}}_{TOF} (arb. units);n#sigma^{#pi}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsKa", "Identified electrons;n#sigma^{#it{e}}_{TPC} (arb. units);n#sigma^{#it{K}}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsKa", "Identified electrons;n#sigma^{#it{e}}_{TOF} (arb. units);n#sigma^{#it{K}}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsPr", "Identified electrons;n#sigma^{#it{e}}_{TPC} (arb. units);n#sigma^{p}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsPr", "Identified electrons;n#sigma^{#it{e}}_{TOF} (arb. units);n#sigma^{p}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCsignalVsZ", "Identified muons;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCsignalVsP", "Identified muons;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCsignalVsPt", "Identified muons;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCsignalVsEta", "Identified muons;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCsignalVsPhi", "Identified muons;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Muon/hTOFsignalVsP", "Identified muons;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCnSigmaVsP", "Identified muons;Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTOFnSigmaVsP", "Identified muons;Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsEl", "Identified muons;n#sigma^{#mu}_{TPC} (arb. units);n#sigma^{#it{e}}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsEl", "Identified muons;n#sigma^{#mu}_{TOF} (arb. units);n#sigma^{#it{e}}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsPi", "Identified muons;n#sigma^{#mu}_{TPC} (arb. units);n#sigma^{#pi}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsPi", "Identified muons;n#sigma^{#mu}_{TOF} (arb. units);n#sigma^{#pi}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsKa", "Identified muons;n#sigma^{#mu}_{TPC} (arb. units);n#sigma^{#it{K}}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsKa", "Identified muons;n#sigma^{#mu}_{TOF} (arb. units);n#sigma^{#it{K}}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsPr", "Identified muons;n#sigma^{#mu}_{TPC} (arb. units);n#sigma^{p}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsPr", "Identified muons;n#sigma^{#mu}_{TOF} (arb. units);n#sigma^{p}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCsignalVsZ", "Identified pions;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCsignalVsP", "Identified pions;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCsignalVsPt", "Identified pions;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCsignalVsEta", "Identified pions;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCsignalVsPhi", "Identified pions;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Pion/hTOFsignalVsP", "Identified pions;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCnSigmaVsP", "Identified pions;Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTOFnSigmaVsP", "Identified pions;Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsEl", "Identified pions;n#sigma^{#pi}_{TPC} (arb. units);n#sigma^{#it{e}}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsEl", "Identified pions;n#sigma^{#pi}_{TOF} (arb. units);n#sigma^{#it{e}}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsMu", "Identified pions;n#sigma^{#pi}_{TPC} (arb. units);n#sigma^{#mu}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsMu", "Identified pions;n#sigma^{#pi}_{TOF} (arb. units);n#sigma^{#mu}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsKa", "Identified pions;n#sigma^{#pi}_{TPC} (arb. units);n#sigma^{#it{K}}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsKa", "Identified pions;n#sigma^{#pi}_{TOF} (arb. units);n#sigma^{#it{K}}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsPr", "Identified pions;n#sigma^{#pi}_{TPC} (arb. units);n#sigma^{p}_{TPC} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsPr", "Identified pions;n#sigma^{#pi}_{TOF} (arb. units);n#sigma^{p}_{TOF} (arb. units)", HistType::kTH2D, {axisNsigma, axisNsigma}); + histos.add("Tracks/GoodTrack/PID/Others/hTPCsignalVsZ", "Identified NOT electron/Muon/Pion;Track z-vertex (cm);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisZvtx, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Others/hTPCsignalVsP", "Identified NOT electron/Muon/Pion;Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Others/hTPCsignalVsPt", "Identified NOT electron/Muon/Pion;Track #it{p_{#rm T}} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPt, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Others/hTPCsignalVsEta", "Identified NOT electron/Muon/Pion;Track #eta (-);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisEta, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Others/hTPCsignalVsPhi", "Identified NOT electron/Muon/Pion;Track #phi (rad);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisPhi, axisTPCdEdx}); + histos.add("Tracks/GoodTrack/PID/Others/hTOFsignalVsP", "Identified NOT electron/Muon/Pion;Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); if (doTwoTracks) { histos.add("EventTwoTracks/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); @@ -247,6 +291,7 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); @@ -254,6 +299,8 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); histos.add("EventTwoTracks/hDaughtersPvsITSclusterSize", ";Average ITS cluster size;Daughter #it{p} (GeV/c)", HistType::kTH2D, {axisAvgITSclsSizes, axisMomSigned}); histos.add("EventTwoTracks/hDaughtersPvsITSclusterSizeXcos", ";Average ITS cluster size x cos(#lambda);Daughter #it{p} (GeV/c)", HistType::kTH2D, {axisAvgITSclsSizes, axisMomSigned}); + histos.add("EventTwoTracks/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/PID/hTOFsignalVsP", ";Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); histos.add("EventTwoTracks/TwoElectrons/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventTwoTracks/TwoElectrons/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -264,6 +311,7 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/TwoElectrons/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/TwoElectrons/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/TwoElectrons/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/TwoElectrons/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/TwoElectrons/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/TwoElectrons/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/TwoElectrons/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); @@ -278,6 +326,23 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/TwoElectrons/hLeadingPt", ";Leading #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/TwoElectrons/hLeadingPhi", ";Leading #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/TwoElectrons/hLeadingRapidity", ";Leading #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/TwoElectrons/hLeadingPvsOtherP", ";Leading #it{p} (GeV/c); Other #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); + histos.add("EventTwoTracks/TwoElectrons/hLeadingPwideVsOtherPwide", ";Leading #it{p} (GeV/c); Other #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); + histos.add("EventTwoTracks/TwoElectrons/hLeadingPtVsOtherPt", ";Leading #it{p_{T} (GeV/c); Other #it{p_{T} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); + histos.add("EventTwoTracks/TwoElectrons/hLeadingPhiVsOtherPhi", ";Leading #phi (rad); Other #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); + histos.add("EventTwoTracks/TwoElectrons/hLeadingRapVsOtherRap", ";Leading #it{y} (-); Other #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsLP", ";Leading #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsOP", ";Other #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsP", ";Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsLP", ";Leading #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsOP", ";Other #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsLP", ";Leading #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsOP", ";Other #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsLP", ";Leading #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsOP", ";Other #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); histos.add("EventTwoTracks/TwoMuons/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventTwoTracks/TwoMuons/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -288,6 +353,7 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/TwoMuons/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/TwoMuons/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/TwoMuons/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/TwoMuons/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/TwoMuons/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/TwoMuons/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/TwoMuons/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); @@ -297,6 +363,7 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/TwoMuons/hDaughtersPtvsModPhiPtCut", ";Daughter #it{p_{T}} (GeV/c);Daughter fmod(#phi,#pi/9)", HistType::kTH2D, {axisPt, axisModPhi}); histos.add("EventTwoTracks/TwoMuons/hDaughtersPtvsModPhiPtCutTOF", ";Daughter #it{p_{T}} (GeV/c);Daughter fmod(#phi,#pi/9)", HistType::kTH2D, {axisPt, axisModPhi}); histos.add("EventTwoTracks/TwoMuons/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/TwoMuons/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventTwoTracks/TwoPions/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventTwoTracks/TwoPions/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -311,11 +378,13 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/TwoPions/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/TwoPions/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); histos.add("EventTwoTracks/TwoPions/hDaughtersPhi", ";Daughter 1 #phi (rad);Daughter 2 #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); + histos.add("EventTwoTracks/TwoPions/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/TwoPions/hDaughtersPtvsModPhi", ";Daughter #it{p_{T}} (GeV/c);Daughter fmod(#phi,#pi/9)", HistType::kTH2D, {axisPt, axisModPhi}); histos.add("EventTwoTracks/TwoPions/hDaughtersPtvsModPhiTOF", ";Daughter #it{p_{T}} (GeV/c);Daughter fmod(#phi,#pi/9)", HistType::kTH2D, {axisPt, axisModPhi}); histos.add("EventTwoTracks/TwoPions/hDaughtersPtvsModPhiPtCut", ";Daughter #it{p_{T}} (GeV/c);Daughter fmod(#phi,#pi/9)", HistType::kTH2D, {axisPt, axisModPhi}); histos.add("EventTwoTracks/TwoPions/hDaughtersPtvsModPhiPtCutTOF", ";Daughter #it{p_{T}} (GeV/c);Daughter fmod(#phi,#pi/9)", HistType::kTH2D, {axisPt, axisModPhi}); histos.add("EventTwoTracks/TwoPions/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/TwoPions/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventTwoTracks/ElectronMuon/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventTwoTracks/ElectronMuon/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -325,11 +394,13 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/ElectronMuon/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/ElectronMuon/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/ElectronMuon/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/ElectronMuon/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/ElectronMuon/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/ElectronMuon/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/ElectronMuon/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); histos.add("EventTwoTracks/ElectronMuon/hDaughtersPhi", ";Daughter 1 #phi (rad);Daughter 2 #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); histos.add("EventTwoTracks/ElectronMuon/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/ElectronMuon/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventTwoTracks/ElectronPion/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventTwoTracks/ElectronPion/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -339,11 +410,13 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/ElectronPion/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/ElectronPion/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/ElectronPion/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/ElectronPion/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/ElectronPion/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/ElectronPion/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/ElectronPion/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); histos.add("EventTwoTracks/ElectronPion/hDaughtersPhi", ";Daughter 1 #phi (rad);Daughter 2 #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); histos.add("EventTwoTracks/ElectronPion/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/ElectronPion/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventTwoTracks/MuonPion/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventTwoTracks/MuonPion/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -354,11 +427,13 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/MuonPion/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/MuonPion/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/MuonPion/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/MuonPion/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/MuonPion/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/MuonPion/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/MuonPion/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); histos.add("EventTwoTracks/MuonPion/hDaughtersPhi", ";Daughter 1 #phi (rad);Daughter 2 #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); histos.add("EventTwoTracks/MuonPion/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/MuonPion/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventTwoTracks/ElectronMuPi/hNeventsPtCuts", ";Selection (-);Number of events (-)", HistType::kTH1D, {{20, -0.5, 19.5}}); histos.add("EventTwoTracks/ElectronMuPi/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); @@ -369,12 +444,32 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/ElectronMuPi/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/ElectronMuPi/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/ElectronMuPi/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/ElectronMuPi/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/ElectronMuPi/hElectronPtWide", ";Electron #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMomWide}); histos.add("EventTwoTracks/ElectronMuPi/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/ElectronMuPi/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/ElectronMuPi/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); histos.add("EventTwoTracks/ElectronMuPi/hDaughtersPhi", ";Daughter 1 #phi (rad);Daughter 2 #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); histos.add("EventTwoTracks/ElectronMuPi/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/ElectronMuPi/hElectronPvsOtherP", ";Electron #it{p} (GeV/c); #mu/#pi #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); + histos.add("EventTwoTracks/ElectronMuPi/hElectronPwideVsOtherPwide", ";Electron #it{p} (GeV/c); #mu/#pi #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); + histos.add("EventTwoTracks/ElectronMuPi/hElectronPtVsOtherPt", ";Electron #it{p_{T} (GeV/c); #mu/#pi #it{p_{T} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); + histos.add("EventTwoTracks/ElectronMuPi/hElectronPhiVsOtherPhi", ";Electron #phi (rad); #mu/#pi #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); + histos.add("EventTwoTracks/ElectronMuPi/hElectronRapVsOtherRap", ";Electron #it{y} (-); #mu/#pi #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsEP", ";Electron #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsOP", ";#mu/#pi #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsP", ";Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsEP", ";Electron #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsOP", ";Other #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsEP", ";Electron #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsMP", ";Muon #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsPP", ";Pion #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsEP", ";Electron #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsMP", ";Muon #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsPP", ";Pion #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); histos.add("EventTwoTracks/ElectronOther/hNeventsPtCuts", ";Selection (-);Number of events (-)", HistType::kTH1D, {{20, -0.5, 19.5}}); histos.add("EventTwoTracks/ElectronOther/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); @@ -385,12 +480,32 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/ElectronOther/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/ElectronOther/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/ElectronOther/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/ElectronOther/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/ElectronOther/hElectronPtWide", ";Electron #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMomWide}); histos.add("EventTwoTracks/ElectronOther/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/ElectronOther/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/ElectronOther/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); histos.add("EventTwoTracks/ElectronOther/hDaughtersPhi", ";Daughter 1 #phi (rad);Daughter 2 #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); histos.add("EventTwoTracks/ElectronOther/hDaughtersRapidity", ";Daughter 1 #it{y} (-);Daughter 2 #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/ElectronOther/hElectronPvsOtherP", ";Electron #it{p} (GeV/c); Other #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); + histos.add("EventTwoTracks/ElectronOther/hElectronPwideVsOtherPwide", ";Electron #it{p} (GeV/c); Other #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); + histos.add("EventTwoTracks/ElectronOther/hElectronPtVsOtherPt", ";Electron #it{p_{T} (GeV/c); Other #it{p_{T} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); + histos.add("EventTwoTracks/ElectronOther/hElectronPhiVsOtherPhi", ";Electron #phi (rad); Other #phi (rad)", HistType::kTH2D, {axisPhi, axisPhi}); + histos.add("EventTwoTracks/ElectronOther/hElectronRapVsOtherRap", ";Electron #it{y} (-); Other #it{y} (-)", HistType::kTH2D, {axisRap, axisRap}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCsignalVsEP", ";Electron #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCsignalVsOP", ";#it{e}/#mu/#pi #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFsignalVsP", ";Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFsignalVsEP", ";Electron #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFsignalVsOP", ";Other #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsEP", ";Electron #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsMP", ";Muon #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsPP", ";Pion #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsEP", ";Electron #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsMP", ";Muon #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsPP", ";Pion #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); if (doPionStudy) { histos.add("EventTwoTracks/PionsSelection/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); @@ -413,6 +528,7 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/PionsSelection/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/PionsSelection/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/PionsSelection/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/PionsSelection/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/PionsSelection/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/PionsSelection/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/PionsSelection/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); @@ -550,8 +666,10 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/MuonsSelection/hMotherP", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMom}); histos.add("EventTwoTracks/MuonsSelection/hMotherPwide", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMomWide}); histos.add("EventTwoTracks/MuonsSelection/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); + histos.add("EventTwoTracks/MuonsSelection/hJpsiPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventTwoTracks/MuonsSelection/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventTwoTracks/MuonsSelection/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventTwoTracks/MuonsSelection/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); histos.add("EventTwoTracks/MuonsSelection/hDaughtersP", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMom, axisMom}); histos.add("EventTwoTracks/MuonsSelection/hDaughtersPwide", ";Daughter 1 #it{p} (GeV/c);Daughter 2 #it{p} (GeV/c)", HistType::kTH2D, {axisMomWide, axisMomWide}); histos.add("EventTwoTracks/MuonsSelection/hDaughtersPt", ";Daughter 1 #it{p_{T}} (GeV/c);Daughter 2 #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisPt, axisPt}); @@ -579,10 +697,21 @@ struct UpcTauCentralBarrelRL { histos.add("EventTwoTracks/MuonsSelection/hDaughtersPtvsDcaXYPtCut", ";Daughter #it{p_{T}} (GeV/c);Daughter DCA_{XY} (cm)", HistType::kTH2D, {axisPt, axisDCA}); histos.add("EventTwoTracks/MuonsSelection/hDaughtersPvsITSclusterSize", ";Average ITS cluster size;Daughter #it{p} (GeV/c)", HistType::kTH2D, {axisAvgITSclsSizes, axisMomSigned}); histos.add("EventTwoTracks/MuonsSelection/hDaughtersPvsITSclusterSizeXcos", ";Average ITS cluster size x cos(#lambda);Daughter #it{p} (GeV/c)", HistType::kTH2D, {axisAvgITSclsSizes, axisMomSigned}); - histos.add("EventTwoTracks/MuonsSelection/Run2Cuts/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); histos.add("EventTwoTracks/MuonsSelection/Run2Cuts/hInvariantMassWidePtFitPlot", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); histos.add("EventTwoTracks/MuonsSelection/Run2Cuts/hInvariantMassWideCS", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsLP", ";Leading #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsOP", ";Other #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsP", ";Track #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsLP", ";Leading #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsOP", ";Other #it{p} (GeV/c);TOF signal (arb. units)", HistType::kTH2D, {axisMom, axisTOFsignal}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsLP", ";Leading #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsOP", ";Other #it{p} (GeV/c);n#sigma_{TPC} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsP", ";Track #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsLP", ";Leading #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); + histos.add("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsOP", ";Other #it{p} (GeV/c);n#sigma_{TOF} (arb. units)", HistType::kTH2D, {axisMom, axisNsigma}); } } @@ -595,6 +724,8 @@ struct UpcTauCentralBarrelRL { histos.add("EventFourTracks/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventFourTracks/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventFourTracks/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + histos.add("EventFourTracks/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventFourTracks/WithElectron/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventFourTracks/WithElectron/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -603,6 +734,8 @@ struct UpcTauCentralBarrelRL { histos.add("EventFourTracks/WithElectron/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventFourTracks/WithElectron/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventFourTracks/WithElectron/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/WithElectron/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + histos.add("EventFourTracks/WithElectron/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventFourTracks/WithMuon/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventFourTracks/WithMuon/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -611,6 +744,8 @@ struct UpcTauCentralBarrelRL { histos.add("EventFourTracks/WithMuon/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventFourTracks/WithMuon/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventFourTracks/WithMuon/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/WithMuon/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + histos.add("EventFourTracks/WithMuon/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventFourTracks/WithPion/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventFourTracks/WithPion/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -619,6 +754,36 @@ struct UpcTauCentralBarrelRL { histos.add("EventFourTracks/WithPion/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventFourTracks/WithPion/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventFourTracks/WithPion/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/WithPion/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + histos.add("EventFourTracks/WithPion/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); + if (doFourTrackPsi2S) { + histos.add("EventFourTracks/MuonsPions/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); + histos.add("EventFourTracks/MuonsPions/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); + histos.add("EventFourTracks/MuonsPions/hMotherP", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMom}); + histos.add("EventFourTracks/MuonsPions/hMotherPwide", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMomWide}); + histos.add("EventFourTracks/MuonsPions/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); + histos.add("EventFourTracks/MuonsPions/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); + histos.add("EventFourTracks/MuonsPions/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/MuonsPions/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hMotherP", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMom}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hMotherPwide", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMomWide}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/Psi2StoMuMuPiPi/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + + histos.add("EventFourTracks/Psi2StoElElPiPi/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hMotherP", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMom}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hMotherPwide", ";Mother #it{p} (GeV/c);Number of events (-)", HistType::kTH1D, {axisMomWide}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventFourTracks/Psi2StoElElPiPi/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + } } if (doSixTracks) { @@ -630,6 +795,8 @@ struct UpcTauCentralBarrelRL { histos.add("EventSixTracks/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventSixTracks/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventSixTracks/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventSixTracks//hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + histos.add("EventSixTracks/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); histos.add("EventSixTracks/SixPions/hInvariantMass", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMass}); histos.add("EventSixTracks/SixPions/hInvariantMassWide", ";Invariant mass (GeV/c^{2});Number of events (-)", HistType::kTH1D, {axisInvMassWide}); @@ -638,18 +805,19 @@ struct UpcTauCentralBarrelRL { histos.add("EventSixTracks/SixPions/hMotherPt", ";Mother #it{p_{T}} (GeV/c);Number of events (-)", HistType::kTH1D, {axisPt}); histos.add("EventSixTracks/SixPions/hMotherPhi", ";Mother #phi (rad);Number of events (-)", HistType::kTH1D, {axisPhi}); histos.add("EventSixTracks/SixPions/hMotherRapidity", ";Mother #it{y} (-);Number of events (-)", HistType::kTH1D, {axisRap}); + histos.add("EventSixTracks/SixPions/hMotherMassVsPt", ";Invariant mass (GeV/c^{2});Mother #it{p_{T}} (GeV/c)", HistType::kTH2D, {axisInvMassWide, axisPt}); + histos.add("EventSixTracks/SixPions/PID/hTPCsignalVsP", ";Track #it{p} (GeV/c);TPC d#it{E}/d#it{x} (arb. units)", HistType::kTH2D, {axisMom, axisTPCdEdx}); } } // end init // run (always called before process :( ) - void run(ProcessingContext& /*context*/) + void run(ProcessingContext&) { if (verboseInfo) printLargeMessage("RUN METHOD"); - if (verboseDebug) - LOGF(info, "countCollisions = %d", countCollisions); + printDebugMessage(Form("countCollisions = %d", countCollisions)); } // end run @@ -824,6 +992,47 @@ struct UpcTauCentralBarrelRL { return true; } + template + int whatPsi2Schannel(T const& trkDaug1, T const& trkDaug2, T const& trkDaug3, T const& trkDaug4, std::vector& vecPIDidx) + { + TLorentzVector jpsi, daug[4]; + daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); + daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); + daug[2].SetPxPyPzE(trkDaug3.px(), trkDaug3.py(), trkDaug3.pz(), energy(pdg->Mass(trackPDG(trkDaug3)), trkDaug3.px(), trkDaug3.py(), trkDaug3.pz())); + daug[3].SetPxPyPzE(trkDaug4.px(), trkDaug4.py(), trkDaug4.pz(), energy(pdg->Mass(trackPDG(trkDaug4)), trkDaug4.px(), trkDaug4.py(), trkDaug4.pz())); + // Find index of the two largest values + std::vector> vecPts; + for (int i = 0; i < 4; i++) { + vecPts.push_back(std::make_pair(static_cast(daug[i].Pt()), i)); + } + sort(vecPts.begin(), vecPts.end()); + int idx1L = vecPts[vecPts.size() - 1].second; + int idx2L = vecPts[vecPts.size() - 2].second; + int idx3L = vecPts[vecPts.size() - 3].second; + int idx4L = vecPts[vecPts.size() - 4].second; + // Create the jpsi + jpsi = daug[idx1L] + daug[idx2L]; + // The two smallest-pT tracks should be pions + if ((vecPIDidx[idx3L] == P_MUON || vecPIDidx[idx3L] == P_PION) && (vecPIDidx[idx4L] == P_MUON || vecPIDidx[idx4L] == P_PION)) { + // Branch into Jpsi to mumu and Jpsi to elel + if ((vecPIDidx[idx1L] == P_MUON || vecPIDidx[idx1L] == P_PION) && (vecPIDidx[idx2L] == P_MUON || vecPIDidx[idx2L] == P_PION)) { + // Is jpsi mass? + if (jpsi.M() < 2.9 || jpsi.M() > 3.3) + return 0; // Not Psi2S + return 1; + } else if (vecPIDidx[idx1L] == P_ELECTRON && vecPIDidx[idx2L] == P_ELECTRON) { + // Is jpsi mass? + if (jpsi.M() < 2.75 || jpsi.M() > 3.3) + return 0; // Not Psi2S + return 2; + } else { + return 0; // Not Psi2S + } + } else { + return 0; // Not Psi2S + } + } + template void fillHistograms(C reconstructedCollision, Ts reconstructedBarrelTracks) { @@ -834,7 +1043,8 @@ struct UpcTauCentralBarrelRL { printLargeMessage("START LOOPING OVER RECONSTRUCTED COLLISIONS"); } - histos.get(HIST("Events/hCountCollisions"))->Fill(4); // 1, 2 and 3 are reserved for single-gap + histos.get(HIST("Events/hCountCollisions"))->Fill(1); + histos.get(HIST("Events/hNreconstructedTracks"))->Fill(reconstructedBarrelTracks.size()); // Loop over tracks without selections for (auto& track : reconstructedBarrelTracks) { @@ -849,7 +1059,6 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("Tracks/raw/hTrackPtvsModPhi"))->Fill(track.pt(), std::fmod(phi(trkPx, trkPy), o2::constants::math::PI / 9)); if (track.hasTOF()) histos.get(HIST("Tracks/raw/hTrackPtvsModPhiTOF"))->Fill(track.pt(), std::fmod(phi(trkPx, trkPy), o2::constants::math::PI / 9)); - // histosPID.get(HIST("Tracks/raw/PID/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); histos.get(HIST("Tracks/raw/hTrackDcaXY"))->Fill(track.dcaXY()); histos.get(HIST("Tracks/raw/hTrackPtvsDcaXY"))->Fill(track.pt(), track.dcaXY()); histos.get(HIST("Tracks/raw/hTrackDcaZ"))->Fill(track.dcaZ()); @@ -860,27 +1069,6 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("Tracks/raw/TPC/tpcCrossedRows"))->Fill(track.tpcNClsCrossedRows()); histos.get(HIST("Tracks/raw/TPC/tpcCrossedRowsOverFindableCls"))->Fill((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable()))); histos.get(HIST("Tracks/raw/TPC/tpcChi2NCl"))->Fill(track.tpcChi2NCl()); - histosPID.get(HIST("Tracks/raw/PID/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); - if (track.hasTPC()) { - if (track.sign() == 1) { - // histosPID.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); - } else if (track.sign() == -1) { - // histosPID.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); - } else { - printMediumMessage("Track has no charge"); - } - } } // Loop over tracks without selections int countPVGT = 0; @@ -897,6 +1085,7 @@ struct UpcTauCentralBarrelRL { int countTPCxRws70 = 0; int countTPCxRws100 = 0; std::vector vecPVidx; + std::vector vecPIDidx; // Loop over tracks with selections for (auto& track : reconstructedBarrelTracks) { if (track.isPVContributor() != 1) @@ -917,7 +1106,6 @@ struct UpcTauCentralBarrelRL { if (track.hasTOF()) histos.get(HIST("Tracks/GoodTrack/hTrackPtvsModPhiTOF"))->Fill(track.pt(), std::fmod(phi(trkPx, trkPy), o2::constants::math::PI / 9)); histos.get(HIST("Tracks/GoodTrack/hTrackEta"))->Fill(eta(trkPx, trkPy, trkPz)); - // histosPID.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); histos.get(HIST("Tracks/GoodTrack/hTrackDcaXY"))->Fill(track.dcaXY()); histos.get(HIST("Tracks/GoodTrack/hTrackPtvsDcaXY"))->Fill(track.pt(), track.dcaXY()); histos.get(HIST("Tracks/GoodTrack/hTrackDcaZ"))->Fill(track.dcaZ()); @@ -928,27 +1116,6 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("Tracks/GoodTrack/TPC/tpcCrossedRows"))->Fill(track.tpcNClsCrossedRows()); histos.get(HIST("Tracks/GoodTrack/TPC/tpcCrossedRowsOverFindableCls"))->Fill((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable()))); histos.get(HIST("Tracks/GoodTrack/TPC/tpcChi2NCl"))->Fill(track.tpcChi2NCl()); - histosPID.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); - if (track.hasTPC()) { - if (track.sign() == 1) { - // histosPID.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); - } else if (track.sign() == -1) { - // histosPID.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); - } else { - printMediumMessage("Track has no charge"); - } - } if (track.hasTOF()) countTOFtracks++; if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) > 70) @@ -959,39 +1126,20 @@ struct UpcTauCentralBarrelRL { countTPCxRws70++; if (track.tpcNClsCrossedRows() > 100) countTPCxRws100++; - int hypothesisID = testPIDhypothesis(track); + int hypothesisID = testPIDhypothesis(track, cutMyNsigmaTPCPIDselector, cutMyNsigmaTOFPIDselector, usePIDwithTOF, usePIDwithTOFsigmaAfterTPC); + vecPIDidx.push_back(hypothesisID); if (hypothesisID == P_ELECTRON || hypothesisID == P_MUON || hypothesisID == P_PION) { countPVGTselected++; vecPVidx.push_back(track.index()); if (hypothesisID == P_ELECTRON) { countPVGTelectrons++; - // histosPID.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); } else if (hypothesisID == P_MUON) { countPVGTmuons++; - // histosPID.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); } else { countPVGTpions++; - // histosPID.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); } } else { countPVGTothers++; - // histosPID.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); - histosPID.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); } if (abs(track.tpcNSigmaPi()) < cutMyTPCnSigmaPi) countPVGTpionsSelection++; @@ -1024,37 +1172,6 @@ struct UpcTauCentralBarrelRL { auto sign = trkDaug1.sign() * trkDaug2.sign(); bool passAvgITSclsSizesCut = passITSAvgClsSizesLowMomCut(trkDaug1, cutAvgITSclusterSize, cutPtAvgITSclusterSize) && passITSAvgClsSizesLowMomCut(trkDaug2, cutAvgITSclusterSize, cutPtAvgITSclusterSize); - if (trkDaug1.hasTPC()) { - histosPID.get(HIST("EventTwoTracks/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTelectrons == 2) - histosPID.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTmuons == 2) - histosPID.get(HIST("EventTwoTracks/TwoMuons/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTpions == 2) - histosPID.get(HIST("EventTwoTracks/TwoPions/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTmuons == 1) - histosPID.get(HIST("EventTwoTracks/ElectronMuon/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTpions == 1) - histosPID.get(HIST("EventTwoTracks/ElectronPion/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTpions == 1 && countPVGTmuons == 1) - histosPID.get(HIST("EventTwoTracks/MuonPion/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - } - if (trkDaug2.hasTPC()) { - histosPID.get(HIST("EventTwoTracks/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTelectrons == 2) - histosPID.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTmuons == 2) - histosPID.get(HIST("EventTwoTracks/TwoMuons/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTpions == 2) - histosPID.get(HIST("EventTwoTracks/TwoPions/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTmuons == 1) - histosPID.get(HIST("EventTwoTracks/ElectronMuon/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTpions == 1) - histosPID.get(HIST("EventTwoTracks/ElectronPion/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTpions == 1 && countPVGTmuons == 1) - histosPID.get(HIST("EventTwoTracks/MuonPion/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - } - histos.get(HIST("EventTwoTracks/hInvariantMass"))->Fill(mother.M()); histos.get(HIST("EventTwoTracks/hInvariantMassWide"))->Fill(mother.M()); histos.get(HIST("EventTwoTracks/hInvariantMassWideAllPionMass"))->Fill(motherOfPions.M()); @@ -1069,6 +1186,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); histos.get(HIST("EventTwoTracks/hDaughtersPhi"))->Fill(daug[0].Phi(), daug[1].Phi()); histos.get(HIST("EventTwoTracks/hDaughtersRapidity"))->Fill(daug[0].Rapidity(), daug[1].Rapidity()); + histos.get(HIST("EventTwoTracks/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); if (motherOfPions.Pt() < 0.2) { histos.get(HIST("EventTwoTracks/hInvariantMassWideAllPionMassPtCut"))->Fill(motherOfPions.M()); if (passAvgITSclsSizesCut) { @@ -1097,6 +1215,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/TwoElectrons/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/TwoElectrons/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/TwoElectrons/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/TwoElectrons/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/TwoElectrons/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/TwoElectrons/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/TwoElectrons/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); @@ -1109,6 +1228,11 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingPt"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Pt() : daug[1].Pt())); histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingPhi"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Phi() : daug[1].Phi())); histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingRapidity"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Rapidity() : daug[1].Rapidity())); + histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingPvsOtherP"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].P() : daug[1].P()), ((daug[0].P() > daug[1].P()) ? daug[1].P() : daug[0].P())); + histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingPwideVsOtherPwide"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].P() : daug[1].P()), ((daug[0].P() > daug[1].P()) ? daug[1].P() : daug[0].P())); + histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingPtVsOtherPt"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Pt() : daug[1].Pt()), ((daug[0].P() > daug[1].P()) ? daug[1].Pt() : daug[0].Pt())); + histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingPhiVsOtherPhi"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Phi() : daug[1].Phi()), ((daug[0].P() > daug[1].P()) ? daug[1].Phi() : daug[0].Phi())); + histos.get(HIST("EventTwoTracks/TwoElectrons/hLeadingRapVsOtherRap"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Rapidity() : daug[1].Rapidity()), ((daug[0].P() > daug[1].P()) ? daug[1].Rapidity() : daug[0].Rapidity())); if (mother.Pt() < 0.2) { histos.get(HIST("EventTwoTracks/TwoElectrons/hInvariantMassWidePtCut"))->Fill(mother.M()); histos.get(HIST("EventTwoTracks/TwoElectrons/hDaughtersPtvsModPhiPtCut"))->Fill(daug[0].P(), getPhiModN(daug[0].Phi(), trkDaug1.sign(), 1)); @@ -1133,6 +1257,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/TwoMuons/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/TwoMuons/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/TwoMuons/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/TwoMuons/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/TwoMuons/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/TwoMuons/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/TwoMuons/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); @@ -1164,6 +1289,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/ElectronMuon/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronMuon/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/ElectronMuon/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/ElectronMuon/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronMuon/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronMuon/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronMuon/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); @@ -1180,6 +1306,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/TwoPions/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/TwoPions/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/TwoPions/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/TwoPions/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/TwoPions/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/TwoPions/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/TwoPions/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); @@ -1211,6 +1338,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/ElectronPion/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronPion/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/ElectronPion/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/ElectronPion/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronPion/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronPion/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronPion/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); @@ -1227,6 +1355,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/MuonPion/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/MuonPion/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/MuonPion/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/MuonPion/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/MuonPion/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/MuonPion/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/MuonPion/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); @@ -1246,12 +1375,18 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/ElectronMuPi/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hElectronPtWide"))->Fill(electronPt); histos.get(HIST("EventTwoTracks/ElectronMuPi/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hDaughtersPhi"))->Fill(daug[0].Phi(), daug[1].Phi()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hDaughtersRapidity"))->Fill(daug[0].Rapidity(), daug[1].Rapidity()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/hElectronPvsOtherP"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].P() : daug[1].P(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].P() : daug[0].P()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/hElectronPwideVsOtherPwide"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].P() : daug[1].P(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].P() : daug[0].P()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/hElectronPtVsOtherPt"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Pt() : daug[1].Pt(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].Pt() : daug[0].Pt()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/hElectronPhiVsOtherPhi"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Phi() : daug[1].Phi(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].Phi() : daug[0].Phi()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/hElectronRapVsOtherRap"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Rapidity() : daug[1].Rapidity(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].Rapidity() : daug[0].Rapidity()); histos.get(HIST("EventTwoTracks/ElectronMuPi/hNeventsPtCuts"))->Fill(0); if (mother.Pt() < 9.) histos.get(HIST("EventTwoTracks/ElectronMuPi/hNeventsPtCuts"))->Fill(1); @@ -1290,12 +1425,26 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/ElectronOther/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronOther/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventTwoTracks/ElectronOther/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventTwoTracks/ElectronOther/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPtWide"))->Fill(electronPt); histos.get(HIST("EventTwoTracks/ElectronOther/hDaughtersP"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronOther/hDaughtersPwide"))->Fill(daug[0].P(), daug[1].P()); histos.get(HIST("EventTwoTracks/ElectronOther/hDaughtersPt"))->Fill(daug[0].Pt(), daug[1].Pt()); histos.get(HIST("EventTwoTracks/ElectronOther/hDaughtersPhi"))->Fill(daug[0].Phi(), daug[1].Phi()); histos.get(HIST("EventTwoTracks/ElectronOther/hDaughtersRapidity"))->Fill(daug[0].Rapidity(), daug[1].Rapidity()); + if (countPVGTelectrons == 2) { + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPvsOtherP"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].P() : daug[1].P()), ((daug[0].P() > daug[1].P()) ? daug[1].P() : daug[0].P())); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPwideVsOtherPwide"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].P() : daug[1].P()), ((daug[0].P() > daug[1].P()) ? daug[1].P() : daug[0].P())); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPtVsOtherPt"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Pt() : daug[1].Pt()), ((daug[0].P() > daug[1].P()) ? daug[1].Pt() : daug[0].Pt())); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPhiVsOtherPhi"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Phi() : daug[1].Phi()), ((daug[0].P() > daug[1].P()) ? daug[1].Phi() : daug[0].Phi())); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronRapVsOtherRap"))->Fill(((daug[0].P() > daug[1].P()) ? daug[0].Rapidity() : daug[1].Rapidity()), ((daug[0].P() > daug[1].P()) ? daug[1].Rapidity() : daug[0].Rapidity())); + } else { + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPvsOtherP"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].P() : daug[1].P(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].P() : daug[0].P()); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPwideVsOtherPwide"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].P() : daug[1].P(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].P() : daug[0].P()); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPtVsOtherPt"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Pt() : daug[1].Pt(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].Pt() : daug[0].Pt()); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronPhiVsOtherPhi"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Phi() : daug[1].Phi(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].Phi() : daug[0].Phi()); + histos.get(HIST("EventTwoTracks/ElectronOther/hElectronRapVsOtherRap"))->Fill((enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Rapidity() : daug[1].Rapidity(), (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[1].Rapidity() : daug[0].Rapidity()); + } histos.get(HIST("EventTwoTracks/ElectronOther/hNeventsPtCuts"))->Fill(0); if (mother.Pt() < 9.) histos.get(HIST("EventTwoTracks/ElectronOther/hNeventsPtCuts"))->Fill(1); @@ -1331,6 +1480,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/PionsSelection/hMotherPt"))->Fill(motherOfPions.Pt()); histos.get(HIST("EventTwoTracks/PionsSelection/hMotherPhi"))->Fill(motherOfPions.Phi()); histos.get(HIST("EventTwoTracks/PionsSelection/hMotherRapidity"))->Fill(motherOfPions.Rapidity()); + histos.get(HIST("EventTwoTracks/PionsSelection/hMotherMassVsPt"))->Fill(motherOfPions.M(), motherOfPions.Pt()); histos.get(HIST("EventTwoTracks/PionsSelection/hDaughtersP"))->Fill(pion[0].P(), pion[1].P()); histos.get(HIST("EventTwoTracks/PionsSelection/hDaughtersPwide"))->Fill(pion[0].P(), pion[1].P()); histos.get(HIST("EventTwoTracks/PionsSelection/hDaughtersPt"))->Fill(pion[0].Pt(), pion[1].Pt()); @@ -1421,6 +1571,9 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventTwoTracks/MuonsSelection/hDaughtersPtvsDcaXY"))->Fill(trkDaug2.pt(), trkDaug2.dcaXY()); histos.get(HIST("EventTwoTracks/MuonsSelection/hDaughtersPtvsModPhi"))->Fill(muon[0].Pt(), phiModNtrk1); histos.get(HIST("EventTwoTracks/MuonsSelection/hDaughtersPtvsModPhi"))->Fill(muon[1].Pt(), phiModNtrk2); + histos.get(HIST("EventTwoTracks/MuonsSelection/hMotherMassVsPt"))->Fill(motherOfMuons.M(), motherOfMuons.Pt()); + if (motherOfMuons.M() > 2.9 && motherOfMuons.M() < 3.2) + histos.get(HIST("EventTwoTracks/MuonsSelection/hJpsiPt"))->Fill(motherOfMuons.Pt()); if (doJpsiMuMuTests) { if (isNotCloseToTPCBorder(phiModNtrk1, muon[0].Pt(), cutPhiModN1)) histos.get(HIST("EventTwoTracks/MuonsSelection/hDaughtersPtvsModPhiTPCbordersCut1"))->Fill(muon[0].Pt(), phiModNtrk1); @@ -1735,43 +1888,6 @@ struct UpcTauCentralBarrelRL { daug[3].SetPxPyPzE(trkDaug4.px(), trkDaug4.py(), trkDaug4.pz(), energy(pdg->Mass(trackPDG(trkDaug4)), trkDaug4.px(), trkDaug4.py(), trkDaug4.pz())); mother = daug[0] + daug[1] + daug[2] + daug[3]; - if (trkDaug1.hasTPC()) { - histosPID.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTpions == 4) - histosPID.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTpions == 3) - histosPID.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTpions == 3 && countPVGTmuons == 1) - histosPID.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - } - if (trkDaug2.hasTPC()) { - histosPID.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTpions == 4) - histosPID.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTpions == 3) - histosPID.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTpions == 3 && countPVGTmuons == 1) - histosPID.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - } - if (trkDaug3.hasTPC()) { - histosPID.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); - if (countPVGTpions == 4) - histosPID.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTpions == 3) - histosPID.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); - if (countPVGTpions == 3 && countPVGTmuons == 1) - histosPID.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); - } - if (trkDaug4.hasTPC()) { - histosPID.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); - if (countPVGTpions == 4) - histosPID.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); - if (countPVGTelectrons == 1 && countPVGTpions == 3) - histosPID.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); - if (countPVGTpions == 3 && countPVGTmuons == 1) - histosPID.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); - } - histos.get(HIST("EventFourTracks/hInvariantMass"))->Fill(mother.M()); histos.get(HIST("EventFourTracks/hInvariantMassWide"))->Fill(mother.M()); histos.get(HIST("EventFourTracks/hMotherP"))->Fill(mother.P()); @@ -1779,6 +1895,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventFourTracks/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventFourTracks/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventFourTracks/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); // ee, mm, em, pp, ep, mp, pppp, eppp, mppp, pppppp if (countPVGTpions == 4) { @@ -1790,6 +1907,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventFourTracks/WithPion/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventFourTracks/WithPion/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventFourTracks/WithPion/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/WithPion/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); } if (countPVGTelectrons == 1 && countPVGTpions == 3) { histos.get(HIST("Events/hChannelsRatio"))->Fill(7); @@ -1800,6 +1918,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventFourTracks/WithElectron/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventFourTracks/WithElectron/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventFourTracks/WithElectron/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/WithElectron/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); } if (countPVGTpions == 3 && countPVGTmuons == 1) { histos.get(HIST("Events/hChannelsRatio"))->Fill(8); @@ -1810,6 +1929,45 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventFourTracks/WithMuon/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventFourTracks/WithMuon/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventFourTracks/WithMuon/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/WithMuon/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); + } + // Hunting down psi2s: broad acceptance + if (doFourTrackPsi2S) { + if (countPVGTpions == 4 || + (countPVGTpions == 3 && countPVGTmuons == 1) || + (countPVGTpions == 2 && countPVGTmuons == 2) || + (countPVGTpions == 1 && countPVGTmuons == 3) || + countPVGTmuons == 4) { + histos.get(HIST("EventFourTracks/MuonsPions/hInvariantMass"))->Fill(mother.M()); + histos.get(HIST("EventFourTracks/MuonsPions/hInvariantMassWide"))->Fill(mother.M()); + histos.get(HIST("EventFourTracks/MuonsPions/hMotherP"))->Fill(mother.P()); + histos.get(HIST("EventFourTracks/MuonsPions/hMotherPwide"))->Fill(mother.P()); + histos.get(HIST("EventFourTracks/MuonsPions/hMotherPt"))->Fill(mother.Pt()); + histos.get(HIST("EventFourTracks/MuonsPions/hMotherPhi"))->Fill(mother.Phi()); + histos.get(HIST("EventFourTracks/MuonsPions/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/MuonsPions/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); + } + // Hunting down psi2s: ideal case + if (whatPsi2Schannel(trkDaug1, trkDaug2, trkDaug3, trkDaug4, vecPIDidx) == 1) { + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hInvariantMass"))->Fill(mother.M()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hInvariantMassWide"))->Fill(mother.M()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hMotherP"))->Fill(mother.P()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hMotherPwide"))->Fill(mother.P()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hMotherPt"))->Fill(mother.Pt()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hMotherPhi"))->Fill(mother.Phi()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/Psi2StoMuMuPiPi/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); + } + if (whatPsi2Schannel(trkDaug1, trkDaug2, trkDaug3, trkDaug4, vecPIDidx) == 2) { + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hInvariantMass"))->Fill(mother.M()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hInvariantMassWide"))->Fill(mother.M()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hMotherP"))->Fill(mother.P()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hMotherPwide"))->Fill(mother.P()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hMotherPt"))->Fill(mother.Pt()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hMotherPhi"))->Fill(mother.Phi()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventFourTracks/Psi2StoElElPiPi/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); + } } } else if (countPVGTselected == 6 && doSixTracks) { TLorentzVector mother, daug[6]; @@ -1827,37 +1985,6 @@ struct UpcTauCentralBarrelRL { daug[5].SetPxPyPzE(trkDaug6.px(), trkDaug6.py(), trkDaug6.pz(), energy(pdg->Mass(trackPDG(trkDaug6)), trkDaug6.px(), trkDaug6.py(), trkDaug6.pz())); mother = daug[0] + daug[1] + daug[2] + daug[3] + daug[4] + daug[5]; - if (trkDaug1.hasTPC()) { - histosPID.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - if (countPVGTpions == 6) - histosPID.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); - } - if (trkDaug2.hasTPC()) { - histosPID.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - if (countPVGTpions == 6) - histosPID.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); - } - if (trkDaug3.hasTPC()) { - histosPID.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); - if (countPVGTpions == 6) - histosPID.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); - } - if (trkDaug4.hasTPC()) { - histosPID.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); - if (countPVGTpions == 6) - histosPID.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); - } - if (trkDaug5.hasTPC()) { - histosPID.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[4].P(), trkDaug5.tpcSignal()); - if (countPVGTpions == 6) - histosPID.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[4].P(), trkDaug5.tpcSignal()); - } - if (trkDaug6.hasTPC()) { - histosPID.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[5].P(), trkDaug6.tpcSignal()); - if (countPVGTpions == 6) - histosPID.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[5].P(), trkDaug6.tpcSignal()); - } - histos.get(HIST("EventSixTracks/hInvariantMass"))->Fill(mother.M()); histos.get(HIST("EventSixTracks/hInvariantMassWide"))->Fill(mother.M()); histos.get(HIST("EventSixTracks/hMotherP"))->Fill(mother.P()); @@ -1865,6 +1992,7 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventSixTracks/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventSixTracks/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventSixTracks/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventSixTracks/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); // ee, mm, em, pp, ep, mp, pppp, eppp, mppp, pppppp if (countPVGTpions == 6) { @@ -1876,21 +2004,536 @@ struct UpcTauCentralBarrelRL { histos.get(HIST("EventSixTracks/SixPions/hMotherPt"))->Fill(mother.Pt()); histos.get(HIST("EventSixTracks/SixPions/hMotherPhi"))->Fill(mother.Phi()); histos.get(HIST("EventSixTracks/SixPions/hMotherRapidity"))->Fill(mother.Rapidity()); + histos.get(HIST("EventSixTracks/SixPions/hMotherMassVsPt"))->Fill(mother.M(), mother.Pt()); } } else { - if (verboseDebug) { - printMediumMessage("Other particles"); - } + printDebugMessage("Other particles"); } } // end fillHistograms + template + void fillPIDhistograms(C /*reconstructedCollision*/, Ts reconstructedBarrelTracks) + { + + if (isFirstReconstructedCollisions) { + isFirstReconstructedCollisions = false; + if (verboseInfo) + printLargeMessage("START LOOPING OVER RECONSTRUCTED COLLISIONS"); + } + + // Loop over tracks without selections + for (auto& track : reconstructedBarrelTracks) { + float trkPx = track.px(); + float trkPy = track.py(); + float trkPz = track.pz(); + if (track.hasTPC()) { + // histos.get(HIST("Tracks/raw/PID/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) + histos.get(HIST("Tracks/raw/PID/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + if (track.sign() == 1) { + // histos.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/PosCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) + histos.get(HIST("Tracks/raw/PID/PosCharge/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + } else if (track.sign() == -1) { + // histos.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/raw/PID/NegCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) + histos.get(HIST("Tracks/raw/PID/NegCharge/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + } else { + printMediumMessage("Track has no charge"); + } + } + } // Loop over tracks without selections + + int countPVGTselected = 0; + int countPVGTelectrons = 0; + int countPVGTmuons = 0; + int countPVGTpions = 0; + int countPVGTmuonsSelection = 0; + std::vector vecPVidx; + // Loop over tracks with selections + for (auto& track : reconstructedBarrelTracks) { + if (track.isPVContributor() != 1) + continue; + if (cutMyGlobalTracksOnly) { + if (isGlobalTrackReinstatement(track) != 1) + continue; + } + float trkPx = track.px(); + float trkPy = track.py(); + float trkPz = track.pz(); + if (track.hasTPC()) { + // histos.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) + histos.get(HIST("Tracks/GoodTrack/PID/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + if (track.sign() == 1) { + // histos.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) + histos.get(HIST("Tracks/GoodTrack/PID/PosCharge/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + } else if (track.sign() == -1) { + // histos.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) + histos.get(HIST("Tracks/GoodTrack/PID/NegCharge/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + } else { + printMediumMessage("Track has no charge"); + } + } + int hypothesisID = testPIDhypothesis(track, cutMyNsigmaTPCPIDselector, cutMyNsigmaTOFPIDselector, usePIDwithTOF, usePIDwithTOFsigmaAfterTPC); + if (hypothesisID == P_ELECTRON || hypothesisID == P_MUON || hypothesisID == P_PION) { + countPVGTselected++; + vecPVidx.push_back(track.index()); + if (hypothesisID == P_ELECTRON) { + countPVGTelectrons++; + // histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCnSigmaVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcNSigmaEl()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsMu"))->Fill(track.tpcNSigmaEl(), track.tpcNSigmaMu()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsPi"))->Fill(track.tpcNSigmaEl(), track.tpcNSigmaPi()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsKa"))->Fill(track.tpcNSigmaEl(), track.tpcNSigmaKa()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTPCnSigmaElVsPr"))->Fill(track.tpcNSigmaEl(), track.tpcNSigmaPr()); + if (track.hasTOF()) { + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTOFnSigmaVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofNSigmaEl()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsMu"))->Fill(track.tofNSigmaEl(), track.tofNSigmaMu()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsPi"))->Fill(track.tofNSigmaEl(), track.tofNSigmaPi()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsKa"))->Fill(track.tofNSigmaEl(), track.tofNSigmaKa()); + histos.get(HIST("Tracks/GoodTrack/PID/Electron/hTOFnSigmaElVsPr"))->Fill(track.tofNSigmaEl(), track.tofNSigmaPr()); + } + } else if (hypothesisID == P_MUON) { + countPVGTmuons++; + // histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCnSigmaVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcNSigmaMu()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsEl"))->Fill(track.tpcNSigmaMu(), track.tpcNSigmaEl()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsPi"))->Fill(track.tpcNSigmaMu(), track.tpcNSigmaPi()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsKa"))->Fill(track.tpcNSigmaMu(), track.tpcNSigmaKa()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTPCnSigmaMuVsPr"))->Fill(track.tpcNSigmaMu(), track.tpcNSigmaPr()); + if (track.hasTOF()) { + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTOFnSigmaVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofNSigmaMu()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsEl"))->Fill(track.tofNSigmaMu(), track.tofNSigmaEl()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsPi"))->Fill(track.tofNSigmaMu(), track.tofNSigmaPi()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsKa"))->Fill(track.tofNSigmaMu(), track.tofNSigmaKa()); + histos.get(HIST("Tracks/GoodTrack/PID/Muon/hTOFnSigmaMuVsPr"))->Fill(track.tofNSigmaMu(), track.tofNSigmaPr()); + } + } else { + countPVGTpions++; + // histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCnSigmaVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcNSigmaPi()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsEl"))->Fill(track.tpcNSigmaPi(), track.tpcNSigmaEl()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsMu"))->Fill(track.tpcNSigmaPi(), track.tpcNSigmaMu()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsKa"))->Fill(track.tpcNSigmaPi(), track.tpcNSigmaKa()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTPCnSigmaPiVsPr"))->Fill(track.tpcNSigmaPi(), track.tpcNSigmaPr()); + if (track.hasTOF()) { + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTOFnSigmaVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofNSigmaPi()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsEl"))->Fill(track.tofNSigmaPi(), track.tofNSigmaEl()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsMu"))->Fill(track.tofNSigmaPi(), track.tofNSigmaMu()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsKa"))->Fill(track.tofNSigmaPi(), track.tofNSigmaKa()); + histos.get(HIST("Tracks/GoodTrack/PID/Pion/hTOFnSigmaPiVsPr"))->Fill(track.tofNSigmaPi(), track.tofNSigmaPr()); + } + } + } else { + // histos.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsZ"))->Fill(track.z(),track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsPt"))->Fill(track.pt(), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsEta"))->Fill(eta(trkPx, trkPy, trkPz), track.tpcSignal()); + histos.get(HIST("Tracks/GoodTrack/PID/Others/hTPCsignalVsPhi"))->Fill(phi(trkPx, trkPy), track.tpcSignal()); + if (track.hasTOF()) { + histos.get(HIST("Tracks/GoodTrack/PID/Others/hTOFsignalVsP"))->Fill(momentum(trkPx, trkPy, trkPz), track.tofSignal()); + } + } + if (abs(track.tpcNSigmaMu()) < cutMyTPCnSigmaMu) + countPVGTmuonsSelection++; + + } // Loop over tracks with selections + + if (countPVGTselected == 2 && doTwoTracks) { + TLorentzVector daug[2], pion[2], muon[2]; + const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVidx[0]); + const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVidx[1]); + daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); + daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); + pion[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(211), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); + pion[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(211), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); + muon[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(13), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); + muon[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(13), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); + + if (trkDaug1.hasTPC()) { + histos.get(HIST("EventTwoTracks/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/PID/hTOFsignalVsP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + } + if (countPVGTelectrons == 2) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + } + if (countPVGTmuonsSelection == 2 && doMuonStudy) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + } + if (countPVGTmuons == 2) + histos.get(HIST("EventTwoTracks/TwoMuons/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTpions == 2) + histos.get(HIST("EventTwoTracks/TwoPions/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTmuons == 1) + histos.get(HIST("EventTwoTracks/ElectronMuon/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTpions == 1) + histos.get(HIST("EventTwoTracks/ElectronPion/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTpions == 1 && countPVGTmuons == 1) + histos.get(HIST("EventTwoTracks/MuonPion/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1)) { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + } + if ((countPVGTelectrons == 2) || (countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1)) { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFsignalVsP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + } + } + if (trkDaug2.hasTPC()) { + histos.get(HIST("EventTwoTracks/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/PID/hTOFsignalVsP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + } + if (countPVGTelectrons == 2) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } + if (countPVGTmuonsSelection == 2 && doMuonStudy) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } + if (countPVGTmuons == 2) + histos.get(HIST("EventTwoTracks/TwoMuons/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTpions == 2) + histos.get(HIST("EventTwoTracks/TwoPions/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTmuons == 1) + histos.get(HIST("EventTwoTracks/ElectronMuon/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTpions == 1) + histos.get(HIST("EventTwoTracks/ElectronPion/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTpions == 1 && countPVGTmuons == 1) + histos.get(HIST("EventTwoTracks/MuonPion/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1)) { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } + if ((countPVGTelectrons == 2) || (countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1)) { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFsignalVsP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } + } + if (trkDaug1.hasTPC() && trkDaug2.hasTPC()) { + if (countPVGTelectrons == 2) { + if (daug[0].P() > daug[1].P()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsLP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsOP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsLP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsOP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsLP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsLP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsOP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsOP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } else { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsOP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCsignalVsLP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsOP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTPCnSigmaVsLP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsOP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsOP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFsignalVsLP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/TwoElectrons/PID/hTOFnSigmaVsLP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } + } + if (countPVGTmuonsSelection == 2 && doMuonStudy) { + if (daug[0].P() > daug[1].P()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsLP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsOP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsLP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsOP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsLP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsLP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsOP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsOP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } else { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsOP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCsignalVsLP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsOP"))->Fill(daug[0].P(), trkDaug1.tpcNSigmaEl()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTPCnSigmaVsLP"))->Fill(daug[1].P(), trkDaug2.tpcNSigmaEl()); + if (trkDaug1.hasTOF()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsOP"))->Fill(daug[0].P(), trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsOP"))->Fill(daug[0].P(), trkDaug1.tofNSigmaEl()); + } + if (trkDaug2.hasTOF()) { + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFsignalVsLP"))->Fill(daug[1].P(), trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/MuonsSelection/PID/hTOFnSigmaVsLP"))->Fill(daug[1].P(), trkDaug2.tofNSigmaEl()); + } + } + } + if ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1)) { + double electronPt = (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Pt() : daug[1].Pt(); + double electronPID = (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? trkDaug1.tpcSignal() : trkDaug2.tpcSignal(); + double electronNsigma = (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? trkDaug1.tpcNSigmaEl() : trkDaug2.tpcNSigmaEl(); + double otherPt = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? daug[0].Pt() : daug[1].Pt(); + double otherPID = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? trkDaug1.tpcSignal() : trkDaug2.tpcSignal(); + double otherNsigmaMu = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? trkDaug1.tpcNSigmaMu() : trkDaug2.tpcNSigmaMu(); + double otherNsigmaPi = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? trkDaug1.tpcNSigmaPi() : trkDaug2.tpcNSigmaPi(); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsEP"))->Fill(electronPt, electronPID); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCsignalVsOP"))->Fill(otherPt, otherPID); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsEP"))->Fill(electronPt, electronNsigma); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsMP"))->Fill(otherPt, otherNsigmaMu); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTPCnSigmaVsPP"))->Fill(otherPt, otherNsigmaPi); + if (trkDaug1.hasTOF()) { + if (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsEP"))->Fill(electronPt, trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsEP"))->Fill(electronPt, trkDaug1.tofNSigmaEl()); + } else { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsOP"))->Fill(otherPt, trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsMP"))->Fill(otherPt, trkDaug1.tofNSigmaMu()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsPP"))->Fill(otherPt, trkDaug1.tofNSigmaPi()); + } + } + if (trkDaug2.hasTOF()) { + if (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsEP"))->Fill(electronPt, trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsEP"))->Fill(electronPt, trkDaug2.tofNSigmaEl()); + } else { + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFsignalVsOP"))->Fill(otherPt, trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsMP"))->Fill(otherPt, trkDaug2.tofNSigmaMu()); + histos.get(HIST("EventTwoTracks/ElectronMuPi/PID/hTOFnSigmaVsPP"))->Fill(otherPt, trkDaug2.tofNSigmaPi()); + } + } + } + if ((countPVGTelectrons == 2) || (countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1)) { + double electronPt = (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? daug[0].Pt() : daug[1].Pt(); + double electronPID = (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? trkDaug1.tpcSignal() : trkDaug2.tpcSignal(); + double electronNsigma = (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) ? trkDaug1.tpcNSigmaEl() : trkDaug2.tpcNSigmaEl(); + double otherPt = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? daug[0].Pt() : daug[1].Pt(); + double otherPID = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? trkDaug1.tpcSignal() : trkDaug2.tpcSignal(); + double otherNsigmaMu = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? trkDaug1.tpcNSigmaMu() : trkDaug2.tpcNSigmaMu(); + double otherNsigmaPi = (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) ? trkDaug1.tpcNSigmaPi() : trkDaug2.tpcNSigmaPi(); + if (countPVGTelectrons == 2) { + electronPt = (daug[0].Pt() > daug[1].Pt()) ? daug[0].Pt() : daug[1].Pt(); + electronPID = (daug[0].Pt() > daug[1].Pt()) ? trkDaug1.tpcSignal() : trkDaug2.tpcSignal(); + electronNsigma = (daug[0].Pt() > daug[1].Pt()) ? trkDaug1.tpcNSigmaEl() : trkDaug2.tpcNSigmaEl(); + otherPt = (daug[0].Pt() > daug[1].Pt()) ? daug[1].Pt() : daug[0].Pt(); + otherPID = (daug[0].Pt() > daug[1].Pt()) ? trkDaug2.tpcSignal() : trkDaug1.tpcSignal(); + otherNsigmaMu = (daug[0].Pt() > daug[1].Pt()) ? trkDaug2.tpcNSigmaMu() : trkDaug1.tpcNSigmaMu(); + otherNsigmaPi = (daug[0].Pt() > daug[1].Pt()) ? trkDaug2.tpcNSigmaPi() : trkDaug1.tpcNSigmaPi(); + } + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCsignalVsEP"))->Fill(electronPt, electronPID); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCsignalVsOP"))->Fill(otherPt, otherPID); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsEP"))->Fill(electronPt, electronNsigma); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsMP"))->Fill(otherPt, otherNsigmaMu); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTPCnSigmaVsPP"))->Fill(otherPt, otherNsigmaPi); + if (trkDaug1.hasTOF()) { + if (enumMyParticle(trackPDG(trkDaug1)) == P_ELECTRON) { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFsignalVsEP"))->Fill(electronPt, trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsEP"))->Fill(electronPt, trkDaug1.tofNSigmaEl()); + } else { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFsignalVsOP"))->Fill(otherPt, trkDaug1.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsMP"))->Fill(otherPt, trkDaug1.tofNSigmaMu()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsPP"))->Fill(otherPt, trkDaug1.tofNSigmaPi()); + } + } + if (trkDaug2.hasTOF()) { + if (enumMyParticle(trackPDG(trkDaug2)) == P_ELECTRON) { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFsignalVsEP"))->Fill(electronPt, trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsEP"))->Fill(electronPt, trkDaug2.tofNSigmaEl()); + } else { + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFsignalVsOP"))->Fill(otherPt, trkDaug2.tofSignal()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsMP"))->Fill(otherPt, trkDaug2.tofNSigmaMu()); + histos.get(HIST("EventTwoTracks/ElectronOther/PID/hTOFnSigmaVsPP"))->Fill(otherPt, trkDaug2.tofNSigmaPi()); + } + } + } + } + } else if (countPVGTselected == 4 && doFourTracks) { + + TLorentzVector daug[4]; + const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVidx[0]); + const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVidx[1]); + const auto& trkDaug3 = reconstructedBarrelTracks.iteratorAt(vecPVidx[2]); + const auto& trkDaug4 = reconstructedBarrelTracks.iteratorAt(vecPVidx[3]); + daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); + daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); + daug[2].SetPxPyPzE(trkDaug3.px(), trkDaug3.py(), trkDaug3.pz(), energy(pdg->Mass(trackPDG(trkDaug3)), trkDaug3.px(), trkDaug3.py(), trkDaug3.pz())); + daug[3].SetPxPyPzE(trkDaug4.px(), trkDaug4.py(), trkDaug4.pz(), energy(pdg->Mass(trackPDG(trkDaug4)), trkDaug4.px(), trkDaug4.py(), trkDaug4.pz())); + + if (trkDaug1.hasTPC()) { + histos.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTpions == 4) + histos.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTpions == 3) + histos.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTpions == 3 && countPVGTmuons == 1) + histos.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + } + if (trkDaug2.hasTPC()) { + histos.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTpions == 4) + histos.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTpions == 3) + histos.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTpions == 3 && countPVGTmuons == 1) + histos.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + } + if (trkDaug3.hasTPC()) { + histos.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); + if (countPVGTpions == 4) + histos.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTpions == 3) + histos.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); + if (countPVGTpions == 3 && countPVGTmuons == 1) + histos.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); + } + if (trkDaug4.hasTPC()) { + histos.get(HIST("EventFourTracks/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); + if (countPVGTpions == 4) + histos.get(HIST("EventFourTracks/WithPion/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); + if (countPVGTelectrons == 1 && countPVGTpions == 3) + histos.get(HIST("EventFourTracks/WithElectron/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); + if (countPVGTpions == 3 && countPVGTmuons == 1) + histos.get(HIST("EventFourTracks/WithMuon/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); + } + } else if (countPVGTselected == 6 && doSixTracks) { + TLorentzVector daug[6]; + const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVidx[0]); + const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVidx[1]); + const auto& trkDaug3 = reconstructedBarrelTracks.iteratorAt(vecPVidx[2]); + const auto& trkDaug4 = reconstructedBarrelTracks.iteratorAt(vecPVidx[3]); + const auto& trkDaug5 = reconstructedBarrelTracks.iteratorAt(vecPVidx[4]); + const auto& trkDaug6 = reconstructedBarrelTracks.iteratorAt(vecPVidx[5]); + daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); + daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); + daug[2].SetPxPyPzE(trkDaug3.px(), trkDaug3.py(), trkDaug3.pz(), energy(pdg->Mass(trackPDG(trkDaug3)), trkDaug3.px(), trkDaug3.py(), trkDaug3.pz())); + daug[3].SetPxPyPzE(trkDaug4.px(), trkDaug4.py(), trkDaug4.pz(), energy(pdg->Mass(trackPDG(trkDaug4)), trkDaug4.px(), trkDaug4.py(), trkDaug4.pz())); + daug[4].SetPxPyPzE(trkDaug5.px(), trkDaug5.py(), trkDaug5.pz(), energy(pdg->Mass(trackPDG(trkDaug5)), trkDaug5.px(), trkDaug5.py(), trkDaug5.pz())); + daug[5].SetPxPyPzE(trkDaug6.px(), trkDaug6.py(), trkDaug6.pz(), energy(pdg->Mass(trackPDG(trkDaug6)), trkDaug6.px(), trkDaug6.py(), trkDaug6.pz())); + + if (trkDaug1.hasTPC()) { + histos.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + if (countPVGTpions == 6) + histos.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[0].P(), trkDaug1.tpcSignal()); + } + if (trkDaug2.hasTPC()) { + histos.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + if (countPVGTpions == 6) + histos.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[1].P(), trkDaug2.tpcSignal()); + } + if (trkDaug3.hasTPC()) { + histos.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); + if (countPVGTpions == 6) + histos.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[2].P(), trkDaug3.tpcSignal()); + } + if (trkDaug4.hasTPC()) { + histos.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); + if (countPVGTpions == 6) + histos.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[3].P(), trkDaug4.tpcSignal()); + } + if (trkDaug5.hasTPC()) { + histos.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[4].P(), trkDaug5.tpcSignal()); + if (countPVGTpions == 6) + histos.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[4].P(), trkDaug5.tpcSignal()); + } + if (trkDaug6.hasTPC()) { + histos.get(HIST("EventSixTracks/PID/hTPCsignalVsP"))->Fill(daug[5].P(), trkDaug6.tpcSignal()); + if (countPVGTpions == 6) + histos.get(HIST("EventSixTracks/SixPions/PID/hTPCsignalVsP"))->Fill(daug[5].P(), trkDaug6.tpcSignal()); + } + } else { + printDebugMessage("Other particles"); + } + + } // end fillPIDhistograms + void processDGrecoLevel(FullUDCollision const& reconstructedCollision, FullUDTracks const& reconstructedBarrelTracks) { countCollisions++; - fillHistograms(reconstructedCollision, reconstructedBarrelTracks); + if (doMainHistos) + fillHistograms(reconstructedCollision, reconstructedBarrelTracks); + if (doPIDhistos) + fillPIDhistograms(reconstructedCollision, reconstructedBarrelTracks); } // end processDGrecoLevel @@ -1899,26 +2542,29 @@ struct UpcTauCentralBarrelRL { { countCollisions++; - if (reconstructedCollision.gapSide() == 0) - histos.get(HIST("Events/hCountCollisions"))->Fill(1); - if (reconstructedCollision.gapSide() == 1) - histos.get(HIST("Events/hCountCollisions"))->Fill(2); - if (reconstructedCollision.gapSide() == 2) - histos.get(HIST("Events/hCountCollisions"))->Fill(3); - if (reconstructedCollision.gapSide() != whichGapSide) + int gapSide = reconstructedCollision.gapSide(); + int trueGapSide = sgSelector.trueGap(reconstructedCollision, cutMyGapSideFV0, cutMyGapSideFT0A, cutMyGapSideFT0C, cutMyGapSideZDC); + histos.fill(HIST("Events/UDtableGapSide"), gapSide); + histos.fill(HIST("Events/TrueGapSideDiffToTableValue"), gapSide - trueGapSide); + if (useTrueGap) + gapSide = trueGapSide; + + if (gapSide != whichGapSide) return; - fillHistograms(reconstructedCollision, reconstructedBarrelTracks); + if (doMainHistos) + fillHistograms(reconstructedCollision, reconstructedBarrelTracks); + if (doPIDhistos) + fillPIDhistograms(reconstructedCollision, reconstructedBarrelTracks); } // end processDGrecoLevel - void processAnalysisFinished(FullUDCollision const& /*collisions*/) + void processAnalysisFinished(FullUDCollision const&) { if (verboseInfo) - LOGF(info, "####################################### END OF THIS DATAFRAME #######################################"); - if (verboseDebug) - LOGF(info, "countCollisions = %d"); + printLargeMessage("END OF THIS DATAFRAME"); + printDebugMessage(Form("countCollisions = %d", countCollisions)); isFirstReconstructedCollisions = true; } // end processAnalysisFinished diff --git a/PWGUD/Tasks/upcVetoAnalysis.cxx b/PWGUD/Tasks/upcVetoAnalysis.cxx index 4f34a4d0941..0fc65232d0e 100644 --- a/PWGUD/Tasks/upcVetoAnalysis.cxx +++ b/PWGUD/Tasks/upcVetoAnalysis.cxx @@ -23,6 +23,8 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct UpcVetoAnalysis { + bool fIsCreated = false; + // amplitude axis int fNbAmp = 101; double fMinAmp = 0.; @@ -152,7 +154,8 @@ struct UpcVetoAnalysis { int nZdcs = zdcs.size(); const o2::aod::BCs::iterator& fbc = bcs.begin(); - if (fbc.runNumber() != fRun) { + if (fbc.runNumber() != fRun && !fIsCreated) { + fIsCreated = true; getBcInfo(fbc); for (auto i = 0; i < o2::constants::lhc::LHCMaxBunches; ++i) { diff --git a/Scripts/find_dependencies.py b/Scripts/find_dependencies.py index 98fcbc0b9e2..10bd68ee91e 100755 --- a/Scripts/find_dependencies.py +++ b/Scripts/find_dependencies.py @@ -72,7 +72,7 @@ def load_workflows_from_json(): # Get the workflow name from the JSON file name workflow = os.path.basename(file_json).split(".")[0] try: - with open(file_json, "r") as j: + with open(file_json, "r", encoding="utf8", errors="ignore") as j: specs_wf = json.load(j) db_wf[workflow] = specs_wf["workflow"] except FileNotFoundError: diff --git a/Tools/ML/model.h b/Tools/ML/model.h index bb1ac84a8ae..caca77f1a25 100644 --- a/Tools/ML/model.h +++ b/Tools/ML/model.h @@ -111,6 +111,39 @@ class OnnxModel return evalModel(inputTensors); } + // For 2D inputs + template + T* evalModel(std::vector>& input) + { + std::vector inputTensors; + +#if !__has_include() + Ort::MemoryInfo mem_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); +#endif + + for (size_t iinput = 0; iinput < input.size(); iinput++) { + [[maybe_unused]] int totalSize = 1; + int64_t size = input[iinput].size(); + for (size_t idim = 1; idim < mInputShapes[iinput].size(); idim++) { + totalSize *= mInputShapes[iinput][idim]; + } + assert(size % totalSize == 0); + + std::vector inputShape{static_cast(size / totalSize)}; + for (size_t idim = 1; idim < mInputShapes[iinput].size(); idim++) { + inputShape.push_back(mInputShapes[iinput][idim]); + } + +#if __has_include() + inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(input[iinput].data(), size, inputShape)); +#else + inputTensors.emplace_back(Ort::Value::CreateTensor(mem_info, input[iinput].data(), size, inputShape.data(), inputShape.size())); +#endif + } + + return evalModel(inputTensors); + } + // Reset session #if __has_include() void resetSession() { mSession.reset(new Ort::Experimental::Session{*mEnv, modelPath, sessionOptions}); } diff --git a/Tools/PIDML/CMakeLists.txt b/Tools/PIDML/CMakeLists.txt index cb2f87f4204..8ac36a5c0df 100644 --- a/Tools/PIDML/CMakeLists.txt +++ b/Tools/PIDML/CMakeLists.txt @@ -9,16 +9,22 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(pid-ml-producer-mc - SOURCES pidMLProducerMC.cxx +o2physics_add_dpl_workflow(pid-ml-producer + SOURCES pidMLProducer.cxx JOB_POOL analysis PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(pid-ml-producer-data - SOURCES pidMLProducerData.cxx +o2physics_add_dpl_workflow(pid-ml-batch-eff-and-pur-producer + SOURCES pidMLBatchEffAndPurProducer.cxx JOB_POOL analysis - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework ONNXRuntime::ONNXRuntime O2::CCDB O2Physics::DataModel + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pid-ml-eff-and-pur-producer + SOURCES pidMLEffAndPurProducer.cxx + JOB_POOL analysis + PUBLIC_LINK_LIBRARIES O2::Framework ONNXRuntime::ONNXRuntime O2::CCDB O2Physics::DataModel COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(simple-apply-pid-onnx-model diff --git a/Tools/PIDML/KaonPidTask.cxx b/Tools/PIDML/KaonPidTask.cxx index 19c0972be4a..acc29e47bee 100644 --- a/Tools/PIDML/KaonPidTask.cxx +++ b/Tools/PIDML/KaonPidTask.cxx @@ -60,7 +60,6 @@ struct KaonPidTask { Configurable cfgCCDBURL{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB repository"}; Configurable cfgPid{"pid", 321, "PID to predict"}; Configurable cfgCertainty{"certainty", 0.5, "Minimum certainty above which the model accepts a particular type of particle"}; - Configurable cfgDetector{"detector", kTPCTOFTRD, "What detectors to use: 0: TPC only, 1: TPC + TOF, 2: TPC + TOF + TRD"}; Configurable cfgTimestamp{"timestamp", 0, "Fixed timestamp"}; Configurable cfgUseCCDB{"useCCDB", false, "Whether to autofetch ML model from CCDB. If false, local file will be used."}; @@ -85,7 +84,7 @@ struct KaonPidTask { if (cfgUseCCDB) { ccdbApi.init(cfgCCDBURL); // Initializes ccdbApi when cfgUseCCDB is set to 'true' } - pidModel = std::make_shared(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, cfgTimestamp.value, cfgPid.value, static_cast(cfgDetector.value), cfgCertainty.value); + pidModel = std::make_shared(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, cfgTimestamp.value, cfgPid.value, cfgCertainty.value); histos.add("hChargePos", ";z;", kTH1F, {{3, -1.5, 1.5}}); histos.add("hChargeNeg", ";z;", kTH1F, {{3, -1.5, 1.5}}); diff --git a/Tools/PIDML/README.md b/Tools/PIDML/README.md index 57ada2bb48e..1768ac9e900 100644 --- a/Tools/PIDML/README.md +++ b/Tools/PIDML/README.md @@ -1,6 +1,8 @@ # PID ML in O2 -Particle identification is essential in most of the analyzes. The PID ML interface will help you to make use of the machine learning models to improve purity and efficiency of particle kinds for your analysis. A single model is tailored to a specific particle kind, e.g., pions with PID 211. For each track, the model returns a float value in [0, 1] which measures the ''certainty'' of the model that this track is of given kind. +Particle identification is essential in most of the analyzes. +The PID ML interface will help you to make use of the machine learning models to improve purity and efficiency of particle kinds for your analysis. +A single model is tailored to a specific particle kind, e.g., pions with PID 211. For each track, the model returns a float value in [0, 1] which measures the ''certainty'' of the model that this track is of given kind. ## PidONNXModel @@ -11,12 +13,16 @@ This class represents a single ML model from an ONNX file. It requires the follo - CCDB Api instance created in an analysis task - timestamp of the input analysis data -- neded to choose appropriate model - PID to be checked -- detector setup: what detectors should be used for identification. It is described by enum PidMLDetector. Currently available setups: TPC, TPC+TOF, TPC+TOF+TRD - minimum certainty for accepting a track to be of given PID +- *p* limits array - specifiying p limits for each detector configuration (TPC, TPC+TOF, TPC+TOF+TRD) -Let's assume your `PidONNXModel` instance is named `pidModel`. Then, inside your analysis task `process()` function, you can iterate over tracks and call: `pidModel.applyModel(track);` to get the certainty of the model. You can also use `pidModel.applyModelBoolean(track);` to receive a true/false answer, whether the track can be accepted based on the minimum certainty provided to the `PidONNXModel` constructor. +Let's assume your `PidONNXModel` instance is named `pidModel`. +Then, inside your analysis task `process()` function, you can iterate over tracks and call: `pidModel.applyModel(track);` to get the certainty of the model. +You can also use `pidModel.applyModelBoolean(track);` to receive a true/false answer, whether the track can be accepted based on the minimum certainty provided to the `PidONNXModel` constructor. -You can check [a simple analysis task example](https://github.com/AliceO2Group/O2Physics/blob/master/Tools/PIDML/simpleApplyPidOnnxModel.cxx). It uses configurable parameters and shows how to calculate the data timestamp. Note that the calculation of the timestamp requires subscribing to `aod::Collisions` and `aod::BCsWithTimestamps`. For Hyperloop tests, you can set `cfgUseFixedTimestamp` to true with `cfgTimestamp` set to the default value. +You can check [a simple analysis task example](https://github.com/AliceO2Group/O2Physics/blob/master/Tools/PIDML/simpleApplyPidOnnxModel.cxx). +It uses configurable parameters and shows how to calculate the data timestamp. Note that the calculation of the timestamp requires subscribing to `aod::Collisions` and `aod::BCsWithTimestamps`. +For Hyperloop tests, you can set `cfgUseFixedTimestamp` to true with `cfgTimestamp` set to the default value. On the other hand, it is possible to use locally stored models, and then the timestamp is not used, so it can be a dummy value. `processTracksOnly` presents how to analyze on local-only PID ML models. @@ -31,10 +37,10 @@ This is a wrapper around PidONNXModel that contains several models. It has the p Then, obligatory parameters for the interface: - a vector of int output PIDs -- a 2-dimensional LabeledArray of *p*T limits for each PID, for each detector configuration. It describes the minimum *p*T values at which each next detector should be included for predicting given PID +- a 2-dimensional LabeledArray of *p* limits for each PID, for each detector configuration. It describes the minimum *p* values at which each next detector should be included for predicting given PID - a vector of minimum certainties for each PID for accepting a track to be of this PID - boolean flag: whether to switch on auto mode. If true, then *p*T limits and minimum certainties can be passed as an empty array and an empty vector, and the interface will fill them with default configuration: - - *p*T limits: same values for all PIDs: 0.0 (TPC), 0.5 (TPC + TOF), 0.8 (TPC + TOF + TRD) + - *p* limits: same values for all PIDs: 0.0 (TPC), 0.5 (TPC + TOF), 0.8 (TPC + TOF + TRD) - minimum certainties: 0.5 for all PIDs You can use the interface in the same way as the model, by calling `applyModel(track)` or `applyModelBoolean(track)`. The interface will then call the respective method of the model selected with the aforementioned interface parameters. @@ -48,20 +54,49 @@ There is again [a simple analysis task example](https://github.com/AliceO2Group/ Currently, only models for run 285064 (timestamp interval: 1524176895000 - 1524212953000) are uploaded to CCDB, so you can use hardcoded timestamp 1524176895000 for tests. Both model and interface analysis examples can be run with a script: + +### Script for Run2 Converted to Run3 data +```bash +#!/bin/bash + +config_file="my-config.json" + +o2-analysis-tracks-extra-converter --configuration json://$config_file -b | + o2-analysis-timestamp --configuration json://$config_file -b | + o2-analysis-trackextension --configuration json://$config_file -b | + o2-analysis-trackselection --configuration json://$config_file -b | + o2-analysis-multiplicity-table --configuration json://$config_file -b | + o2-analysis-bc-converter --configuration json://$config_file -b | + o2-analysis-collision-converter --configuration json://$config_file -b | + o2-analysis-zdc-converter --configuration json://$config_file -b | + o2-analysis-pid-tof-base --configuration json://$config_file -b | + o2-analysis-pid-tof-beta --configuration json://$config_file -b | + o2-analysis-pid-tof-full --configuration json://$config_file -b | + o2-analysis-pid-tpc-full --configuration json://$config_file -b | + o2-analysis-pid-tpc-base --configuration json://$config_file -b | + o2-analysis-simple-apply-pid-onnx-model --configuration json://$config_file -b +``` +Remember to set every setting, which states that helper task should process Run2 data to `true`. + +### Script for Run3 data ```bash #!/bin/bash config_file="my-config.json" o2-analysis-timestamp --configuration json://$config_file -b | - o2-analysis-trackextension --configuration json://$config_file -b | - o2-analysis-trackselection --configuration json://$config_file -b | - o2-analysis-multiplicity-table --configuration json://$config_file -b | - o2-analysis-fdd-converter --configuration json://$config_file -b | - o2-analysis-pid-tof-base --configuration json://$config_file -b | - o2-analysis-pid-tof-beta --configuration json://$config_file -b | - o2-analysis-pid-tof-full --configuration json://$config_file -b | - o2-analysis-pid-tpc-full --configuration json://$config_file -b | - o2-analysis-simple-apply-pid-onnx-model --configuration json://$config_file -b + o2-analysis-event-selection --configuration json://$config_file -b | + o2-analysis-trackselection --configuration json://$config_file -b | + o2-analysis-multiplicity-table --configuration json://$config_file -b | + o2-analysis-track-propagation --configuration json://$config_file -b | + o2-analysis-pid-tof-base --configuration json://$config_file -b | + o2-analysis-pid-tof-beta --configuration json://$config_file -b | + o2-analysis-pid-tof-full --configuration json://$config_file -b | + o2-analysis-pid-tpc-full --configuration json://$config_file -b | + o2-analysis-pid-tpc-base --configuration json://$config_file -b | + o2-analysis-simple-apply-pid-onnx-model --configuration json://$config_file -b ``` +Remember to set every setting, which states that helper task should process Run3 data to `true`. + + Replace "model" with "interface" in the last line if you want to run the interface workflow. diff --git a/Tools/PIDML/pidMLBatchEffAndPurProducer.cxx b/Tools/PIDML/pidMLBatchEffAndPurProducer.cxx new file mode 100644 index 00000000000..9a611ded269 --- /dev/null +++ b/Tools/PIDML/pidMLBatchEffAndPurProducer.cxx @@ -0,0 +1,246 @@ +// Copyright 2019-2020 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. + +/// \file pidMLBatchEffAndPurProducer +/// \brief Batch PID execution task. It produces derived data needed for ROOT script, which +/// generates efficiency (recall) and purity (precision) analysis of ML Model PID +/// +/// \author MichaƂ Olędzki +/// \author Marek Mytkowski + +#include +#include +#include + +#include "Framework/AnalysisDataModel.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/StaticFor.h" +#include "CCDB/CcdbApi.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Tools/PIDML/pidOnnxModel.h" +#include "Tools/PIDML/pidUtils.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace pidml::pidutils; + +namespace o2::aod +{ +namespace effandpurpidresult +{ +DECLARE_SOA_INDEX_COLUMN(Track, track); //! Track index +DECLARE_SOA_COLUMN(Pid, pid, int32_t); //! PDG particle ID to be tested by the model +DECLARE_SOA_COLUMN(Pt, pt, float); //! particle's pt +DECLARE_SOA_COLUMN(MlCertainty, mlCertainty, float); //! Machine learning model certainty value for track and pid +DECLARE_SOA_COLUMN(NSigma, nSigma, float); //! nSigma value for track and pid +DECLARE_SOA_COLUMN(IsPidMC, isPidMc, bool); //! Is track's mcParticle recognized as "Pid" +DECLARE_SOA_COLUMN(HasTOF, hasTof, bool); //! Does track have TOF detector signal +DECLARE_SOA_COLUMN(HasTRD, hasTrd, bool); //! Does track have TRD detector signal +} // namespace effandpurpidresult + +DECLARE_SOA_TABLE(EffAndPurPidResult, "AOD", "PIDEFFANDPURRES", o2::soa::Index<>, + effandpurpidresult::TrackId, effandpurpidresult::Pid, effandpurpidresult::Pt, effandpurpidresult::MlCertainty, + effandpurpidresult::NSigma, effandpurpidresult::IsPidMC, effandpurpidresult::HasTOF, effandpurpidresult::HasTRD); +} // namespace o2::aod + +struct PidMlBatchEffAndPurProducer { + Produces effAndPurPIDResult; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + static constexpr int32_t currentRunNumber = -1; + static constexpr uint32_t kNPids = 6; + static constexpr int32_t kPids[kNPids] = {2212, 321, 211, -211, -321, -2212}; + static constexpr std::string_view kParticleLabels[kNPids] = {"2212", "321", "211", "0211", "0321", "02212"}; + static constexpr std::string_view kParticleNames[kNPids] = {"proton", "kaon", "pion", "antipion", "antikaon", "antiproton"}; + + std::array, kNPids> hTracked; + std::array, kNPids> hMCPositive; + + o2::ccdb::CcdbApi ccdbApi; + std::vector models; + + Configurable> cfgPids{"pids", std::vector(kPids, kPids + kNPids), "PIDs to predict"}; + Configurable> cfgDetectorsPLimits{"detectors-p-limits", std::array(pidml_pt_cuts::defaultModelPLimits), "\"use {detector} when p >= y_{detector}\": array of 3 doubles [y_TPC, y_TOF, y_TRD]"}; + Configurable cfgPathCCDB{"ccdb-path", "Users/m/mkabus/PIDML", "base path to the CCDB directory with ONNX models"}; + Configurable cfgCCDBURL{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB repository"}; + Configurable cfgUseCCDB{"use-ccdb", true, "Whether to autofetch ML model from CCDB. If false, local file will be used."}; + Configurable cfgPathLocal{"local-path", "/home/mkabus/PIDML/", "base path to the local directory with ONNX models"}; + Configurable cfgUseFixedTimestamp{"use-fixed-timestamp", false, "Whether to use fixed timestamp from configurable instead of timestamp calculated from the data"}; + Configurable cfgTimestamp{"timestamp", 1524176895000, "Hardcoded timestamp for tests"}; + + Filter trackFilter = requireGlobalTrackInFilter(); + + using BigTracks = soa::Filtered>; + + void initHistos() + { + static const AxisSpec axisPt{50, 0, 3.1, "pt"}; + + static_for<0, kNPids - 1>([&](auto i) { + if (std::find(cfgPids.value.begin(), cfgPids.value.end(), kPids[i]) != cfgPids.value.end()) { + hTracked[i] = histos.add(Form("%s/hPtMCTracked", kParticleLabels[i].data()), Form("Tracked %ss vs pT", kParticleNames[i].data()), kTH1F, {axisPt}); + hMCPositive[i] = histos.add(Form("%s/hPtMCPositive", kParticleLabels[i].data()), Form("MC Positive %ss vs pT", kParticleNames[i].data()), kTH1F, {axisPt}); + } + }); + } + + void init(InitContext const&) + { + if (cfgUseCCDB) { + ccdbApi.init(cfgCCDBURL); + } + + initHistos(); + } + + std::optional getPartIndex(int32_t pdgCode) + { + std::optional index; + + if (std::find(cfgPids.value.begin(), cfgPids.value.end(), pdgCode) != cfgPids.value.end()) { + switch (pdgCode) { + case 2212: + index = 0; + break; + case 321: + index = 1; + break; + case 211: + index = 2; + break; + case -211: + index = 3; + break; + case -321: + index = 4; + break; + case -2212: + index = 5; + break; + } + } + + return index; + } + + void fillTrackedHist(int32_t pdgCode, float pt) + { + auto ind = getPartIndex(pdgCode); + if (ind) { + hTracked[ind.value()]->Fill(pt); + } + } + + void fillMCPositiveHist(int32_t pdgCode, float pt) + { + auto ind = getPartIndex(pdgCode); + if (ind) { + hMCPositive[ind.value()]->Fill(pt); + } + } + + typedef struct nSigma_t { + double tpc, tof, composed; + } nSigma_t; + + const nSigma_t getNSigma(const BigTracks::iterator& track, const int32_t& cfgPid) + { + nSigma_t nSigma; + + switch (TMath::Abs(cfgPid)) { + case 11: // electron + nSigma.tof = track.tofNSigmaEl(); + nSigma.tpc = track.tpcNSigmaEl(); + break; + case 13: // muon + nSigma.tof = track.tofNSigmaMu(); + nSigma.tpc = track.tpcNSigmaMu(); + break; + case 211: // pion + nSigma.tof = track.tofNSigmaPi(); + nSigma.tpc = track.tpcNSigmaPi(); + break; + case 321: // kaon + nSigma.tof = track.tofNSigmaKa(); + nSigma.tpc = track.tpcNSigmaKa(); + break; + case 2212: // proton + nSigma.tof = track.tofNSigmaPr(); + nSigma.tpc = track.tpcNSigmaPr(); + break; + } + + if (!inPLimit(track, cfgDetectorsPLimits.value[kTPCTOF]) || tofMissing(track)) { + nSigma.composed = TMath::Abs(nSigma.tpc); + } else { + nSigma.composed = TMath::Hypot(nSigma.tof, nSigma.tpc); + } + + int32_t sign = cfgPid > 0 ? 1 : -1; + if (sign != track.sign()) { + nSigma.composed = std::numeric_limits::max(); + } + + return nSigma; + } + + void process(aod::Collisions const& collisions, BigTracks const& tracks, aod::BCsWithTimestamps const&, aod::McParticles const& mcParticles) + { + effAndPurPIDResult.reserve(mcParticles.size()); + + auto bc = collisions.iteratorAt(0).bc_as(); + if (cfgUseCCDB && bc.runNumber() != currentRunNumber) { + uint64_t timestamp = cfgUseFixedTimestamp ? cfgTimestamp.value : bc.timestamp(); + for (const int32_t& pid : cfgPids.value) + models.emplace_back(PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, + ccdbApi, timestamp, pid, 1.1, &cfgDetectorsPLimits.value[0])); + } else { + for (int32_t& pid : cfgPids.value) + models.emplace_back(PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, + ccdbApi, -1, pid, 1.1, &cfgDetectorsPLimits.value[0])); + } + + for (auto& mcPart : mcParticles) { + // eta cut is done in requireGlobalTrackInFilter() so we cut it only here + if (mcPart.isPhysicalPrimary() && TMath::Abs(mcPart.eta()) < kGlobalEtaCut) { + fillMCPositiveHist(mcPart.pdgCode(), mcPart.pt()); + } + } + + for (auto& track : tracks) { + if (track.has_mcParticle()) { + auto mcPart = track.mcParticle(); + if (mcPart.isPhysicalPrimary()) { + fillTrackedHist(mcPart.pdgCode(), track.pt()); + + for (size_t i = 0; i < cfgPids.value.size(); ++i) { + float mlCertainty = models[i].applyModel(track); + nSigma_t nSigma = getNSigma(track, cfgPids.value[i]); + bool isMCPid = mcPart.pdgCode() == cfgPids.value[i]; + + effAndPurPIDResult(track.index(), cfgPids.value[i], track.pt(), mlCertainty, nSigma.composed, isMCPid, track.hasTOF(), track.hasTRD()); + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tools/PIDML/pidMLEffAndPurProducer.cxx b/Tools/PIDML/pidMLEffAndPurProducer.cxx new file mode 100644 index 00000000000..7e626a8d631 --- /dev/null +++ b/Tools/PIDML/pidMLEffAndPurProducer.cxx @@ -0,0 +1,213 @@ +// Copyright 2019-2020 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. + +/// \file pidMLEffAndPurProducer.cxx +/// \brief Produce pt histograms for tracks accepted by ML network and for MC mcParticles. +/// +/// \author MichaƂ Olędzki +/// \author Marek Mytkowski + +#include + +#include "Framework/AnalysisDataModel.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "CCDB/CcdbApi.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Tools/PIDML/pidOnnxModel.h" +#include "pidOnnxModel.h" +#include "Tools/PIDML/pidUtils.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace pidml::pidutils; + +struct PidMlEffAndPurProducer { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + PidONNXModel pidModel; + Configurable cfgPid{"pid", 211, "PID to predict"}; + Configurable cfgNSigmaCut{"n-sigma-cut", 3.0f, "TPC and TOF PID nSigma cut"}; + Configurable> cfgDetectorsPLimits{"detectors-p-limits", std::array(pidml_pt_cuts::defaultModelPLimits), "\"use {detector} when p >= y_{detector}\": array of 3 doubles [y_TPC, y_TOF, y_TRD]"}; + Configurable cfgCertainty{"certainty", 0.5, "Min certainty of the model to accept given mcPart to be of given kind"}; + + Configurable cfgPathCCDB{"ccdb-path", "Users/m/mkabus/PIDML", "base path to the CCDB directory with ONNX models"}; + Configurable cfgCCDBURL{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB repository"}; + Configurable cfgUseCCDB{"use-ccdb", true, "Whether to autofetch ML model from CCDB. If false, local file will be used."}; + Configurable cfgPathLocal{"local-path", "/home/mkabus/PIDML", "base path to the local directory with ONNX models"}; + + Configurable cfgUseFixedTimestamp{"use-fixed-timestamp", false, "Whether to use fixed timestamp from configurable instead of timestamp calculated from the data"}; + Configurable cfgTimestamp{"timestamp", 1524176895000, "Hardcoded timestamp for tests"}; + + o2::ccdb::CcdbApi ccdbApi; + int currentRunNumber = -1; + + Filter trackFilter = requireGlobalTrackInFilter(); + + using BigTracks = soa::Filtered>; + + typedef struct nSigma_t { + double tpc, tof; + } nSigma_t; + + nSigma_t GetNSigma(const BigTracks::iterator& track) + { + nSigma_t nSigma; + + switch (TMath::Abs(cfgPid)) { + case 11: // electron + nSigma.tof = track.tofNSigmaEl(); + nSigma.tpc = track.tpcNSigmaEl(); + break; + case 13: // muon + nSigma.tof = track.tofNSigmaMu(); + nSigma.tpc = track.tpcNSigmaMu(); + break; + case 211: // pion + nSigma.tof = track.tofNSigmaPi(); + nSigma.tpc = track.tpcNSigmaPi(); + break; + case 321: // kaon + nSigma.tof = track.tofNSigmaKa(); + nSigma.tpc = track.tpcNSigmaKa(); + break; + case 2212: // proton + nSigma.tof = track.tofNSigmaPr(); + nSigma.tpc = track.tpcNSigmaPr(); + break; + } + + return nSigma; + } + + bool IsNSigmaAccept(const BigTracks::iterator& track, nSigma_t& nSigma) + { + // FIXME: for current particles it works, but there are some particles, + // which can have different sign and pdgSign + int sign = cfgPid > 0 ? 1 : -1; + if (track.sign() != sign) + return false; + + if (!inPLimit(track, cfgDetectorsPLimits.value[kTPCTOF]) || tofMissing(track)) { + if (TMath::Abs(nSigma.tpc) >= cfgNSigmaCut) + return false; + } else { + if (TMath::Hypot(nSigma.tof, nSigma.tpc) >= cfgNSigmaCut) + return false; + } + + return true; + } + + void init(InitContext const&) + { + if (cfgUseCCDB) { + ccdbApi.init(cfgCCDBURL); + } else { + pidModel = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, + cfgPid.value, cfgCertainty.value, &cfgDetectorsPLimits.value[0]); + } + + const AxisSpec axisPt{100, 0, 5.0, "pt"}; + const AxisSpec axisP{100, 0, 5.0, "p"}; + const AxisSpec axisBeta{100, 0, 1.0, "beta"}; + const AxisSpec axisTPCSignal{100, 0, 120.0, "dEdx"}; + const AxisSpec axisNSigma{100, -5.0, 5.0, "n-sigma"}; + + // Monte Carlo + histos.add("hPtMCPositive", "hPtMCPositive", kTH1F, {axisPt}); + histos.add("hPtMCTracked", "hPtMCTracked", kTH1F, {axisPt}); + + // Machine learning PID + histos.add("hPtMLPositive", "hPtMLPositive", kTH1F, {axisPt}); + histos.add("hPtMLTruePositive", "hPtMLTruePositive", kTH1F, {axisPt}); + + // NSigma PID + histos.add("hPtNSigmaPositive", "hPtNSigmaPositive", kTH1F, {axisPt}); + histos.add("hPtNSigmaTruePositive", "hPtNSigmaTruePositive", kTH1F, {axisPt}); + + // Context detectors' data + histos.add("full/hPtTOFBeta", "full/hPtTOFBeta", kTH2F, {axisP, axisBeta}); + histos.add("full/hPtTPCSignal", "full/hPtTPCSignal", kTH2F, {axisP, axisTPCSignal}); + histos.add("full/hPtTOFNSigma", "full/hPtTOFNSigma", kTH2F, {axisP, axisNSigma}); + histos.add("full/hPtTPCNSigma", "full/hPtTPCNSigma", kTH2F, {axisP, axisNSigma}); + + histos.add("hPtTOFNSigma", "hPtTOFNSigma", kTH2F, {axisP, axisNSigma}); + histos.add("hPtTPCNSigma", "hPtTPCNSigma", kTH2F, {axisP, axisNSigma}); + } + + void process(aod::Collisions const& collisions, BigTracks const& tracks, aod::BCsWithTimestamps const&, aod::McParticles const& mcParticles) + { + auto bc = collisions.iteratorAt(0).bc_as(); + if (cfgUseCCDB && bc.runNumber() != currentRunNumber) { + uint64_t timestamp = cfgUseFixedTimestamp ? cfgTimestamp.value : bc.timestamp(); + pidModel = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, timestamp, + cfgPid.value, cfgCertainty.value, &cfgDetectorsPLimits.value[0]); + } + + for (auto& mcPart : mcParticles) { + // eta cut is included in requireGlobalTrackInFilter() so we cut it only here + if (mcPart.isPhysicalPrimary() && TMath::Abs(mcPart.eta()) < kGlobalEtaCut && mcPart.pdgCode() == pidModel.mPid) { + histos.fill(HIST("hPtMCPositive"), mcPart.pt()); + } + } + + for (auto& track : tracks) { + if (track.has_mcParticle()) { + auto mcPart = track.mcParticle(); + if (mcPart.isPhysicalPrimary()) { + bool mlAccepted = pidModel.applyModelBoolean(track); + nSigma_t nSigma = GetNSigma(track); + bool nSigmaAccepted = IsNSigmaAccept(track, nSigma); + + LOGF(debug, "collision id: %d track id: %d mlAccepted: %d nSigmaAccepted: %d p: %.3f; x: %.3f, y: %.3f, z: %.3f", + track.collisionId(), track.index(), mlAccepted, nSigmaAccepted, track.p(), track.x(), track.y(), track.z()); + + if (mcPart.pdgCode() == pidModel.mPid) { + histos.fill(HIST("full/hPtTOFNSigma"), track.p(), nSigma.tof); + histos.fill(HIST("full/hPtTPCNSigma"), track.p(), nSigma.tpc); + histos.fill(HIST("hPtMCTracked"), track.pt()); + } + + histos.fill(HIST("full/hPtTOFBeta"), track.pt(), track.beta()); + histos.fill(HIST("full/hPtTPCSignal"), track.pt(), track.tpcSignal()); + + if (mlAccepted) { + if (mcPart.pdgCode() == pidModel.mPid) { + histos.fill(HIST("hPtMLTruePositive"), track.pt()); + } + histos.fill(HIST("hPtMLPositive"), track.pt()); + } + + if (nSigmaAccepted) { + histos.fill(HIST("hPtTOFNSigma"), track.p(), nSigma.tof); + histos.fill(HIST("hPtTPCNSigma"), track.p(), nSigma.tpc); + + if (mcPart.pdgCode() == pidModel.mPid) { + histos.fill(HIST("hPtNSigmaTruePositive"), track.pt()); + } + histos.fill(HIST("hPtNSigmaPositive"), track.pt()); + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tools/PIDML/pidMLProducer.cxx b/Tools/PIDML/pidMLProducer.cxx new file mode 100644 index 00000000000..67cf4308a5e --- /dev/null +++ b/Tools/PIDML/pidMLProducer.cxx @@ -0,0 +1,341 @@ +// Copyright 2019-2020 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. + +/// \file pidMLProducer.cxx +/// \brief Produce PID ML skimmed data from MC or data files. +/// +/// \author Maja Kabus +/// \author Marek Mytkowski + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/StaticFor.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Tools/PIDML/pidML.h" +#include "Tools/PIDML/pidUtils.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace pidml::pidutils; + +// Naming convention +// Data: experimental data without simulation +// MC: experimental data with Monte Carlo simulation +// ML: only columns used by Machine Learning network +struct PidMlProducer { + Produces pidTracksTableDataML; + Produces pidTracksTableData; + Produces pidTracksTableMCML; + Produces pidTracksTableMC; + + Filter trackFilter = requireGlobalTrackInFilter(); + + // Data tracks + using BigTracksDataML = soa::Filtered>; + using BigTracksData = soa::Filtered>; + + // MC tracks + using BigTracksMCML = soa::Filtered>; + using BigTracksMC = soa::Filtered>; + + using MyCollisionML = aod::Collisions::iterator; + using MyCollision = soa::Join::iterator; + + static constexpr uint32_t nCharges = 2; + + static constexpr std::string_view histPrefixes[nCharges] = {"minus", "plus"}; + + // 2D + std::array, nCharges> hTPCSigvsP; + std::array, nCharges> hTOFBetavsP; + std::array, nCharges> hTOFSigvsP; + std::array, nCharges> hFilteredTOFSigvsP; + std::array, nCharges> hTRDPattvsP; + std::array, nCharges> hTRDSigvsP; + + // 1D + std::array, nCharges> hP; + std::array, nCharges> hPt; + std::array, nCharges> hPx; + std::array, nCharges> hPy; + std::array, nCharges> hPz; + std::array, nCharges> hX; + std::array, nCharges> hY; + std::array, nCharges> hZ; + std::array, nCharges> hAlpha; + std::array, nCharges> hTrackType; + std::array, nCharges> hTPCNClsShared; + std::array, nCharges> hDcaXY; + std::array, nCharges> hDcaZ; + std::array, nCharges> hPdgCode; + std::array, nCharges> hIsPrimary; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + static const char* genTagvsP(const char* name) + { + return Form("%s vs #it{p};#it{p} (GeV/#it{c});%s", name, name); + } + + template + void initHistSign() + { + hTPCSigvsP[prefixInd] = registry.add(Form("%s/hTPCSigvsP", histPrefixes[prefixInd].data()), genTagvsP("TPC Signal"), HistType::kTH2F, {{500, 0., 10.}, {1000, 0., 600.}}); + hTOFBetavsP[prefixInd] = registry.add(Form("%s/hTOFBetavsP", histPrefixes[prefixInd].data()), genTagvsP("TOF beta"), HistType::kTH2F, {{500, 0., 10.}, {6000, -3., 3.}}); + hTOFSigvsP[prefixInd] = registry.add(Form("%s/hTOFSigvsP", histPrefixes[prefixInd].data()), genTagvsP("TOF signal"), HistType::kTH2F, {{500, 0., 10.}, {10000, -5000., 80000.}}); + hFilteredTOFSigvsP[prefixInd] = registry.add(Form("%s/filtered/hTOFSigvsP", histPrefixes[prefixInd].data()), genTagvsP("TOF signal (filtered)"), HistType::kTH2F, {{500, 0., 10.}, {10000, -5000., 80000.}}); + hTRDPattvsP[prefixInd] = registry.add(Form("%s/hTRDPattvsP", histPrefixes[prefixInd].data()), genTagvsP("TRD pattern"), HistType::kTH2F, {{500, 0., 10.}, {110, -10., 100.}}); + hTRDSigvsP[prefixInd] = registry.add(Form("%s/hTRDSigvsP", histPrefixes[prefixInd].data()), genTagvsP("TRD signal"), HistType::kTH2F, {{500, 0., 10.}, {2500, -2., 100.}}); + hP[prefixInd] = registry.add(Form("%s/hP", histPrefixes[prefixInd].data()), "#it{p};#it{p} (GeV/#it{c})", HistType::kTH1F, {{500, 0., 6.}}); + hPt[prefixInd] = registry.add(Form("%s/hPt", histPrefixes[prefixInd].data()), "#it{p}_{t};#it{p}_{t} (GeV/#it{c})", HistType::kTH1F, {{500, 0., 6.}}); + hPx[prefixInd] = registry.add(Form("%s/hPx", histPrefixes[prefixInd].data()), "#it{p}_{x};#it{p}_{x} (GeV/#it{c})", HistType::kTH1F, {{1000, -6., 6.}}); + hPy[prefixInd] = registry.add(Form("%s/hPy", histPrefixes[prefixInd].data()), "#it{p}_{y};#it{p}_{y} (GeV/#it{c})", HistType::kTH1F, {{1000, -6., 6.}}); + hPz[prefixInd] = registry.add(Form("%s/hPz", histPrefixes[prefixInd].data()), "#it{p}_{z};#it{p}_{z} (GeV/#it{c})", HistType::kTH1F, {{1000, -6., 6.}}); + hX[prefixInd] = registry.add(Form("%s/hX", histPrefixes[prefixInd].data()), "#it{x};#it{x}", HistType::kTH1F, {{1000, -2., 2.}}); + hY[prefixInd] = registry.add(Form("%s/hY", histPrefixes[prefixInd].data()), "#it{y};#it{y}", HistType::kTH1F, {{1000, -2., 2.}}); + hZ[prefixInd] = registry.add(Form("%s/hZ", histPrefixes[prefixInd].data()), "#it{z};#it{z}", HistType::kTH1F, {{1000, -10., 10.}}); + hAlpha[prefixInd] = registry.add(Form("%s/hAlpha", histPrefixes[prefixInd].data()), "alpha;alpha", HistType::kTH1F, {{1000, -5., 5.}}); + hTrackType[prefixInd] = registry.add(Form("%s/hTrackType", histPrefixes[prefixInd].data()), "Track Type;Track Type", HistType::kTH1F, {{300, 0., 300.}}); + hTPCNClsShared[prefixInd] = registry.add(Form("%s/hTPCNClsShared", histPrefixes[prefixInd].data()), "hTPCNClsShared;hTPCNClsShared", HistType::kTH1F, {{100, 0., 100.}}); + hDcaXY[prefixInd] = registry.add(Form("%s/hDcaXY", histPrefixes[prefixInd].data()), "#it{DcaXY};#it{DcaXY}", HistType::kTH1F, {{1000, -1., 1.}}); + hDcaZ[prefixInd] = registry.add(Form("%s/hDcaZ", histPrefixes[prefixInd].data()), "#it{DcaZ};#it{DcaZ}", HistType::kTH1F, {{1000, -1., 1.}}); + } + + template + void initHistSignMC() + { + initHistSign(); + hPdgCode[prefixInd] = registry.add(Form("%s/hPdgCode", histPrefixes[prefixInd].data()), "#it{PdgCode};#it{PdgCode}", HistType::kTH1F, {{2500, 0., 2500.}}); + hIsPrimary[prefixInd] = registry.add(Form("%s/hIsPrimary", histPrefixes[prefixInd].data()), "#it{IsPrimary};#it{IsPrimary}", HistType::kTH1F, {{4, -0.5, 1.5}}); + } + + template + void fillHistSign(const T& track) + { + hTPCSigvsP[prefixInd]->Fill(track.p(), track.tpcSignal()); + hTOFBetavsP[prefixInd]->Fill(track.p(), track.beta()); + hTOFSigvsP[prefixInd]->Fill(track.p(), track.tofSignal()); + if (tofMissing(track)) { + hFilteredTOFSigvsP[prefixInd]->Fill(track.p(), kTOFMissingSignal); + } else { + hFilteredTOFSigvsP[prefixInd]->Fill(track.p(), track.tofSignal()); + } + hTRDPattvsP[prefixInd]->Fill(track.p(), track.trdPattern()); + hTRDSigvsP[prefixInd]->Fill(track.p(), track.trdSignal()); + hP[prefixInd]->Fill(track.p()); + hPt[prefixInd]->Fill(track.pt()); + hPx[prefixInd]->Fill(track.px()); + hPy[prefixInd]->Fill(track.py()); + hPz[prefixInd]->Fill(track.pz()); + hX[prefixInd]->Fill(track.x()); + hY[prefixInd]->Fill(track.y()); + hZ[prefixInd]->Fill(track.z()); + hAlpha[prefixInd]->Fill(track.alpha()); + hTrackType[prefixInd]->Fill(track.trackType()); + hTPCNClsShared[prefixInd]->Fill(track.tpcNClsShared()); + hDcaXY[prefixInd]->Fill(track.dcaXY()); + hDcaZ[prefixInd]->Fill(track.dcaZ()); + } + + template + void fillHistSignMC(const T& track, uint32_t pdgCode, uint8_t isPrimary) + { + fillHistSign(track); + hPdgCode[prefixInd]->Fill(pdgCode); + hIsPrimary[prefixInd]->Fill(isPrimary); + } + + template + void fillHistMC(const T& track, uint32_t pdgCode, uint8_t isPrimary) + { + if (track.sign() < 0) { + fillHistSignMC<0>(track, pdgCode, isPrimary); + } else { + fillHistSignMC<1>(track, pdgCode, isPrimary); + } + } + + template + void fillHist(const T& track) + { + if (track.sign() < 0) { + fillHistSign<0>(track); + } else { + fillHistSign<1>(track); + } + } + + void init(InitContext&) + { + if (doprocessMcMl || doprocessMcAll) { + initHistSignMC<0>(); + initHistSignMC<1>(); + } else { + initHistSign<0>(); + initHistSign<1>(); + } + } + + template + float getTOFSignal(T const& track) + { + return tofMissing(track) ? std::numeric_limits::quiet_NaN() : track.tofSignal(); + } + + template + float getTOFBeta(T const& track) + { + return tofMissing(track) ? std::numeric_limits::quiet_NaN() : track.beta(); + } + + template + float getTRDSignal(T const& track) + { + return trdMissing(track) ? std::numeric_limits::quiet_NaN() : track.trdSignal(); + } + + template + uint8_t getTRDPattern(T const& track) + { + return trdMissing(track) ? static_cast(0U) : track.trdPattern(); + } + + void processDataML(MyCollisionML const& /*collision*/, BigTracksDataML const& tracks) + { + for (const auto& track : tracks) { + pidTracksTableDataML(track.tpcSignal(), getTRDSignal(track), getTRDPattern(track), + getTOFSignal(track), getTOFBeta(track), + track.p(), track.pt(), track.px(), track.py(), track.pz(), + track.sign(), + track.x(), track.y(), track.z(), + track.alpha(), + track.trackType(), + track.tpcNClsShared(), + track.dcaXY(), track.dcaZ()); + + fillHist(track); + } + } + PROCESS_SWITCH(PidMlProducer, processDataML, "Produce only ML real data", true); + + void processDataAll(MyCollision const& collision, BigTracksData const& tracks) + { + for (const auto& track : tracks) { + pidTracksTableData(collision.centRun2V0M(), + collision.multFV0A(), collision.multFV0C(), collision.multFV0M(), + collision.multFT0A(), collision.multFT0C(), collision.multFT0M(), + collision.multZNA(), collision.multZNC(), + collision.multTracklets(), collision.multTPC(), + track.tpcSignal(), getTRDSignal(track), getTRDPattern(track), + track.trackEtaEmcal(), track.trackPhiEmcal(), + getTOFSignal(track), getTOFBeta(track), + track.p(), track.pt(), track.px(), track.py(), track.pz(), + track.sign(), + track.x(), track.y(), track.z(), + track.alpha(), + track.trackType(), + track.tpcNClsShared(), + track.dcaXY(), track.dcaZ(), + track.tpcNSigmaEl(), track.tpcExpSigmaEl(), track.tpcExpSignalDiffEl(), + track.tofNSigmaEl(), track.tofExpSigmaEl(), track.tofExpSignalDiffEl(), + track.tpcNSigmaMu(), track.tpcExpSigmaMu(), track.tpcExpSignalDiffMu(), + track.tofNSigmaMu(), track.tofExpSigmaMu(), track.tofExpSignalDiffMu(), + track.tpcNSigmaPi(), track.tpcExpSigmaPi(), track.tpcExpSignalDiffPi(), + track.tofNSigmaPi(), track.tofExpSigmaPi(), track.tofExpSignalDiffPi(), + track.tpcNSigmaKa(), track.tpcExpSigmaKa(), track.tpcExpSignalDiffKa(), + track.tofNSigmaKa(), track.tofExpSigmaKa(), track.tofExpSignalDiffKa(), + track.tpcNSigmaPr(), track.tpcExpSigmaPr(), track.tpcExpSignalDiffPr(), + track.tofNSigmaPr(), track.tofExpSigmaPr(), track.tofExpSignalDiffPr()); + + fillHist(track); + } + } + PROCESS_SWITCH(PidMlProducer, processDataAll, "Produce all real data", false); + + void processMcMl(MyCollisionML const& /*collision*/, BigTracksMCML const& tracks, aod::McParticles const& /*mctracks*/) + { + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + const auto mcParticle = track.mcParticle_as(); + uint8_t isPrimary = static_cast(mcParticle.isPhysicalPrimary()); + uint32_t pdgCode = mcParticle.pdgCode(); + pidTracksTableMCML(track.tpcSignal(), getTRDSignal(track), getTRDPattern(track), + getTOFSignal(track), getTOFBeta(track), + track.p(), track.pt(), track.px(), track.py(), track.pz(), + track.sign(), + track.x(), track.y(), track.z(), + track.alpha(), + track.trackType(), + track.tpcNClsShared(), + track.dcaXY(), track.dcaZ(), + pdgCode, + isPrimary); + + fillHistMC(track, pdgCode, isPrimary); + } + } + PROCESS_SWITCH(PidMlProducer, processMcMl, "Produce only ML MC essential data", false); + + void processMcAll(MyCollision const& collision, BigTracksMC const& tracks, aod::McParticles const& /*mctracks*/) + { + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + const auto mcParticle = track.mcParticle_as(); + uint8_t isPrimary = static_cast(mcParticle.isPhysicalPrimary()); + uint32_t pdgCode = mcParticle.pdgCode(); + pidTracksTableMC(collision.centRun2V0M(), + collision.multFV0A(), collision.multFV0C(), collision.multFV0M(), + collision.multFT0A(), collision.multFT0C(), collision.multFT0M(), + collision.multZNA(), collision.multZNC(), + collision.multTracklets(), collision.multTPC(), + track.tpcSignal(), getTRDSignal(track), getTRDPattern(track), + track.trackEtaEmcal(), track.trackPhiEmcal(), + getTOFSignal(track), getTOFBeta(track), + track.p(), track.pt(), track.px(), track.py(), track.pz(), + track.sign(), + track.x(), track.y(), track.z(), + track.alpha(), + track.trackType(), + track.tpcNClsShared(), + track.dcaXY(), track.dcaZ(), + track.tpcNSigmaEl(), track.tpcExpSigmaEl(), track.tpcExpSignalDiffEl(), + track.tofNSigmaEl(), track.tofExpSigmaEl(), track.tofExpSignalDiffEl(), + track.tpcNSigmaMu(), track.tpcExpSigmaMu(), track.tpcExpSignalDiffMu(), + track.tofNSigmaMu(), track.tofExpSigmaMu(), track.tofExpSignalDiffMu(), + track.tpcNSigmaPi(), track.tpcExpSigmaPi(), track.tpcExpSignalDiffPi(), + track.tofNSigmaPi(), track.tofExpSigmaPi(), track.tofExpSignalDiffPi(), + track.tpcNSigmaKa(), track.tpcExpSigmaKa(), track.tpcExpSignalDiffKa(), + track.tofNSigmaKa(), track.tofExpSigmaKa(), track.tofExpSignalDiffKa(), + track.tpcNSigmaPr(), track.tpcExpSigmaPr(), track.tpcExpSignalDiffPr(), + track.tofNSigmaPr(), track.tofExpSigmaPr(), track.tofExpSignalDiffPr(), + pdgCode, + isPrimary); + + fillHistMC(track, pdgCode, isPrimary); + } + } + PROCESS_SWITCH(PidMlProducer, processMcAll, "Produce all MC data", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/Tools/PIDML/pidMLProducerData.cxx b/Tools/PIDML/pidMLProducerData.cxx deleted file mode 100644 index 0db70ae821e..00000000000 --- a/Tools/PIDML/pidMLProducerData.cxx +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2019-2020 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. - -/// \file pidMLProducerData.cxx -/// \brief Produce PID ML skimmed data from data files. -/// -/// \author Maja Kabus -/// -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Tools/PIDML/pidML.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -#include "Framework/runDataProcessing.h" - -struct PidMlProducerData { - Produces pidTracksTableML; - Produces pidTracksTable; - - Filter trackFilter = requireGlobalTrackInFilter(); - using BigTracksML = soa::Filtered>; - using MyCollisionML = aod::Collisions::iterator; - using BigTracks = soa::Filtered>; - using MyCollision = soa::Join::iterator; - - HistogramRegistry registry{ - "registry", - {{"hTPCSigvsPt", "TPC signal vs #it{p}_{T};#it{p}_{T} (GeV/#it{c});TPC signal", {HistType::kTH2F, {{500, 0., 10.}, {1000, 0., 600.}}}}, - {"hTOFBetavsPt", "TOF beta vs #it{p}_{T};#it{p}_{T} (GeV/#it{c});TOF beta", {HistType::kTH2F, {{500, 0., 10.}, {500, 0., 2.}}}}, - {"hTRDSigvsPt", "TRD signal vs #it{p}_{T};#it{p}_{T} (GeV/#it{c});TRD signal", {HistType::kTH2F, {{500, 0., 10.}, {2500, 0., 100.}}}}}}; - - void processML(MyCollisionML const& /*collision*/, BigTracksML const& tracks) - { - for (const auto& track : tracks) { - pidTracksTableML(track.tpcSignal(), track.trdSignal(), track.trdPattern(), - track.tofSignal(), track.beta(), - track.p(), track.pt(), track.px(), track.py(), track.pz(), - track.sign(), - track.x(), track.y(), track.z(), - track.alpha(), - track.trackType(), - track.tpcNClsShared(), - track.dcaXY(), track.dcaZ()); - - registry.fill(HIST("hTPCSigvsPt"), track.pt(), track.tpcSignal()); - registry.fill(HIST("hTOFBetavsPt"), track.pt(), track.beta()); - registry.fill(HIST("hTRDSigvsPt"), track.pt(), track.trdSignal()); - } - } - PROCESS_SWITCH(PidMlProducerData, processML, "Produce only ML real data", true); - - void processAll(MyCollision const& collision, BigTracks const& tracks) - { - for (const auto& track : tracks) { - pidTracksTable(collision.centRun2V0M(), - collision.multFV0A(), collision.multFV0C(), collision.multFV0M(), - collision.multFT0A(), collision.multFT0C(), collision.multFT0M(), - collision.multZNA(), collision.multZNC(), - collision.multTracklets(), collision.multTPC(), - track.tpcSignal(), track.trdSignal(), track.trdPattern(), - track.trackEtaEmcal(), track.trackPhiEmcal(), - track.tofSignal(), track.beta(), - track.p(), track.pt(), track.px(), track.py(), track.pz(), - track.sign(), - track.x(), track.y(), track.z(), - track.alpha(), - track.trackType(), - track.tpcNClsShared(), - track.dcaXY(), track.dcaZ(), - track.tpcNSigmaEl(), track.tpcExpSigmaEl(), track.tpcExpSignalDiffEl(), - track.tofNSigmaEl(), track.tofExpSigmaEl(), track.tofExpSignalDiffEl(), - track.tpcNSigmaMu(), track.tpcExpSigmaMu(), track.tpcExpSignalDiffMu(), - track.tofNSigmaMu(), track.tofExpSigmaMu(), track.tofExpSignalDiffMu(), - track.tpcNSigmaPi(), track.tpcExpSigmaPi(), track.tpcExpSignalDiffPi(), - track.tofNSigmaPi(), track.tofExpSigmaPi(), track.tofExpSignalDiffPi(), - track.tpcNSigmaKa(), track.tpcExpSigmaKa(), track.tpcExpSignalDiffKa(), - track.tofNSigmaKa(), track.tofExpSigmaKa(), track.tofExpSignalDiffKa(), - track.tpcNSigmaPr(), track.tpcExpSigmaPr(), track.tpcExpSignalDiffPr(), - track.tofNSigmaPr(), track.tofExpSigmaPr(), track.tofExpSignalDiffPr()); - - registry.fill(HIST("hTPCSigvsPt"), track.pt(), track.tpcSignal()); - registry.fill(HIST("hTOFBetavsPt"), track.pt(), track.beta()); - registry.fill(HIST("hTRDSigvsPt"), track.pt(), track.trdSignal()); - } - } - PROCESS_SWITCH(PidMlProducerData, processAll, "Produce all real data", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/Tools/PIDML/pidMLProducerMC.cxx b/Tools/PIDML/pidMLProducerMC.cxx deleted file mode 100644 index d7362d993a3..00000000000 --- a/Tools/PIDML/pidMLProducerMC.cxx +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2019-2020 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. - -/// \file pidMLProducerMc.cxx -/// \brief Produce PID ML skimmed data from MC files. -/// -/// \author Maja Kabus - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Tools/PIDML/pidML.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -#include "Framework/runDataProcessing.h" - -struct PidMlProducerMc { - Produces pidTracksTableML; - Produces pidTracksTable; - - Filter trackFilter = requireGlobalTrackInFilter(); - - using BigTracksML = soa::Filtered>; - using MyCollisionML = aod::Collisions::iterator; - using BigTracks = soa::Filtered>; - using MyCollision = soa::Join::iterator; - - HistogramRegistry registry{ - "registry", - {{"hTPCSigvsPt", "TPC signal vs #it{p}_{T};#it{p}_{T} (GeV/#it{c});TPC signal", {HistType::kTH2F, {{500, 0., 10.}, {1000, 0., 600.}}}}, - {"hTOFBetavsPt", "TOF beta vs #it{p}_{T};#it{p}_{T} (GeV/#it{c});TOF beta", {HistType::kTH2F, {{500, 0., 10.}, {500, 0., 2.}}}}, - {"hTRDSigvsPt", "TRD signal vs #it{p}_{T};#it{p}_{T} (GeV/#it{c});TRD signal", {HistType::kTH2F, {{500, 0., 10.}, {2500, 0., 100.}}}}}}; - - void processML(MyCollisionML const& /*collision*/, BigTracksML const& tracks, aod::McParticles const& /*mctracks*/) - { - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - continue; - } - const auto mcParticle = track.mcParticle_as(); - uint8_t isPrimary = (uint8_t)mcParticle.isPhysicalPrimary(); - pidTracksTableML(track.tpcSignal(), track.trdSignal(), track.trdPattern(), - track.tofSignal(), track.beta(), - track.p(), track.pt(), track.px(), track.py(), track.pz(), - track.sign(), - track.x(), track.y(), track.z(), - track.alpha(), - track.trackType(), - track.tpcNClsShared(), - track.dcaXY(), track.dcaZ(), - mcParticle.pdgCode(), - isPrimary); - - registry.fill(HIST("hTPCSigvsPt"), track.pt(), track.tpcSignal()); - registry.fill(HIST("hTOFBetavsPt"), track.pt(), track.beta()); - registry.fill(HIST("hTRDSigvsPt"), track.pt(), track.trdSignal()); - } - } - PROCESS_SWITCH(PidMlProducerMc, processML, "Produce only ML MC essential data", true); - - void processAll(MyCollision const& collision, BigTracks const& tracks, aod::McParticles const& /*mctracks*/) - { - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - continue; - } - const auto mcParticle = track.mcParticle_as(); - uint8_t isPrimary = (uint8_t)mcParticle.isPhysicalPrimary(); - pidTracksTable(collision.centRun2V0M(), - collision.multFV0A(), collision.multFV0C(), collision.multFV0M(), - collision.multFT0A(), collision.multFT0C(), collision.multFT0M(), - collision.multZNA(), collision.multZNC(), - collision.multTracklets(), collision.multTPC(), - track.tpcSignal(), track.trdSignal(), track.trdPattern(), - track.trackEtaEmcal(), track.trackPhiEmcal(), - track.tofSignal(), track.beta(), - track.p(), track.pt(), track.px(), track.py(), track.pz(), - track.sign(), - track.x(), track.y(), track.z(), - track.alpha(), - track.trackType(), - track.tpcNClsShared(), - track.dcaXY(), track.dcaZ(), - track.tpcNSigmaEl(), track.tpcExpSigmaEl(), track.tpcExpSignalDiffEl(), - track.tofNSigmaEl(), track.tofExpSigmaEl(), track.tofExpSignalDiffEl(), - track.tpcNSigmaMu(), track.tpcExpSigmaMu(), track.tpcExpSignalDiffMu(), - track.tofNSigmaMu(), track.tofExpSigmaMu(), track.tofExpSignalDiffMu(), - track.tpcNSigmaPi(), track.tpcExpSigmaPi(), track.tpcExpSignalDiffPi(), - track.tofNSigmaPi(), track.tofExpSigmaPi(), track.tofExpSignalDiffPi(), - track.tpcNSigmaKa(), track.tpcExpSigmaKa(), track.tpcExpSignalDiffKa(), - track.tofNSigmaKa(), track.tofExpSigmaKa(), track.tofExpSignalDiffKa(), - track.tpcNSigmaPr(), track.tpcExpSigmaPr(), track.tpcExpSignalDiffPr(), - track.tofNSigmaPr(), track.tofExpSigmaPr(), track.tofExpSignalDiffPr(), - mcParticle.pdgCode(), - isPrimary); - - registry.fill(HIST("hTPCSigvsPt"), track.pt(), track.tpcSignal()); - registry.fill(HIST("hTOFBetavsPt"), track.pt(), track.beta()); - registry.fill(HIST("hTRDSigvsPt"), track.pt(), track.trdSignal()); - } - } - PROCESS_SWITCH(PidMlProducerMc, processAll, "Produce all MC data", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/Tools/PIDML/pidOnnxInterface.h b/Tools/PIDML/pidOnnxInterface.h index 0cf8b473d4a..03e7bc19146 100644 --- a/Tools/PIDML/pidOnnxInterface.h +++ b/Tools/PIDML/pidOnnxInterface.h @@ -36,17 +36,17 @@ auto certainties_v = std::vector{certainties, certainties + nPids}; // default values for the cuts constexpr double cuts[nPids][nCutVars] = {{0.0, 0.5, 0.8}, {0.0, 0.5, 0.8}, {0.0, 0.5, 0.8}, {0.0, 0.5, 0.8}, {0.0, 0.5, 0.8}, {0.0, 0.5, 0.8}}; - // row labels static const std::vector pidLabels = { "211", "321", "2212", "0211", "0321", "02212"}; // column labels static const std::vector cutVarLabels = { "TPC", "TPC + TOF", "TPC + TOF + TRD"}; + } // namespace pidml_pt_cuts struct PidONNXInterface { - PidONNXInterface(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, std::vector const& pids, o2::framework::LabeledArray const& pTLimits, std::vector const& minCertainties, bool autoMode) : mNPids{pids.size()}, mPTLimits{pTLimits} + PidONNXInterface(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, std::vector const& pids, o2::framework::LabeledArray const& pLimits, std::vector const& minCertainties, bool autoMode) : mNPids{pids.size()}, mPLimits{pLimits} { if (pids.size() == 0) { LOG(fatal) << "PID ML Interface needs at least 1 output pid to predict"; @@ -54,7 +54,7 @@ struct PidONNXInterface { std::set tmp; for (auto& pid : pids) { if (!tmp.insert(pid).second) { - LOG(fatal) << "PID M Interface: output pids cannot repeat!"; + LOG(fatal) << "PID ML Interface: output pids cannot repeat!"; } } @@ -68,9 +68,7 @@ struct PidONNXInterface { minCertaintiesFilled = minCertainties; } for (std::size_t i = 0; i < mNPids; i++) { - for (uint32_t j = 0; j < kNDetectors; j++) { - mModels.emplace_back(localPath, ccdbPath, useCCDB, ccdbApi, timestamp, pids[i], (PidMLDetector)(kTPCOnly + j), minCertaintiesFilled[i]); - } + mModels.emplace_back(localPath, ccdbPath, useCCDB, ccdbApi, timestamp, pids[i], minCertaintiesFilled[i], mPLimits[i]); } } PidONNXInterface() = default; @@ -84,12 +82,8 @@ struct PidONNXInterface { float applyModel(const T& track, int pid) { for (std::size_t i = 0; i < mNPids; i++) { - if (mModels[i * kNDetectors].mPid == pid) { - for (uint32_t j = 0; j < kNDetectors; j++) { - if (track.pt() >= mPTLimits[i][j] && (j == kNDetectors - 1 || track.pt() < mPTLimits[i][j + 1])) { - return mModels[i * kNDetectors + j].applyModel(track); - } - } + if (mModels[i].mPid == pid) { + return mModels[i].applyModel(track); } } LOG(error) << "No suitable PID ML model found for track: " << track.globalIndex() << " from collision: " << track.collision().globalIndex() << " and expected pid: " << pid; @@ -100,12 +94,8 @@ struct PidONNXInterface { bool applyModelBoolean(const T& track, int pid) { for (std::size_t i = 0; i < mNPids; i++) { - if (mModels[i * kNDetectors].mPid == pid) { - for (uint32_t j = 0; j < kNDetectors; j++) { - if (track.pt() >= mPTLimits[i][j] && (j == kNDetectors - 1 || track.pt() < mPTLimits[i][j + 1])) { - return mModels[i * kNDetectors + j].applyModelBoolean(track); - } - } + if (mModels[i].mPid == pid) { + return mModels[i].applyModelBoolean(track); } } LOG(error) << "No suitable PID ML model found for track: " << track.globalIndex() << " from collision: " << track.collision().globalIndex() << " and expected pid: " << pid; @@ -116,12 +106,12 @@ struct PidONNXInterface { void fillDefaultConfiguration(std::vector& minCertainties) { // FIXME: A more sophisticated strategy should be based on pid values as well - mPTLimits = o2::framework::LabeledArray{pidml_pt_cuts::cuts[0], pidml_pt_cuts::nPids, pidml_pt_cuts::nCutVars, pidml_pt_cuts::pidLabels, pidml_pt_cuts::cutVarLabels}; + mPLimits = o2::framework::LabeledArray{pidml_pt_cuts::cuts[0], pidml_pt_cuts::nPids, pidml_pt_cuts::nCutVars, pidml_pt_cuts::pidLabels, pidml_pt_cuts::cutVarLabels}; minCertainties = std::vector(mNPids, 0.5); } std::vector mModels; std::size_t mNPids; - o2::framework::LabeledArray mPTLimits; + o2::framework::LabeledArray mPLimits; }; #endif // TOOLS_PIDML_PIDONNXINTERFACE_H_ diff --git a/Tools/PIDML/pidOnnxModel.h b/Tools/PIDML/pidOnnxModel.h index 8764496c25c..207bc18cd8e 100644 --- a/Tools/PIDML/pidOnnxModel.h +++ b/Tools/PIDML/pidOnnxModel.h @@ -17,22 +17,27 @@ #ifndef TOOLS_PIDML_PIDONNXMODEL_H_ #define TOOLS_PIDML_PIDONNXMODEL_H_ +#include +#include +#include #include #include #include #include #include #include - #if __has_include() #include #else #include #endif + #include "rapidjson/document.h" #include "rapidjson/filereadstream.h" - #include "CCDB/CcdbApi.h" +#include "Tools/PIDML/pidUtils.h" + +using namespace pidml::pidutils; enum PidMLDetector { kTPCOnly = 0, @@ -41,6 +46,13 @@ enum PidMLDetector { kNDetectors ///< number of available detectors configurations }; +namespace pidml_pt_cuts +{ +// TODO: for now first limit wouldn't be used, +// network needs TPC, so we can either do not cut it by p or return 0.0f as prediction +constexpr std::array defaultModelPLimits({0.0, 0.5, 0.8}); +} // namespace pidml_pt_cuts + // TODO: Copied from cefpTask, shall we put it in some common utils code? namespace { @@ -63,8 +75,12 @@ bool readJsonFile(const std::string& config, rapidjson::Document& d) struct PidONNXModel { public: - PidONNXModel(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, int pid, PidMLDetector detector, double minCertainty) : mDetector(detector), mPid(pid), mMinCertainty(minCertainty) + PidONNXModel(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, + int pid, double minCertainty, const double* pLimits = &pidml_pt_cuts::defaultModelPLimits[0]) + : mPid(pid), mMinCertainty(minCertainty), mPLimits(pLimits, pLimits + kNDetectors) { + assert(mPLimits.size() == kNDetectors); + std::string modelFile; loadInputFiles(localPath, ccdbPath, useCCDB, ccdbApi, timestamp, pid, modelFile); @@ -131,27 +147,21 @@ struct PidONNXModel { return getModelOutput(track) >= mMinCertainty; } - PidMLDetector mDetector; int mPid; double mMinCertainty; private: void getModelPaths(std::string const& path, std::string& modelDir, std::string& modelFile, std::string& modelPath, int pid, std::string const& ext) { - modelDir = path + "/TPC"; - if (mDetector >= kTPCTOF) { - modelDir += "_TOF"; - } - if (mDetector >= kTPCTOFTRD) { - modelDir += "_TRD"; - } + modelDir = path; + modelFile = "attention_model_"; - modelFile = "simple_model_"; if (pid < 0) { modelFile += "0" + std::to_string(-pid); } else { modelFile += std::to_string(pid); } + modelFile += ext; modelPath = modelDir + "/" + modelFile; } @@ -208,55 +218,64 @@ struct PidONNXModel { { // TODO: Hardcoded for now. Planning to implement RowView extension to get runtime access to selected columns // sign is short, trackType and tpcNClsShared uint8_t - float scaledX = (track.x() - mScalingParams.at("fX").first) / mScalingParams.at("fX").second; - float scaledY = (track.y() - mScalingParams.at("fY").first) / mScalingParams.at("fY").second; - float scaledZ = (track.z() - mScalingParams.at("fZ").first) / mScalingParams.at("fZ").second; - float scaledAlpha = (track.alpha() - mScalingParams.at("fAlpha").first) / mScalingParams.at("fAlpha").second; - float scaledTPCNClsShared = (static_cast(track.tpcNClsShared()) - mScalingParams.at("fTPCNClsShared").first) / mScalingParams.at("fTPCNClsShared").second; - float scaledDcaXY = (track.dcaXY() - mScalingParams.at("fDcaXY").first) / mScalingParams.at("fDcaXY").second; - float scaledDcaZ = (track.dcaZ() - mScalingParams.at("fDcaZ").first) / mScalingParams.at("fDcaZ").second; float scaledTPCSignal = (track.tpcSignal() - mScalingParams.at("fTPCSignal").first) / mScalingParams.at("fTPCSignal").second; - std::vector inputValues{track.px(), track.py(), track.pz(), static_cast(track.sign()), scaledX, scaledY, scaledZ, scaledAlpha, static_cast(track.trackType()), scaledTPCNClsShared, scaledDcaXY, scaledDcaZ, track.p(), scaledTPCSignal}; + std::vector inputValues{scaledTPCSignal}; + + // When TRD Signal shouldn't be used we pass quiet_NaNs to the network + if (!inPLimit(track, mPLimits[kTPCTOFTRD]) || trdMissing(track)) { + inputValues.push_back(std::numeric_limits::quiet_NaN()); + inputValues.push_back(std::numeric_limits::quiet_NaN()); + } else { + float scaledTRDSignal = (track.trdSignal() - mScalingParams.at("fTRDSignal").first) / mScalingParams.at("fTRDSignal").second; + inputValues.push_back(scaledTRDSignal); + inputValues.push_back(track.trdPattern()); + } - if (mDetector >= kTPCTOF) { + // When TOF Signal shouldn't be used we pass quiet_NaNs to the network + if (!inPLimit(track, mPLimits[kTPCTOF]) || tofMissing(track)) { + inputValues.push_back(std::numeric_limits::quiet_NaN()); + inputValues.push_back(std::numeric_limits::quiet_NaN()); + } else { float scaledTOFSignal = (track.tofSignal() - mScalingParams.at("fTOFSignal").first) / mScalingParams.at("fTOFSignal").second; float scaledBeta = (track.beta() - mScalingParams.at("fBeta").first) / mScalingParams.at("fBeta").second; inputValues.push_back(scaledTOFSignal); inputValues.push_back(scaledBeta); } - if (mDetector >= kTPCTOFTRD) { - float scaledTRDSignal = (track.trdSignal() - mScalingParams.at("fTRDSignal").first) / mScalingParams.at("fTRDSignal").second; - float scaledTRDPattern = (track.trdPattern() - mScalingParams.at("fTRDPattern").first) / mScalingParams.at("fTRDPattern").second; - inputValues.push_back(scaledTRDSignal); - inputValues.push_back(scaledTRDPattern); - } + float scaledX = (track.x() - mScalingParams.at("fX").first) / mScalingParams.at("fX").second; + float scaledY = (track.y() - mScalingParams.at("fY").first) / mScalingParams.at("fY").second; + float scaledZ = (track.z() - mScalingParams.at("fZ").first) / mScalingParams.at("fZ").second; + float scaledAlpha = (track.alpha() - mScalingParams.at("fAlpha").first) / mScalingParams.at("fAlpha").second; + float scaledTPCNClsShared = (static_cast(track.tpcNClsShared()) - mScalingParams.at("fTPCNClsShared").first) / mScalingParams.at("fTPCNClsShared").second; + float scaledDcaXY = (track.dcaXY() - mScalingParams.at("fDcaXY").first) / mScalingParams.at("fDcaXY").second; + float scaledDcaZ = (track.dcaZ() - mScalingParams.at("fDcaZ").first) / mScalingParams.at("fDcaZ").second; - return inputValues; - } + inputValues.insert(inputValues.end(), {track.p(), track.pt(), track.px(), track.py(), track.pz(), static_cast(track.sign()), scaledX, scaledY, scaledZ, scaledAlpha, static_cast(track.trackType()), scaledTPCNClsShared, scaledDcaXY, scaledDcaZ}); - // FIXME: Temporary solution, new networks will have sigmoid layer added - float sigmoid(float x) - { - float value = std::max(-100.0f, std::min(100.0f, x)); - return 1.0f / (1.0f + std::exp(-value)); + return inputValues; } template float getModelOutput(const T& track) { + // First rank of the expected model input is -1 which means that it is dynamic axis. + // Axis is exported as dynamic to make it possible to run model inference with the batch of + // tracks at once in the future (batch would need to have the same amount of quiet_NaNs in each row). + // For now we hardcode 1. + static constexpr int64_t batch_size = 1; auto input_shape = mInputShapes[0]; + input_shape[0] = batch_size; + std::vector inputTensorValues = createInputsSingle(track); std::vector inputTensors; + #if __has_include() inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(inputTensorValues.data(), inputTensorValues.size(), input_shape)); #else - Ort::MemoryInfo mem_info = - Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); + Ort::MemoryInfo mem_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.emplace_back(Ort::Value::CreateTensor(mem_info, inputTensorValues.data(), inputTensorValues.size(), input_shape.data(), input_shape.size())); - #endif // Double-check the dimensions of the input tensor @@ -285,7 +304,7 @@ struct PidONNXModel { LOG(debug) << "output tensor shape: " << printShape(outputTensors[0].GetTensorTypeAndShapeInfo().GetShape()); const float* output_value = outputTensors[0].GetTensorData(); - float certainty = sigmoid(*output_value); // FIXME: Temporary, sigmoid will be added as network layer + float certainty = *output_value; return certainty; } catch (const Ort::Exception& exception) { LOG(error) << "Error running model inference: " << exception.what(); @@ -314,6 +333,7 @@ struct PidONNXModel { std::shared_ptr mSession = nullptr; #endif + std::vector mPLimits; std::vector mInputNames; std::vector> mInputShapes; std::vector mOutputNames; diff --git a/Tools/PIDML/pidUtils.h b/Tools/PIDML/pidUtils.h new file mode 100644 index 00000000000..4c101e30b19 --- /dev/null +++ b/Tools/PIDML/pidUtils.h @@ -0,0 +1,46 @@ +// Copyright 2019-2020 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. + +/// \file pidUtils.h +/// \brief Common constants and functions for PID. +/// +/// \author Marek Mytkowski + +#ifndef TOOLS_PIDML_PIDUTILS_H_ +#define TOOLS_PIDML_PIDUTILS_H_ + +#include + +namespace pidml::pidutils +{ +constexpr double kTOFMissingSignal = -999.0f; +constexpr double kGlobalEtaCut = 0.8f; + +template +bool trdMissing(const T& track) +{ + return !track.hasTRD(); +} + +template +bool tofMissing(const T& track) +{ + return !track.hasTOF(); +} + +template +bool inPLimit(const T& track, double pLimit) +{ + return track.p() >= pLimit; +} +} // namespace pidml::pidutils + +#endif // TOOLS_PIDML_PIDUTILS_H_ diff --git a/Tools/PIDML/qaPidML.cxx b/Tools/PIDML/qaPidML.cxx index accd055222c..54cafc437ab 100644 --- a/Tools/PIDML/qaPidML.cxx +++ b/Tools/PIDML/qaPidML.cxx @@ -13,6 +13,8 @@ /// \author Ɓukasz Sawicki /// \since +#include + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" @@ -21,13 +23,12 @@ #include "Common/DataModel/PIDResponse.h" #include #include "Tools/PIDML/pidOnnxModel.h" -#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct pidml { +struct QaPidML { static const int maxP = 5; // nb of bins for TH1 hists static const int binsNb = 100; @@ -47,9 +48,9 @@ struct pidml { // available particles: 211, 2212, 321 static constexpr int particlesPdgCode[numParticles] = {211, 2212, 321}; - // values of track momentum when to switch from only TPC signal to combined TPC and TOF signal + // values of track momentum when to switch from only TPC signal to combined TPC and TOF signal and to TPC+TOF+TRD // i-th momentum corresponds to the i-th particle - static constexpr float pSwitchValue[numParticles] = {0.5, 0.8, 0.5}; + static constexpr double pSwitchValue[numParticles][kNDetectors] = {{0.0, 0.5, 0.8}, {0.0, 0.8, 0.8}, {0.0, 0.5, 0.8}}; HistogramRegistry histReg{ "allHistograms", @@ -244,34 +245,35 @@ struct pidml { template void fillMcHistos(const T& track, const int pdgCode) { - // pions if (pdgCode == 211) { + // pions histReg.fill(HIST("MC/211"), track.pt()); } else if (pdgCode == -211) { + // antipions histReg.fill(HIST("MC/0211"), track.pt()); - } - // protons - else if (pdgCode == 2212) { + } else if (pdgCode == 2212) { + // protons histReg.fill(HIST("MC/2212"), track.pt()); } else if (pdgCode == -2212) { + // antiprotons histReg.fill(HIST("MC/02212"), track.pt()); - } - // kaons - else if (pdgCode == 321) { + } else if (pdgCode == 321) { + // kaons histReg.fill(HIST("MC/321"), track.pt()); } else if (pdgCode == -321) { + // antikaons histReg.fill(HIST("MC/0321"), track.pt()); - } - // electrons - else if (pdgCode == 11) { + } else if (pdgCode == 11) { + // electrons histReg.fill(HIST("MC/11"), track.pt()); } else if (pdgCode == -11) { + // positrons histReg.fill(HIST("MC/011"), track.pt()); - } - // muons - else if (pdgCode == 13) { + } else if (pdgCode == 13) { + // muons histReg.fill(HIST("MC/13"), track.pt()); } else if (pdgCode == -13) { + // antimuons histReg.fill(HIST("MC/013"), track.pt()); } else { histReg.fill(HIST("MC/else"), track.pt()); @@ -326,15 +328,9 @@ struct pidml { void pidML(const T& track, const int pdgCodeMC) { float pidCertainties[3]; - if (track.p() < pSwitchValue[i]) { - pidCertainties[0] = model211TPC.applyModel(track); - pidCertainties[1] = model2212TPC.applyModel(track); - pidCertainties[2] = model321TPC.applyModel(track); - } else { - pidCertainties[0] = model211All.applyModel(track); - pidCertainties[1] = model2212All.applyModel(track); - pidCertainties[2] = model321All.applyModel(track); - } + pidCertainties[0] = model211.applyModel(track); + pidCertainties[1] = model2212.applyModel(track); + pidCertainties[2] = model321.applyModel(track); int pid = getParticlePdg(pidCertainties); // condition for sign: we want to work only with pi, p and K, without antiparticles if (pid == particlesPdgCode[i] && track.sign() == 1) { @@ -346,14 +342,10 @@ struct pidml { } } - // one model for one particle; Model with all TPC and TOF signal - PidONNXModel model211All; - PidONNXModel model2212All; - PidONNXModel model321All; - // Model with only TPC signal model - PidONNXModel model211TPC; - PidONNXModel model2212TPC; - PidONNXModel model321TPC; + // one model for one particle + PidONNXModel model211; + PidONNXModel model2212; + PidONNXModel model321; Configurable cfgPathCCDB{"ccdb-path", "Users/m/mkabus/PIDML", "base path to the CCDB directory with ONNX models"}; Configurable cfgCCDBURL{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB repository"}; @@ -368,13 +360,9 @@ struct pidml { if (cfgUseCCDB) { ccdbApi.init(cfgCCDBURL); } else { - model211All = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 211, kTPCTOF, 0.5f); - model2212All = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 2211, kTPCTOF, 0.5f); - model321All = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 321, kTPCTOF, 0.5f); - - model211TPC = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 211, kTPCOnly, 0.5f); - model2212TPC = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 2211, kTPCOnly, 0.5f); - model321TPC = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 321, kTPCOnly, 0.5f); + model211 = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 211, 0.5f, pSwitchValue[0]); + model2212 = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 2211, 0.5f, pSwitchValue[1]); + model321 = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, 321, 0.5f, pSwitchValue[2]); } } @@ -384,13 +372,9 @@ struct pidml { { auto bc = collisions.iteratorAt(0).bc_as(); if (cfgUseCCDB && bc.runNumber() != currentRunNumber) { - model211All = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 211, kTPCTOF, 0.5f); - model2212All = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 2211, kTPCTOF, 0.5f); - model321All = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 321, kTPCTOF, 0.5f); - - model211TPC = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 211, kTPCOnly, 0.5f); - model2212TPC = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 2211, kTPCOnly, 0.5f); - model321TPC = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 321, kTPCOnly, 0.5f); + model211 = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 211, 0.5f, pSwitchValue[0]); + model2212 = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 2211, 0.5f, pSwitchValue[1]); + model321 = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, bc.timestamp(), 321, 0.5f, pSwitchValue[2]); } for (auto& track : tracks) { @@ -410,6 +394,6 @@ struct pidml { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; } diff --git a/Tools/PIDML/simpleApplyPidOnnxInterface.cxx b/Tools/PIDML/simpleApplyPidOnnxInterface.cxx index 85847320787..82f644103ed 100644 --- a/Tools/PIDML/simpleApplyPidOnnxInterface.cxx +++ b/Tools/PIDML/simpleApplyPidOnnxInterface.cxx @@ -14,6 +14,8 @@ /// /// \author Maja Kabus +#include + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "CCDB/CcdbApi.h" @@ -21,8 +23,6 @@ #include "Common/DataModel/PIDResponse.h" #include "Tools/PIDML/pidOnnxInterface.h" -#include - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/Tools/PIDML/simpleApplyPidOnnxModel.cxx b/Tools/PIDML/simpleApplyPidOnnxModel.cxx index 00dc843ca47..e261c1e10bc 100644 --- a/Tools/PIDML/simpleApplyPidOnnxModel.cxx +++ b/Tools/PIDML/simpleApplyPidOnnxModel.cxx @@ -14,6 +14,8 @@ /// /// \author Maja Kabus +#include + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "CCDB/CcdbApi.h" @@ -21,8 +23,6 @@ #include "Common/DataModel/PIDResponse.h" #include "Tools/PIDML/pidOnnxModel.h" -#include - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -40,7 +40,6 @@ DECLARE_SOA_TABLE(MlPidResults, "AOD", "MLPIDRESULTS", o2::soa::Index<>, mlpidre struct SimpleApplyOnnxModel { PidONNXModel pidModel; // One instance per model, e.g., one per each pid to predict - Configurable cfgDetector{"detector", kTPCTOFTRD, "What detectors to use: 0: TPC only, 1: TPC + TOF, 2: TPC + TOF + TRD"}; Configurable cfgPid{"pid", 211, "PID to predict"}; Configurable cfgCertainty{"certainty", 0.5, "Min certainty of the model to accept given particle to be of given kind"}; @@ -68,7 +67,7 @@ struct SimpleApplyOnnxModel { if (cfgUseCCDB) { ccdbApi.init(cfgCCDBURL); } else { - pidModel = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, cfgPid.value, static_cast(cfgDetector.value), cfgCertainty.value); + pidModel = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, -1, cfgPid.value, cfgCertainty.value); } } @@ -77,7 +76,7 @@ struct SimpleApplyOnnxModel { auto bc = collisions.iteratorAt(0).bc_as(); if (cfgUseCCDB && bc.runNumber() != currentRunNumber) { uint64_t timestamp = cfgUseFixedTimestamp ? cfgTimestamp.value : bc.timestamp(); - pidModel = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, timestamp, cfgPid.value, static_cast(cfgDetector.value), cfgCertainty.value); + pidModel = PidONNXModel(cfgPathLocal.value, cfgPathCCDB.value, cfgUseCCDB.value, ccdbApi, timestamp, cfgPid.value, cfgCertainty.value); } for (auto& track : tracks) { diff --git a/Tutorials/PWGCF/TwoParticleCorrelations/src/firstcfcorrelations.cxx b/Tutorials/PWGCF/TwoParticleCorrelations/src/firstcfcorrelations.cxx index bd4d9dfd4f5..cdec4f3ca95 100644 --- a/Tutorials/PWGCF/TwoParticleCorrelations/src/firstcfcorrelations.cxx +++ b/Tutorials/PWGCF/TwoParticleCorrelations/src/firstcfcorrelations.cxx @@ -39,7 +39,7 @@ struct firstcorrelations { } template - void fillQA(TCollision collision, float centrality, TTracks tracks) + void fillQA(TCollision /*collision*/, float /*centrality*/, TTracks /*tracks*/) { } @@ -50,7 +50,7 @@ struct firstcorrelations { } template - void fillCorrelations(TTarget target, TTracks tracks1, TTracks tracks2, float centrality, float posZ) + void fillCorrelations(TTarget /*target*/, TTracks /*tracks1*/, TTracks /*tracks2*/, float /*centrality*/, float /*posZ*/) { } diff --git a/Tutorials/src/TrainingTree.h b/Tutorials/src/TrainingTree.h index 93b4741a951..229b8393193 100644 --- a/Tutorials/src/TrainingTree.h +++ b/Tutorials/src/TrainingTree.h @@ -45,7 +45,7 @@ auto meanPt(Tracks const& tracks) auto apt = 0.f; auto npt = 0; for (auto& track : tracks) { - if (isfinite(track.pt()) && (std::abs(track.pt()) > 1e-3)) { + if (std::isfinite(track.pt()) && (std::abs(track.pt()) > 1e-3)) { ++npt; apt += track.pt(); } diff --git a/Tutorials/src/reweighting.cxx b/Tutorials/src/reweighting.cxx index d1c88c22657..72c17a1cb29 100644 --- a/Tutorials/src/reweighting.cxx +++ b/Tutorials/src/reweighting.cxx @@ -37,6 +37,7 @@ #include "Framework/AnalysisTask.h" #include "Common/DataModel/Multiplicity.h" #include "TrainingTree.h" +#include using namespace o2; using namespace o2::framework; @@ -181,7 +182,7 @@ struct ConsumeWeights { /// fill histograms with using BDT scores produced by previous task as weights for (auto& track : tracks) { - if (isfinite(track.pt())) { + if (std::isfinite(track.pt())) { registry.fill(HIST("Weighted/Tracks/Pt"), track.pt(), collision.weight()); } } @@ -201,7 +202,7 @@ struct ConsumeWeights { /// fill histograms without weights for (auto& track : tracks) { - if (isfinite(track.pt())) { + if (std::isfinite(track.pt())) { registry.fill(HIST("Tracks/Pt"), track.pt()); } } diff --git a/cmake/O2PhysicsDefineOptions.cmake b/cmake/O2PhysicsDefineOptions.cmake index d647fa2fde0..95868fe8904 100644 --- a/cmake/O2PhysicsDefineOptions.cmake +++ b/cmake/O2PhysicsDefineOptions.cmake @@ -18,4 +18,6 @@ function(o2physics_define_options) option(ENABLE_CASSERT "Enable asserts" OFF) option(ENABLE_UPGRADES "Enable detectors for upgrades" OFF) + + option(O2PHYSICS_WARNINGS_AS_ERRORS "Treat selected warnings as errors" OFF) endfunction() diff --git a/dependencies/O2PhysicsCompileFlags.cmake b/dependencies/O2PhysicsCompileFlags.cmake index c29d8c4a996..50967b17ea6 100644 --- a/dependencies/O2PhysicsCompileFlags.cmake +++ b/dependencies/O2PhysicsCompileFlags.cmake @@ -11,13 +11,53 @@ include_guard() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-error \ --Werror=deprecated-enum-float-conversion \ --Werror=narrowing \ --Werror=parentheses \ --Werror=return-type \ --Werror=uninitialized \ --Werror=unused") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + +# Enabled warnings supported by Clang and GCC, not treated as errors +set(O2PHYSICS_WARNINGS_COMMON_NO_ERROR "sign-compare") + +# Enabled warnings supported by Clang only, not treated as errors +set(O2PHYSICS_WARNINGS_CLANG_NO_ERROR "") + +# Enabled warnings supported by GCC only, not treated as errors +set(O2PHYSICS_WARNINGS_GCC_NO_ERROR "") + +# Function to build a list of warning flags from their names +function(o2_build_warning_flags) + cmake_parse_arguments(PARSE_ARGV 0 A "" "PREFIX;OUTPUTVARNAME" "WARNINGS") + if(A_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unexpected unparsed arguments: ${A_UNPARSED_ARGUMENTS}") + endif() + list(TRANSFORM A_WARNINGS STRIP) + list(TRANSFORM A_WARNINGS PREPEND ${A_PREFIX}) + string(JOIN " " OUTPUT ${A_WARNINGS}) + set(${A_OUTPUTVARNAME} ${OUTPUT} PARENT_SCOPE) +endfunction() + +message(STATUS "O2PHYSICS_WARNINGS_AS_ERRORS: ${O2PHYSICS_WARNINGS_AS_ERRORS}") + +# Treat warnings as errors. +if(O2PHYSICS_WARNINGS_AS_ERRORS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + # Set warning flags for all platforms. + o2_build_warning_flags(PREFIX "-Wno-error=" + OUTPUTVARNAME O2PHYSICS_CXX_WARNINGS_COMMON_NO_ERROR + WARNINGS ${O2PHYSICS_WARNINGS_COMMON_NO_ERROR}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${O2PHYSICS_CXX_WARNINGS_COMMON_NO_ERROR}") + if(APPLE) + # Set warning flags for macOS only. + o2_build_warning_flags(PREFIX "-Wno-error=" + OUTPUTVARNAME O2PHYSICS_CXX_WARNINGS_APPLE_NO_ERROR + WARNINGS ${O2PHYSICS_WARNINGS_CLANG_NO_ERROR}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${O2PHYSICS_CXX_WARNINGS_APPLE_NO_ERROR}") + elseif(UNIX) + # Set warning flags for Linux only. + o2_build_warning_flags(PREFIX "-Wno-error=" + OUTPUTVARNAME O2PHYSICS_CXX_WARNINGS_UNIX_NO_ERROR + WARNINGS ${O2PHYSICS_WARNINGS_GCC_NO_ERROR}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${O2PHYSICS_CXX_WARNINGS_UNIX_NO_ERROR}") + endif() +endif() IF (ENABLE_TIMETRACE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftime-trace")